vue实现的多页面项目如何优化打包的步骤详解


Posted in Javascript onJuly 19, 2020

遇到的问题

在多页面框架打包的过程中会,随着业务的增加页面越来越多,使用的三方包也会越来越多,但并不是所有页面都会使用到三方插件,使用webpack打包会让所有的三方包打包到一起,会导致vendor.js(三方包打包后的文件)越来越大,即使没使用过三方插件的页面也会引入,页面加载会越来越慢.

如何优化

  •  使用cdn引入,这种就每次新建一个页面的时候手动通过cdn的方式引入,但是并不是特别好的方式,还需要手动加入.
  • 就是使用splitChunks分割三方包,将三方包单独打包出来,根据页面的依赖情况自动注入,但是这种情况分离的三方包并不会自动注入到对应的页面中去,所以就写了个自动注入的插件,原理就是在html页面生成之后,根据页面所依赖的chunks找到对应的静态资源,然后将得到的静态资源注入到页面中去。

 自定义webpack插件

webpack 就像一条生产线,要经过一系列处理流程后才能将源文件转换成输出结果。 这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。webpack 通过 Tapable 来组织这条复杂的生产线。 webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作。

webpack本身引入的有tapable插件来管理构建流程,在编译的时候会触发tapalbe的钩子事件,我们编写一个webpack插件就是找到对应的钩子,然后写入自己的业务,就是在钩子上注册自己的事件,和发布订阅模式是一样的,当webpack构建时插件注册的事件就会在钩子触发的时候执行。

每个 Webpack 插件都需要向外暴露一个 apply(compiler) 方法,在compiler上找到对应的钩子写入自己的业务处理。

目前这个插件处理的就是在生成了html页面之后把页面对应的js和css插入到html代码中,因此这个插件是依赖于 html-webpack-plugin 的,他会向 complation 中再注入一个钩子 htmlWebpackPluginAfterHtmlProcessing 当该钩子触发时,已经生成了一个html页面

compiler.hooks.compilation.tap(
  this.constructor.name,
  compilation => {
   let hook = compilation.hooks.htmlWebpackPluginAfterHtmlProcessing;

   hook.tapAsync(
     this.constructor.name,
     (htmlPluginData, callback) => {
      try {
       // 当htmlWebpackPluginAfterHtmlProcessing钩子触发后会调用addLinks方法,传入compilation和当前当html页面信息
       callback(null, this.addLinks(compilation, htmlPluginData));
      } catch (error) {
       callback(error);
      }
     }
   );
  }
);
// 将页面所依赖的js和css注入到页面中
addLinks(compilation, htmlPluginData){
 // 获取当前页面所依赖的chunk
 const extractedChunks = extractChunks({
  compilation,
  optionsInclude: Object.keys(htmlPluginData.assets.chunks),
 });

 ...
 // 获取所有chunks的files
 const allFiles = extractedChunks.reduce((accumulated, chunk) => {
  return accumulated.concat(chunk.files);
 }, []);

 // 这一步是将根据allFiles处理后的链接注入到html页面
 htmlPluginData.html = insertLinksIntoHtml({
  links,
  html: htmlPluginData.html,
 });

 return htmlPluginData;
}

具体例子如下:

// vue.config.js
const { resolve } = require('path')
const getEntries = require('./build/getEntries')
const WebpackBundleAnalyzer = require('webpack-bundle-analyzer')
const AutoInjectPlugin = require('auto-inject-plugin')
const pages = getEntries(resolve(__dirname, 'src/features/*/index.js'))
module.exports = {
 pages,
 productionSourceMap: false,
 assetsDir: 'static',
 publicPath: '/',
 chainWebpack: config => {
  config.resolve.alias.set('vue$', 'vue/dist/vue.esm.js')
  if(process.env.NODE_ENV === 'production'){
   // 分离第三方包
   config.optimization.splitChunks({
    chunks: 'all',
    cacheGroups: {
     libs: {
      name: 'chunk-libs',
      test: /[\\/]node_modules[\\/]/,
      priority: 10,
      chunks: 'initial'
     },
     elementUI: {
      name: 'chunk-elementUI',
      priority: 20,
      test: /[\\/]node_modules[\\/]_?element-ui(.*)/,
     },
     swiper: {
      name: 'chunk-swiper',
      priority: 20,
      test: /[\\/]node_modules[\\/]_?swiper(.*)/,
     }
    }
   })
   // 将依赖自动注入到对应页面中
   config.plugin('AutoInjectPlugin').use(AutoInjectPlugin)
   config.optimization.runtimeChunk({name: 'manifest'})
  }

  if(process.env.npm_config_report){
   config.plugin('analyzer').use(WebpackBundleAnalyzer.BundleAnalyzerPlugin)
  }
  config
   .plugin('copy')
   .tap(args => {
    const { toType } = args[0][0]
    args[0] = []
    args[0].push({
     from: resolve(__dirname, 'public'),
     to: resolve(__dirname, 'dist/static/js'),
     toType
    })
    return args
   })
 }
}

抽离第三方包后的前后对比:

抽离前

vue实现的多页面项目如何优化打包的步骤详解

抽离后

vue实现的多页面项目如何优化打包的步骤详解

使用自动注入插件前后生成的html页面:

使用前:

<!DOCTYPE html>
<html lang=en>

<head>
 <meta charset=UTF-8>
 <meta name=viewport content="width=device-width,initial-scale=1">
 <title>Document</title>
 <link href=/bk_static/css/chunk-elementUI.ad4ace96.css rel=preload as=style>
 <link href=/bk_static/css/home.340fe3f2.css rel=preload as=style>
 <link href=/bk_static/js/chunk-elementUI.1ea80d29.js rel=preload as=script>
 <link href=/bk_static/js/chunk-libs.89fd9e1d.js rel=preload as=script>
 <link href=/bk_static/js/home.12708c2b.js rel=preload as=script>
 <link href=/bk_static/js/manifest.1dcac3f8.js rel=preload as=script>
 <link href=/bk_static/css/home.340fe3f2.css rel=stylesheet>
</head>

<body>
 <div id=root></div>
 <script src=/bk_static/js/home.12708c2b.js></script>
</body>

</html>

所依赖的代码并未自动引入进来

使用后:

<!DOCTYPE html>
<html lang=en>

<head>
 <meta charset=UTF-8>
 <meta name=viewport content="width=device-width,initial-scale=1">
 <title>Document</title>
 <link href=/bk_static/css/chunk-elementUI.ad4ace96.css rel=preload as=style>
 <link href=/bk_static/css/home.340fe3f2.css rel=preload as=style>
 <link href=/bk_static/js/chunk-elementUI.1ea80d29.js rel=preload as=script>
 <link href=/bk_static/js/chunk-libs.89fd9e1d.js rel=preload as=script>
 <link href=/bk_static/js/home.aa83744c.js rel=preload as=script>
 <link href=/bk_static/js/manifest.1dcac3f8.js rel=preload as=script>
 <link href=/bk_static/css/home.340fe3f2.css rel=stylesheet>
 <link href="/bk_static/css/chunk-elementUI.ad4ace96.css" rel="external nofollow" rel=stylesheet>
</head>

<body>
 <div id=root></div>
 <script src=/bk_static/js/home.aa83744c.js></script>
 <script src=/bk_static/js/chunk-elementUI.1ea80d29.js></script>
 <script src=/bk_static/js/chunk-libs.89fd9e1d.js></script>
 <script src=/bk_static/js/manifest.1dcac3f8.js></script>
</body>

</html>

所依赖的代码已经自动注入html页面中.

插件地址: auto-inject-plugin

Demo地址: vue-multipage

到此这篇关于vue实现的多页面项目如何优化打包的步骤详解的文章就介绍到这了,更多相关vue多页面优化打包内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
避免回车键导致的页面无意义刷新的解决方法
Apr 12 Javascript
获取下拉列表框的值是数组,split,$.inArray示例
Nov 13 Javascript
jQuery Form 页面表单提交的小例子
Nov 15 Javascript
js实现动态改变字体大小代码
Jan 02 Javascript
JavaScript类型系统之正则表达式
Jan 05 Javascript
confirm确认对话框的实现方法总结
Jun 17 Javascript
js中 计算两个日期间的工作日的简单实例
Aug 08 Javascript
Bootstrap3 Grid system原理及应用详解
Sep 30 Javascript
Angular5中状态管理的实现
Sep 03 Javascript
JS中注入eval, Function等系统函数截获动态代码
Apr 03 Javascript
javascript将16进制的字符串转换为10进制整数hex
Mar 05 Javascript
使用Vue3+Vant组件实现App搜索历史记录功能(示例代码)
Jun 09 Vue.js
vue tab切换,解决echartst图表宽度只有100px的问题
Jul 19 #Javascript
vue中echarts图表大小适应窗口大小且不需要刷新案例
Jul 19 #Javascript
完美解决vue 中多个echarts图表自适应的问题
Jul 19 #Javascript
vue实现多个echarts根据屏幕大小变化而变化实例
Jul 19 #Javascript
解决vue一个页面中复用同一个echarts组件的问题
Jul 19 #Javascript
浅谈vue单页面中有多个echarts图表时的公用代码写法
Jul 19 #Javascript
echarts.js 动态生成多个图表 使用vue封装组件操作
Jul 19 #Javascript
You might like
教你如何把一篇文章按要求分段
2006/10/09 PHP
php 判断访客是否为搜索引擎蜘蛛的函数代码
2011/07/29 PHP
PHP实现从上往下打印二叉树的方法
2018/01/18 PHP
JavaScript 模拟用户单击事件
2009/12/31 Javascript
使用js获取QueryString的方法小结
2010/02/28 Javascript
基于JQuery的浮动DIV显示提示信息并自动隐藏
2011/02/11 Javascript
探讨JavaScript标签位置的存放与功能有无关系
2016/01/15 Javascript
第一次接触神奇的Bootstrap网格系统
2016/07/27 Javascript
React简单介绍
2017/05/24 Javascript
基于JavaScript实现选项卡效果
2017/07/21 Javascript
vue上传图片组件编写代码
2017/07/26 Javascript
JS原生数据双向绑定实现代码
2017/08/14 Javascript
实例教学如何写vue插件
2017/11/30 Javascript
分享5个小技巧让你写出更好的 JavaScript 条件语句
2018/10/20 Javascript
小程序从手动埋点到自动埋点的实现方法
2019/01/24 Javascript
微信小程序实现星级评价
2019/11/20 Javascript
JS 设计模式之:工厂模式定义与实现方法浅析
2020/05/06 Javascript
[03:01]2014DOTA2国际邀请赛 小组赛7月13日TOPPLAY
2014/07/14 DOTA
python将html转成PDF的实现代码(包含中文)
2013/03/04 Python
使用Python导出Excel图表以及导出为图片的方法
2015/11/07 Python
Python计算不规则图形面积算法实现解析
2019/11/22 Python
Python如何使用OS模块调用cmd
2020/02/27 Python
PyQT5 实现快捷键复制表格数据的方法示例
2020/06/19 Python
HTML5本地存储之Database Storage应用介绍
2013/01/06 HTML / CSS
澳大利亚网上玩具商店:Mr Toys Toyworld
2018/03/25 全球购物
英国50岁以上人群的交友网站:Ourtime
2018/03/28 全球购物
酒店总经理欢迎词
2014/01/15 职场文书
会计助理岗位职责
2014/02/17 职场文书
组织鉴定材料
2014/06/02 职场文书
2014年政协委员工作总结
2014/12/01 职场文书
2015年预防青少年违法犯罪工作总结
2015/05/22 职场文书
同事去世追悼词
2015/06/23 职场文书
谢师宴学生答谢词
2015/09/30 职场文书
四年级数学教学反思
2016/02/16 职场文书
2019最新版火锅店的创业计划书 !
2019/07/12 职场文书
pytorch 实现多个Dataloader同时训练
2021/05/29 Python