里程二:全栈项目实践总结(前端工程化搭建)

2 阅读6分钟

一:什么是前端工程化

前端工程化,简单来说,就是将软件工程的原理、思想和方法系统地应用到前端开发的全过程中。 它并非指某一个具体的工具或技术,而是一整套解决方案,旨在通过标准化、模块化、自动化、规范化的手段,来解决前端开发日益复杂化所带来的各种问题。

二:核心目标

  • 提升开发效率:通过自动化工具、脚手架、组件复用等手段,减少重复性劳动,让开发者专注于业务逻辑的实现。
  • 保证代码质量:通过代码规范、静态检查、单元测试、代码审查等机制,尽早发现并预防错误,确保项目的健壮性和可维护性。
  • 优化用户体验:通过构建优化(如代码压缩、合并、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 
                 }
             }
        }
    }
}

生产环境

为什么生产环境需要不同的配置
  • 生产环境追求更小的代码体积、更快的加载速度、更好的运行性能和更强的缓存策略
  • 代码压缩与体积优化

开发环境下,代码需要保持可读性(保留空格、变量名、注释),方便断点调试。但在生产环境,必须进行压缩优化:

  1. JavaScript 压缩
  2. CSS 压缩
  3. Tree Shaking
  • 环境变量注入与功能分支

生产环境需要将 process.env.NODE_ENV 设置为 'production'。这不仅是一个标识,更关键的是:

  1. 许多库(如 React、Vue)会根据该变量自动剔除开发专用代码(如警告日志、热更新逻辑、开发者工具支持),从而减小体积并提升运行时性能。
  2. 业务代码中可以通过环境变量区分接口域名、日志级别等。
  • 资源持久化缓存策略

生产环境需要最大化利用浏览器缓存,这要求生成的文件名具有确定性且能随内容变化而更新

  1. 文件名哈希:使用 [contenthash] 为输出文件命名,只有文件内容改变时,哈希值才会变化,从而让浏览器准确识别是否需要重新下载。
  2. 分离第三方库:通过 splitChunks 将 node_modules 中的依赖单独打包成 vendor 文件。这类代码变更频率低,可以设置更长的缓存时间,避免因业务代码更新导致用户重复下载庞大的依赖库。
  • 性能边界与构建优化

开发环境为了启动速度快,会牺牲部分优化能力;生产环境则可以进行耗时的深度优化:

  1. 更严格的 Source Map:生产环境通常使用 hidden-source-map 或直接关闭,避免暴露源码,同时提升构建速度(开发环境常用 eval-cheap-module-source-map)。
  2. CSS 提取:开发环境常用 style-loader 将 CSS 通过 <style> 标签动态注入,便于热更新;生产环境则使用 MiniCssExtractPlugin 提取为独立的 .css 文件,利用浏览器的并行加载能力,并避免 FOUC(无样式内容闪烁)。
  3. 资源内联阈值:对小图片或字体文件,生产环境可配置转为 Base64 内联,减少 HTTP 请求数。
  • 运行时性能优化

生产环境关注代码在用户浏览器中的执行效率:

  1. 代码分割:通过 splitChunks 精细化拆分公共代码,避免重复打包,利用多路并行下载能力加快首屏加载。
  2. 作用域提升ModuleConcatenationPlugin 在 production 模式下默认开启,将多个模块合并到一个闭包中,减少函数包裹带来的运行时开销和内存占用。
  3. 移除调试代码:自动移除 console.logdebugger 等语句。

开发环境

为什么开发环境需要不同的配置
  • 因为开发环境与生产环境的核心目标截然相反
  • 如果直接使用生产环境的配置来开发,你会遇到构建慢、调试难、热更新失效等问题,严重影响开发效率。反之,如果用开发环境的配置去部署,线上用户会面临页面加载慢、体积过大、缓存混乱的糟糕体验
  • 构建速度与反馈效率

开发过程中,开发者希望“代码保存后能立刻看到效果”。

  1. 开发环境:追求极致的启动速度和热更新速度。使用 webpack-dev-server 配合 HotModuleReplacement,只编译修改的部分,秒级反馈。配置上会尽量跳过耗时的代码压缩和复杂的计算。
  • 调试体验与代码可读性

开发环境的核心任务是“定位 Bug”,而生产环境的核心任务是“保护源码”

  1. 必须生成高质量的 Source Map(如 eval-cheap-module-source-map),让你在浏览器开发者工具中看到未压缩、结构清晰、带有原始变量名的源代码,能精准定位到具体行数
  • 热更新机制

这是区分开发与生产最典型的功能差异。

  1. 利用 webpack-dev-server 在内存中维护文件,无需写入磁盘。通过 WebSocket 实现热更新(HMR) ,修改 CSS 或 React/Vue 组件时,页面无需刷新就能保留当前状态直接更新,这是开发效率的关键。
  2. 在应用运行过程中,替换、添加或删除模块,而无需刷新整个页面,同时保留当前的应用状态**