详解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 相关文章推荐
JavaScript中获取未知对象属性的代码
Apr 27 Javascript
教你如何在 Javascript 文件里使用 .Net MVC Razor 语法
Jul 23 Javascript
php常见的页面跳转方法汇总
Apr 15 Javascript
JavaScript常用标签和方法总结
Sep 01 Javascript
深入浅析JS是按值传递还是按引用传递(推荐)
Sep 18 Javascript
简单理解vue中实例属性vm.$els
Dec 01 Javascript
简单几步实现返回顶部效果
Dec 05 Javascript
vue2.0 axios前后端数据处理实例代码
Jun 30 Javascript
Angular 如何使用第三方库的方法
Apr 18 Javascript
JS中判断某个字符串是否包含另一个字符串的五种方法
May 03 Javascript
手挽手带你学React之React-router4.x的使用
Feb 14 Javascript
MutationObserver在页面水印实现起到的作用详解
Jul 07 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 mssql 数据库分页SQL语句
2008/12/16 PHP
PHP两种快速排序算法实例
2015/02/15 PHP
PHP使用mysqldump命令导出数据库
2015/04/14 PHP
thinkPHP5.0框架自动加载机制分析
2017/03/18 PHP
PHP基于SimpleXML生成和解析xml的方法示例
2017/07/17 PHP
PDO::query讲解
2019/01/29 PHP
Laravel 5.5 异常处理 &amp; 错误日志的解决
2019/10/17 PHP
js刷新框架子页面的七种方法代码
2008/11/20 Javascript
js禁止document element对象选中文本实现代码
2013/03/21 Javascript
jQuery随机切换图片的小例子
2013/04/18 Javascript
javascript原生和jquery库实现iframe自适应高度和宽度
2014/07/18 Javascript
JS递归遍历对象获得Value值方法技巧
2016/06/14 Javascript
微信小程序自定义模态对话框实例详解
2017/08/16 Javascript
详解react-native-fs插件的使用以及遇到的坑
2017/09/12 Javascript
vue-cli常用设置总结
2018/02/24 Javascript
使用Vue开发自己的Chrome扩展程序过程详解
2019/06/21 Javascript
用Golang运行JavaScript的实现示例
2019/11/25 Javascript
vue远程加载sfc组件思路详解
2019/12/25 Javascript
vue+vant实现商品列表批量倒计时功能
2020/01/13 Javascript
vue+elementUI中表格高亮或字体颜色改变操作
2020/11/02 Javascript
Python random模块(获取随机数)常用方法和使用例子
2014/05/13 Python
老生常谈python函数参数的区别(必看篇)
2017/05/29 Python
Python socket 套接字实现通信详解
2019/08/27 Python
使用OpenCV获取图片连通域数量,并用不同颜色标记函
2020/06/04 Python
python json.dumps() json.dump()的区别详解
2020/07/14 Python
带你学习Python如何实现回归树模型
2020/07/16 Python
AmazeUI 网格的实现示例
2020/08/13 HTML / CSS
蔻驰英国官网:COACH英国
2020/07/19 全球购物
校园报刊亭的创业计划书
2014/01/02 职场文书
英语教学随笔感言
2014/02/20 职场文书
大学新闻系应届生求职信
2014/06/02 职场文书
电视新闻稿
2015/07/17 职场文书
个人落户申请书怎么写?
2019/06/28 职场文书
聊聊JS ES6中的解构
2021/04/29 Javascript
python 如何做一个识别率百分百的OCR
2021/05/29 Python
springboot临时文件存储目录配置方式
2021/07/01 Java/Android