浅谈前端工程化理解

浅谈前端工程化理解

前言

本文是个人学习实践过程中的记录及理解,如有错漏欢迎指出。

相关知识来源于哲玄前端(抖音ID:44622831736)大前端全栈实践课程

什么叫前端工程化?

一句话概括:把前端开发流程系统化、自动化、规范化,让代码像"产品"一样可以被构建、测试、部署和维护。 其中包括 规范、工具链、流程、体系

而这样的"工业流水线"为了解决这些痛点:

  • 代码无规范 → 难维护
  • 手工构建、发布 → 易出错、效率低
  • 页面越来越复杂 → 打包体积、性能成瓶颈
  • 团队协作缺乏统一 → 冲突频繁,复用差
  • 上线风险高 → 缺少测试、监控、回滚机制

工程化涉及的核心环节

  1. 开发阶段

    • 模块化 / 组件化

      • JS 模块化( ESMCommonJS
      • CSS 模块化( CSS Modules、预处理器)
      • 组件化(React/Vue/Svelte 等)
    • 语法增强

      • Babel/SWC 转译,TypeScript 静态类型
      • PostCSSLessSass
    • 代码规范

      • ESLintPrettierStylelint
      • Git hooks
      • Commit message 规范( commitlint, conventional commits
  2. 构建阶段

    • 打包构建工具WebpackViteRollup
    • 资源优化Tree ShakingCode Splitting、懒加载
    • 多环境配置dev/test/staging/prod
  3. 测试阶段

    • 单元测试JestVitestMocha
    • 集成测试CypressPlaywright
    • 端到端测试(E2E) :保证整体业务流程正确
  4. 发布 & 运维阶段

    • 持续集成 / 持续部署(CI/CD)GitHub ActionsGitLab CIJenkins
    • 自动化构建:push → 构建 → 测试 → 部署 → 通知
    • 灰度发布 / A/B 测试 / 版本回滚
    • CDN 缓存、前端监控(埋点、性能、错误上报)
  5. 协作 & 维护

    • Monorepo/ 多包管理TurborepoLerna
    • 文档体系Storybookdocusaurustypedoc
    • 脚手架 / 模板化Vue CLI 等)
    • 持续优化:性能指标、包体积分析、依赖治理

随着前端技术愈发成熟和工作团队的扩张,开发过程中我们会愈发注重模块化、组件化、类型约束、代码编程规范等,诞生出包括像 EggSalis 等奉行"约定优于配置" 的框架,以及课程中的 eplis-core ,这些工具能够帮助团队按照 一套统一的约定 开发应用,帮助开发团队和开发人员降低开发和维护成本。

这些涉及开发阶段的工具和操作应该是工作中经常遇到,是我们所熟悉的。这时应该意识到,不是仅仅"用 webpack 等打包工具就是工程化" ,其实我们一直参与到某个 理念 + 实践体系 中,其目标是 用工程化方法论去管理和优化前端开发的整个生命周期

我们接触最多的除开发阶段外,便是构建阶段,该产出与我们系统性能息息相关。

工程化构建

开发一个系统通常会涉及到大量的代码,为了提升开发效率,也为了方便团队管理维护,开发者会像上述按照一定的约定或规范进行开发。

而浏览器并不能完全直接识别这些文件,所以我们需要将其转换成浏览器(或者某个应用)能够识别、执行的文件,然后在浏览器中完成页面展示。

这时,借助打包工具,我们可以大大缩短人力成本,仅通过一条命令,便可让工具按照预设的配置一步到位输出预想产物。这将极大地提高打包效率。

那么这些工具做了什么呢?

它会按照我们提供的入口文件,读取与之相关的模块及依赖,按照我们提供的规则,规定何种类型文件使用何种 解析器 (某些解析器需借助额外的插件,如 vue-loader)解析编译,转译完成后打包输出,我们可以将其注入到某个页面中,便可获得浏览器能够识别、执行的页面。

不过这仅仅是冰山一角,现打包工具拥有成熟的插件机制,具备很高的可扩展性,可根据自己的业务场景定制配置,从而极大降低了应用的开发成本。

本次学习中使用的工具是 webpack,所以用 webpack 举例。

但请注意,什么工具不重要,只要能实现你想要的效果

比如:

  • 混用 SPA + MPA

    通常 单页面应用 (SPA) 通过插件按照指定模板生成一个 HTML 文件,将 chunk 全部注入该页面,打包出一个入口(通常是 index.html)。而页面内容的变化,通过 前端路由 + JS 动态渲染 来完成,用户点击链接时,不会重新请求整个页面,而是局部更新。

    优点

    • 前后端分离,前端控制路由与渲染,交互流畅。
    • 体验接近原生 App,切换页面不卡顿。
    • 资源可缓存,后续访问快。

    缺点

    • 首屏加载慢(要加载完整的 JS 框架、路由、业务逻辑)。-
    • SEO 不友好(因为页面内容由 JS 渲染)。
    • 复杂应用里,打包体积大,可能影响性能。

    多页面应用 (MPA) 则是每个页面对应一个 独立的 HTML 文件 ,请求新页面时,浏览器会重新加载 HTML、CSS、JS,页面之间 没有前端路由的强绑定,切换页面会整页刷新。

    优点

    • 首屏快(直接返回服务端渲染好的 HTML)。
    • SEO 友好(内容直接在 HTML 中,搜索引擎容易抓取)。
    • 适合业务隔离(不同页面可以独立构建、独立部署)。

    缺点

    • 页面切换慢,每次都要重新加载资源。
    • 前后端耦合度高,不便于前后端分离。
    • 公共资源(JS/CSS)可能重复加载。

    为了 平衡体验、性能、维护成本,我们可以适当结合两者,通过多入口打包,但每个入口内部又是一个 SPA。

    webpack 为例,我们提供多个打包入口配置,借助 HtmlWebpackPlugin 插件根据入口配置生成相应的 HTML 文件,其会将每个打包入口配置中文件所引用的资源分别注入到各自的 HTML 文件中,从而生成多个 系统入口。

    这时每个 SPA 内部用 前端路由(Vue Router、React Router) 管理页面切换,而系统入口通过 服务端路由 控制访问。

  • 热更新

    模块热替换(hot module replacement 简称 HMR)webpack 提供的功能之一。webpack 提供了 HMR 功能,需做的仅需更新 webpack-dev-server 的配置,便使用 webpack 内置的 HMR 插件。

    如果你在技术选型中使用了 webpack-dev-middleware 而没有使用 webpack-dev-server,请使用 webpack-hot-middleware 依赖包,以在你的自定义服务器或应用程序上启用 HMR。

    java 复制代码
    module.exports = {
        devServer: {
          static: './dist',
          hot: true,
        }
    }

    等多关于 webpack-dev-server 的配置详情可以查看这里

    其工作原理:

    • 监控到源文件发生改变
    • 重新构建打包到指定位置(一般为内存)
    • 通知应用程序资源发生改变,检查更新
    • 应用程序异步下载更新,并同步应用更新

    如果我们使用自定义服务器启用 HMR 会发现:

    • webpack-dev-middleware 负责监控源文件的改变,并按传入编译器重新构建。
    • webpack-hot-middleware 负责监测更新信息,并通知应用程序更新。
    • HotModuleReplacementPlugin 接收更信信息后,完成下载并应用更新。

优化

  • 分包

    项目在开发过程中,我们会复用部分代码以提升开发效率,但在打包时这部分代码会根据入口文件引用重复打包到多个入口的 chunk 中,这很明显不是我们希望的。

    这时便需要为打包工具添加分包策略,虽然像 webpack 具有默认分包策略,但默认情况下,它只会影响到按需加载的 chunks。

    我们想要获得的分包情况:

    • 体积较大、不常更改的独立第三方库及生态依赖,如 VuePinia ➡︎ Vue

    • 剩余的第三方库 ➡︎ vendor 包

    • 公共业务代码 ➡︎ common 包

    • 不符合上诉情况,根据入口配置正常打包

    如果 UI 库使用的是按需加载,建议单独分为一个包,避免因为加载的组件前后不一,第三方库的包 contenthash 等改变,导致缓存失效。

    这样分包的好处是可以使用浏览器可以并行下载的优势,并且不常改变的包可以被浏览器有效缓存起来。

    分包不是越多越好。首先服务器不支持http2.0的情况不支持多路复用,浏览器(谷歌)只能同时并发同域名的6个请求,零碎的 chunk 可能会增加 请求数(即使 HTTP/2/3 也有开销),所以请权衡利弊后再按需求制定分包策略。

  • 优化 loader 转译过程

    • 利用多线程加速耗时操作

      使用 happypackthread-loader 帮助开启线程池,将工作交给多个工作线程处理。

      thread-laoderwebpack 官方支持的,同时也支持缓存和 worker 复用,能缩短二次构建时间。

      happypack 已经停止维护,适合 webpack 旧版本使用。

      开启进程开销,小文件/轻量 loader 反而可能更慢。

      推荐仅在耗时的操作中使用,适合 CPU 密集型 loader。

      使用时也切勿开启过多工作线程将 CPU 占满,导致 I/O 操作切换频繁

    • 细分 loader 需要处理的范围,充分利用 includeexclude 等属性
  • 提取公共 css 样式并压缩体积

    • 使用 mini-css-extract-plugin 根据 CSS 文件中的样式使用情况,将公共部分提取到一起

      此插件不能与 loader 链中的 style-loader 一同使用!!!

      可按需求配合 splitChunks.cacheGroups 分包,可将提取到的 CSS 文件放到一个独立文件中。

      yaml 复制代码
      splitChunks: {
            cacheGroups: {
              styles: {
                type: "css/mini-extract", // type 用于匹配 .css 文件
                name: "styles",
                chunks: "all", 
                enforce: true, // 强制执行
              },
            },
          },
    • css-minimizer-webpack-plugin 将提取出来的 CSS 资源进行压缩

  • 压缩 js 文件体积

    Terseresbuild 皆是优秀的解析器/压缩器工具集。

    • EsbuildPlugin 拥有极致的性能,但压缩产物体积稍大一些。
    • TerserWebpackPlugin 拥有海量配置,兼容性强,可以进行非常激进的代码压缩和转换,往往能得到最小的产物体积

    这是一场"时间换空间"的经典权衡。EsbuildPlugin 用微不足道的空间(体积略增)换取了巨大的时间节省(构建速度飞跃),而 TerserWebpackPlugin 则愿意花费更多时间来打磨出体积最小的代码。 对于大多数现代项目而言,esbuild 带来的开发体验提升往往比那一点点的体积优化更有价值。

  • source-map 映射源根据不同环境选择不同策略

    选择一种 source map 风格来增强调试过程。不同的值会明显影响到构建(build)和重新构建(rebuild)的速度。

    arduino 复制代码
    // webpack 通过配置项 devtool 切换
    devtool: "[inline-|hidden-|eval-][cheap-[module-]]source-map"
    • eval- → 用 eval() 包裹模块,构建快。
    • inline- → source map 直接内联到 JS 中。
    • hidden- → 生成 map 文件,但不在 JS 里声明引用。
    • cheap- → 只映射到行,不包含列,不包含 loader 前的源码。
    • module- → 包含 loader 转换前的源码映射(更精确)。
  • 合理使用浏览器缓存,给产物文件添加 contenthashhashchunkHash 的设置
  • 打开构建缓存落盘,加快二次构建
  • 充分运用 tree-shaking (树摇)

以上便是此次学习的全部总结,当然这些只是构建知识的部分应用,更是前端工程化工作中的冰山一角,未来还有许多知识、理念需要了解与掌握,希望能抛砖引玉,如果有更多有意思的知识,欢迎分享。

相关推荐
豐儀麟阁贵6 分钟前
8.5在方法中抛出异常
java·开发语言·前端·算法
zengyuhan50336 分钟前
Windows BLE 开发指南(Rust windows-rs)
前端·rust
醉方休39 分钟前
Webpack loader 的执行机制
前端·webpack·rust
前端老宋Running1 小时前
一次从“卡顿地狱”到“丝般顺滑”的 React 搜索优化实战
前端·react.js·掘金日报
隔壁的大叔1 小时前
如何自己构建一个Markdown增量渲染器
前端·javascript
用户4445543654261 小时前
Android的自定义View
前端
WILLF1 小时前
HTML iframe 标签
前端·javascript
枫,为落叶1 小时前
Axios使用教程(一)
前端
小章鱼学前端1 小时前
2025 年最新 Fabric.js 实战:一个完整可上线的图片选区标注组件(含全部源码).
前端·vue.js
ohyeah1 小时前
JavaScript 词法作用域、作用域链与闭包:从代码看机制
前端·javascript