1.目录结构
2.配置所需依赖
npm i
"devDependencies": {
"@babel/core": "^7.8.4",
"@babel/preset-env": "^7.8.4",
"@types/node": "^14.0.11",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"compression-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^6.0.2",
"core-js": "^3.6.4",
"css-loader": "^3.5.3",
"file-loader": "^6.0.0",
"html-loader": "^1.1.0",
"html-webpack-plugin": "^4.3.0",
"mini-css-extract-plugin": "^0.9.0",
"postcss-loader": "^3.0.0",
"postcss-preset-env": "^6.7.0",
"regenerator-runtime": "^0.13.3",
"style-loader": "^1.2.1",
"url-loader": "^4.1.0",
"webpack": "^4.43.0",
"webpack-bundle-analyzer": "^3.8.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^4.2.2"
},
3.项目运行
4.项目打包
5.详细配置说明
(1)入口配置
由于我们是多页面应用程序,所以入口配置应是多个(我们项目中的所有页面都需要配置),所以我们需要一个多页面的配置如下pages.js
// 多页配置
module.exports = {
// 页面名称(对应 chunk 名)
index: {
js: "./src/pages/index", // 页面入口js
html: "./src/pages/index/index.html", // 页面使用的html模板
out: "index.html", // 输出目录中的页面文件名
},
about: {
js: "./src/pages/about",
html: "./src/pages/about/index.html",
out: "about.html",
},
//有多少写多少
};
接着在我们webpack.config.js基础配置中,循环以上内容配置,如下:
const pages = require("./pages"); // 加载多页配置
// 获取入口配置
function getEntry() {
const entry = {};
for (const key in pages) {
entry[key] = pages[key].js;
}
return entry;
}
(2)HtmlWebpackPlugin 配置
HtmlWebpackPlugin也是每个页面都需要配置的,所以我们也可以用循环一次性给配置了,如下:
function getHtmlPlugins() {
const plugins = [];
for (const key in pages) {
plugins.push(
new HtmlWebpackPlugin({
chunks: [key], // 使用的chunk
template: path.resolve(__dirname, pages[key].html),
filename: pages[key].out,
})
);
}
return plugins;
}
(3)webpack基本配置
module.exports = {
entry: getEntry(), // 获取入口配置
output: {
filename: "js/[name].[chunkhash:5].js", // js 输出到 dist/js/xxx
publicPath: "/", // 公用的公共路径 /
path: path.resolve(__dirname, "dist"), // 输出目录为 dist
},
resolve: {
//可以去别名
alias: {
"@": path.resolve(__dirname, "src"), // 别名 @ = src目录
_: __dirname, // 别名 _ = 工程根目录
},
},
stats: {
colors: true, // 打包时使用不同的颜色区分信息
modules: false, // 打包时不显示具体模块信息
entrypoints: false, // 打包时不显示入口模块信息
children: false, // 打包时不显示子模块信息
},
module: {
rules: [
{
// 各种图片、字体文件,均交给 url-loader 处理
test: /\.(png)|(gif)|(jpg)|(svg)|(bmp)|(eot)|(woff)|(ttf)$/i,
use: [
{
loader: "url-loader",
options: {
limit: 10 * 1024, //只要文件不超过 100*1024 字节,则使用base64编码,否则,交给file-loader进行处理
name: "static/[name].[hash:5].[ext]",
},
},
],
},
{
// 所有的 css 后需考虑引入less/less-loader
test: /\.(css)$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{ test: /\.js$/, use: "babel-loader" },
],
},
plugins: [
new CleanWebpackPlugin(), // 应用 清除输出目录 插件
new CopyPlugin({
// 应用 复制文件 插件
patterns: [
{
from: path.resolve(__dirname, "public"), // 将public目录中的所有文件
to: "./", // 复制到 输出目录 的根目录
},
],
}),
...getHtmlPlugins(), // 应用所有页面模板,输出到指定的目录
new MiniCssExtractPlugin({
// 打包 css 代码 到文件中
filename: "css/[name].css",
chunkFilename: "css/common.[hash:5].css" // 针对公共样式的文件名
}),
],
};
(4)开发环境配置
const merge = require("webpack-merge");
const baseConfig = require("./webpack.config.js");
// 从基本配置中合并
// 合并利用 webpack-merge 完成
const devConfig = {
mode: "development",
devtool: "source-map",
devServer: {
open: true,
port: 8080,
proxy: {
// 如果开发环境中有跨域问题,在这里配置代理
},
stats: "minimal",
}
};
//后面的配置覆盖前面的
module.exports = merge(baseConfig, devConfig);
(5)生产环境配置
const merge = require("webpack-merge");
const baseConfig = require("./webpack.config.js");
const WebpackBundleAnalyzer = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
const CmpressionWebpackPlugin = require("compression-webpack-plugin");
//从基本配置中合并
const prodConfig = {
mode: "production",
devtool: "none",
optimization: {
splitChunks: {
//分包配置
chunks: "all",
cacheGroups: {
styles: {
minSize: 0,
test: /\.css$/,
minChunks: 2,
},
},
},
},
plugins: [new WebpackBundleAnalyzer(), new CmpressionWebpackPlugin()],
};
module.exports = merge(baseConfig, prodConfig);