详解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 10 Javascript
设置iframe的document.designMode后仅Firefox中其body.innerHTML为br
Feb 27 Javascript
下载文件个别浏览器文件名乱码解决办法
Mar 19 Javascript
JS Replace()的高级使用方法介绍
Jun 29 Javascript
Js保留小数点的4种效果实现代码分享
Apr 12 Javascript
jquery实现侧边弹出的垂直导航
Dec 09 Javascript
Bootstrap导航栏各元素操作方法(表单、按钮、文本)
Dec 28 Javascript
JavaScript实现替换字符串中最后一个字符的方法
Mar 07 Javascript
Javascript实现倒计时时差效果
May 18 Javascript
JS库之Particles.js中文开发手册及参数详解
Sep 13 Javascript
vue发送ajax请求详解
Oct 09 Javascript
vue-cli 为项目设置别名的方法
Oct 15 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
利用phpexcel把excel导入数据库和数据库导出excel实现
2014/01/09 PHP
WordPress中查询文章的循环Loop结构及用法分析
2015/12/17 PHP
微信公众号支付之坑:调用支付jsapi缺少参数 timeStamp等错误解决方法
2016/01/12 PHP
Thinkphp3.2.3分页使用实例解析
2016/07/28 PHP
PHP数组式访问接口ArrayAccess用法分析
2017/12/28 PHP
实例讲解PHP中使用命名空间
2019/01/27 PHP
PHP whois查询类定义与用法示例
2019/04/03 PHP
mapper--图片热点区域高亮组件官方站点
2007/12/22 Javascript
JS 无法通过W3C验证的处理方法
2010/03/09 Javascript
使用javascript:将其它类型值转换成布尔类型值的解决方法详解
2013/05/07 Javascript
ECMA5数组的新增方法有哪些及forEach()模仿实现
2015/11/03 Javascript
浅谈angularJS中的事件
2016/07/12 Javascript
Select2.js下拉框使用小结
2016/10/24 Javascript
jQuery extend()详解及简单实例
2017/05/06 jQuery
Node.js 使用递归实现遍历文件夹中所有文件
2017/09/18 Javascript
three.js 将图片马赛克化的示例代码
2020/07/31 Javascript
flask中使用SQLAlchemy进行辅助开发的代码
2013/02/10 Python
Python内置函数的用法实例教程
2014/09/08 Python
Python字符串特性及常用字符串方法的简单笔记
2016/01/04 Python
Python入门_浅谈字符串的分片与索引、字符串的方法
2017/05/16 Python
python+mongodb数据抓取详细介绍
2017/10/25 Python
python库lxml在linux和WIN系统下的安装
2018/06/24 Python
python调用外部程序的实操步骤
2019/03/04 Python
python3.7简单的爬虫实例详解
2019/07/08 Python
Pandas时间序列:时期(period)及其算术运算详解
2020/02/25 Python
Html5如何唤起百度地图App的方法
2019/01/27 HTML / CSS
中国最大的潮流商品购物网站:YOHO!BUY有货
2017/01/07 全球购物
电子商务专业在校生实习自我鉴定
2013/09/29 职场文书
小学生爱国演讲稿
2014/04/25 职场文书
小学亲子活动总结
2014/07/01 职场文书
交通工程专业推荐信
2014/09/06 职场文书
工作骂脏话检讨书
2014/10/05 职场文书
退学证明范本3篇
2014/10/29 职场文书
《好妈妈胜过好老师》:每个孩子的优秀都是有源头的
2020/01/03 职场文书
Python用any()函数检查字符串中的字母以及如何使用all()函数
2022/04/14 Python
vscode内网访问服务器的方法
2022/06/28 Servers