webpack优化提升构建速度

Webpack 的最简单的配置如下:

module.exports = {
  entry: {
    app: './src/app.js'
  },
  
  output: {
    path: path.join(__dirname, 'dist-[hash]'),
    filename: '[name].[hash].js'
  }
};

这样的配置会将我们的文件打包成为一个 app.[hash].js 文件。这样针对的一般是我们的项目不算大的情况,并且公用模块比较少的情况(。

对于项目中有用到预处理器,ES2015+ 或者其余的需要编译后在浏览器上运行的语言,我们需要做的就是为这些东西添加上对应的 loader,然后,Webpack 就会自动的帮我们进行处理了(老实说,这一步还是挺方便的)。

一些 loader 配置示例如下:

rules: [
  {
    test: /\.jsx?$/,
    loader: ['babel-loader?presets[]=react,presets[]=latest&compact=false'],
  }, {
    test: /\.scss$/,
    loader: [
      'style-loader',
      'css-loader',
      'postcss-loader',
      'sass-loader'
    ],
  }, {
    test: /\.jpe?g|png|svg|gif/,
    loader: ['url-loader?limit=8192&name=assets/images/[name]-[hash].[ext]'],
  }
]

我们就可以使用 Webpack 的 CommonsChunkPlugin 来将这些公用的代码打包成一个文件,然后,将我们页面的业务代码打包成为一个文件。

以下几个方面入手优化:

  • 减少构建的文件,减小文件大小:项目中存在太多的无用的文件和代码,先删除这些无用的东西
  • 移除 CommonsChunkPlugin
  • Search with Google

我在网上找到了许多相关的问题,关键性的建议有以下几个:

  • css-loader 的版本回溯到 0.15 及其以前的版本

  • 使用 HappyPack

  • 使用 DllPlugin

第一点,降低 css-loader 的版本。

在 GitHub 上有这样一个 issue:0.15.0+ makes Webpack load slowly。按照 issue 中大家的讨论,我将我们项目中的 css-loader 的版本降到了 0.14.5。满怀期待的以为这样就能够提升一部分速度,但是,结果是令人失望的——构建的速度并没有明显的改变。我试着构建了好几遍,速度依然没有提升,所以,第一个方法失败,我将 css-loader 的版本恢复了回来。

继续尝试第二个方法,也是本文将要重点说明的方法之一,那就是使用 HappyPack

HappyPack 允许 Webpack 使用 Node 多线程进行构建来提升构建的速度。

使用的方法与在 Webpack 中定义 loader 的方法类似,只是说,我们把构建需要的 loader 放到了 HappyPack 中,让 HappyPack 来为我们进行相应的操作,我们只需要在 Webpack 的配置中引入 HappyPack 的 loader 的配置就好了。

编译 .scss 文件的 loader 这样写:

new HappyPack({
  id: 'scss',
  threads: 4,
  loaders: [
    'style-loader',
    'css-loader',
    'postcss-loader',
    'sass-loader',
  ],
})

其中,threads 指明 HappyPack 使用多少子进程来进行编译,一般设置为 4 为最佳。
由于 HappyPack 对 url-loader 和 file-loader 的支持度的问题,所以,我们此处,打包图片文件的时候,并没有使用 HappyPack。
定义好了我们 HappyPack 的 loader 之后,我们直接在我们的 Webpack 的配置的 plugins 一项中,引入就好了。

那么,我们在编译的时候,就会看到下面的输出:


编译过程

我们发现,单独使用 HappyPack 的情况下,构建速度并没有明显的提升(当然,或许有所提升不明显)。

我们将采取第三种方案,那就是 DllPlugin

在 Webpack 中,DllPlugin 并不是单独的使用的,而是需要与一个名为 DllReferencePlugin 的插件结合起来使用的。

在 Windows 中,有大量的 .dll 文件,称为动态链接库 (可以在其他模块中进行调用的函数和数据)。
动态链接库提供了将应用模块化的方式,应用的功能可以在此基础上更容易被复用。

类似的,我们其实要做的也是将各个模块中公用的部分给打包成为一个公用的模块。这个模块就包含了我们的其他模块中需要的函数和数据(比如,其他组件所需的 React 库)。

使用 DllPlugin 的时候,会生成一个 manifest.json 这个文件,所存储的就是各个模块和所需公用模块的对应关系。

我们不如直接来看看这个插件到底是怎么使用的:

首先,我们需要一个文件,这个文件包含所有的第三方或者公用的模块和库,我们在此将其命名为 vendor.js,文件的内容如下:

import 'react';
import 'react-dom';

在打包的时候,我们将这些公用的模块单独打包成一个文件,然后,通过生成的 manifest.json 文件对应过去。所以,我们需要单独创建一个 webpack.config.vendor.js

const webpack = require('webpack');
const path = require('path');

module.exports = {
  entry: {
    vendor: [path.join(__dirname, 'src', 'vendor.js')],
  },

  output: {
    path: path.join(__dirname, 'dist-[hash]'),
    filename: '[name].js',
    library: '[name]',
  },

  plugins: [
    new webpack.DllPlugin({
      path: path.join(__dirname, 'dll', '[name]-manifest.json'),
      filename: '[name].js',
      name: '[name]',
    }),
  ]
};

可以看到,我们主要的操作是在 plugins 配置中,生成的文件名就是我们所定义的 entry 的名称,JSON 文件名可以根据自己的需要来命名。像上面这样,我们就可以将我们的一些公用模块打包出来了。

运行以下命令:

webpack -p --progress --config webpack.config.vendor.js

我们就可以看到这样的输出:

如上 输出

这样,我们就完成了构建的第一步。下一步,我们需要在构建应用的配置文件中,加入我们的 DllPlugin 的配置。

这时候,我们就需要用到 DllReferencePlugin 了。

在我们的主要配置文件中,加入以下的配置:

const manifest = require('./dll/vendor-manifest.json');

// ... 其他完美的配置

plugins: [
  new webpack.DllReferencePlugin({
    manifest,
  }),
],

就这样,我们的所有工作就完成了,我们只需要运行一条命令,就能够看到构建速度的巨大提升。

我们运行 npm run build dll,通过 DllPlugin 和 HappyPack 进行构建.

另外,还有几点建议:
Webpack 和一些 Plugin/Loader 都有 Cache 选项。开启 Cache 选项,有利用提高构建性能。

​比如:使用 babel-loader 的时候开启 cacheDirectory 选项,会较为明显的提升构建速度

 module: {
    rules: [{
        test: /\.js$/,
        use: ['babel-loader?cacheDirectory'],
        include: path.join(__dirname, 'app')
    }]
 }

在进行这一优化手段的时候,可以借助可视化工具进行 chunk 体积和内容的分析。方便进一步调整 webpack 的配置。主要有以下两种方法:

  1. 使用 webpack 的 profile 命令生成 JSON 文件,并且把 JSON 上传到相应的在线网站进行可视化分析。
webpack --profile --json > stat.json

使用 webpack-visualizer 进行分析
推荐使用 webpack-bundle-analyzer:

^ ^ 希望在工作中实践继续优化 💪💪

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容