本文主要介绍两个插件的使用,DllPlugin 和 DllReferencePlugin,后者配合前者使用。css
项目 Github 地址:https://github.com/luxiancan/vue-permission-managehtml
打包会输出一个类 dll 包(dll 包源于 windows 的动态连接库),这些代码自己不会执行,主要是提供给咱们的业务代码引用。(好比 dll 中有一个工具方法为获取本月日期数组,这个方法自己并不会执行,可是当咱们的业务中须要获取本月日期时,就会引用这个方法在咱们的业务中执行相关逻辑)。vue
DllPlugin 能够将特定的类库提早打包而后引入。这种方式能够极大的减小打包类库的次数,只有当类库更新版本才有须要从新打包,而且也实现了将公共代码抽离成单独文件的优化方案。node
简单来讲就是:
将静态资源文件(运行依赖包)与业务代码源文件分开打包,先使用 DllPlugin 给静态资源打包,再使用 DllReferencePlugin 让源文件引用资源文件。webpack
当咱们一个项目引入了多个较大的包之后,这些包自己并不会运行,咱们也不会修改这些包的代码,可是每当咱们修改了业务代码以后,这些包也会被从新打包。极大的浪费了时间,这时咱们就须要使用这个工具预先把静态资源提早打包,之后修改源文件再打包时就不会打包这些静态资源文件了。ios
咱们以 vue-cli 生成的项目为例:git
## 全局安装 vue-cli 脚手架 和 webpack cnpm install -g vue-cli webpack-dev-server ## 初始化项目 winpty vue.cmd init webpack vue-permission-manage cd vue-permission-manage ## 安装基础配置包 cnpm install ## 安装依赖模块(静态资源) cnpm install vuex axios element-ui echarts -S
安装完成后的目录结构 (此处已经隐藏 node_modules 文件夹):github
咱们编辑 main.js,引入咱们所安装的静态资源,结果为:web
import 'babel-polyfill'; // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue'; import App from './App'; import router from './router'; import store from './store/store.js'; import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import '@/assets/css/normalize.css'; import '@/assets/css/common.scss'; import httpRequest from '@/assets/js/service/http.js'; import '@/assets/js/service/mock.js'; Vue.config.productionTip = false; Vue.use(ElementUI); Vue.prototype.$http = httpRequest; /* eslint-disable no-new */ new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' });
回到命令窗口,执行打包命令:vue-router
## 编译打包 npm run build
截图中能够看见 Time:65164ms,打包花费了65秒,vue 全家桶以及刚才引入的各类包和源代码所有被打包了。(打包时间也跟电脑配置有关,你们的都不同,可能个人笔记本比较low因此有点慢吧,影响不大,往下走)
咱们才引入了5-6个包而已,就已经花费了65秒,若是之后还要加上各类包及静态资源,打包时间确定会更久。
这就是咱们为何要引入 DllPlugin 的缘由!
咱们知道,咱们刚才所引入的 vue 或者 axios 之类的,咱们只是使用它们,并不会改变它们的源码,它们自己也不会运行,那么咱们就能够把这些模块拆分出来提早打包。
那么如何提早打包它们呢? 咱们在根目录的 build 文件夹下建立一个 webpack 配置文件(webpack.dll.conf.js),既然这个文件是 webpack 配置文件,那么它的格式确定也和 webpack 的其余配置文件同样:
var path = require('path'); var webpack = require('webpack'); /* 将特定的类库提早打包而后引入,不但可以极大减小打包时间, 也实现了将公共代码抽离成单独文件的优化方案,能够很大程度的减少打包以后的文件体积。 */ module.exports = { // 你想要提早打包的类库的数组。注意 vue 要写成别名 entry: { // 若是这些类库有版本更新了(通常不多更新),就须要从新执行 npm run dll 打包类库,再执行 npm run build 打包项目上线 // 这里用 vendor 做为 key 值表示后文用到的 [name] ,后续生成的打包文件就为 vendor-manifest.json vendor.dll.js vendor: ['vue/dist/vue.esm.js', 'vuex', 'axios', 'vue-router', 'element-ui', 'echarts'] }, output: { path: path.join(__dirname, '../static/js'), // 打包后文件输出的位置,放到项目根目录的 static/js 下 filename: '[name].dll.js', // 打包后的文件名 vendor.dll.js library: '[name]_library' // vendor.dll.js 中暴露出的全局变量名,主要是给 DllPlugin 中的 name 使用。 // 因此这里须要和 webpack.DllPlugin 中的 name: '[name]_library', 保持一致。 }, plugins: [ new webpack.DllPlugin({ // manifest.json 生成的文件夹及名字,这里路径写成 .. 表明上一级目录,也就是让它生成在了根目录下 path: path.join(__dirname, '../[name]-manifest.json'), // 和 output.library 保持一致便可 name: '[name]_library', // manifest 文件中请求的上下文,默认为本文件的上下文 context: __dirname }), // 压缩打包的文件,使用 UglifyJsPlugin 插件压缩代码 new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) ] };
重点:这里引入的 Dllplugin 插件,该插件将生成一个 manifest.json 文件,该文件供 webpack.dll.conf.js 中加入的 DllReferencePlugin 使用,使咱们所编写的源文件能正确地访问到咱们所须要的静态资源(运行时依赖包)。相关字段的解释已经在代码注释中写明。
编写该 webpack 配置以后,咱们就能够预打包资源文件了。
## 以指定的 webpack 配置文件执行打包 webpack --config build/webpack.dll.conf.js
emmm。。。感受这命令有点难记哎,那咱们就将它加入 package.json 里吧
"scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "lint": "eslint --ext .js,.vue src test/unit", "dll": "webpack --config build/webpack.dll.conf.js", "build": "node build/build.js" },
预打包资源文件:
npm run dll
能够看到 dll 相关的资源文件已经打包成功,此时的目录结构:
可见咱们的目录结构中 static 下生成了 js 子目录,打包好的 dll 文件(js/vendor.dll.js)就放在该目录下,除此以外根目录中还生成了 vendor-manifest.json。
如今咱们已经再也不须要将那些静态资源包跟源文件一块儿打包了,可是这也须要在源文件的 webpack.base.conf.js 中配置 DllReferencePlugin 使用 vendor-manifest.json 来引用这个 dll。
这一步咱们只须要改写 vue-cli 为咱们生成好的 build/webpack.base.conf.js
便可:
该文件主要是添加了 plugins 配置:
plugins: [ new webpack.DllReferencePlugin({ context: __dirname, // 与 Dllplugin 里的 context 所指向的上下文保持一致,这里都是指向了当前文件的 build 目录 manifest: require('../vendor-manifest.json') // 引入 Dllplugin 所生成的的 manifest }) ],
到这里配置完这个就。。哦还没完别急,咱们须要手动在根目录的 index.html 里引入生成的 dll 库
<body> <div id="app"></div> <!-- built files will be auto injected --> <script src="./static/js/vendor.dll.js"></script> <!--引入 vendor.dll.js --> </body>
好的,激动人心的时刻终于来了!!!咱们如今只须要 npm run build
看时间Time:20746ms!!!,比起以前的65秒咱们缩短到了20秒左右!时间就是$$,时间就是生命啊!!
日后若是咱们只是改动了业务代码,就不须要从新打包那些个各类庞大的类库了。不过还要注意一点,若是相关类库版本更新了,再次执行 npm install 的时候类库源码有更新,此时就须要从新执行一下 npm run dll 再执行 npm run build。为此,咱们在 package.json 再加一个命令 dll_build:
"scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "lint": "eslint --ext .js,.vue src test/unit", "dll": "webpack --config build/webpack.dll.conf.js", "build": "node build/build.js", "dll_build": "npm run dll && npm run build" },
第一次打包时,或者类库版本更新了,执行 npm run dll_build
就行了~
到这里优化就结束啦,文章有不妥的地方欢迎指出留言哦,以为不错的话点个赞点个星吧 hhh,github 源码地址在文章开头哦~
参考资料:
webpack 中文文档 | webpack 中文网
webpack进阶——DllPlugin优化打包性能(基于vue-cli)