祝大家新年快乐, 万事如意, 新年发大财
临近春节, 公司很多同事都提前回家过年, 剩余人员根据禅道去修改 bug, 当 bug 修正完毕以后, 我们需要重新打包给运维, 上测试服给测试同事提测, 但是由于项目本体比较庞大, 所以打包时间太过漫长 (二十五分钟以上), 所以有了打包优化的想法 (其实想法早就有了, 但是因为平时工作计划比较充实, 所以一直没有去完成这个工作), 这次正好有时间, 所以去重新考虑了这个问题!
话不多说, 直接开始正文吧
先给大家看一下项目的目录结构:
就是正常的项目结构, 简单说一下吧:
build 文件夹包含的是一些打包配置的一下东西
config 文件夹是项目的基础配置
dist 是打包之后的文件
node_modules 是项目的依赖包
src 文件夹里面是项目的源码
static 文件夹里面放的是一些项目使用的静态资源
index.html 是项目的首页
package.json 文件是项目的配置 json
yarn.lock 是使用 yarn 锁定项目用的依赖
优化思路
项目打包时间长, 原因无外乎就是项目整体比较庞大依赖复杂组件之前拆分不够合理
对于这三个问题呢, 我们可以针对下面这几个方面去做一下处理:
对项目进行路由屏蔽, 只打包自己需要打包的部分 (我司就是好几个项目合并在了一起, 至于原因则是 需求类似, 所以放在一起比较省事 -_-||| 开发过程中是省了不少事, 但是现在一样要还的!!!!)
依赖关系复杂, 这里说的是项目中的依赖模块比较多, 像我们现在这个项目, 光算依赖包的话就有 40+, 另外一个重要原因就是组件之间存在相同引用的依赖解决思路是把项目中重用的依赖抽离出来进行单独打包
组件在写的过程中, 需要考虑好这个组件的使用方向, 以及实现功能, 不能混为一谈
实际操作
有了整体的思路, 那么开搞就可以啦 去 webpack 文档去看了一下有一个 DllPlugin, 这个插件就是帮助我们解决问题的关键, 下面是我 webpack.dll.config 的代码:
- var path = require("path");
- var webpack = require("webpack");
- function resolve (dir) {
- return path.join(__dirname, '..', dir)
- }
- module.exports = {
- // 你想要打包的模块的数组
- entry: {
- vendor: ['vue', 'lodash', 'vuex', 'axios', 'vue-router', 'iview', 'element-ui',
- 'echarts','xlsx','jquery','vue-fullcalendar','vue-cookie','handsontable']
- },
- output: {
- path: path.join(__dirname, '../dist/vendor-dll-js'), // 打包后文件输出的位置
- filename: '[name].dll.js',
- library: '[name]_library'
- // vendor.dll.js 中暴露出的全局变量名
- // 主要是给 DllPlugin 中的 name 使用,
- // 故这里需要和 webpack.DllPlugin 中的 `name: '[name]_library',` 保持一致
- },
- resolve: {
- extensions: ['.js', '.vue', '.json'],
- alias: {
- 'vue
我们需要将项目中具有重用性的包抽离出来, 放在 vendor 数组里面, 然后在下面 output 里面定义一下打包输出的文件路径, 然后在 resolve 里面配置解析参数, 最后定义使用的 DllPlugin 插件, UglifyJsPlugin 是压缩 js 的插件
Dllplugin 里的 path, 会输出一个 vendor-manifest.json, 这是用来做关联 id 的, 打包的时候不会打包进去, 所以不用放到 static 里 然后运行一下
webpack -p --progress --config build/webpack.dll.conf.js
成功以后, static 下会有 dll.vendor.js, 根目录下会有 vendor.manifest.json 各自打开看一下, 就会看到依赖库的源码和匹配 id
ok, 到这里, 抽离依赖库的事情就完成了, 那么接下来问题就是怎么引用呢, 怎么在 dev 和 build 跑呢?
这里补了一点 dll 和 commonsChunk 概念上的区别, commonsChunk 之所以慢和大, 是因为每次 run 的时候, 都会去做一次打包, 而实际上我们不会一直去更新我们引用的依赖库, 所以 dll 的做法就等于是, 事先先打包好依赖库, 然后只对每次都修改的 js 做打包
继续上面的步骤, 我们需要根据生成的 json 文件去修改 webpack.base.config 文件:
- const manifest = require('../vendor-manifest.json')
- ......
- plugins: [
- new webpack.DllReferencePlugin({
- manifest
- })
- ]
然后打开 index.html, 在底部加上
- <script src="./static/dll.vendor.js"></script>
- ;
执行一下 npm run build, 一起正常的话, 表示你的操作是正确的
升级处理
至此优化的问题基本已经解决了, 但是在处理过程中需要进行复制粘贴, 还要对 index.html 文件进行操作, 如果是对于项目不熟悉的人来进行开发项目的话, 就会出现一些小的问题, 所以我决定继续往下研究一下:
思路还是上面的思路, 我们下面需要进行的操作呢就是对与之前的处理进行优化, 通过配置文件, 和命令去实现我们想要的效果
首先我们将上面 webpack.dll.config 文件里面的 entry 配置项拿出来, 在 config 文件夹下新建一个 dll.js
- module.exports = {
- entry: {
- // 这里的依赖顺序必须是: 对象从上往下依赖, 数组从右到左依赖 (如果互不依赖的可以忽略顺序)
- ui: ['iview', 'element-ui'],
- tool: ['lodash', 'jquery', 'axios', 'vue-fullcalendar'],
- vue: ['vue', 'vuex', 'vue-router', 'vue-cookie'],
- xlsx: ['xlsx'],
- echarts: ['echarts'],
- other: ['handsontable'],
- },
- outFile: '../static/dll'
- };
这里面其实就是我们一开始写的 entry 的配置项, 根据这个 js 去打包的文件有一个顺序, 就是我总结的这个:
这里的依赖顺序必须是: 对象从上往下依赖, 数组从右到左依赖 (如果互不依赖的可以忽略顺序)
如果不按照这个顺序去写的话, 会出现依赖错误的问题!!!
然后在 output 里面再进行一下配置:
- output: {
- path: path.join(__dirname, dllConfig.outFile), // 打包后文件输出的位置
- filename: '[name].dll.[chunkhash].js',
- library: '[name]_library'
- // 主要是给 DllPlugin 中的 name 使用,
- // 故这里需要和 webpack.DllPlugin 中的 `name: '[name]_library',` 保持一致
- },
这样在执行
webpack -p --progress --config build/webpack.dll.conf.js
指令的时候会生成如下:
是不是看到文件后面的 hash 就一脸懵逼, 这怎么办, 我们没有办法去进行复制粘贴了!!(我们的目的不就是不进行复制粘贴吗 正经脸 -_-)
要实现命令操作之后不进行复制粘贴操作就需要使用 webpack 的 HtmlWebpackPlugin 插件
在 plugins 里面配置一下 HtmlWebpackPlugin
- new HtmlWebpackPlugin({
- filename: path.join(__dirname, '../', config.dev.index),
- template: 'index.ejs',
- inject: false
- }),
然后在根目录添加一个 index.ejs 模版 (ejsGitHub 地址), index.ejs 中代码如下:
- <body>
- <div id="app"></div>
- <!-- dll files will be auto injected -->
- <% for (var chunk in htmlWebpackPlugin.files.chunks) { %><script type="text/javascript" src="/<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
- <% } %>
- <!-- built files will be auto injected -->
- </body>
最后需要在 config 文件夹下的 index.js 进行一下修改: 在 dev 中添加:
index: 'index.html',
项目在执行 dev 指令或者 build 指令之前需要先执行:
webpack -p --progress --config build/webpack.dll.conf.js
在 dll 指令结束后 执行其他操作就可以完美的玩耍了
总结
至此代码打包优化的整个过程就基本结束了, 测试一下, 15 分钟左右就可以完成打包, 比之前打包快了将近 10 分钟, 可以说是非常成功的一次尝试!!
最后祝各位勤劳睿智闷骚正念, 外表冷漠内心狂热, 颜值负分, 人设冰点的程序猿们, 节日快乐!
: 'vue/dist/vue.esm.js',我们需要将项目中具有重用性的包抽离出来, 放在 vendor 数组里面, 然后在下面 output 里面定义一下打包输出的文件路径, 然后在 resolve 里面配置解析参数, 最后定义使用的 DllPlugin 插件, UglifyJsPlugin 是压缩 js 的插件
Dllplugin 里的 path, 会输出一个 vendor-manifest.json, 这是用来做关联 id 的, 打包的时候不会打包进去, 所以不用放到 static 里 然后运行一下
webpack -p --progress --config build/webpack.dll.conf.js
成功以后, static 下会有 dll.vendor.js, 根目录下会有 vendor.manifest.json 各自打开看一下, 就会看到依赖库的源码和匹配 id
ok, 到这里, 抽离依赖库的事情就完成了, 那么接下来问题就是怎么引用呢, 怎么在 dev 和 build 跑呢?
这里补了一点 dll 和 commonsChunk 概念上的区别, commonsChunk 之所以慢和大, 是因为每次 run 的时候, 都会去做一次打包, 而实际上我们不会一直去更新我们引用的依赖库, 所以 dll 的做法就等于是, 事先先打包好依赖库, 然后只对每次都修改的 js 做打包
继续上面的步骤, 我们需要根据生成的 json 文件去修改 webpack.base.config 文件:
- const manifest = require('../vendor-manifest.json')
- ......
- plugins: [
- new webpack.DllReferencePlugin({
- manifest
- })
- ]
然后打开 index.html, 在底部加上
- <script src="./static/dll.vendor.js"></script>
- ;
执行一下 npm run build, 一起正常的话, 表示你的操作是正确的
升级处理
至此优化的问题基本已经解决了, 但是在处理过程中需要进行复制粘贴, 还要对 index.html 文件进行操作, 如果是对于项目不熟悉的人来进行开发项目的话, 就会出现一些小的问题, 所以我决定继续往下研究一下:
思路还是上面的思路, 我们下面需要进行的操作呢就是对与之前的处理进行优化, 通过配置文件, 和命令去实现我们想要的效果
首先我们将上面 webpack.dll.config 文件里面的 entry 配置项拿出来, 在 config 文件夹下新建一个 dll.js
- module.exports = {
- entry: {
- // 这里的依赖顺序必须是: 对象从上往下依赖, 数组从右到左依赖 (如果互不依赖的可以忽略顺序)
- ui: ['iview', 'element-ui'],
- tool: ['lodash', 'jquery', 'axios', 'vue-fullcalendar'],
- vue: ['vue', 'vuex', 'vue-router', 'vue-cookie'],
- xlsx: ['xlsx'],
- echarts: ['echarts'],
- other: ['handsontable'],
- },
- outFile: '../static/dll'
- };
这里面其实就是我们一开始写的 entry 的配置项, 根据这个 js 去打包的文件有一个顺序, 就是我总结的这个:
这里的依赖顺序必须是: 对象从上往下依赖, 数组从右到左依赖 (如果互不依赖的可以忽略顺序)
如果不按照这个顺序去写的话, 会出现依赖错误的问题!!!
然后在 output 里面再进行一下配置:
- output: {
- path: path.join(__dirname, dllConfig.outFile), // 打包后文件输出的位置
- filename: '[name].dll.[chunkhash].js',
- library: '[name]_library'
- // 主要是给 DllPlugin 中的 name 使用,
- // 故这里需要和 webpack.DllPlugin 中的 `name: '[name]_library',` 保持一致
- },
这样在执行
webpack -p --progress --config build/webpack.dll.conf.js
指令的时候会生成如下:
是不是看到文件后面的 hash 就一脸懵逼, 这怎么办, 我们没有办法去进行复制粘贴了!!(我们的目的不就是不进行复制粘贴吗 正经脸 -_-)
要实现命令操作之后不进行复制粘贴操作就需要使用 webpack 的 HtmlWebpackPlugin 插件
在 plugins 里面配置一下 HtmlWebpackPlugin
- new HtmlWebpackPlugin({
- filename: path.join(__dirname, '../', config.dev.index),
- template: 'index.ejs',
- inject: false
- }),
然后在根目录添加一个 index.ejs 模版 (ejsGitHub 地址), index.ejs 中代码如下:
- <body>
- <div id="app"></div>
- <!-- dll files will be auto injected -->
- <% for (var chunk in htmlWebpackPlugin.files.chunks) { %><script type="text/javascript" src="/<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
- <% } %>
- <!-- built files will be auto injected -->
- </body>
最后需要在 config 文件夹下的 index.js 进行一下修改: 在 dev 中添加:
index: 'index.html',
项目在执行 dev 指令或者 build 指令之前需要先执行:
webpack -p --progress --config build/webpack.dll.conf.js
在 dll 指令结束后 执行其他操作就可以完美的玩耍了
总结
至此代码打包优化的整个过程就基本结束了, 测试一下, 15 分钟左右就可以完成打包, 比之前打包快了将近 10 分钟, 可以说是非常成功的一次尝试!!
最后祝各位勤劳睿智闷骚正念, 外表冷漠内心狂热, 颜值负分, 人设冰点的程序猿们, 节日快乐!
来源: https://juejin.im/post/5a8797c15188257a836c385d