一:什么是前端工程化
前端工程化,简单来说,就是将软件工程的原理、思想和方法系统地应用到前端开发的全过程中。 它并非指某一个具体的工具或技术,而是一整套解决方案,旨在通过标准化、模块化、自动化、规范化的手段,来解决前端开发日益复杂化所带来的各种问题。
二:核心目标
- 提升开发效率:通过自动化工具、脚手架、组件复用等手段,减少重复性劳动,让开发者专注于业务逻辑的实现。
- 保证代码质量:通过代码规范、静态检查、单元测试、代码审查等机制,尽早发现并预防错误,确保项目的健壮性和可维护性。
- 优化用户体验:通过构建优化(如代码压缩、合并、Tree Shaking)、性能监控、按需加载等手段,提升应用的加载速度和运行流畅度。
- 降低协作成本:通过统一的开发流程、标准化的目录结构、清晰的模块划分,让团队成员能够高效协作,并降低新成员的上手难度。
三:设计
资源模块处理
- js ['babel-loader','@babel/preset-env','@babel/plugin-transform-runtime']
- vue ['vue-loader']
- css ['style-loader','css-loader','postcss-loader']
- less ['style-loader', 'css-loader', 'less-loader']
- 图片资源
- 字体资源
分包策略
分包是我们在构建代码中常见的一种优化策略,最主要的目的是将我们庞大的代码拆分成多个小块(chunk),按需加载或并行加载,以优化应用的加载性能、缓存效率和运行效率。
为什么要分包
- 减少初始加载时间:避免一次性加载所有代码,只加载当前页面必需的代码。
- 利用缓存:将不常变动的第三方库单独打包,利用浏览器缓存长期复用。
- 避免重复代码:多个入口共享的模块可以提取成公共 chunk,减少总体积。
分包/拆包实现
在 entry 配置中配置多个入口。单页应用(SPA):一个入口起点,多页应用(MPA):多个入口起点。
配置splitChunks,主要是将我们的入口文件大小拆分减少体积,我们可以将js文件拆分三种类型
- vendor: 第三方 lib 库 ,基本不会改动,除非依赖版本升级。
- common: 业务组件代码的公共部分抽取出来,改动较少。
- entry.{page}: 不用页面 entry 里的业务组件代码的差异部分,会经常改动。
- 目的: 把改动和引用频率不一样的 js 区分出来,以达到更好利用浏览器缓存的效果。
module.exports = {
enter: {
mian1:'入口一',
main2:'入口二'
},
optimization: {
runtimeChunk: true,
splitChunks: {
chunks: 'all',
maxAsyncRequests: 10,
maxInitialRequests: 10,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
priority: 0,
enforce: true,
reuseExistingChunk: true
},
common: {
name: 'common',
minChunks: 2,
minSize: 1,
priority: -10,
reuseExistingChunk: true
}
}
}
}
}
生产环境
为什么生产环境需要不同的配置
- 生产环境追求更小的代码体积、更快的加载速度、更好的运行性能和更强的缓存策略
- 代码压缩与体积优化
开发环境下,代码需要保持可读性(保留空格、变量名、注释),方便断点调试。但在生产环境,必须进行压缩优化:
- JavaScript 压缩
- CSS 压缩
- Tree Shaking
- 环境变量注入与功能分支
生产环境需要将
process.env.NODE_ENV设置为'production'。这不仅是一个标识,更关键的是:
- 许多库(如 React、Vue)会根据该变量自动剔除开发专用代码(如警告日志、热更新逻辑、开发者工具支持),从而减小体积并提升运行时性能。
- 业务代码中可以通过环境变量区分接口域名、日志级别等。
- 资源持久化缓存策略
生产环境需要最大化利用浏览器缓存,这要求生成的文件名具有确定性且能随内容变化而更新
- 文件名哈希:使用
[contenthash]为输出文件命名,只有文件内容改变时,哈希值才会变化,从而让浏览器准确识别是否需要重新下载。- 分离第三方库:通过
splitChunks将node_modules中的依赖单独打包成vendor文件。这类代码变更频率低,可以设置更长的缓存时间,避免因业务代码更新导致用户重复下载庞大的依赖库。
- 性能边界与构建优化
开发环境为了启动速度快,会牺牲部分优化能力;生产环境则可以进行耗时的深度优化:
- 更严格的 Source Map:生产环境通常使用
hidden-source-map或直接关闭,避免暴露源码,同时提升构建速度(开发环境常用eval-cheap-module-source-map)。- CSS 提取:开发环境常用
style-loader将 CSS 通过<style>标签动态注入,便于热更新;生产环境则使用MiniCssExtractPlugin提取为独立的.css文件,利用浏览器的并行加载能力,并避免 FOUC(无样式内容闪烁)。- 资源内联阈值:对小图片或字体文件,生产环境可配置转为 Base64 内联,减少 HTTP 请求数。
- 运行时性能优化
生产环境关注代码在用户浏览器中的执行效率:
- 代码分割:通过
splitChunks精细化拆分公共代码,避免重复打包,利用多路并行下载能力加快首屏加载。- 作用域提升:
ModuleConcatenationPlugin在 production 模式下默认开启,将多个模块合并到一个闭包中,减少函数包裹带来的运行时开销和内存占用。- 移除调试代码:自动移除
console.log、debugger等语句。
开发环境
为什么开发环境需要不同的配置
- 因为开发环境与生产环境的核心目标截然相反
- 如果直接使用生产环境的配置来开发,你会遇到构建慢、调试难、热更新失效等问题,严重影响开发效率。反之,如果用开发环境的配置去部署,线上用户会面临页面加载慢、体积过大、缓存混乱的糟糕体验
- 构建速度与反馈效率
开发过程中,开发者希望“代码保存后能立刻看到效果”。
- 开发环境:追求极致的启动速度和热更新速度。使用
webpack-dev-server配合HotModuleReplacement,只编译修改的部分,秒级反馈。配置上会尽量跳过耗时的代码压缩和复杂的计算。
- 调试体验与代码可读性
开发环境的核心任务是“定位 Bug”,而生产环境的核心任务是“保护源码”
- 必须生成高质量的 Source Map(如
eval-cheap-module-source-map),让你在浏览器开发者工具中看到未压缩、结构清晰、带有原始变量名的源代码,能精准定位到具体行数
- 热更新机制
这是区分开发与生产最典型的功能差异。
- 利用
webpack-dev-server在内存中维护文件,无需写入磁盘。通过 WebSocket 实现热更新(HMR) ,修改 CSS 或 React/Vue 组件时,页面无需刷新就能保留当前状态直接更新,这是开发效率的关键。- 在应用运行过程中,替换、添加或删除模块,而无需刷新整个页面,同时保留当前的应用状态**