详解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 相关文章推荐
childNodes.length与children.length的区别
May 14 Javascript
Jquery获取元素的父容器对象示例代码
Feb 10 Javascript
jQuery源码解读之removeClass()方法分析
Feb 20 Javascript
javascript实现checkBox的全选,反选与赋值
Mar 12 Javascript
图文详解Heap Sort堆排序算法及JavaScript的代码实现
May 04 Javascript
JavaScript中Form表单技术汇总(推荐)
Jun 26 Javascript
JS实现简单的tab切换选项卡效果
Sep 21 Javascript
jquery广告无缝轮播实例
Jan 05 Javascript
requirejs + vue 项目搭建详解
Jun 16 Javascript
详解.vue文件中监听input输入事件(oninput)
Sep 19 Javascript
js异步接口并发数量控制的方法示例
Nov 22 Javascript
WebWorker 封装 JavaScript 沙箱详情
Nov 02 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
推荐文章系统(一)
2006/10/09 PHP
隐藏你的.php文件的实现方法
2007/03/19 PHP
PHP系列学习之日期函数使用介绍
2012/08/18 PHP
php面向对象之反射功能与用法分析
2017/03/29 PHP
laravel框架实现敏感词汇过滤功能示例
2020/02/15 PHP
js函数使用技巧之 setTimeout(function(){},0)
2009/02/09 Javascript
node.js中的fs.read方法使用说明
2014/12/17 Javascript
纯JS代码实现一键分享功能
2016/04/20 Javascript
深入理解jQuery layui分页控件的使用
2016/08/17 Javascript
什么是JavaScript中的结果值?
2016/10/08 Javascript
Angular JS数据的双向绑定详解及实例
2016/12/31 Javascript
Angularjs 动态添加指令并绑定事件的方法
2017/04/13 Javascript
Node.js+ES6+dropload.js实现移动端下拉加载实例
2017/06/01 Javascript
VSCode使用之Vue工程配置eslint
2019/04/30 Javascript
node读写Excel操作实例分析
2019/11/06 Javascript
javascript实现左右缓动动画函数
2020/11/25 Javascript
微信小程序实现天气预报功能(附源码)
2020/12/10 Javascript
nestjs返回给前端数据格式的封装实现
2021/02/22 Javascript
[02:12]探秘2016国际邀请赛中国区预选赛选手房间
2016/06/25 DOTA
[02:33]2018DOTA2亚洲邀请赛赛前采访——LGD
2018/04/04 DOTA
[51:43]OG vs LGD 2018国际邀请赛淘汰赛BO3 第五场 8.26
2018/08/30 DOTA
Python中的进程分支fork和exec详解
2015/04/11 Python
深入解答关于Python的11道基本面试题
2017/04/01 Python
用Python将一个列表分割成小列表的实例讲解
2018/07/02 Python
Django 限制用户访问频率的中间件的实现
2018/08/23 Python
在Python中预先初始化列表内容和长度的实现
2019/11/28 Python
django 连接数据库出现1045错误的解决方式
2020/05/14 Python
python中time.ctime()实例用法
2021/02/03 Python
服务行业个人求职的自我评价
2013/12/12 职场文书
心得体会范文
2014/01/04 职场文书
建筑安全员岗位职责
2014/03/13 职场文书
领导班子自我剖析材料
2014/08/16 职场文书
科技馆观后感
2015/06/08 职场文书
2016年度基层党建工作公开承诺书
2016/03/25 职场文书
MySQL慢查询的坑
2021/04/28 MySQL
Python爬虫网络请求之代理服务器和动态Cookies
2022/04/12 Python