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 进阶篇1 正则表达式,cookie管理,userData
Mar 14 Javascript
javascript弹出页面回传值的方法
Jan 28 Javascript
Javascript实现商品秒杀倒计时(时间与服务器时间同步)
Sep 16 Javascript
用vue和node写的简易购物车实现
Apr 25 Javascript
微信小程序之网络请求简单封装实例详解
Jun 28 Javascript
详解JSON Web Token 入门教程
Jul 30 Javascript
vue forEach循环数组拿到自己想要的数据方法
Sep 21 Javascript
深入理解Node内建模块和对象
Mar 12 Javascript
利用weixin-java-miniapp生成小程序码并直接返回图片文件流的方法
Mar 29 Javascript
通过扫小程序码实现网站登陆功能
Aug 22 Javascript
聊聊Vue中provide/inject的应用详解
Nov 10 Javascript
vue实现数据控制视图的原理解析
Jan 07 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
Discuz!5的PHP代码高亮显示插件(黑暗中的舞者更新)
2007/01/29 PHP
PHP根据IP判断地区名信息的示例代码
2014/03/03 PHP
实现php删除链表中重复的结点
2018/09/27 PHP
Jqyery中同等与js中windows.onload的应用
2011/05/10 Javascript
Node.js中使用事件发射器模式实现事件绑定详解
2014/08/15 Javascript
jQuery中innerWidth()方法用法实例
2015/01/19 Javascript
常用DOM整理
2015/06/16 Javascript
jquery+ajax+text文本框实现智能提示完整实例
2016/07/09 Javascript
用JS编写一个函数,返回数组中重复出现过的元素(实例)
2017/09/14 Javascript
react-native中ListView组件点击跳转的方法示例
2017/09/30 Javascript
实现div滚动条默认最底部以及默认最右边的示例代码
2017/11/15 Javascript
详解node.js 下载图片的 2 种方式
2018/03/02 Javascript
vue如何在自定义组件中使用v-model
2018/05/14 Javascript
关于node-bindings无法在Electron中使用的解决办法
2018/12/18 Javascript
JS实现数组去重,显示重复元素及个数的方法示例
2019/01/21 Javascript
微信JS-SDK updateAppMessageShareData安卓不能自定义分享详解
2019/03/29 Javascript
[03:19]2016国际邀请赛中国区预选赛第四日TOP10镜头集锦
2016/07/01 DOTA
python根据路径导入模块的方法
2014/09/30 Python
对于Python的框架中一些会话程序的管理
2015/04/20 Python
python遍历序列enumerate函数浅析
2017/10/17 Python
pandas通过loc生成新的列方法
2018/11/28 Python
Python 异常的捕获、异常的传递与主动抛出异常操作示例
2019/09/23 Python
详解python路径拼接os.path.join()函数的用法
2019/10/09 Python
Django实现基于类的分页功能
2019/10/31 Python
基于python3实现倒叙字符串
2020/02/18 Python
python+selenium 脚本实现每天自动登记的思路详解
2020/03/11 Python
Python 合并拼接字符串的方法
2020/07/28 Python
Kipling凯浦林美国官网:世界著名时尚休闲包袋品牌
2016/08/24 全球购物
Doyoueven官网:澳大利亚健身服饰和配饰品牌
2019/03/24 全球购物
公共汽车、火车和飞机票的通用在线预订和销售平台:INFOBUS
2019/11/30 全球购物
新闻专业应届生求职信
2013/10/31 职场文书
工作决心书范文
2014/03/11 职场文书
开展创先争优活动总结
2014/08/28 职场文书
2016感恩母亲节校园广播稿
2015/12/17 职场文书
合理缓解职场压力,让你随时保持最佳状态!
2019/06/21 职场文书
Java 语言中Object 类和System 类详解
2021/07/07 Java/Android