webpack性能优化vue系列,从27s到2s的改变

1,166 阅读2分钟

1、speed-measure-webpack-plugin 插件可以测量各个插件和loader所花费的时间,使用之后,构建时,会得到类似下面这样的信息:

image.png

使用步骤

cnpm i speed-measure-webpack-plugin
//vue.config.js下
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
module.exports = {
  // 添加分析工具
  chainWebpack: config => {
    config.plugin('speed-measure-webpack-plugin').use(SpeedMeasurePlugin).end();
  },
};

2、生成打包后文件体积图

使用步骤

cnpm i webpack-bundle-analyzer
//vue.config.js下
module.exports = {
  // 添加分析工具
  chainWebpack: config => {
    config
      .plugin('webpack-bundle-analyzer')
      .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
      .end();
  },
};

3、exclude/include,cache-loader,thread-loader

简介

1、我们可以通过 excludeinclude 配置来确保转译尽可能少的文件。顾名思义,exclude 指定要排除的文件,include 指定要包含的文件。

exclude 的优先级高于 include,在 includeexclude 中使用绝对路径数组,尽量避免 exclude,更倾向于使用 include

2、在一些性能开销较大的 loader 之前添加 cache-loader,将结果缓存中磁盘中。默认保存在 node_modueles/.cache/cache-loader 目录下。

3、除了使用 Happypack 外,我们也可以使用 thread-loader ,把 thread-loader 放置在其它 loader 之前,那么放置在这个 loader 之后的 loader 就会在一个单独的 worker 池中运行。

在 worker 池(worker pool)中运行的 loader 是受到限制的。例如:

  • 这些 loader 不能产生新的文件。
  • 这些 loader 不能使用定制的 loader API(也就是说,通过插件)。
  • 这些 loader 无法获取 webpack 的选项设置。

使用步骤

cnpm install cache-loader -D
cnpm install thread-loader -D
//vue.config.js下
const path = require('path');

const path = require('path');

module.exports = {
  configureWebpack: config => {
    config.module.rules.push(
          {
        test: /\.js[x]?$/,
        use: ['babel-loader'],
        include: [path.resolve(__dirname, 'src')],
      },
      {
        test: /\.jsx?$/,
        use: ['cache-loader', 'babel-loader'],
      },
      {
        test: /\.jsx?$/,
        use: ['thread-loader', 'cache-loader', 'babel-loader'],
      }
    );
  },
};

4、开启打包缓存(重点)

//vue.config.js下

module.exports = {
  configureWebpack: config => {
    config.cache = {
      type: 'filesystem',
      allowCollectingMemory: true,
    };
  },
};

5、noParse

如果一些第三方模块没有AMD/CommonJS规范版本,可以使用 noParse 来标识这个模块,这样 Webpack 会引入这些模块,但是不进行转化和解析,从而提升 Webpack 的构建性能 ,例如:jquery 、lodash

module.exports = {
  configureWebpack: config => {
      config.module.noParse = /jquery|lodash/;
  },
};

6、externals

我们可以将一些JS文件存储在 CDN 上(减少 Webpack打包出来的 js 体积),在 index.html 中通过 <script> 标签引入,如:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="root">root</div>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
</body>
</html>

我们希望在使用时,仍然可以通过 import 的方式去引用(如 import $ from 'jquery'),并且希望 webpack 不会对其进行打包,此时就可以配置 externals

module.exports = {
  configureWebpack: config => {
      config.externals={ //jquery通过script引入之后,全局中即有了 jQuery 变量
                        'jquery': 'jQuery'
                        }
  },
};

7、抽离公共代码

抽离公共代码是对于多页应用来说的,如果多个页面引入了一些公共模块,那么可以把这些公共的模块抽离出来,单独打包。公共代码只需要下载一次就缓存起来了,避免了重复下载。

抽离公共代码对于单页应用和多页应该在配置上没有什么区别,都是配置在 optimization.splitChunks 中。

module.exports = {
  configureWebpack: config => {
    config.optimization = {
      splitChunks: {
        cacheGroups: {
          vendor: {
            chunks: 'all',
            test: /node_modules/,
            name: 'vendor',
            minChunks: 1,
            maxInitialRequests: 5,
            minSize: 0,
            priority: 100,
          },
          common: {
            chunks: 'all',
            test: /[\\/]src[\\/]js[\\/]/,
            name: 'common',
            minChunks: 2,
            maxInitialRequests: 5,
            minSize: 0,
            priority: 60,
          },
          styles: {
            name: 'styles',
            test: /\.(sa|sc|c)ss$/,
            chunks: 'all',
            enforce: true,
          },
          runtimeChunk: {
            name: 'manifest',
          },
        },
      },
    };
    // }
  },
};