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 相关文章推荐
location.href用法总结(最主要的)
Dec 27 Javascript
jquery让返回的内容显示在特定div里(代码少而精悍)
Jun 23 Javascript
js实现浏览器窗口大小被改变时触发事件的方法
Feb 02 Javascript
使用jQuery实现图片遮罩半透明坠落遮挡
Mar 16 Javascript
vuejs动态组件给子组件传递数据的方法详解
Sep 09 Javascript
JavaScript中双向数据绑定详解
May 03 Javascript
微信小程序 监听手势滑动切换页面实例详解
Jun 15 Javascript
客户端(vue框架)与服务器(koa框架)通信及服务器跨域配置详解
Aug 26 Javascript
Vue.js实现图片的随意拖动方法
Mar 08 Javascript
JavaScript实现随机点名器实例详解
May 07 Javascript
再也不怕 JavaScript 报错了,怎么看怎么处理都在这儿
Dec 09 Javascript
vue前端工程的搭建
Mar 31 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
如何选购合适的收音机
2021/03/01 无线电
可以保证单词完整性的PHP英文字符串截取代码分享
2014/07/15 PHP
php实现QQ小程序发送模板消息功能
2019/09/18 PHP
自动更新作用
2006/10/08 Javascript
html读出文本文件内容
2007/01/22 Javascript
图片自动缩小的js代码,用以防止图片撑破页面
2007/03/12 Javascript
javascript 获取所有id中包含某关键字的控件的实现代码
2010/11/25 Javascript
jQuery学习笔记 更改jQuery对象
2012/09/19 Javascript
angularJS结合canvas画图例子
2015/02/09 Javascript
jquery京东商城双11焦点图多图广告特效代码分享
2015/09/06 Javascript
JS实现仿雅虎首页快捷登录入口及导航模块效果
2015/09/19 Javascript
JS实现新浪博客左侧的Blog管理菜单效果代码
2015/10/22 Javascript
JS使用cookie实现DIV提示框只显示一次的方法
2015/11/05 Javascript
js获取腾讯视频ID的方法
2016/10/03 Javascript
详解微信小程序开发之下拉刷新 上拉加载
2016/11/24 Javascript
jQuery图片轮播功能实例代码
2017/01/29 Javascript
详谈构造函数加括号与不加括号的区别
2017/10/26 Javascript
使用JavaScript中的lodash编写双色球效果
2018/06/24 Javascript
一次Webpack配置文件的分离实战记录
2018/11/30 Javascript
微信小程序MUI导航栏透明渐变功能示例(通过改变rgba的a值实现)
2019/01/24 Javascript
webpack proxy 使用(代理的使用)
2020/01/10 Javascript
Vue与React的区别和优势对比
2020/12/18 Vue.js
详解vue之自行实现派发与广播(dispatch与broadcast)
2021/01/19 Vue.js
[05:59]带你看看DPC的台前幕后
2021/03/11 DOTA
python列表推导式入门学习解析
2019/12/02 Python
HTML5标签与HTML4标签的区别示例介绍
2013/07/18 HTML / CSS
泰国办公用品购物网站:OfficeMate
2018/02/04 全球购物
英国门把手公司:Door Handle Company
2019/05/12 全球购物
大学生找工作推荐信范文
2013/11/28 职场文书
80后职场人的职业生涯规划
2014/03/08 职场文书
小学语文业务学习材料
2014/06/02 职场文书
园林专业毕业生自荐信
2014/07/04 职场文书
2014年卫生院工作总结
2014/12/03 职场文书
2015新学期家长寄语
2015/02/26 职场文书
干货!开幕词的写作方法
2019/04/02 职场文书
Go并发4种方法简明讲解
2022/04/06 Golang