注:文章理解源于哲玄前端(全栈)的大前端全栈实践
什么是前端构建
.html、.js 及 .css 在浏览器的共同工作,可以渲染出可交互的丰富网页内容。然而,在实际开发中,我们编写的都是 .vue 或 .jsx 等浏览器无法识别的业务文件。而将业务文件解析为浏览器识别的文件,即为 前端构建 。
行业内前端构建工具包含 Webpack 、 Vite 、 Rollup 等,本文采用 Webpack5 进行实现。
前端构建核心步骤
而解析引擎的核心三个步骤分别是: 解析编译 、模块分包 、 压缩优化
- 解析编译在
Webpack5中主要通过以下方式实现:- 使用
config.entry配置入口文件。 - 使用
config.resolve配置模块解析的行为。 - 使用
config.loader配置各种类型文件的解析。 - 使用
config.plugins配置loader无法实现的功能。
- 使用
在多页面应用中,我们需要一个约定:所有入口文件应放在 pages 文件夹下,并以 entry.*.js 命名。通过结合 glob 库和 html-webpack-plugin 插件,可以自动生成入口配置和打包文件引入。
const glob = require("glob");
const path = require("path");
const HTMLWebpackPlugin = require("html-webpack-plugin");
const pageEntries = {};
const htmlWebpackPluginList = [];
// 获取 app/pages 目录下所有入口文件 (entry.xxx.js)
const entryList = path.resolve(process.cwd(), "./app/pages/**/entry.*.js");
glob.sync(entryList).forEach((file) => {
const entryName = path.basename(file, ".js");
// 构造 entry
pageEntries[entryName] = file;
// 构造最终渲染的页面文件
htmlWebpackPluginList.push(
// html-webpack-plugin 辅助注入打包后的 bundle 文件到 tpl 文件中
new HTMLWebpackPlugin({
// 产物 (最终模板) 输出路径
filename: path.resolve(
process.cwd(),
"./app/public/dist/",
`${entryName}.tpl`
),
// 指定使用的模板文件
template: path.resolve(process.cwd(), "./app/view/entry.tpl"),
// 要注入的代码块
chunks: [entryName],
})
);
});
- 模块分包和压缩优化:这些通常通过 config.optimization 配置实现。
开发环境与生产环境的配置
开发环境
开发环境的核心是启动热模块替换功能(HMR)和开发服务器。为深入理解开发服务器的工作原理,可以自行实现一个开发服务器,也可以使用 Webpack 的官方开发服务器。
以下是一个自定义开发服务器的实现示例:
// 本地开发启动 devServer
const express = require("express");
const path = require("path");
const webpack = require("webpack");
const consoler = require("consoler");
const devMiddleware = require("webpack-dev-middleware");
const hotMiddleware = require("webpack-hot-middleware");
// 从 webpack.dev.js 获取 webpack 配置 和devServer 配置
const { webpackConfig, DEV_SERVER_CONFIG } = require("./config/webpack.dev.js");
const app = express();
const compiler = webpack(webpackConfig);
// 静态文件目录
app.use(express.static(path.join(__dirname, "../public/dist")));
// 引入 devMiddleware 中间件 (监控文件改动)
app.use(
devMiddleware(compiler, {
// 落地文件
writeToDisk: (filePath) => filePath.endsWith(".tpl"),
// 资源路径
publicPath: webpackConfig.output.publicPath,
// headers 配置
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, PORT, PUT, DELETE, PATCH, OPTIONS",
"Access-Control-Allow-Headers":
"X-Request-With, content-type, Authorization",
},
stats: {
colors: true,
},
})
);
// 引入 hotMiddleware 中间件 (实现热更新通讯)
app.use(
hotMiddleware(compiler, {
path: `/${DEV_SERVER_CONFIG.HMR_PATH}`,
log: () => {},
})
);
consoler.info("请等待 webpack 初次构建完成提示...");
// 启动 devServer 服务
const port = DEV_SERVER_CONFIG.PORT;
app.listen(port, () => {
console.log(`app listening on port: ${port}`);
});
生产环境
在生产环境中,重点是提升打包效率和优化性能。例如:
- 压缩资源文件(如 JavaScript、CSS 和图片)。
- 提炼 CSS 资源为独立文件。
- 使用多进程打包以提高构建速度。
- 管理产物文件夹,确保干净和有序。
总结
通过前端构建,我们可以将复杂的业务文件解析为浏览器可识别的资源文件,从而实现现代化的前端开发流程。
例如,以下代码无法直接在浏览器中运行:
// index.js
import _ from "lodash";
import "./index.css";
这是因为现代前端开发依赖于构建工具来管理代码和资源,通过自动化流程生成最终的可执行文件。这正是前端工程化的意义所在。