luoxue-victor / my-blog

公众号【前端技匠】作者

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

专题15: webpack性能优化2 (happypack、dllplugin、cache-loader)

luoxue-victor opened this issue · comments

webpack编译优化

本章内容

  1. cache-loader
  2. DllPlugin
  3. threadLoader

cache-loader

cache-loader 主要是将打包好的文件缓存在硬盘的一个目录里,一般存在 node_modules/.cache 下,当你再次 build 的时候如果此文件没有修改就会从缓存中读取已经编译过的文件,只有有改动的才会被编译,这样就大大降低了编译的时间。尤其是项目越大时越明显。

此项目使用前后数据对比 3342ms --> 2432ms 效果还是比较明显

这里只对 babel 加入了 cache-loader,因为我们的 ts/js 都是由 babel 进行编译的,不需要对 ts-loader 缓存(我们也没有用到)

config/cacheLoader.js

module.exports = (config, resolve) => {
  const baseRule = config.module.rule('js').test(/.js|.tsx?$/);
  const babelPath = resolve('babel.js')
  const babelConf = require(babelPath);
  const version = require(resolve('node_modules/@babel/core/package.json')).version
  return () => {
    baseRule
      .exclude
      .add(filepath => {
        // 不缓存 node_modules 下的文件
        return /node_modules/.test(filepath)
      })
      .end()
      .use('cache-loader')
      .loader('cache-loader')
      .options({
        // 缓存位置
        cacheDirectory: resolve('node_modules/.cache/babel')
      })
  }
}

DllPlugin

DllPlugin 是将第三方长期不变的包与实际项目隔离开来并分别打包,当我们 build 时再将已经打包好的 dll 包引进来就 ok 了

我提取了两个包 vue、react,速度差不多提升了 200ms,从 2698ms 到 2377ms

打包 dll

build/dll.js

const path = require("path");
const dllPath = path.join(process.cwd(), 'dll');
const Config = require('webpack-chain');
const config = new Config();
const webpack = require('webpack')
const rimraf = require('rimraf');
const ora = require('ora')
const chalk = require('chalk')
const BundleAnalyzerPlugin = require('../config/BundleAnalyzerPlugin')(config)

BundleAnalyzerPlugin()
config
  .entry('dll')
  .add('vue')
  .add('react')
  .end()
  .set('mode', "production")
  .output
  .path(dllPath)
  .filename('[name].js')
  .library("[name]")
  .end()
  .plugin('DllPlugin')
  .use(webpack.DllPlugin, [{
    name: "[name]",
    path: path.join(process.cwd(), 'dll', 'manifest.json'),
  }])
  .end()

rimraf.sync(path.join(process.cwd(), 'dll'))
const spinner = ora('开始构建项目...')
spinner.start()

webpack(config.toConfig(), function (err, stats) {
  spinner.stop()
  if (err) throw err
  process.stdout.write(stats.toString({
    colors: true,
    modules: false,
    children: false,
    chunks: false,
    chunkModules: false
  }) + '\n\n')

  if (stats.hasErrors()) {
    console.log(chalk.red('构建失败\n'))
    process.exit(1)
  }
  console.log(chalk.cyan('build完成\n'))
})

将 dll 包合并

const webpack = require('webpack')

module.exports = (config, resolve) => {
  return () => {
    config.plugin('DllPlugin')
      .use(webpack.DllReferencePlugin, [{
        context: process.cwd(),
        manifest: require(resolve('dll/manifest.json'))
      }])
  }
}

threadLoader