6.配置—下-灵析社区

懒人学前端

二、生产环境

生产环境调优

配置文件

在实际的项目中,我们经常会有区分环境的需求,如本地环境、测试环境、生产环境。不同的环境往往对应一些不同的配置,如 mode、环境变量等,如何通过 webpack 按照不同环境采用不同配置呢?一般有以下两种方式。

1、使用同一个配置文件,不同环境传入不同变量来控制配置

webpack.config.js

...
const NODE_ENV = process.env.NODE_ENV;
const isDev = NODE_ENV === 'development';

module.exports = {
    mode: NODE_ENV,
    devtool: isDev ? 'source-map' : 'inline-source-map',
    ...
}

package.json

{
  ...
  "scripts": {
    "dev": "NODE_ENV=development webpack", // 开发环境
    "build": "NODE_ENV=production webpack" // 生产环境
  }
}

上面的配置中,通过在 package.json 中修改 NPM Scripts,传入 NODE_ENV 变量。开发环境参数值为 development,生产环境参数值为 production。在 webpack 配置文件中使用 Node.js 的 process 对象获取传入的参数。执行 npm run dev 即执行开发环境配置,生成的打包文件中包含 source map 文件同时 index.js 中包含 source map 映射路径。执行 npm run build 同理执行生产环境配置,生成的打包文件中 index.js 文件不包含 source map 映射路径。至此我们成功的区分了不同环境。

2、为不同环境创建各自的配置文件

生产环境创建一个 prod.config.js 文件,开发环境配置一个 dev.config.js 文件,修改 package.json 中的 scripts,不同命令执行不同的配置文件。

prod.config.js

const path = require('path');

module.exports = {
  mode: 'production',
  devtool: 'hidden-source-map',
  entry: {
    index: './src/index.js',
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js',
  },
}

dev.config.js

const path = require('path');

module.exports = {
  mode: 'development',
  devtool: 'source-map',
  entry: {
    index: './src/index.js',
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js',
  },
}

package.json

{
  ...
  "scripts": {
    "dev": "webpack --config=dev.config.js", // 开发环境
    "build": "webpack --config=prod.config.js" // 生产环境
  }
}

上面的两个配置文件中,项目入口出口都一样,只有打包模式和 source map 模式不同,分别执行 npm run dev 和 npm run build 可以看到生成文件内容不同。对于需要多种环境配置的文件中,我们可以将环境中共用的部分如入口、出口等配置提取出来放在一个公共配置中,将公共配置提取到 common.config.js 中,个性化配置放在不同环境对应的配置中,通过 webpack-merge 插件将配置组合起来。下面以生产环境配置为例。

prod.config.js

const commonConfig = require('./common.config.js');
const { merge } = require('webpack-merge');

module.exports = merge(commonConfig, {
  mode: 'production',
  devtool: 'hidden-source-map'
});

common.config.js

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

执行打包命令后查看输出文件,可以看到输出内容与单独配置无异。

区分环境变量

通常我们需要为生产环境和本地环境添加不同的环境变量,在 Webpack 中可以使用 DefinePlugin 进行设置,在 5.1 章节我们已经对 DefinePlugin 配置做过详细的介绍,所以下面我们只加一个区分服务地址的配置。

prod.config.js

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

module.exports = {
   ...
    plugins: [
        ...
        new webpack.DefinePlugin({
            BASE_URL: 'http://ip:8201'
        })
    ]
}

dev.config.js

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

module.exports = {
   ...
    plugins: [
        ...
        new webpack.DefinePlugin({
            BASE_URL: 'http://localhost:8201'
        })
    ]
}

index.js

...
console.log(BASE_URL)

执行不同环境的打包命令,即可区分不同的服务地址。

资源压缩

在将项目资源发布到线上环境前,我们通常会进行代码压缩,或者叫 uglify,意思是移除空格并混淆代码,一般在压缩后代码体积会变小同时代码变得不可读,在一定程度上增加了安全性。

压缩 JavaScript

Webpack 5 中已经集成了 terser-webpack-plugin 来压缩我们的代码,当我们在 webapck.config.js 中 mode 设置为 production 时,打包后的代码会被压缩。如果想自定义添加压缩配置,我们需要安装 terser-webpack-plugin,下面以删除代码中 console.log 为例。

安装 terser-webpack-plugin

npm install terser-webpack-plugin -D

prod.config.js

const TerserPlugin = require('terser-webpack-plugin');
...
module.exports = merge(commonConfig, {
  ...
  optimization: {
    // 在不设置 mode 的情况下,minimize 设置为 true 也会开启压缩
    // minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            pure_funcs: ['console.log'],
          },
        },
      }),
    ],
  },
});

index.js

const add = (a, b) => {
   return a + b
}
const addRes = add(3, 7);
const divElement = document.createElement('div');
divElement.innerHTML = addRes;
document.body.appendChild(divElement);
console.log(addRes);

执行打包命令后,可以看到生成的 bundle 文件中已经移除了 console.log 代码。

压缩 CSS

在压缩 CSS 文件之前,我们要先使用 MiniCssExtractPlugin 插件将样式文件提取出来,接着使用 css-minimizer-webpack-plugin 插件进行压缩。

css-minimizer-webpack-plugin 插件开启压缩的配置方式也是传入到 minimizer 中,与 terser-webpack-plugin 类似,只是传入压缩插件本身的配置不同。

安装 css-minimizer-webpack-plugin

npm install css-minimizer-webpack-plugin -D

prod.config.js

...
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = merge(commonConfig, {
  devtool: 'hidden-source-map',
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              esModule: true,
            },
          },
          'css-loader',
        ],
      },
    ],
  },
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [new MiniCssExtractPlugin()],
});

index.js

import styles from './index.css';
const divElement = document.createElement('div');
divElement.innerHTML = 'demo';
divElement.className = 'demo';
document.body.appendChild(divElement);

index.css

.demo {
    color: red;
}

执行 npm run build,可以看到打包文件中的 index.css 文件内容已被压缩。

资源体积监控

在实际的项目开发中,webpack 打包的体积速度往往是我们比较关注的问题,我们可以通过打包后输出文件包的大小来分析每个模块的体积,但这种反向分析往往会花费很多时间。VS Code 中有一个插件 Import Cost 可以帮助我们持续监控引入模块(主要是node_module中的模块)的大小。它会为我们计算该模块压缩后及 gzip 后将占多大体积。

当我们发现某些包过大就可以采取一些措施,比如 lodash 中只引入使用到的子模块。

另外一个很有用的工具是 webpack-bundle-analyzer,它能帮助我们分析 bundle 的构成,webpack-bundle-analyzer 可以帮我们生成一张 bundle 的模块组成结构图,每个模块所占的体积一目了然。

安装 webpack-bundle-analyzer

npm install webpack-bundle-analyzer -D

prod.config.js

...
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = merge(commonConfig, {
  ...
  plugins: [
    new BundleAnalyzerPlugin()
  ]
});

执行打包命令后,浏览器中会启动 bundle 组成结构图,包括各模块体积。

最后我们还可以自动化的对资源体积进行监控,bundlesize 可以帮我们做到这一点。

安装 bundlesize

npm install bundlesize -D

package.json

{
  ...
  "scripts": {
    "test": "bundlesize",
    "dev": "webpack --config dev.config.js",
    "build": "webpack  --config prod.config.js"
  },
  "bundlesize": [
    {
      "path": "./dist/index.js",
      "maxSize": "1 kB"
    }
  ],
}

执行 npm test 控制台中可以看到检测结果。

总结

本章我们介绍了在生产环境下可以做哪些配置。我们介绍了使用配置文件区分环境、传入不同环境变量、如何开启压缩并且如何做自定义压缩、监控输出资源体积等方法。对于使用的插件都只是简单介绍了如何使用,详细的配置可以参照官网。

阅读量:1234

点赞量:0

收藏量:0