摘要:如今,它已经成为后端工程必不可少的基础工具之一。 除了广泛用于后端项目发布前的打包外,还起到开发过程中本地后端资源服务器模块的热更新、结合等作用。代码检测工具还可以实现对后端项目严格的校准审查。源代码。
如今,Webpack已经成为后端项目必不可少的基础工具之一。 除了广泛用于后端项目发布前的打包之外,它还充当开发过程中的本地后端资源服务器(assetsserver)和热模块替换(hot module replacement)。 )、APIProxy等角色,结合ESLint等代码检测工具,也可以实现对源代码的严格校准和检测。
前面说过,后端从开发到部署都离不开Webpack的参与,而Webpack只有一个默认的配置文件,即webpack.config.js。 所以问题就出现了,在开发期间和部署之前之间。 应该使用相同的 webpack 配置吗? 答案肯定是否定的。 由于 webpack.config.js 是一个 JS 文件,我们其实可以在该文件中编写 JavaScript 业务逻辑,并读取环境变量 NODE_ENV 来判断当前是在开发(dev)还是最终的生产环境(Production),但是很多朋友用来在根目录下的 webpack.config.js 中混合这三者的配置webpack配置常量,通过许多分散的 if...else 来“暂时”确定某个插件或某个 loader 的配置项,并不断减少loader 和插件,webpack.config.js 随着时间的推移变得越来越长,代码的可读性和可维护性也大大提高。
我想通过这篇文章来介绍一种使用3个JS文件来配置Webpack的方法。 它借鉴了很多开源项目的配置,也结合了我们开发过程中遇到的各种问题的解决方案。
本文提到的配置是基于Webpack2或以上版本的。 建议使用3.0及以上版本。
开发环境和生产环境的区别
您需要三个配置文件
webpack.base.config.js
在 base 文件里,你需要将开发环境和生产环境中通用的配置集中放在这里:
const CleanWebpackPlugin = require("clean-webpack-plugin");
const path = require("path");
const webpack = require("webpack");
// 配置常量
// 源代码的根目录(本地物理文件路径)
const SRC_PATH = path.resolve("./src");
// 打包后的资源根目录(本地物理文件路径)
const ASSETS_BUILD_PATH = path.resolve("./build");
// 资源根目录(可以是 CDN 上的绝对路径,或相对路径)
const ASSETS_PUBLIC_PATH = "/assets/";
module.exports = {
context: SRC_PATH, // 设置源代码的默认根路径
resolve: {
extensions: [".js", ".jsx"] // 同时支持 js 和 jsx
},
entry: {
// 注意 entry 中的路径都是相对于 SRC_PATH 的路径
vendor: "./vendor",
a: ["./entry-a"],
b: ["./entry-b"],
c: ["./entry-c"]
},
output: {
path: ASSETS_BUILD_PATH,
publicPath: ASSETS_PUBLIC_PATH,
filename: "./[name].js"
},
module: {
rules: [
{
enforce: "pre", // ESLint 优先级高于其他 JS 相关的 loader
test: /.jsx?$/,
exclude: /node_modules/,
loader: "eslint-loader"
},
{
test: /.jsx?$/,
exclude: /node_modules/,
// 建议把 babel 的运行时配置放在 .babelrc 里,从而与 eslint-loader 等共享配置
loader: "babel-loader"
},
{
test: /.(png|jpg|gif)$/,
use:
[
{
loader: "url-loader",
options:
{
limit: 8192,
name: "images/[name].[ext]"
}
}
]
},
{
test: /.woff(2)?(?v=[0-9].[0-9].[0-9])?$/,
use:
[
{
loader: "url-loader",
options:
{
limit: 8192,
mimetype: "application/font-woff",
name: "fonts/[name].[ext]"
}
}
]
},
{
test: /.(ttf|eot|svg)(?v=[0-9].[0-9].[0-9])?$/,
use:
[
{
loader: "file-loader",
options:
{
limit: 8192,
mimetype: "application/font-woff",
name: "fonts/[name].[ext]"
}
}
]
}
]
},
plugins: [
// 每次打包前,先清空原来目录中的内容
new CleanWebpackPlugin([ASSETS_BUILD_PATH], { verbose: false }),
// 启用 CommonChunkPlugin
new webpack.optimize.CommonsChunkPlugin({
names: "vendor",
minChunks: Infinity
})
]
};
webpack.dev.config.js
这是用于开发环境的 Webpack 配置,继承自 base:
const webpack = require("webpack");
// 读取同一目录下的 base config
const config = require("./webpack.base.config");
// 添加 webpack-dev-server 相关的配置项
config.devServer = {
contentBase: "./",
hot: true,
publicPath: "/assets/"
};
// 有关 Webpack 的 API 本地代理,另请参考 https://webpack.github.io/docs/webpack-dev-server.html#proxy
config.module.rules.push(
{
test: /.less$/,
use: [
"style-loader",
"css-loader",
"less-loader"
],
exclude: /node_modules/
}
);
// 真实场景中,React、jQuery 等优先走全站的 CDN,所以要放在 externals 中
config.externals = {
react: "React",
"react-dom": "ReactDOM"
};
// 添加 Sourcemap 支持
config.plugins.push(
new webpack.SourceMapDevToolPlugin({
filename: "[file].map",
exclude: ["vendor.js"] // vendor 通常不需要 sourcemap
})
);
// Hot module replacement
Object.keys(config.entry).forEach((key) => {
// 这里有一个私有的约定,如果 entry 是一个数组,则证明它需要被 hot module replace
if (Array.isArray(config.entry[key])) {
config.entry[key].unshift(
"webpack-dev-server/client?http://0.0.0.0:8080",
"webpack/hot/only-dev-server"
);
}
});
config.plugins.push(
new webpack.HotModuleReplacementPlugin()
);
module.exports = config;
webpack.config.js
这是用于生产环境的 webpack 配置,同样继承自 base:
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
// 读取同一目录下的 base config
const config = require("./webpack.base.config");
config.module.rules.push(
{
test: /.less$/,
use: ExtractTextPlugin.extract(
{
use: [
"css-loader",
"less-loader"
],
fallback: "style-loader"
}
),
exclude: /node_modules/
}
);
config.plugins.push(
// 官方文档推荐使用下面的插件确保 NODE_ENV
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "production")
}),
// 启动 minify
new webpack.LoaderOptionsPlugin({ minimize: true }),
// 抽取 CSS 文件
new ExtractTextPlugin({
filename: "[name].css",
allChunks: true,
ignoreOrder: true
})
);
module.exports = config;
现在您的项目文件夹中应该有三个 Webpack 配置文件,它们是:
webpack.base.config.js
webpack.dev.config.js
webpack.config.js
最后还需要在package.json中添加相应的配置:
{
...
"scripts": {
"build": "webpack --optimize-minimize",
"dev": "webpack-dev-server --config webpack.dev.config.js",
"start": "npm run dev" // 或添加你自己的 start 逻辑
},
...
}
和很多项目一样webpack配置常量,在开发环境中,需要使用 npmrundev 来启动,而在生产环境中,则需要使用 npmrunbuild 来发布。