详解webpack性能优化——DLL


Posted in Javascript onOctober 20, 2017

Webpack性能优化的方式有很多种,本文之所以将 dll 单独讲解,是因为 dll 是一种最简单粗暴并且极其有效的优化方式。

在通常的打包过程中,你所引用的诸如:jquery、bootstrap、react、react-router、redux、antd、vue、vue-router、vuex 等等众多库也会被打包进 bundle 文件中。由于这些库的内容基本不会发生改变,每次打包加入它们无疑是一种巨大的性能浪费。

Dll 的技术就是在第一次时将所有引入的库打包成一个 dll.js 的文件,将自己编写的内容打包为 bundle.js 文件,这样之后的打包只用处理 bundle 部分。

以一个 Vue 项目为例,首先创建一个名为 webpack.dll.config.js 的文件

var path = require("path"),
fs = require('fs'),

webpack = require("webpack");

var vendors = [

'vue', 

'vue-router', 

'vuex'
];

module.exports = {

entry: {


vendor: vendors

},

output: {


path: path.join(__dirname, "dist"),


filename: "Dll.js",


library: "[name]_[hash]"

},

plugins: [


new webpack.DllPlugin({



path: path.join(__dirname, "dist", "manifest.json"),



name: "[name]_[hash]",



context: __dirname


})

]
};

这个文件的作用是将 vue、vue-router 以及 vuex 合并打包为一个名为 Dll.js 的静态资源包,同时生成一个 manifest.json 文件方便对 Dll.js 中的模块进行引用。

要注意的是,执行 webpack 命令是默认执行该目录下名为 webpack.config.js 或者 webpackfile.js 的文件。所以需要通过 --config 指令手动指定该文件,最后加入 -p 指令将 Dll.js 压缩。

$ webpack --config webpack.dll.config.js -p

这样,在项目根目录下就会多增加一个 dist 文件夹,其中有压缩之后的 Dll.js 与 manifest.json 文件。

manifest.json 文件内容如下,给各个模块赋予 id 以便引用。

{
 "name": "vendor_2beb750db72b1cda4321",
 "content": {
  "./node_modules/process/browser.js": {
   "id": 0,
   "meta": {}
  },
  "./node_modules/vue-router/dist/vue-router.esm.js": {
   "id": 1,
   "meta": {
    "harmonyModule": true
   },
   "exports": [
    "default"
   ]
  },
  "./node_modules/vue/dist/vue.runtime.esm.js": {
   "id": 2,
   "meta": {
    "harmonyModule": true
   },
   "exports": [
    "default"
   ]
  },
//.......

最后在 webpack.config.js 中添加引用。在 plugins 属性中添加 DllReferencePlugin 插件,并指明 manifest.json 文件的引用路径。

//...
plugins: [
  new webpack.DllReferencePlugin({
    context: __dirname,
    manifest: require('./dist/manifest.json')
  })
]

在确保成功执行 webpack.dll.config.js 文件后,执行 webpack -p 进行项目打包。

详解webpack性能优化——DLL

可以看到打包在 Dll 文件中的文件都被 delegated(委派) ,而不是直接打进 bundle 文件中。

这样我们就将所有的资源完成打包,生成的 dist 目录如下:

详解webpack性能优化——DLL

不过 dist 文件夹要想作为一个完整的工程还少一个 html 文件,我创建了一个名为 pack.js 的文件,使用 nodejs 的 fileSystem 对 html 文件进行修改并拷贝。

pack.js

var fs = require('fs');

fs.readFile('./index.html', 'utf8', (err, data) => {
  if (!err) {
    var dataStr = data.toString(),
    timestamp = (new Date()).getTime();
  
    dataStr = dataStr
          .replace('bundle.js', 'bundle.js?v='+timestamp)
          .replace('<!-- dll -->', '<script src="./dist/Dll.js?v='+ timestamp +'"></script>');

    fs.writeFile('./dist/index.html', dataStr, (error) => {
      if (!error) {
        console.log('HTML file copy successfully');
      } else {
        console.log(error);
      }
    });
  } else {
    console.log(err);
  }
});

我们需要在模块的入口 html 中添加 <!-- dll --> 的占位字符,pack.js 的作用就是将 html 文件拷贝一份到 dist 目录下,同时将 <!-- dll --> 替换为引用 Dll.js 的 script 标签,并在引用文件后添加时间戳。

<!-- .... -->
<body>
<div id="demo" class="container"></div>

<!-- dll -->
<script src="./bundle.js"></script>
</body>
</html>

在执行 webpack -p 打包后,输入下面命令运行 pack.js,就会在 dist 目录下生成 html 文件。

$ node pack.js

详解webpack性能优化——DLL

内容如下:

<!-- .... -->
<body>
<div id="demo" class="container"></div>

<script src="./dist/Dll.js?v=1488250309725"></script>
<script src="./bundle.js?v=1488250309725"></script>
</body>
</html>

这样 dist 文件夹就作为一个完整的、不需要任何手动操作、已经压缩混淆后的项目可以直接进行线上的部署。

实际项目模板参考地址如下。由于笔者作为 React 与 Vue 的双持开发者,所以创建了两个模板,以便之后通过 yomen(yo) 之类的进行脚手架工具化。

https://github.com/Darylxyx/generator-yx-react

https://github.com/Darylxyx/generator-yx-vue

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
学习js所必须要知道的一些
Mar 07 Javascript
在模板页面的js使用办法
Apr 01 Javascript
JS 跳转页面延迟2种方法
Mar 29 Javascript
关于jQuery参考实例 1.0 jQuery的哲学
Apr 07 Javascript
Tab切换组件(选项卡功能)实例代码
Nov 21 Javascript
JavaScript里四舍五入函数round用法实例
Apr 06 Javascript
jQuery实现在下拉列表选择时获取json数据的方法
Apr 16 Javascript
PHP+MySQL+jQuery随意拖动层并即时保存拖动位置实例讲解
Oct 09 Javascript
AngularJS 验证码60秒倒计时功能的实现
Jun 05 Javascript
vue 封装自定义组件之tabal列表编辑单元格组件实例代码
Sep 07 Javascript
jQuery实现checkbox即点即改批量删除及中间遇到的坑
Nov 11 jQuery
vuejs实现下拉框菜单选择
Oct 23 Javascript
vue利用better-scroll实现轮播图与页面滚动详解
Oct 20 #Javascript
浅谈如何使用 webpack 优化资源
Oct 20 #Javascript
利用jQuery实现简单的拖曳效果实例代码
Oct 20 #jQuery
Js利用prototype自定义数组方法示例
Oct 20 #Javascript
js 中rewrap-ajax.js插件实例代码
Oct 20 #Javascript
jQuery访问浏览器本地存储cookie、localStorage和sessionStorage的基本用法
Oct 20 #jQuery
JS 中使用Promise 实现红绿灯实例代码(demo)
Oct 20 #Javascript
You might like
通过PHP CLI实现简单的数据库实时监控调度
2009/07/01 PHP
php的hash算法介绍
2014/02/13 PHP
php中 $$str 中 &quot;$$&quot; 的详解
2015/07/06 PHP
PHP利用正则表达式将相对路径转成绝对路径的方法示例
2017/02/28 PHP
PHP实现的多维数组去重操作示例
2018/07/21 PHP
不要小看注释掉的JS 引起的安全问题
2008/12/27 Javascript
javascript动态加载二
2012/08/22 Javascript
js jquery分别实现动态的文件上传操作按钮的添加和删除
2014/01/13 Javascript
jQuery实现鼠标可拖动调整表格列宽度
2014/05/26 Javascript
Js类的静态方法与实例方法区分及jQuery拓展的两种方法
2016/06/03 Javascript
mvvm双向绑定机制的原理和实现代码(推荐)
2016/06/07 Javascript
Highcharts入门之简介
2016/08/02 Javascript
JS 动态判断PC和手机浏览器实现代码
2016/09/21 Javascript
原生JS实现《别踩白块》游戏(兼容IE)
2017/02/20 Javascript
Angular-Ui-Router+ocLazyLoad动态加载脚本示例
2017/03/02 Javascript
js继承的这6种方式!(上)
2019/04/23 Javascript
探究一道价值25k的蚂蚁金服异步串行面试题
2020/08/21 Javascript
python文件名和文件路径操作实例
2017/09/29 Python
Python爬虫获取整个站点中的所有外部链接代码示例
2017/12/26 Python
python实现数据库跨服务器迁移
2018/04/12 Python
Numpy截取指定范围内的数据方法
2018/11/14 Python
Python面向对象之类的内置attr属性示例
2018/12/14 Python
用Python编写一个高效的端口扫描器的方法
2018/12/20 Python
Myprotein中国网站:欧洲畅销运动营养品牌
2021/02/11 全球购物
写一个在SQL Server创建表的SQL语句
2012/03/10 面试题
95%的面试官都会问到的50道Java线程题,附答案
2012/08/03 面试题
零件设计自荐信范文
2013/11/27 职场文书
优秀高中生事迹材料
2014/02/11 职场文书
机关工会开展学习雷锋活动总结
2014/03/01 职场文书
公司保密承诺书
2014/03/27 职场文书
美食节目策划方案
2014/05/31 职场文书
节能环保家庭事迹材料
2014/08/27 职场文书
机关职员工作检讨书
2014/10/23 职场文书
企业财务人员岗位职责
2015/04/14 职场文书
2015年平安创建工作总结
2015/04/29 职场文书
呼啸山庄读书笔记
2015/06/29 职场文书