Vue+ElementUI项目使用webpack输出MPA

目录

  • 一. 需求分析
  • 二. 原方案分析
  • 三. 多页面改造3步走
  • 四. 小结

示例代码托管在:http://www.github.com/dashnowords/blogs

博客园地址:《大史住在大前端》原创博文目录

华为云社区地址:【你要的前端打怪升级指南】

一. 需求分析

为另一个项目提供可嵌入的功能单页,大部分页面使用时都是独立功能页,个别页面带有左侧边栏(相当于3-4个页面的整合形态),由于资源定位地址的限定,每个页面打包为单页后,入口html文件需要定制命名,且脚本和样式文件需要放在指定的路径下,公共资源地址也必须替换成特殊字符以适配母系统的调用逻辑(比如下面结构中应用jquery.min.js的路径可能是{{publicRoot}}/{{publicLib}}/jquery.minjs)。假设原工程中拥有AB这2个旧页面,现在需要开发CDE这3个页面,目录结构要求如下:

蓝色部分为旧资源,绿色部分为新开发需求。

二. 原方案分析

原方案采用Vue+ElementUI进行开发,构建过程基本是零配置的,开发效率非常高,页面风格也统一,但零配置的构建过程只能生成SPA模式的应用,所以原方案的做法是:

  1. 将构建过程中需要定制的量提取到config.js文件中进行统一管理,大致形式如下:

    //config.js
    module.exports = {
        A:{
            publicPath:'{{publicRoot}}/{{publicLib}}'
            prodFileName:'A.html',
            entryKey:'public/A',
            entryPath:'public/A/A.js'
        },
        B:{
            //...
        }
        //...
    }
  2. 开发过程中使用统一的路由文件router.js,打包过程中在main.js中引用对应页面的XX.router.spa.js作为路由,而将其他页面注释掉,打包时传入命令行参数--key=XXX,key值在打包脚本中被解析后从config.js中取出打包需要的设置参数,然后将目标页面打包为独立页面,其他页面虽然也在工程中,但并不参与打包。
    // 入口文件src/main.js
    import router from './pages/C/router.spa';
    //import router from './pages/D/router.spa';
    //import router from './pages/E/router.spa';

上述打包过程在使用中出现了很多问题:

  • 公共依赖没有剥离,vueElementUI会被打包进每一个单页面,使得每个打包出的index.js几乎有1.2MB大小,这种空间浪费是没必要的。
  • 公共样式没有形成独立文件,这使得每当有样式细节发生变更,就需要手动将每个页面逐一进行重新出包。
  • 页面增多后在main.js中会有很多独立路由,如果开发中进行了跨页面修改,很可能在main.js中激活的路由为C页面路由时,打包时--key参数的值却传成了D,这种情况并不会引起报错,但事实上构建结果确实错误的。
  • 由于入口文件保持main.js没有变化,所以在不同页面打包时,结果都输出在dist目录下,需要手动与母工程中的地址去匹配,操作繁琐。

三. 多页面改造3步走

上面的问题实际上都是因为原方案将一个多页面开发需求按照单页面应用来实现而造成的,需要对自动化构建工程进行一些定制。

1.分离webpack配置

本例中开发环境和最终打包的主要差异在于路由上,开发中由于可能需要进行跨页面开发,可以使用单入口和独立路由,而进行生产环境构建时则需要输出多页面应用,所以首先要做的就是将原本的webpack.config.js文件拆分为webpack.base.js,webpack.dev.js,webpack.prod.js三个文件,webpack.base.js为环境无差别的配置,然后依据构建模式的不同,使用webpack-merge插件将环境相关的配置与基本配置进行合并:

/*webpack.base.js示例*/
const argv = require('yargs-parser')(process.argv.slice(2));
const env_short = argv.env.all ? 'all' : argv.p ? 'prod':'dev';
const webpackConfig = require(`./config/webpack.${env_short}`);//根据-p属性加载webpack的dev配置或prod配置
const merge = require('webpack-merge');

//基本配置
const baseConfig = {
    //....
}

//输出合并后的配置
module.exports = merge(baseConfig, webpackConfig);

webpack.dev.js保持原本的SPA开发的设置即可满足需求。

2. 抽离外部引用

本例中较大的外部应用是vueElementUI,很多开发者一直使用自动化脚手架工具,并没有意识到这两个库作为外部依赖该如何引入工程。公共库的抽离需要在webpack配置中将其填写在external配置项中:

module.exports = {
 //...
  externals:{
      vue:'Vue',
      'element-ui':'ELEMENT'
  },
  //...
}

key为引用的模块名,value为这个模块引入后对应的全局命名,external配置项的含义是:请不要将这个模块注入编译后的JS文件里,对于源代码里出现的任何import/require这个模块的语句,请将它保留并根据模块化标准进行依赖方式适配

Tips:

  1. Vue做为外部依赖时有很多构建包,本例中因为使用webpack进行了构建,没有在线编译模板的需求,所以不需要引入完整的Vue,而只需要引入压缩后的只包含运行时的版本vue.runtime.min.js即可。
  2. 外部引入库时需要注意命名,比如上例中的ELEMENT,开发者通常会填写为自己在代码中使用的ElementUI而引起报错,当不确定名称时,有个简单的办法就是找一个CDN的资源看一下,通常代码最开始都是UMD规范的固定结构,很容易看到关键词(如下图所示)。

然后将资源的CDN地址或是本地公共库地址加入到index.html中,你可以使用模板语法,然后从html-webpack-plugin插件实例化时传入定制参数:

<!--html文件模板-->
<body>
  <div id="app"></div>
  <script src="<%= htmlWebpackPlugin.options.vue_path %>"></script>
  <script src="<%= htmlWebpackPlugin.options.elementUI_path %>"></script>
  <script src="<%= htmlWebpackPlugin.options.tpl_entryPath %>/index.js"></script>
</body>
//webpack.prod.js
module.exports = {
    //...
  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html',//生成index.html时依据的模板
      filename: '.....',
      inject:false,
      tpl_entryPath:'....',
      vue_path:'.....',
      elementUI_path:'.....',
    }),
    //new BundleAnalyzerPlugin()
  ],
}

最终打包后生成的index.html文件大致如下:

<body>
  <div id="app"></div>
  <script src="{{publicRoot}}/{{publicLib}}/vue.min.js"></script>
  <script src="{{publicRoot}}/{{publicLib}}/element-ui.js"></script>
  <script src="public/A/A.js"></script>
</body>

如果第三方库从本地加载,则需要将/node_modules/element-ui/lib/index.js/node_modules/vue/dist/vue.runtime.min.js两个依赖文件拷贝到lib文件夹中的对应地址,这样访问index.html时就可以以外部依赖的形式将其加载进来。样式文件的剥离直接使用插件完成即可,webpack4以前的版本使用extract-text-webpack-plugin,从4.0版本后统一使用mini-css-extract-plugin

3. 为webpack定制多入口

多入口的配置是多页面应用打包的关键,由于打包结果存在嵌套目录,所以需要对entry对象的键值进行一些定制,打包后的路径信息是直接通过key值来定制的,同时需要实例化多个HtmlWebpackPlugin来为每一个入口文件生成一个对应的index.html访问入口,定制参数可以在实例化时传入:

//webpack.prod.js
module.exports = {
    entry:{
        'C/index':'./src/pages/C/C.entry.js',
        'DESK/D/index':'./src/pages/D/D.entry.js',
        'DESK/E/index':'./src/pages/E/E.entry.js'
    }
    //...
    plugins:[
       new HtmlWebpackPlugin({...paramsC}),
       new HtmlWebpackPlugin({...paramsD}),
       new HtmlWebpackPlugin({...paramsE}),
    ]
}

当然你可以将entryplugins数组的组装过程剥离到其他文件中,然后直接引用:

当然,每个页面的入口文件X.entry.js相当于旧方案中main.js文件中移除被注释掉的未启用路由信息后剩余的部分,它足以支撑每个单页独立被访问。

四. 小结

经上述改造后,在dist目录中输出的结构和需求中public目录下的结构就保持一致了,而且每个页面的index.js文件也缩小到了100K左右。当然你也可以使用node.js去编写一些自动化脚本,将后续的替换过程也自动化,或者继续对webpack的打包过程进行优化,本文就不再赘述了。

原文地址:https://www.cnblogs.com/dashnowords/p/11415211.html

时间: 2024-10-10 16:29:34

Vue+ElementUI项目使用webpack输出MPA的相关文章

如何降低Vue.js项目中Webpack打包文件的大小?

https://blog.csdn.net/maray/article/details/50988500?utm_source=blogxgwz0 import Blur from 'vux/src/components/blur/index.vue' import Cell from 'vux/src/components/cell/index.vue' import Range from 'vux/src/components/range/index.vue' import Toast fr

vue+vue-router+axios+element-ui构建vue实战项目之七(渲染content.vue内容)

在上一节<vue+vue-router+axios+element-ui构建vue实战项目之六(渲染index.vue列表)>中,我们从后端接口获取数据,并成功渲染出一个列表. 这节内容,我们来做内容页面. 编写src/page/content.vue 文件 话不多说,直接上代码 1 <template> 2 <div> 3 <h3>{{getMsg.title}}</h3> 4 <p>作者:{{getMsg.author.login

webpack 打包和手动创建一个vue的项目

首先我们为啥要用webpack,为啥不用其他的打包的工具. 先听我捋捋, Webpack有人也称之为 模块打包机 ,由此也可以看出Webpack更侧重于模块打包,当然我们可以把开发中的所有资源(图片.js文件.css文件等)都可以看成模块,最初Webpack本身就是为前端JS代码打包而设计的,后来被扩展到其他资源的打包处理.Webpack是通过loader(加载器)和plugins(插件)对资源进行处理的. Gulp侧重于前端开发的 整个过程 的控制管理(像是流水线),我们可以通过给gulp配置

前端框架及项目面试-聚焦Vue、React、Webpack

第1章 课程导学介绍课程制作的背景和课程主要内容. 第2章 课程介绍先出几道面试真题,引导思考.带着问题来继续学习,效果更好. 第3章 Vue 使用Vue 是前端面试必考内容,首先要保证自己要会使用 Vue .本章讲解 Vue 基本使用.组件使用.高级特性和 Vuex Vue-router ,这些部分的知识点和面试题. 第4章 Vue 原理要保证自己的面试竞争力,必须掌握 Vue 原理,前端高级面试或者大厂面试中常考.本章讲解虚拟DOM,diff 算法,响应式,模板编译,组件渲染等 Vue 原理

vue.js项目构建之vue-router2.0的使用

vue-router2.0官方文档地址:http://router.vuejs.org/zh-cn/index.html 单页应用? 单页应用程序(SPA,single page web application). SPA其实就是整个网站只有一个页面,只改变页面的显示内容,不需要改变整个网页. vue.js 的单页面应用是基于路由和组件的.路由用于设定访问路径,并将路径和组件映射起来.页面内容切换这里就是组件的切换. vue-router是vue.js官方的路由插件,适合构建单页面应用. vue

VUE 前端项目优化方法

前端项目通过webpack打包会生成app.js和vendor.js,如果第三方组件依赖过多,会造成打包后的vendor.js过大,页面首次加载的时候会出现白屏时间过长,影响用户体验.对此,我们需要通过下面的方法对前端项目进行优化,减小打包后生成的js大小,从而提高加载速度.下面以USM项目为例,进行优化: 一.公用静态资源通过CDN加载 目前所有项目都通过npm包的形式引入vue.vue-router.axios.vuex.element-ui.ucar-view这些第三方包,webpack打

vue ssr 项目改造经历

vue ssr 项目改造经历 由于工作项目需求,需要将原有的项目改造,vue ssr 没有用到nuxt,因为vue ssr更利于seo,没办法,一个小白的改造经历, 首先说明一下,小白可以借鉴,高手也可以点评一下,因为,我写的不一定准确,只是针对我的项目. 下面先说一下大致: 原有项目有用到element,在改造ssr过程中,是很坑的.如果可以的话,还是强烈建议你重新改写成nuxt项目.由于我是小白,所以开始时候备份了一下项目,然后开始网上查找相关文章. 1.首先是这位大神的文章https://

vue.js项目构建基础

这里构建的vue.js项目依赖node服务器运行. 项目搭建完整步骤: 安装node.js ,转至nodeJs网站http://nodejs.cn/ 下载nodeJs进行安装. 安装完毕检查nodeJs安装是否成功? nodeJs安装完成,自带npm,可以检查npm是否已经安装 安装webpack. webpack是一个模块加载器兼打包工具,在vue项目中,为了更好的管理代码使用模块系统,使用webpack打包. 安装webpack  查看webpack是否安装成功? 安装 vue-cli 脚手

Vue 实际项目中你可能会遇见的坑

纸上得来终觉浅,绝知此事要躬行! Vue的文档和教程看的太多,小的demo做的多,也不如自己实际的进行一个完整项目的开发.只有做了才知道原来问题这么多,这里列举了一些你做demo教程可能不会遇见的坑. 一.项目的登录拦截及用户权限访问控制问题. 一个很常见的需求就是对未登录的用户进行路由拦截和用户的权限访问,如果你的项目之前是通过后台控制访问路由的,那么之前的后端现在可能需要在前端也需要控制了,由于我们用vue脚手架搭建的都是纯前端的路由访问,先看看我们的一般的项目路径: 你可能会注意到Vue的