从零搭建一个现代前端项目的那些事儿

Agent实验员
2025-06-14 17:12
阅读 606

去年年底,我接手了一个新项目——公司要开发一款面向中小企业的数据可视化工具。作为一个“从零开始”的项目,它没有遗留代码包袱,理论上可以自由选择技术栈,听起来像是个挺爽的活儿。但实际情况远比我想象中复杂得多。

初衷与背景:为什么要做这件事?

初衷与背景:为什么要做这件事?

在项目启动前,我们团队已经意识到,现有的几个产品项目因为技术栈老旧、构建方式混乱,导致后期维护成本越来越高。因此这次我们要彻底“重开一局”,从头设计一个现代化的前端项目结构,目标是:

  • 高可维护性,方便多人协作
  • 快速构建和部署流程
  • 支持跨浏览器兼容(IE11必须兼容)
  • 高性能,用户体验优先

说白了,我们想做一个“能跑五年都不怕过时”的项目结构。

面临的挑战:理想很丰满,现实很骨感

面临的挑战:理想很丰满,现实很骨感

刚开始做的时候,我以为这只是一个技术选型+搭架子的过程,但实际上我们遇到了不少问题:

  1. 技术栈该如何选?React 还是 Vue?ESLint + Prettier 怎么配置才不打架?
  2. 工程化怎么搞?Webpack/Vite 谁更适合初期?要不要用 monorepo?
  3. 团队协作规范难统一。每个开发习惯不同,Git 提交信息乱七八糟。
  4. UI 框架怎么接入?引入 Ant Design,结果发现样式加载太多,首屏性能被拉垮。
  5. IE11 兼容性问题层出不穷,Babel、Polyfill、PostCSS 都得一一处理。
  6. 构建过程太慢,本地开发服务器启动要等三四分钟,严重影响效率。

这些问题一个个堆上来的时候,我才意识到:所谓“从零开始”,其实是从一堆未知开始。

我们的技术方案:稳中求进,务实为先

我们的技术方案:稳中求进,务实为先

综合权衡之后,我们选择了以下技术栈:

  • 框架:React + React Hooks
  • 状态管理:Redux Toolkit(轻量且内置 immutable)
  • UI 框架:Ant Design + 可按需加载的 babel-plugin-import
  • 构建工具:Webpack + Babel + PostCSS
  • 组件库开发:Storybook
  • 代码规范:ESLint + Prettier + Husky + lint-staged
  • CI/CD:GitHub Actions + Docker 构建部署

技术细节拆解

1. 模块化设计先行

我们在 src/ 下建立了清晰的目录结构:

src/
│
├── assets/          # 静态资源
├── components/      # 公共组件
├── layouts/         # 页面布局
├── pages/           # 页面级组件
├── services/        # 接口封装
├── store/           # Redux 状态管理
├── utils/           # 工具函数
├── App.jsx          # 主入口
└── index.js         # ReactDOM.render

这种结构保证了模块之间耦合度低,便于扩展和测试。

2. 引入 Ant Design 并按需加载

最开始直接导入整个 antd,打包体积瞬间暴增。后来改用 babel-plugin-import 实现按需加载:

// 安装插件
npm install --save-dev babel-plugin-import

// 在 .babelrc 中添加
{
  "plugins": [
    ["import", { "libraryName": "antd", "style": "css" }]
  ]
}

这样引入组件时会自动加载对应样式,体积减少了近 60%。

3. Webpack 构建优化

为了让首次加载更快,我们做了以下几个优化点:

  • 使用 SplitChunksPlugin 拆分 Vendor 和业务代码
  • 通过 CSS Minimizer Plugin 压缩 CSS 文件
  • 图片压缩:url-loader + imagemin-webpack-plugin

还有一点特别重要的是,对 IE11 的 Polyfill 处理。一开始没加,上线后发现有些方法根本不可用。后来加上:

// 在 webpack.config.js entry 添加
entry: {
  app: ['@babel/polyfill', './src/index.js']
}

同时在 Babel config 加上预设:

{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "ie": "11"
      },
      "useBuiltIns": "usage",
      "corejs": 3
    }]
  ]
}

解决了兼容性问题。

4. 规范化提交与检查机制

为了避免一团乱麻的 Git 记录,我们引入了 Husky + lint-staged,在每次 commit 前跑 ESLint 和 Prettier:

npm install husky lint-staged eslint prettier --save-dev

然后在 package.json 里加了:

{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.js": [
      "eslint . --ext .js",
      "prettier --write src/**/*.js",
      "git add"
    ],
    "*.css": "prettier --write"
  }
}

从此再也不担心有人写错格式或者提交未修复的警告了。

开发中的几个大坑

1. Webpack 配置错误导致 HMR 失效

有一次本地开发环境的热更新一直失效。查了好久才发现是我在 Webpack Dev Server 的配置里误删了 hot: true,结果页面每次修改都刷新而不是局部热更新,白白浪费了不少时间。

2. Ant Design 图标不显示

项目刚上线时有个页面图标全白,最后发现是在 IE11 上 SVG 无法正确渲染。我们临时换成 iconfont 方案,虽然不够优雅但也算是兜住了。

3. Storybook 不支持按需加载

我们在用 Storybook 写组件文档时,发现 antd 按需加载的插件没有生效。最后手动加了个 .storybook/webpack.config.js,在里面重新引入了 babel-plugin-import 才解决。

这些小插曲让我深刻体会到一点:前端工程从来都不是“搭好框架就万事大吉”,每一个细节都要反复验证。

效果和收益:不止是一个脚手架

经过两个月的打磨,我们的“现代化前端基础架构”基本成型。效果如何呢?

  • 本地开发服务器冷启动速度控制在 15 秒以内
  • 首次访问加载时间从 8s 缩短到 2.5s(移动端实测)
  • 团队协作更加顺畅,代码风格统一
  • CI 流程自动化完成构建和部署,出错率显著降低
  • 有了清晰的模块划分,后续新增功能模块变得简单可控

更重要的是,我们现在回头看之前的项目,会发现很多“那时候要是知道就好了”的经验,都沉淀到了这个新架构中。

一些实战建议送给你

如果你也在打算从零搭建一个现代化的前端项目,这里是我踩过的坑总结出来的一些建议:

✅ 技术选型别贪多,以团队为主

很多人喜欢追“最流行”的技术,但其实最重要的是团队熟悉度。比如如果你团队里没人用 Vue 3 + Typescript,那不如选一个更稳妥的组合。毕竟项目是要交付的,不是拿来练手的。

✅ 结构清晰比命名规范更重要

再牛的命名规范也挡不住混乱的目录结构。建议一开始就规划好层级关系,哪怕是简单的文件夹分类,也能为将来的重构节省大量时间。

✅ 不要忽视性能优化和兼容性

尤其做企业级应用时,用户可能还在用 IE11。一定要尽早考虑兼容问题,不要等上线后再去补窟窿。

✅ 组件库+文档并行开发

如果你也在做一个组件库级别的项目,强烈建议一边开发一边写 Storybook 文档。不仅能快速看效果,还能形成可视化的组件库说明。

✅ 启动器不要太依赖脚手架

Create React App 很方便,但在真正复杂的项目里,迟早要“eject”。不如早点自己搭一个轻量版的 Webpack 配置,既能学到东西,又能灵活控制。


这篇文章写到这里,其实不只是分享一个技术方案,更像是记录一段真实的经历。我始终相信,一个好的前端架构,不是靠某个炫技的新特性堆出来的,而是靠日复一日的实践、一次次失败后的反思,慢慢打磨出来的。

希望这篇实战经验,能在你下一个项目启动时有所帮助。如果哪天你在开发过程中遇到类似的问题,欢迎留言交流,一起进步!


文末小彩蛋 🍭

“有时候我们会因为一个构建工具的报错花了一整天都没解决,第二天却发现只是少加了一个空格。但正是这些看似无聊的琐碎工作,才最终构成了一个稳定运行的系统。” —— 来自深夜调试现场的感悟

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝