详解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 相关文章推荐
符合W3C网页标准的iframe标签的使用方法
Jul 19 Javascript
在html页面上拖放移动标签
Jan 08 Javascript
javascript数组去掉重复
May 12 Javascript
一个获取第n个元素节点的js函数
Sep 02 Javascript
Javascript for in的缺陷总结
Feb 03 Javascript
Angular实现下载安装包的功能代码分享
Sep 05 Javascript
微信小程序返回多级页面的实现方法
Oct 27 Javascript
Bootstrap3.3.7导航栏下拉菜单鼠标滑过展开效果
Oct 31 Javascript
详解Vue SPA项目优化小记
Jul 03 Javascript
详解如何在webpack中做预渲染降低首屏空白时间
Aug 22 Javascript
vue项目中在可编辑div光标位置插入内容的实现代码
Jan 07 Javascript
antd-DatePicker组件获取时间值,及相关设置方式
Oct 27 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 读取shell管道传输过来的内容
2010/03/01 PHP
PHP版 汉字转码的实现详解
2013/06/09 PHP
php调用mysql存储过程实例分析
2014/12/29 PHP
微信支付开发动态链接Native支付
2016/07/12 PHP
php微信浏览器分享设置以及回调详解
2016/08/01 PHP
iis 7下安装laravel 5.4环境的方法教程
2017/06/14 PHP
PHP实现SMTP邮件的发送实例
2018/09/27 PHP
EXTJS FORM HIDDEN TEXTFIELD 赋值 使用value不好用的问题
2011/04/16 Javascript
JavaScript高级程序设计 阅读笔记(十三) js定义类或对象
2012/08/14 Javascript
浅谈javascript属性onresize
2015/04/20 Javascript
JS模拟实现Select效果代码
2015/09/24 Javascript
Vuejs第八篇之Vuejs组件的定义实例解析
2016/09/05 Javascript
JS实现的表头列头固定页面功能示例
2017/01/10 Javascript
JavaScript基本类型值-Undefined、Null、Boolean
2017/02/23 Javascript
利用Angular+Angular-Ui实现分页(代码加简单)
2017/03/10 Javascript
详解利用Angular实现多团队模块化SPA开发框架
2017/11/27 Javascript
全站最详细的Vuex教程
2018/04/13 Javascript
判断iOS、Android以及PC端的示例代码
2018/11/15 Javascript
vue 集成jTopo 处理方法
2019/08/07 Javascript
JavaScript回调函数callback用法解析
2020/01/14 Javascript
Python的多态性实例分析
2015/07/07 Python
Django添加feeds功能的示例
2018/08/07 Python
python tornado微信开发入门代码
2018/08/24 Python
python调试神器PySnooper的使用
2019/07/03 Python
简单了解python变量的作用域
2019/07/30 Python
python实现图片转换成素描和漫画格式
2020/08/19 Python
德国百年厨具品牌WMF美国站:WMF美国
2016/09/12 全球购物
多媒体编辑专业毕业生推荐信
2013/11/05 职场文书
社区志愿者活动方案
2014/08/18 职场文书
防灾减灾活动总结
2014/08/30 职场文书
奉献家乡演讲稿
2014/09/16 职场文书
群众路线专项整治方案
2014/10/27 职场文书
优秀少先队辅导员事迹材料
2014/12/24 职场文书
2016学习依法治国心得体会
2016/01/15 职场文书
幼儿园科学课教学反思
2016/03/03 职场文书
python opencv通过按键采集图片源码
2021/05/20 Python