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 相关文章推荐
Javascript和Ajax中文乱码吐血版解决方案
Dec 21 Javascript
基于JQuery的动态删除Table表格的行和列的代码
May 12 Javascript
优化innerHTML操作(提高代码执行效率)
Aug 20 Javascript
JS 模态对话框和非模态对话框操作技巧汇总
Apr 15 Javascript
jQuery判断iframe中元素是否存在的方法
May 11 Javascript
js实现的彩色方块飞舞奇幻效果
Jan 27 Javascript
Javascript typeof与instanceof的区别
Oct 18 Javascript
js制作可以延时消失的菜单
Jan 13 Javascript
浅谈jQuery中事情的动态绑定
Feb 12 Javascript
js图片放大镜实例讲解(必看篇)
Jul 17 Javascript
socket io与vue-cli的结合使用的示例代码
Nov 01 Javascript
vue router-link 默认a标签去除下划线的实现
Nov 06 Javascript
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
如何利用php+mysql保存和输出文件
2006/10/09 PHP
PHP PDO fetch 模式各种参数的输出结果一览
2015/01/07 PHP
详解PHP使用Redis存储session时的一个Warning定位
2017/07/05 PHP
thinkPHP和onethink微信支付插件分享
2019/08/11 PHP
初学prototype,发个JS接受URL参数的代码
2006/09/25 Javascript
Js+Flash实现访问剪切板操作
2012/11/20 Javascript
js获取指定日期周数以及星期几的小例子
2014/06/27 Javascript
jQuery中:input选择器用法实例
2015/01/03 Javascript
浅谈利用JavaScript进行的DDoS攻击原理与防御
2015/06/04 Javascript
Three.js学习之正交投影照相机
2016/08/01 Javascript
jquery层级选择器(匹配父元素下的子元素实现代码)
2016/09/05 Javascript
nodejs读取并去重excel文件
2018/04/22 NodeJs
解决循环中setTimeout执行顺序的问题
2018/06/20 Javascript
Element Table的row-class-name无效与动态高亮显示选中行背景色
2018/11/30 Javascript
小谈angular ng deploy的实现
2020/04/07 Javascript
js实现ajax的用户简单登入功能
2020/06/18 Javascript
vue将data恢复到初始状态 &amp;&amp; 重新渲染组件实例
2020/09/04 Javascript
11个Javascript小技巧帮你提升代码质量(小结)
2020/12/28 Javascript
Python引用类型和值类型的区别与使用解析
2017/10/17 Python
python3学习之Splash的安装与实例教程
2018/07/09 Python
TensorFlow Session会话控制&amp;Variable变量详解
2018/07/30 Python
python装饰器简介---这一篇也许就够了(推荐)
2019/04/01 Python
python多线程与多进程及其区别详解
2019/08/08 Python
Python操作Excel工作簿的示例代码(\*.xlsx)
2020/03/23 Python
150行python代码实现贪吃蛇游戏
2020/04/24 Python
python3让print输出不换行的方法
2020/08/24 Python
几款好用的python工具库(小结)
2020/10/20 Python
FC-Moto英国:欧洲最大的摩托车服装和头盔商店之一
2019/08/25 全球购物
小学爱国卫生月活动总结
2014/06/30 职场文书
大学毕业生推荐信
2014/07/09 职场文书
2014-2015学年工作总结
2014/11/27 职场文书
师德师风学习材料
2014/12/19 职场文书
2015入党个人自传范文
2015/06/26 职场文书
如何写一份成功的商业计划书
2019/06/25 职场文书
你为什么是穷人?可能是这5个缺点造成
2019/07/11 职场文书
Android Flutter实现图片滑动切换效果
2022/04/07 Java/Android