3

我们在上一篇一步步学Webpack4(1)-- 开发环境搭建入门中使用Webpack完成了开发环境搭建的入门实战练习,这次我们来学习如何配置生产环境.

本章按照分离配置 - 减少打包体积 - 提供基本调试支持的步骤进行:

1. 分离配置

1.1 分离配置原因 & 分离方式

当前项目中已经有一个 webpack.config.js 配置文件并且运行良好,但是这个配置只适用于开发环境, 开发环境和生产环境的项目构建目标不一样.

开发环境的构建目标是具备方便问题追溯的source-map & 修改保存代码之后的实时加载或者热模块更新,一切为方便开发服务; 生产环境的构建目标更多是通过生成更小的打包文件、更轻的source map、最优化的资源利用,最终实现加载时间的优化.为了在开发环境与生产环境都达到最优的效果,官方文档建议为环境编写独立的配置.

1.2 执行分离:

虽然说开发环境与生产环境将会被分离,但是他们还是一部分配置可以通用的. 依据DRY原则(Don‘t repeat yourself), 我们将保留一份通用配置,并借助 webpack-merge 在特定环境配置中调用通用配置.

  • 步骤一、安装:webpack-merge

    npm install --save-dev webpack-merge
  • 步骤二、分离配置:

在项目根目录添加 webpack.commom.jswebpack.dev.jswebpack.prod.js 三个文件, 将webpack.config.js 拆解放入三个文件中,文件的完整代码如下所示:

webpack.commom.js

const path = require("path");
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: {
        app: './src/index.js'
    },
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')        
    },
    plugins: [
        new CleanWebpackPlugin(['dist']),
        new HtmlWebpackPlugin({
            inject: false,
            template: 'index.html',
            filename: 'index.html'
        })
    ],
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: [
                    'file-loader'
                ]
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/,
                use: [
                    'file-loader'
                ]
            },
            {
                test: /\.xml$/,
                use: [
                    'xml-loader'
                ]
            }
        ]
    }
}

webpack.dev.js

const merge = require('webpack-merge');
const common = require('./webpack.common');
const webpack = require('webpack');

module.exports = merge( common, {
    devtool: 'inline-source-map',
    devServer: {
        contentBase: './dist',
        hot: true
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin()
    ]
});

webpack.prod.js

const merge = require('webpack-merge');
const common = require('webpack.common.js');

module.exports = merge(common, {
    // 暂无配置
});
  • 步骤三、修改package.json 配置, 将脚本更新为运行对应环境的配置. 开始开发工作时,使用 npm start 运行webpack-dev-server; 开始打包准备发布时,运行 npm build 运行webpack.
{
  "name": "webpack-stepbystep",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "start": "webpack-dev-server --open --config webpack.dev.js",
    "build": "webpack --config webpack.prod.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "^0.1.19",
    "css-loader": "^1.0.0",
    "csv-loader": "^3.0.2",
    "file-loader": "^2.0.0",
    "html-webpack-plugin": "^3.2.0",
    "style-loader": "^0.23.1",
    "webpack": "^4.23.0",
    "webpack-cli": "^3.1.2",
    "webpack-dev-server": "^3.1.10",
    "webpack-merge": "^4.1.4",
    "xml-loader": "^1.2.1"
  },
  "dependencies": {
    "lodash": "^4.17.11"
  }
}

虽然项目配置架构与脚本已经完成,但是生产环境的配置还是空白的.生产环境配置的需要实现的基本功能有:

  • 减少打包文件体积
  • 支持生产环境下基本调试功能

2. 生产环境配置--减少打包文件体积

2.1 添加模块

想要知道完成生产配置之后的效果,需要源文件不变,通过对比修改生产配置文件之后的结果来验证. 于是我们先为 print.js 添加一个 ”不被调用“ 的方法模块,看看最终有没有方法可以更好地优化代码.添加模块之后的完整代码如下所示:

print.js

export default function printMe () {
    console.log('Updating print.js');
}

export function printTest () {
    console.log('Testing');
}

2.2 执行普通模式打包

为了接下来编译的时候代码不被压缩,所以暂时将webpack的配置改为 mode: 'development' , 完整配置如下所示:

webpack.prod.js

const merge = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
    mode: 'development'
});

在终端输入 npm run build,根据当前 webpack.prod.js 完成打包,结果如下所示:

图片描述

图片描述

虽然代码没有引用 printTest 模块,但是 mode: development 模式下的打包文件还是包含了该模块. 编译完的js打包文件 main.js 大小居然达到了575kb,引用了一个lodash库和一个printMe模块就半M了...

2.3 压缩打包代码

接着读官方文档Tree Shaking, 了解到一个叫做摇树(Tree Shaking)的概念,官方给出的理解方法是:

图片描述

意思就是把应用当成一棵树,那些真正被调用的源代码和库是长在树上的绿色叶子,那些没有被调用的库和代码就是已经枯死的叶子,你可以通过摇晃这颗树把树上的枯叶摇下来,也就是说应用里没用到的代码和库可以通过“摇树”移除.

回想一下上次打包的结果,统一文件的未被调用模块代码也被打包到打包的js文件中,那么也就意味着loadsh库也是这样被打包的,那么我们现在要做的事情就是实现“摇树“,移除Webpack构建的依赖关系图中无用的代码和库.

官方文档的Tree ShakingProduction说得让人头大 (并且脱发) , 说了挺多摇树和生产环境的东西但是让人无从下手,直到我看到 Miniication 小节的这一句:

图片描述

然后查了相关资料后我才发现,其实在Webpack4之后的Webpack已经自带压缩和“摇树”了,只要将 webpack.prod.jsmode: 'development' 改为 mode: 'production' ,完整代码如下所示:

webpack.prod.js

const merge = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
    mode: 'production'
});

打包完成之后的 main.js 只剩下77kb了,压缩了至少80%吧,并且里面已经移除了没有调用的模块,成功完成减少文件体积的需求:

图片描述

3. 生产环境配置--基本调试支持

官方建议在生产环境开启source map,理由是对于调试以及应用评分有帮助. 配置起来也是十分简单, 只需要加入一行 devtool: 'source-map'

webpack.prod.js

const merge = require('webpack-merge');
const common = require('./webpack.common.js');

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

在看看打包结果,发现打包后原来所有文件大小不变,但是多出了一个700kb的map文件,做哦那个应该就是生产环境中映射源代码吧,生产环境对于基本调试的支持也成功实现了:

图片描述

至此生产环境的基本配置已经全部完成

4. 项目地址

To be continued...

系列文章


Nodreame
155 声望32 粉丝

伪全栈|前端|前软粉