一、区分环境

目前所有的webpack配置信息都是放到一个配置文件中的:webpack.config.js

当配置越来越多时,这个文件会变得越来越不容易维护;

并且某些配置是在开发环境需要使用的,某些配置是在生成环境需要使用的

最好对配置进行划分,方便维护和管理

  • 方案一:编写两个不同的配置文件,开发和生成时,分别加载不同的配置文件即可
1
2
"build": "webpack --config ./config/webpack.prod.js",
"serve": "webpack serve --config ./config/webpack.dev.js",
  • 方式二:使用相同的一个入口配置文件,通过设置参数来区分它们
1
2
"build2": "webpack --config ./config/webpack.common.js --env production",
"serve2": "webpack serve --config ./config/webpack.common.js --env development"
1
2
3
4
5
6
7
8
9
module.exports = function(env) {
const isProduction = env.production;
process.env.NODE_ENV = isProduction ? "production": "development";

const config = isProduction ? prodConfig : devConfig;
const mergeConfig = merge(commonConfig, config);

return mergeConfig;
};

入口文件解析

之前编写入口文件的规则是这样的:./src/index.js,但是如果配置文件所在的位置变成了 config 目录,我们是否应该变成 ../src/index.js呢?

  • 这样编写,会发现是报错的,依然要写成 ./src/index.js;

  • 因为入口文件其实是和另一个属性时有关的 context;

  • context的作用是用于解析入口(entry point)和加载器(loader):

  • 官方说法:默认是当前路径(经过测试,默认应该是webpack的启动目录,也就是根目录)

  • 另外推荐在配置中传入一个值;

抽离文件

路径文件path.js

1
2
3
4
5
6
7
8
9
const path = require('path');
// node中的api
const appDir = process.cwd();
///Users/michstabe/Documents/Project/vs-project/Learn_Webpack/02_webpack进阶/02_webpack的环境分离
//项目根目录
console.log('-----------------------------------', process.cwd());
const resolveApp = (relativePath) => path.resolve(appDir, relativePath);
module.exports = resolveApp;

公共配置文件 webpack.common.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
const resolveApp = require('./paths');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const { merge } = require('webpack-merge');

const prodConfig = require('./webpack.prod');
const devConfig = require('./webpack.dev');

const commonConfig = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: resolveApp('./build'),
},
resolve: {
extensions: ['.wasm', '.mjs', '.js', '.json', '.jsx', '.ts', '.vue'],
alias: {
'@': resolveApp('./src'),
pages: resolveApp('./src/pages'),
},
},
module: {
rules: [
{
test: /\.jsx?$/i,
use: 'babel-loader',
},
{
test: /\.vue$/i,
use: 'vue-loader',
},
{
test: /\.css/i,
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
}),
new VueLoaderPlugin(),
],
};

//根据环境合并代码
module.exports = function(env) {
const isProduction = env.production;
//这里为babel.config.js配置下
process.env.NODE_ENV = isProduction ? 'production' : 'development';
const config = isProduction ? prodConfig : devConfig;
const mergeConfig = merge(commonConfig, config);
return mergeConfig;
};

开发环境webpack.dev.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const resolveApp = require('./paths');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const isProduction = false;

module.exports = {
mode: "development",
devServer: {
hot: true,
hotOnly: true,
compress: true,
contentBase: resolveApp("./why"),
watchContentBase: true,
proxy: {
"/why": {
target: "http://localhost:8888",
pathRewrite: {
"^/why": ""
},
secure: false,
changeOrigin: true
}
},
historyApiFallback: {
rewrites: [
{from: /abc/, to: "/index.html"}
]
}
},
plugins: [
// 开发环境
new ReactRefreshWebpackPlugin(),
]
}

生产环境webpack.prod.js

1
2
3
4
5
6
7
8
9
10
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const isProduction = true;

module.exports = {
mode: "production",
plugins: [
// 生成环境
new CleanWebpackPlugin({}),
]
}

注意babel.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const presets = [
["@babel/preset-env"],
["@babel/preset-react"],
];
const plugins = [];
const isProduction = process.env.NODE_ENV === "production";

// React HMR -> 模块的热替换 必然是在开发时才有效果
if (!isProduction) {
plugins.push(["react-refresh/babel"]);
} else {

}
module.exports = {
presets,
plugins
}