阅读 95

webpack深入浅出(四)| 小册免费学

缩小文件搜索范围

随着时间和业务量的累积,代码变得越来越臃肿,打包时间变得越来越长,这无疑是一件很头疼的事情(虽然现在大部分都是CI/CD构建),缩小搜索范围也可以减少构建时间

使用loader编译文件是一件很耗时的工作,使用include或者exclude来缩小检索文件的范围

  module: {
    rules: [
      {
        // 如果项目源码中只有 js 文件就不要写成 /\.jsx?$/,提升正则表达式性能
        test: /\.js$/,
        // 开启缓存来加快速度
        use: [
          {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true
            }
          }
        ],
        // 只对项目根目录下的 src 目录中的文件采用 babel-loader
        include: path.resolve(__dirname, 'src'),
      },
    ]
  },
复制代码

webpack寻找依赖时会先在当前目录下寻找node_modules,找不到再去上级目录寻找,如果项目所有的依赖都在./node_modules中时,可以设置绝对路径来减少依赖寻找时间

  resolve: {
    modules: [path.resolve(__dirname, 'node_modules')]
  },
复制代码

很多依赖包下载时会有已经打包好的文件。我们在引用时可以尝试使用别名来引用这些构建好的产物来节约打包时间

module.exports = {
  resolve: {
    alias: {
      'react': path.resolve(__dirname, './node_modules/react/dist/react.min.js'), // react15
      // 'react': path.resolve(__dirname, './node_modules/react/umd/react.production.min.js'), // react16
    }
  },
};
复制代码

这种文件跟jquery一样规模庞大,而且没有标准的模块化,可以配合noParse忽略掉

  module: {
    noParse: [/react\.min\.js$/],
  },
复制代码

JS 代码优化

Tree shaking 起源于rollup,可以移除 JavaScript 上下文中的未引用代码,删掉用不着的代码,能够有效减少 JS 代码文件的大小。

const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()],
  },
};
复制代码

起用ParallelUglifyPlugin 多线程代码压缩,由于压缩 JavaScript 代码需要先把代码解析成用 Object 抽象表示的 AST 语法树,再去应用各种规则分析和处理 AST,导致这个过程计算量巨大,耗时非常多。开启多线程之后可以加快解析速度

const path = require('path');
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');

module.exports = {
  plugins: [
    new ParallelUglifyPlugin({
      // 传递给 UglifyJS 的参数
      uglifyJS: {
        output: {
          // 不美化代码
          beautify: false,
          // 删除所有的注释
          comments: false,
        },
        compress: {
          // 删除没有用到的代码时不输出警告
          warnings: false,
          // 删除所有的 console 语句
          drop_console: true,
          // 内嵌定义了但是只用到一次的变量
          collapse_vars: true,
          // 提取出出现多次但是没有定义成变量去引用的静态值
          reduce_vars: true,
        }
      },
    }),
  ],
};
复制代码
  • test:使用正则去匹配哪些文件需要被 ParallelUglifyPlugin 压缩,默认是 /.js$/,也就是默认压缩所有的 .js 文件。
  • include:使用正则去命中需要被 ParallelUglifyPlugin 压缩的文件。默认为 []
  • exclude:使用正则去命中不需要被 ParallelUglifyPlugin 压缩的文件。默认为 []
  • cacheDir:缓存压缩后的结果,下次遇到一样的输入时直接从缓存中获取压缩后的结果并返回。cacheDir 用于配置缓存存放的目录路径。默认不会缓存,想开启缓存请设置一个目录路径。
  • workerCount:开启几个子进程去并发的执行压缩。默认是当前运行电脑的 CPU 核数减去1。
  • sourceMap:是否输出 Source Map,这会导致压缩过程变慢。
  • uglifyJS:用于压缩 ES5 代码时的配置,Object 类型,直接透传给 UglifyJS 的参数。
  • uglifyES:用于压缩 ES6 代码时的配置,Object 类型,直接透传给 UglifyES 的参数(不可与uglifyJS同时使用)。

为了避免重复加载,将公共部分单独分离出来,也是一种优化的方式

  optimization: {
    splitChunks: {
      chunks: "all", 
      // 所有的 chunks 代码公共的部分分离出来成为一个单独的文件,可选值all/async/initial
      name: 'common', // 给分离出来的 chunk 起个名字
    },
  },
复制代码

结语

到这里我们已经学习了webpack的很多配置方法,其实webpack的配置方法并不难,难的是要去掌握海量插件的配置参数,不论是什么,最好的学习工具就是官方文档,毕竟那是开发者给出的指南,没有人比开发者更熟悉。博客什么的只是其他人总结出来的‘’快餐‘,想要深入了解还是要回归文档。

此外,在海量的插件中学会搜索自己需要的插件也是一项技能。

本文正在参与「掘金小册免费学啦!」活动, 点击查看活动详情

文章分类
前端
文章标签