4-2 Development 和 Production 模式的区分打包

1. 简介

接上节4-1 Tree Shaking 概念详解末尾,我们可以看到,在 mode 进行切换时,webpack.config.js 的配置也是不一样的。这很好理解,开发环境中我们更多地是考虑开发和调试方便,生产环境我们更多考虑性能。但我们总不会每次切换环境的时候,还要手动去更改配置吧。最简单就是保存两份配置,对应不同的环境。

2. 开发环境配置

// webpack.dev.js
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin');
var path = require('path');
var webpack = require('webpack');

module.exports = {
    mode: 'development',
    entry: {
        index: "./src/index.js",
    },
    devtool: "cheap-module-eval-source-map",
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: "[name].js"
    },
    devServer: {
        contentBase: path.resolve(__dirname, 'dist'),
        open: true,
        port: 3000,
        hot: true // 开启热更新
    },
    module: {
        rules: [
            {
                test: /\.(jpg|jpeg|png|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        name: '[name].[ext]',
                        limit: 2048
                    }
                }
            },
            {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
            },
            {
                test: /\.scss$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'postcss-loader',
                    'sass-loader',
                ]
            },
            {
                test: /\.(eot|svg|ttf|woff)$/,
                use: 'file-loader'
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html"
        }),
        new CleanWebpackPlugin(),
        new webpack.HotModuleReplacementPlugin()
    ]
};
"dev": "webpack-dev-server --config webpack.dev.js"

3. 生产环境配置

// webpack.prod.js
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin');
var path = require('path');

module.exports = {
    mode: 'production',
    entry: {
        index: "./src/index.js",
    },
    devtool: "cheap-module-source-map",
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: "[name].js"
    },
    module: {
        rules: [
            {
                test: /\.(jpg|jpeg|png|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        name: '[name].[ext]',
                        limit: 2048
                    }
                }
            },
            {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
            },
            {
                test: /\.scss$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'postcss-loader',
                    'sass-loader',
                ]
            },
            {
                test: /\.(eot|svg|ttf|woff)$/,
                use: 'file-loader'
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html"
        }),
        new CleanWebpackPlugin()
    ]
};
"build": "webpack --config webpack.prod.js"

4. 公共配置抽取

可以看到开发环境和生产环境配置,存在很多一致的地方,写两套即浪费代码体积,又增加维护成本,我们尝试将其抽取。

// webpack.common.js
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin');
var path = require('path');

module.exports = {
    entry: {
        index: "./src/index.js",
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: "[name].js"
    },
    module: {
        rules: [
            {
                test: /\.(jpg|jpeg|png|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        name: '[name].[ext]',
                        limit: 2048
                    }
                }
            },
            {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
            },
            {
                test: /\.scss$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'postcss-loader',
                    'sass-loader',
                ]
            },
            {
                test: /\.(eot|svg|ttf|woff)$/,
                use: 'file-loader'
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html"
        }),
        new CleanWebpackPlugin()
    ]
};

提取后,dev 和 prod 如下:

// webpack.dev.js
var path = require('path');
var webpack = require('webpack');

module.exports = {
    mode: 'development',
    devtool: "cheap-module-eval-source-map",
    devServer: {
        contentBase: path.resolve(__dirname, 'dist'),
        open: true,
        port: 3000,
        hot: true // 开启热更新
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin()
    ]
};
// webpack.prod.js

module.exports = {
    mode: 'production',
    devtool: "cheap-module-source-map"
};

5. 合并配置

上面提取公共配置以后,dev 和 prod 的配置只剩很小一部分了,那么如何将公共配置与单独的环境配置合并到一起呢?需要使用 webpack-merge 库。

npm i webpack-merge -D
// webpack.dev.js
var path = require('path');
var webpack = require('webpack');
var merge = require('webpack-merge');
var commonConfig = require('./webpack.common');

var devConfig = {
    mode: 'development',
    devtool: "cheap-module-eval-source-map",
    devServer: {
        contentBase: path.resolve(__dirname, 'dist'),
        open: true,
        port: 3000,
        hot: true // 开启热更新
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin()
    ]
};

module.exports = merge(commonConfig, devConfig);
// webpack.prod.js
var merge = require('webpack-merge');
var commonConfig = require('./webpack.common');

var prodConfig = {
    mode: 'production',
    devtool: "cheap-module-source-map"
};

module.exports = merge(commonConfig, prodConfig);

6. mode 选择

webpack 可以使用 mode 告知 webpack 使用相应模式的内置优化。可以理解为一系列配置的合集就是 mode。


4-2 Development 和 Production 模式的区分打包_第1张图片
image.png

7. 移动配置文件

现在的配置文件很分散,我们将他们挪到同一个目录 build 下:


4-2 Development 和 Production 模式的区分打包_第2张图片
image.png
  "scripts": {
    "dev": "webpack --config ./build/webpack.dev.js --watch",
    "dev-server": "webpack-dev-server --config ./build/webpack.dev.js",
    "build": "webpack --config ./build/webpack.prod.js"
  },

运行打包命令 npm run dev


4-2 Development 和 Production 模式的区分打包_第3张图片
image.png

发现,build 目录下多了一个 dist。我们修改源码后,重新打包,发现 build/dist 的页面更新,但是 dist 下没有更新。这说明,代码输出的地址发生了改变,并且清除旧的打包代码插件的作用地址也发生了改变。这两个分别对应 output 和 CleanWebpackPlugin。
我们先改一下 output,如下:

    output: {
        path: path.resolve(__dirname, '../dist'),
        filename: "[name].js"
    },

删掉两个 dist,打包后如下:


4-2 Development 和 Production 模式的区分打包_第4张图片
image.png

说明输出地址已经正确了。我们在 dist 加一个文件 temp.js,重新打包,如下:


4-2 Development 和 Production 模式的区分打包_第5张图片
image.png

temp.js 消失了,说明 CleanWebpackPlugin 已经正确生效。这一点和视屏讲述不一样,因为 CleanWebpackPlugin 已经升级,会将作用目标定为 output.path,不需要再像旧版一样传入 root 来指定根目录。详见 https://github.com/johnagan/clean-webpack-plugin/issues/106。

参考

https://www.webpackjs.com/concepts/mode/
https://www.npmjs.com/package/clean-webpack-plugin

你可能感兴趣的:(4-2 Development 和 Production 模式的区分打包)