11 实战中的配置技巧
11.1 环境区分
11.1.1 为什么要区分环境
- 生产模式
- 需要:代码压缩,tree-shaking
- 不需要:详细的source-map,开启开发模式
- 开发模式
- 需要:详细的source-map,开启开发模式
- 不需要:代码压缩,代码混淆等
11.1.2 环境区分要点
- 区分要点
- 根据不同环境进行打包,一般在process.env设置
- 有时需要在js代码中获取环境,可以借助插件完成
11.1.3 不同环境不同配置文件webpack.xxxconfig.js
- 生产模式和开发模式相同的webpack配置放到webpack.baseconfig.js里
- 开发模式的webpack配置放到webpack.devconfig.js
- 生产模式的webpack配置放到webpack.proconfig.js
配置文件
// webpack.baseconfig.js
const htmlwebpack = require('html-webpack-plugin');
module.exports = {
entry: { // 多入口写法:入口名称+入口文件
app: ["./app.js"]
},
output: {
path: __dirname + '/dist', // 绝对路径,__dirname是node的全局变量,表示当前目录的绝对路径
filename: "[name].[chunkhash:4].bundle.js", //将name加到filename里,打包结果文件是app.bundle.js和app2.bundle.js,hash是对文件是否有改变的标志,:4表示截取前4位
publicPath: "www.xx.com"
},
// loader
module: {
rules: [
{
// 每个对象是一个loader
test: /\.js$/,
use: {
loader: 'babel-loader'
}
}
]
},
plugins: [
new htmlwebpack({
template: './index.html',// 写法1,指定html模板
filename: "index.html"
})
],
resolve: {
},
optimization: {
}
}
// webpack.devconfig.js
const base = require("./webpack.baseconfig.js");
const merge = require("webpack-merge").merge;
module.exports = merge(base, {
mode: "development",
devServer: {
port: 2000,
hot: true,//热更新
}
});
// webpack.proconfig.js
const base = require("./webpack.baseconfig.js");
const merge = require("webpack-merge").merge;
module.exports = merge(base, {
mode: "production"
});
打包命令
打包命令
{
"name": "webpackDemo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config ./webpack.proconfig.js",
"dev": "webpack-dev-server --config ./webpack.devconfig.js"
}
}
打包结果
打生产包
命令:npm run build
结果
本地项目启动
命令:npm run dev
前端项目按照不同的环境划分不同的配置,按照不同的脚本进行打包。
理解平时npm run build,npm run dev的本质。
11.1.4 环境判断 cross-env
通过node脚本指令指定环境变量。
1 安装cross-env
安装cross-env的包,命令npm install cross-env --save-dev
2 node脚本指令
脚本指令cross-env NODE_ENV=development
// package.json
{
"name": "webpackDemo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "cross-env NODE_ENV=production webpack --config ./webpack.proconfig.js",
"dev": "cross-env NODE_ENV=development webpack-dev-server --config ./webpack.devconfig.js"
},
}
配置文件里打印下NODE_ENV的值process.env.NODE_ENV
// webpack.baseconfig.js
const htmlwebpack = require('html-webpack-plugin');
console.log(process.env.NODE_ENV)
module.exports = {
...
}
3 打包
npm run build
4 应用
根据NODE_ENV的值判断当前环境,使用相应的loader.
// webpack.baseconfig.js
const htmlwebpack = require('html-webpack-plugin');
console.log(process.env.NODE_ENV)
module.exports = {
entry: { // 多入口写法:入口名称+入口文件
app: ["./app.js"]
},
output: {
path: __dirname + '/dist', // 绝对路径,__dirname是node的全局变量,表示当前目录的绝对路径
filename: "[name].[chunkhash:4].bundle.js", //将name加到filename里,打包结果文件是app.bundle.js和app2.bundle.js,hash是对文件是否有改变的标志,:4表示截取前4位
publicPath: "www.xx.com"
},
// loader
module: {
rules: [
{
// 每个对象是一个loader
test: /\.css$/,
use: [
process.env.NODE_ENV === 'production' ? minicss.loader : 'style-loader', 'css-loader'
]
}
]
},
}
此外,对于不好处理的配置,可以用变量存储根据环境变化的配置,然后配置到module.exports的对象中。此处不赘述。——编程式配置
11.1.5 webpack指令
通过webpack本身指令做环境判断的方案。
11.1.5.1 webpack --help
webpack --help
只要在命令行运行的工具,都有–help查看帮助的指令
执行结果如下。
如–config后可以跟一个config文件,还有–env<value…>
11.1.5.2 webpack --env
1 指定env
// package.json
{
"name": "webpackDemo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --config ./webpack.proconfig.js --env production",
}
}
2 config文件接收env
env作为方法入参传给config文件。
因此exports出去的是一个方法,入参为env,这个方法return一个merge方法。
// webpack.proconfig.js
const base = require("./webpack.baseconfig.js");
const merge = require("webpack-merge").merge;
// module.exports = merge(base, {
// mode: "production"
// });
module.exports = function (env) {
return merge(base(env), {
mode: "production"
})
}
实际用到env的是baseconfig,因此还需要作为入参传给base方法,即baseconfig export出来的也需要是一个方法。
当然baseconfig也是return一个对象。
const htmlwebpack = require('html-webpack-plugin');
console.log(process.env.NODE_ENV)
module.exports = function (env) {
console.log("🚀 ~ env:", env)
return {
entry: {
app: ["./app.js"]
},
output: {
path: __dirname + '/dist',
filename: "[name].[chunkhash:4].bundle.js",
publicPath: "www.xx.com"
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.css$/,
use: [
process.env.NODE_ENV === 'production' ? minicss.loader : 'style-loader', 'css-loader'
]
}
]
},
plugins: [
new htmlwebpack({
template: './index.html',
filename: "index.html"
})
]
}
}
// module.exports = {
// entry: { // 多入口写法:入口名称+入口文件
// app: ["./app.js"]
// },
// output: {
// path: __dirname + '/dist', // 绝对路径,__dirname是node的全局变量,表示当前目录的绝对路径
// filename: "[name].[chunkhash:4].bundle.js", //将name加到filename里,打包结果文件是app.bundle.js和app2.bundle.js,hash是对文件是否有改变的标志,:4表示截取前4位
// publicPath: "www.xx.com"
// },
// // loader
// module: {
// rules: [
// {
// // 每个对象是一个loader
// test: /\.js$/,
// use: {
// loader: 'babel-loader'
// }
// },
// {
// // 每个对象是一个loader
// test: /\.css$/,
// use: [
// process.env.NODE_ENV === 'production' ? minicss.loader : 'style-loader', 'css-loader'
// ]
// }
// ]
// },
// plugins: [
// new htmlwebpack({
// template: './index.html',// 写法1,指定html模板
// filename: "index.html"
// })
// ]
// }
3 打包
npm run build
"build": "webpack --config ./webpack.proconfig.js --env production",这里env也可以指定为其他内容
4 总结
webpack --env配置并不方便,需要修改config.js的export的方法。
11.1.6 webpack的DefinePlugin插件
给业务代码提供环境变量。
11.2 优化相关
11.2.1 优化webpack打包速度
- 打包分析
- 官方方案,–json输出打包结果分析json —— 不推荐
- webpack-bundle-analyzer
1 获取json的方式
1 配置命令
在package.json的scripts里配置指令--json>stats.json
"getjson": "cross-env NODE_ENV=production webpack --config ./webpack.proconfig.js --json>stats.json"
2 运行指令
npm run getjson
执行结果,生成一个stats.json文件。
3 json分析
如果https://webpack.js.org/analyse/网站可以加载,上传2生成的json文件,即可出现分析结果。
webpack官方文档: https://webpack.js.org/
json分析:https://webpack.js.org/analyse/
anyway,我们来看后面的方案。
2 webpack-bundle-analyzer
1 安装webpack-bundle-analyzer
npm install webpack-bundle-analyzer --save-dev
2 引入并注册插件
const webpackbundleanalyzer = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
module.exports = {
plugins: [
new webpackbundleanalyzer()
]
}
3 打包
npm run build
打包完成后自动打开一个网站。
通过下图可以看出打包出一个app.js,包括lodash.js文件。
4 结果分析
可以了解项目的引用关系,以及文件的大小。在大型项目里可以发现较大的模块,以优化打包的体积。
- start:原始大小
- Parsed:压缩大小
- Gzipped:压缩大小
3 提升打包速度
如何提升打包速度。
1 dll优化
- 提前打包不变的包(例如第三方库)
- 通知到正式打包
- dll处理过的不再处理
需要手动在index.html引入提前打的不变的包
p10 33:00
4 减小包体积
- 压缩程度
- webpack能做到的极致压缩,不只是代码上的物理压缩(压缩为一行代码),而是直接输出最终执行的代码。
- webpack还可以混淆代码,如语义化的变量用a b c代替,避免上线后代码被窃取。
- 打包
- 引入某个有100个方法的库,只用到f1方法,应该只将f1方法打包进来——最节省代码体积的做法。
引入了lodash,vue,axios这些包,一般不会用到这些包里的所有方法,只会用到一部分
那么可以将用到的方法进行打包,用不到的方法不会打包进来。
- 打包局限性
- 在类上定义的方法,会全部被打包。
- 如何不会全部被打包
- 单独定义方法然后export 单个方法(js文件里每个方法单独export)
- 然后用到f1方法就只引入f1方法