详解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 相关文章推荐
解放web程序员的输入验证
Oct 06 Javascript
Javascript &amp; DHTML 实例编程(教程)DOM基础和基本API
Jun 02 Javascript
扩展jQuery 键盘事件的几个基本方法
Oct 30 Javascript
SinaEditor使用方法详解
Dec 28 Javascript
JavaScript极简入门教程(二):对象和函数
Oct 25 Javascript
jQuery实现视频作为全屏幕背景
Dec 18 Javascript
js实现文字滚动效果
Mar 03 Javascript
es6新特性之 class 基本用法解析
May 05 Javascript
Vue.js实现双向数据绑定方法(表单自动赋值、表单自动取值)
Aug 27 Javascript
vue实现双向绑定和依赖收集遇到的坑
Nov 29 Javascript
vue中的双向数据绑定原理与常见操作技巧详解
Mar 16 Javascript
js String.prototype.trim字符去前后空格的扩展
Aug 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 strlen mb_strlen计算中英文混排字符串长度
2009/07/10 PHP
是 WordPress 让 PHP 更流行了 而不是框架
2016/02/03 PHP
PHP微信红包生成代码分享
2016/10/06 PHP
PHP实现简易blog的制作
2016/10/24 PHP
浅析php-fpm静态和动态执行方式的比较
2016/11/09 PHP
jQuery文本框(input textare)事件绑定方法教程
2013/04/24 Javascript
js string 转 int 注意的问题小结
2013/08/15 Javascript
js解决弹窗问题实现班级跳转DIV示例
2014/01/06 Javascript
javascript获取文档坐标和视口坐标
2015/05/26 Javascript
jquery点击缩略图切换视频播放特效代码分享
2015/09/15 Javascript
jquery判断复选框是否被选中的方法
2015/10/16 Javascript
解决angular的$http.post()提交数据时后台接收不到参数值问题的方法
2015/12/10 Javascript
基于AngularJS+HTML+Groovy实现登录功能
2016/02/17 Javascript
jQuery ajax的功能实现方法详解
2017/01/06 Javascript
微信小程序 动态的设置图片的高度和宽度详解及实例代码
2017/02/24 Javascript
jQuery模拟下拉框选择对应菜单的内容
2017/03/07 Javascript
结合Vue控制字符和字节的显示个数的示例
2018/05/17 Javascript
详解使用mpvue开发github小程序总结
2018/07/25 Javascript
vue主动刷新页面及列表数据删除后的刷新实例
2018/09/16 Javascript
vue 出现data-v-xxx的原因及解决
2020/08/04 Javascript
JS typeof fn === 'function' &amp;&amp; fn()详解
2020/08/22 Javascript
Python XML RPC服务器端和客户端实例
2014/11/22 Python
Python实现的多线程同步与互斥锁功能示例
2017/11/30 Python
Python使用Selenium+BeautifulSoup爬取淘宝搜索页
2018/02/24 Python
Python matplotlib生成图片背景透明的示例代码
2019/08/30 Python
python GUI库图形界面开发之PyQt5窗口控件QWidget详细使用方法
2020/02/26 Python
增大python字体的方法步骤
2020/07/05 Python
css3强大的动画效果animate使用说明及浏览器兼容介绍
2013/01/09 HTML / CSS
优秀医生事迹材料
2014/02/12 职场文书
普通大学毕业生自荐信范文
2014/02/23 职场文书
生日庆典策划方案
2014/06/02 职场文书
单位证明范文
2015/06/18 职场文书
昆虫记读书笔记
2015/06/26 职场文书
2016年小学生寒假总结
2015/10/10 职场文书
SQL写法--行行比较
2021/08/23 SQL Server
简单聊一聊SQL注入及防止SQL注入
2022/03/23 MySQL