我们在上一篇一步步学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.js
、webpack.dev.js
、webpack.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 Shaking和Production说得让人头大 (并且脱发) , 说了挺多摇树和生产环境的东西但是让人无从下手,直到我看到 Miniication
小节的这一句:
然后查了相关资料后我才发现,其实在Webpack4之后的Webpack已经自带压缩和“摇树”了,只要将 webpack.prod.js
的 mode: '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. 项目地址
- webpack-stepbystep
To be continued...
系列文章
- 一步步学Webpack4(0)-- 实战起步
- 一步步学Webpack4(1)-- 开发环境搭建入门