webpack开发环境调优(一)|小册免费学

765 阅读4分钟

Webpack 作为打包工具的重要使命之一就是提升效率。下面我们记录一些对日常开发有一定帮助的 Webpack 插件以及调试方法,本系列文章将包含以下内容:

1. Webpack 开发效率插件

这里我们记录几个使用较广的插件,可以从不同的方面对 Webpack 的能力进行增强。

1.1 webpack-dashboard

Webpack 每一次构建结束后都会在控制台输出一些打包相关的信息,但是这些信息是以列表的形式展示的,有时会显得不够直观。webpack-dashboard 就是用来更好地展示这些信息的。

安装命令:yarn add webpack-dashboard --save-dev

我们需要把 webpack-dashboard 作为插件添加到 Webpack 配置中:

const DashboardPlugin = require('webpack-dashboard/plugin');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: '[name].js',
  },
  mode: 'development',
  plugins: [
    new DashboardPlugin()
  ]
}

为了使 webpack-dashboard 生效还要更改一下 webpack 的启动方式,就是用 webpack-dashboard 模块命令替代原来的 webpack 或者 webpack-dev-server 命令,并将原有的启动命令作为参数传给它。

假设原本的启动命令如下:

// package.json
{
  ...
  "scripts": {
    "dev": "webpack-dev-server"
  }
}

执行yarn dev启动后效果如图:

原始开发服务启动.png

加上 webpack-dashboard 后则变成:

// package.json
{
  ...
  "scripts": {
    "dev": "webpack-dashboard -- webpack-dev-server"
  }
}

执行yarn dev启动后效果如图:

webpack-dashboard.png

webpack-dashboard 的控制台分为几个面板来展示不同方面的信息。比如左上角的 Log 面板就是 Webpack 本身的日志;下面的 Modules 面板则是此次参与打包的模块,从中我们可以看出哪些模块资源占用比较多;而从右下方的 Problems 面板中可以看到构建过程中的警告和错误等。

1.2 webpack-merge

对于需要配置多种打包环境的项目来说,webpack-merge 是一个非常实用的工具。假设我们的项目有3种不同的配置,分别对应本地环境、测试环境和生产环境。每一个环境对应的配置都不同,但也有一些公共的部分,那么我们就可以将这些公共的部分提取出来。假设我们创建一个 webpack.common.js 来存放所有这些配置,如下所示:

// webpack.common.js
module.exports = {
  entry: './src/app.js',
  output: {
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: 'file-loader'
      }
    ]
  },
  plugins: [
    // 用于生成 index.html
    new HtmlWebpackPlugin({
      title: 'Webpack Tutorials',
      meta: {
        viewport: 'width=device-width'
      },
      template: './template/index.html'
    })
  ]
}

每一个环境又有一个相对应的配置文件,如对于生产环境的 webpack.prod.js。假如不借助任何工具,我们自己从 webpack.common.js 引入公共配置,则大概如下所示:

// webpack.prod.js
const commonConfig = require('./webpack.common.js');
module.exports = Object.assign(commonConfig, {
  mode: 'production'
});

这样看起来很简单,但问题是,假如我们想修改一下 CSS 的打包规则,例如用 mini-css-extract-plugin 将样式单独打包出来应该怎么办呢?这时就需要添加一些代码:

// webpack.prod.js
const commonConfig = require('./webpack.common.js');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = Object.assign(commonConfig, {
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: 'file-loader'
      },
      {
        test: /\.css$/,
        use: [ MiniCssExtractPlugin.loader, 'css-loader' ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin()
  ]
});

mini-css-extract-plugin 与 extract-text-webpack-plugin 相比:

  • 异步加载
  • 没有重复的编译(性能)
  • 更容易使用
  • 特定于CSS

是不是一下子感觉有些冗余了呢?这是因为通过 Object.assign 方法会把同名属性的值覆盖掉,所以必须替换掉整个 module 的配置。

下面我们看一下如何用 webpack-merge 来解决这个问题。安装:yarn add webpack-merge -D

更改 webpack.prod.js 如下:

// webpack.prod.js
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.common.js');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = merge(commonConfig, {
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [ MiniCssExtractPlugin.loader, 'css-loader' ]
      }
    ]
  },
  plugins: [ new MiniCssExtractPlugin() ]
});

使用 merge 方法后的效果相当于:

module.exports = {
  entry: './src/app.js',
  output: {
    filename: '[name].js'
  },
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: 'file-loader'
      },
      {
        test: /\.css$/,
        use: [ MiniCssExtractPlugin.loader, 'css-loader' ]
      }
    ]
  },
  plugins: [
    // 用于生成 index.html
    new HtmlWebpackPlugin({
      title: 'Webpack Tutorials',
      meta: {
        viewport: 'width=device-width'
      },
      template: './template/index.html'
    }),
    new MiniCssExtractPlugin()
  ]
};

merge 方法会对值类型进行覆盖,对数组进行合并拓展。

1.3 speed-measure-webpack-plugin

觉得 Webpack 构建很慢但又不清楚如何下手优化吗?那么可以试试 speed-measure-webpack-plugin 这个插件(简称 SMP)。SMP 可以分析出 Webpack 整个打包过程中在各个 loader 和 plugins 上耗费的时间,这将会有助于找出构建过程中的性能瓶颈。

安装:yarn add speed-measure-webpack-plugin -D

SMP 的使用很简单,只要用它的 wrap 方法包裹在 Webpack 的配置对象外面即可。

// webpack.config.js
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const smp = new SpeedMeasurePlugin();
module.exports = smp.wrap({
  entry: './src/main.js',
  ......
})

执行 Webpack 构建命令,将会输出 SMP 的时间测量结果,如下图:

smp.png

从上面的分析结果就可以找出哪些构建步骤耗时较长,以便于优化和反复测试。

1.4 size-plugin

一般而言,随着项目的开发产出的资源会越来越大,最终生成的资源会逐渐变得臃肿。size-plugin 这个插件可以帮助监控资源体积的变化,尽早地发现问题。

安装:yarn add size-plugin -D

size-plugin 的配置同样很简单:

const path = require('path');
const SizePlugin = require('size-plugin');

module.exports = {
  ......,
  plugins: [
  	new SizePlugin()
  ]
}

在每次执行 Webpack 打包命令后,size-plugin 都会输出本次构建的资源体积(gzip过后),以及与上次构建相比体积变化了多少,如图:

size-plugin.png

该插件目前还不够完善,理想情况下它应该可以把这些结果以文件的形式输出来,这样就变与我们在持续集成平台上对结果进行对比。不过它还在快速完善中,也许未来会添加类似的功能。

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