ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

React前端工程化重构实战:从组件设计到构建优化全记录

React前端工程化重构实战:从组件设计到构建优化全记录

说个事儿。最近在推进一个内部代号叫“rea”的前端项目,名字没什么特殊含义,就是团队里随手敲的三个字母,但做着做着发现,这个项目把React应用从“能跑”到“跑得稳、跑得快、跑得明白”的整个工程化过程完整走了一遍。很多朋友问我这个代号是不是某个框架的缩写,其实不是,它就是一次前端工程化重构的项目代号,代号叫什么都行,关键是背后那一整套取舍和落地动作。

这篇文章就把“rea”项目从设计到落地的完整过程拆开讲,包括目录怎么规划、技术栈怎么选、组件怎么拆、状态怎么管、构建怎么优化,以及实际踩过的坑和排查思路。无论你是刚接触React的新人,还是正在折腾团队前端基建的开发者,应该都能从这里找到能直接抄作业的东西。

1. 拿到“rea”这个代号,我想解决什么问题

1.1 为什么是“rea”:一个代号背后的技术指向

先说清楚,项目代号“rea”不是“real”也不是“request”,它仅仅是为了在文档和分支命名里好写、好记。但既然代号叫“rea”,项目本身的定位就得跟React生态强相关——这其实是一个基于React的Web应用从零重构的工程化项目。

为什么需要重构?因为旧项目的状态很典型:业务逻辑全部堆在页面组件里,一个文件几百行甚至上千行,状态散落在各个组件内部,没有任何全局管理;接口请求直接写在生命周期函数里,错误处理靠alert弹窗;样式靠全局class命名,改一个地方崩三个页面。最要命的是,项目没有构建规范,开发环境和生产环境用同一套配置,打包出来的资源文件巨大无比。这类问题在小团队里太常见了。

所以“rea”项目的核心目标可以概括成三件事:第一,把组件体系重新梳理一遍,做到可复用、可维护;第二,把状态管理和接口层做结构化设计,让数据流向清晰;第三,建立一套完整的工程化体系,包括代码规范、构建优化、部署流程,让项目具备长期迭代的底气。

1.2 这个项目到底要干什么

“rea”不是一个业务系统,而是一个技术底座。它要承载的是团队未来所有中后台页面的开发,所以从一开始就不能只盯着某一个页面怎么实现,而是要思考一个通用的React应用应该具备哪些基础能力。

我列了一下“rea”需要覆盖的范围:

  • 脚手架与项目初始化:一套开箱即用的目录结构和配置模板。
  • 组件体系:包含基础UI组件、业务组件和页面组件的分层设计。
  • 状态管理:全局状态与局部状态的边界划分。
  • 路由与权限:基于角色的路由守卫和页面级权限控制。
  • 数据请求层:统一封装请求实例、拦截器、错误处理和缓存策略。
  • 构建优化:开发体验与生产性能的平衡。
  • 代码质量:ESLint、Prettier、TypeScript 检查、单元测试。
  • 部署发布:多环境配置、构建产物分析、持续集成。

这些能力每一项拆开都不复杂,但合在一起就成了一个完整的前端工程体系。这篇文章主要讲我在“rea”里实际怎么设计、怎么选型、怎么落地,以及为什么做出这些选择。后面所有内容都基于真实操作记录,而不是泛泛而谈的架构图。

2. 整体设计:搭一个什么样的前端工程骨架

2.1 目录结构:怎么摊开才不打架

项目一开始,我就花了不少时间在目录规划上。很多人觉得目录结构是小事,但一个团队十几个人同时在一个仓库里提交代码,目录乱掉的后果就是组件互相引入、样式互相覆盖、工具函数重复写了三个版本。

“rea”最终采用的是按模块划分的目录结构,核心思路是“功能内聚、跨模块共享”。

src/ api/ # 接口请求层 assets/ # 静态资源 components/ # 公共组件 common/ # 基础 UI 组件 business/ # 业务组件 config/ # 全局配置 hooks/ # 自定义 Hook layouts/ # 布局组件 pages/ # 页面级组件 dashboard/ user/ report/ router/ # 路由配置 store/ # 全局状态 styles/ # 全局样式 types/ # 全局类型定义 utils/ # 工具函数

这个结构的关键在于pages目录下按照业务模块分组,每个模块内部再按“页面—组件—状态—样式”组织。比如pages/user目录下可以有UserList.tsx、UserEdit.tsx、components/子目录、useUserStore.ts等。

把状态文件放在页面模块内部,而不是堆到全局store里面,这是我特别想强调的一点。很多项目把所有的状态都放进全局Store,导致Store越来越臃肿,全局命名空间冲突,调试的时候一个状态改了不知道是哪里改的。“rea”的约定是:只有真正跨页面共享的全局态才放store,页面内部的UI态直接写在组件里,页面间偶尔要共享的数据就放在页面模块自己的store子文件里,用的时候再挂到全局。

这个约定看起来简单,但执行起来需要对团队成员做约束。我在项目里专门写了一份VSCode工作区配置,把目录规范做成了编辑器提示,谁新建文件放错目录会立刻看到警告。这个思路后来证明非常有效,目录规范不再是一纸文档,而是真正落到了每天的开发动作里。

2.2 技术选型:React生态里怎么挑

“rea”的技术选型没有追求“最新最热”,而是以稳为主,同时兼顾未来三五年的演进空间。

框架层用的React 18,函数组件加Hooks,这个没什么好说的,React生态已经全面转向Hooks。路由用的React Router 6,状态管理用的Zustand,不是Redux Toolkit。

有人会问,为什么不选Redux Toolkit?Redux在团队里有熟悉的人、生态完善、调试工具强大,但它的样板代码还是偏多,对“rea”这个规模的项目来说有点重。Zustand的语法更轻,直接用Hooks风格写Store,团队上手成本低,而且它对TypeScript的支持很舒服。我实测下来,一个中型项目中后台页面,用Zustand写的Store代码量大概是Redux Toolkit的一半左右。

请求层为了统一和可控,直接用原生fetch做基础封装,没有引入axios。axios确实在拦截器、取消请求这些能力上更顺手,但其原理和本质与fetch封装差别不大。对“rea”来说,我们只需要统一的baseURL配置、请求头注入、鉴权失效处理和错误提示拦截,这些用fetch封装完全够用。而且不引入额外依赖,构建体积也小一些。

UI层面没有引入重型组件库,而是基于一套轻量的设计规范自己写常用组件。这个选择有得有失。好处是完全可控,不担心组件库升级带来破坏性变更;坏处是工作量大一点,所以“rea”的组件库只覆盖了表格、表单、弹窗、通知、分页这些高频场景,低频的复杂组件还是允许业务自己实现。

2.3 规范约束:团队协作的底线

“rea”项目从第一天起就接入了ESLint和Prettier,并且规则不是默认配置,而是做了统一约定。

TypeScript严格模式是必须的,strict为true。团队里有人嫌严格模式麻烦,觉得any用起来省事,遇到类型报错就as any一把梭。但“rea”的规矩是:禁止在业务代码里出现显式any,实在写不出来类型的地方需要写注释说明原因。有了这条硬性约束,代码里的隐性Bug少了很多。

代码风格统一用Prettier,配置了单引号、无分号、缩进2格。这个配置在团队内部讨论过,有人习惯分号,有人不习惯,但既然想统一,就找一个相对主流的风格固化下来。配置好后接入了husky的pre-commit钩子,提交代码前自动格式化加lint检查,不合格的代码根本进不了仓库。这一步是真的能治“风格不统一”的病。

除了代码风格,还有一个容易被忽略的规范是git分支规范和提交信息规范。main分支保护,只允许通过PR合并;提交流程统一走feat、fix、chore的前缀;每个PR必须关联需求单号。这些看着像流程上的事,但对项目长期健康的帮助非常大。没有这套约束,项目代码很快会回到“谁都能改、改了不知道影响谁”的混沌状态。

3. 核心细节解析与实操要点

3.1 组件设计:从页面到零件的拆分逻辑

“rea”里组件拆分的粒度是我一直在琢磨的事。拆太细,组件数量爆炸,一层套一层,调用链路极长;拆太粗,组件内部又要处理太多分支逻辑,和没拆一样。最终我定了一个“三层组件”模型。

  • 基础组件(common):按钮、输入框、弹窗、表格这类纯展示型组件,只负责外观和基本交互,不承载任何业务逻辑。
  • 业务组件(business):由基础组件组合而成,封装某一块业务语义,比如“用户选择器”“组织树选择”“审批状态标签”。业务组件内部可以调用接口、处理数据,但不感知页面布局。
  • 页面组件(pages):负责页面布局、数据组装、交互编排,由多个业务组件和基础组件拼接而成。

这个模型的约束重点是:页面组件不应该直接使用基础组件,业务组件不应该直接写接口调用之外的东西。举一个实际例子:一个“用户管理页面”的表格,页面组件负责从Store拿用户列表数据,然后传给“用户表格”这个业务组件渲染;列配置、操作按钮的渲染逻辑都在业务组件内部。“用户表格”组件可以被“用户分配”页面和“用户管理”页面同时复用,只是数据来源不同。

这个设计带来的直接好处是,当交互细节变化时,只需要改动对应的业务组件,而不会波及页面组件。比如某个表格的性别字段从“男/女”改成了自定义字典,改动就发生在业务组件的单元格渲染函数里,页面层完全不需要动。这种隔离效果在需求频繁变动的业务场景里尤其宝贵。

组件设计里还有一个细节是Props的设计。我给自己定了一个原则:组件的Props要尽量内聚,不要散开传一堆无关的字段。比如表格组件接收的columns和dataSource,最好包装成一个带语义的对象,而不是把dataSource.loading、dataSource.list、dataSource.page分开传。这样上层数据结构变化时,只需要在组件内部做兼容,调用方不用跟着改。这个原则说起来容易,做起来很容易被忽略,尤其是在时间紧的时候,人都倾向于“先写出来再说”。

3.2 状态管理:什么时候用本地状态什么时候用全局

状态管理是React项目里最容易走极端的地方。新手倾向于什么东西都放组件useState,导致兄弟组件通信要靠props一层层传;老手容易什么东西都塞全局Store,最后全局状态变成一团乱麻。

“rea”的约定是:状态按生命周期划分,全局Store只放跨页面、跨组件树、且需要在持久化后恢复的状态。

具体划分如下:

状态类型存放位置典型场景
组件内部UI状态组件内useState弹窗开关、表单值、折叠面板
页面级共享状态页面模块内的Store列表筛选条件、表格分页
全局跨页面状态全局Store用户信息、权限点、系统字典
服务端状态请求层管理,不放入Store接口拉取的业务数据

这里有个反直觉的决策:接口拉取的数据,比如用户列表、订单明细,默认不放进状态管理Store。“rea”的请求层会做缓存和失效控制,页面组件直接通过自定义Hook拿数据,数据变化由Hook自己触发刷新,而不是把所有数据都挂到全局Store里。

这个设计来自一个实际痛点:之前项目里某个页面一打开,就把接口数据塞进Redux,切到别的页面再切回来,数据还在,但已经过期了。每次都得在不同生命周期里处理数据刷新,逻辑极其繁琐。后来改成自定义Hook管理服务端状态,页面进入时自动请求,页面离开时自动销毁缓存,状态天然跟页面生命周期绑定,大大简化了代码。

给个简单示例,这个Hook专门处理服务端数据请求:

// hooks/useFetchData.ts import { useCallback, useEffect, useState } from 'react' interface UseFetchDataOptions<T> { fetcher: () => Promise<T> initialData?: T deps?: React.DependencyList onError?: (err: unknown) => void } export function useFetchData<T>({ fetcher, initialData, deps = [], onError, }: UseFetchDataOptions<T>) { const [data, setData] = useState<T | undefined>(initialData) const [loading, setLoading] = useState(false) const [error, setError] = useState<unknown>(null) const refresh = useCallback(async () => { setLoading(true) setError(null) try { const result = await fetcher() setData(result) } catch (err) { setError(err) onError?.(err) } finally { setLoading(false) } }, deps) useEffect(() => { refresh() }, [refresh]) return { data, loading, error, refresh } }

这个Hook在项目里被广泛使用,遇到需要再次请求的场景,直接调用refresh,数据就会刷新。对比之前每个页面都要自己写useEffect请求数据,代码量少了一大截,而且由于统一了加载和错误处理,交互体验也标准了。

3.3 路由与权限:入口守卫怎么做才稳

路由权限是“rea”项目里比较关键的一块。中后台系统基本都需要做登录态校验和页面级权限控制,如果这个写得不稳,用户可以直接通过URL绕过权限检查,这是个安全事故级别的Bug。

“rea”的路由设计分两层:静态路由和动态路由。

静态路由包括登录页、404页、500页这类不需要权限判断的页面。动态路由则是根据当前用户的权限点,从路由配置表中过滤出可访问的路由,再动态挂载到React Router里。

核心逻辑是路由守卫组件,它包裹在所有需要鉴权的路由外层:

// router/AuthGuard.tsx import { Navigate, Outlet, useLocation } from 'react-router-dom' import { useUserStore } from '@/store/user' const AuthGuard = () => { const token = useUserStore((state) => state.token) const location = useLocation() if (!token) { return <Navigate to="/login" state={{ from: location.pathname }} replace /> } // 校验当前用户是否对该路径有权限 const hasPermission = checkPermission(location.pathname) if (!hasPermission) { return <Navigate to="/403" replace /> } return <Outlet /> } export default AuthGuard

守卫组件的核心原则是:凡是没有token的一律跳到登录页,登录后URL里带的state.from会被保留,登录完成后可以跳回原页面。这个体验细节很多系统没做,用户被强制踢出登录后,重新登录还得手动找刚才的页面,很烦。

对于页面级权限,我在路由配置里维护了permission字段,组件通过当前用户的权限点集合来判断是否为null,null就直接不渲染该路由。特别注意一点,路由权限只是前端控制,真正的数据权限必须在后端接口层面校验,前端只能作为体验层面的拦截。

有一个容易踩的坑:动态路由如果是在登录后才根据用户权限生成的,一旦用户权限发生变化(比如角色被调整),路由表不会自动刷新,需要主动重新拉取权限并重建路由。这就得在权限Store里设计一个refreshRoutes的action,挂在登录态校验之后。不处理的话,就会出现用户权限明明变了,但前端还能访问旧页面的问题。

4. 实操过程:从零把“rea”跑起来

4.1 初始化与依赖安装

“rea”项目并不是用create-react-app初始化的,而是使用Vite搭建。在当下的React项目里,Vite在开发启动速度和热更新体验上有明显优势,对一个需要高频迭代的业务项目来说,开发体验直接影响效率。

初始化命令如下:

npm create vite@latest rea -- --template react-ts

这一步会生成一个带React和TypeScript的最小模板,接下来安装项目需要的核心依赖:

npm install react-router-dom zustand npm install -D eslint prettier husky lint-staged typescript @types/react @types/react-dom

依赖装好后,我要做的第一件事不是写业务,而是把这个模板里的默认文件全部清理干净,只保留最基本的入口和tsconfig,然后把目录结构按照前面说的方式建好。这个“清理”步骤很多人会跳过,但它特别重要——模板自带的示例组件和样式如果不删,过几天就会被新代码覆盖,文件里残留的废代码会干扰后续维护。

需要注意一个点:Vite模板默认生成的tsconfig.json可能没有开启严格模式,需要手动加上"strict": true。如果没有开启,TypeScript的保护效果会大打折扣。我在初始化时就把这个配好,后面团队写代码遇到类型错误会尽早暴露。

4.2 配置工程化基础设施

工程化基础设施包含三件套:ESLint、Prettier、husky。

ESLint配置我选择eslint-config-airbnb作为基底,再叠加React和TypeScript的规则。但必须说明,airbnb的规则对中后台业务项目来说有些过于严格,比如react/require-default-props在函数组件里就很多余,所以我直接关掉了几个针对小项目没必要的规则。不要为了规则而规则,lint的最终目的是减少Bug、统一风格,不是让提交代码变得痛苦。

ESLint扁平化配置(eslint.config.js)示例如下:

import js from '@eslint/js' import tseslint from 'typescript-eslint' import reactHooks from 'eslint-plugin-react-hooks' import reactRefresh from 'eslint-plugin-react-refresh' export default tseslint.config( { ignores: ['dist'] }, { files: ['**/*.{ts,tsx}'], extends: [ js.configs.recommended, ...tseslint.configs.recommended, reactHooks.configs['recommended-latest'], ], plugins: { 'react-refresh': reactRefresh, }, rules: { '@typescript-eslint/no-explicit-any': 'error', '@typescript-eslint/explicit-module-boundary-types': 'off', 'react-hooks/exhaustive-deps': 'error', }, }, )

这里要提醒,ESLint v9的口径和v8有差异,配置写法不太一样。我在“rea”用的Vite模板自带ESLint v9,所以走的是扁平化配置,如果网友还在用旧的eslintrc文件,迁移时需要注意这个差异,不然会报配置格式不兼容的错误。

husky的设置也顺便说一下:

npx husky init

这条命令会在项目根目录生成.husky/pre-commit文件,然后在里面加入lint-staged的调用:

npx lint-staged

同时package.json里配置lint-staged:

{ "lint-staged": { "*.{ts,tsx}": ["eslint --fix", "prettier --write"] } }

这样每次提交,改动过的文件会自动做格式化和lint修复,不满足要求的文件提交不了。这个机制可以避免“我本地没问题,提交之后CI挂了”的尴尬局面。

4.3 构建优化与性能基线

构建优化这一块,“rea”没有做特别夸张的微优化,只做了几件收益明显的事情。

第一是路由懒加载。把页面组件改成通过lazy动态导入,这样打包时Vite自动代码分割,首屏只加载当前路由对应的页面脚本,而不是一次性把几百个页面全拉下来。示例:

import { lazy } from 'react' const Dashboard = lazy(() => import('@/pages/dashboard')) const UserList = lazy(() => import('@/pages/user/UserList'))

第二是配置构建分析,确认每一个体积偏大的依赖。我用了打包产物分析工具,发现打包出来的vendor里,图表库占了非常大的比例。经过沟通,业务方同意把某张低频使用的图表改成按需引入,首屏脚本直接小了约30%。构建优化这种事,必须对症下药,不分析就乱拆依赖反而会造成没必要的返工。

第三是资源压缩和缓存策略。Vite默认在生产环境做CDN和文件名hash处理,我额外开启了gzip压缩。在代理层或者服务器加了对应配置后,静态资源体积还能再降一些。这步操作本身不算复杂,难的是要确保服务器端配置同步,光改前端没用。

“rea”的性能基线定了三条,每次发版前用轻量脚本检查,不合格就拦截发布:

  • 首屏请求总大小(gzip后)不超过限定值。
  • 首屏加载耗时不超过限定值。
  • 页面切换的平均耗时不超过限定值。

这些基线会随着业务增长动态调整,但有了基线之后,谁都不敢再随便往首屏里塞大体积依赖了。

5. 常见问题与排查技巧实录

5.1 问得最多的5个问题

我在“rea”的开发过程中,被问到最多的几个问题,基本每个React工程化项目都会遇到,这里整理成表格方便速查。

问题表现可能原因排查思路
页面刷新后404前端路由刷新时找不到对应静态文件服务器需配置单页应用回退,将所有路由重定向到index.html
状态更新了但页面不刷新Store或组件层级里有多份状态副本检查是否在组件中拷贝了Store数据,中断了响应式链接
构建产物巨大大体积依赖被全部打包,未做按需引入或代码分割用构建分析工具定位产物,优先处理体积最大的模块
登录后没有跳回原页面登录逻辑未记录来源路径在登录页读取路由state.from,登录成功后用replace跳转
路由权限变化不生效动态路由表未随权限刷新权限变更后主动重建路由表,而不是等待页面reload

这五个问题里,第一个“刷新404”是部署新手最容易碰到的。开发模式下一切正常,一部署到服务器就坏,因为开发服务器本身会做SPA回退,但很多静态服务器不会。解决方式是在服务器配置里加上try_files的规则,把所有请求都try到index.html,让前端路由托管页面。nginx的配置写法如下:

location / { try_files $uri $uri/ /index.html; }

这个配置虽然简单,但值一顿饭钱,凡是部署过React应用的人应该都会心一笑。

5.2 我踩过的几个坑

“rea”项目里我踩过不少坑,挑几个印象最深的分享。

第一个坑是依赖版本冲突。某次升级一个UI相关的库,升级完发现另一个库的编译报错了,仔细看是对手版本要求的React版本不一致。这类问题在大型依赖树上特别常见。我的建议是,不要随便偷懒用npm install xxx@latest,而是要明确要看版本的兼容范围,升级时最好先查一下对方库的peerDependencies。现在npm和pnpm的lock机制在一定程度上能兜底,但如果真遇到兼容问题,排查起来还是很花时间的。

第二个坑是构建时全局变量替换。我们生产环境需要注入一个接口网关地址,这个地址在构建时才能确定,不能硬编码在代码里。Vite在define里可以做这个事,但千万要注意,define里配置的值会被直接替换进代码,如果值里带了引号或者特殊字符,构建时会报语法错误。我第一次配置时没注意那引号问题,打包环境直接崩了,排查半天才发现是这细节导致的。

第三个坑关于状态管理的“幽灵状态”。我们把服务端缓存设计在自定义Hook里,正常页面切换时没问题,但有一次某个页面在关闭时没有清掉Hook里的定时器,导致切到别的页面后接口还在持续请求,拖垮了整个后端。从那以后,“rea”里所有涉及定时器、订阅的操作,都必须写在useEffect的清理函数里。这个教训不是新知识,但真的很容易被忽略,尤其在一个大型团队里,写组件的人换了,清理逻辑可能就漏了。

第四个坑是关于Vite的缓存问题。开发环境下改了环境变量或者公共配置后,页面偶尔没有反应,重启开发服务器有时候也没用。后来发现是node_modules里的缓存目录被污染了,直接删除node_modules/.vite目录再重启就正常了。这种问题其实也很常见,如果遇到热更新不生效、页面上遍布旧代码的情况,优先考虑这个。

5.3 给新手的几个独家建议

基于“rea”的开发经验,我给出几个实操建议,这些建议是我自己边做边总结出来的,不一定会出现在官方文档里。

第一,组件库的探索阶段不要急着全部组件化。很多人一上来就把所有视觉元素抽成组件,结果一改设计稿就要改一大片组件。建议是先写业务页面,运行一段时间后发现某些真的被反复复用的部分,再抽成组件。过早抽象比延迟抽象更麻烦。

第二,请求层一定要统一处理错误。不要在业务代码里到处写try-catch,这会大幅提升代码的噪音。统一在请求拦截器里判断code,非200就弹提示、打日志,业务代码只需要关心成功的数据分支。这样代码不仅干净了,出错时排查也更方便。

第三,定时任务、轮询、长连接这类逻辑一定要集中管理,不要散落在各个组件里。我来回重构了两次才意识到,最好的做法是做一个通用的轮询Hook,统一配置间隔、销毁逻辑和错误恢复策略。如果每个页面都自己写一套轮询,一旦用户切页,定时器没清理,后患无穷。

第四,提交代码前先用构建命令跑一遍。有时候lint过了、类型检查过了,但真正的生产构建会失败。尤其是修改了环境变量、alias路径、依赖版本之后,生产构建是最容易露馅的。不是每次都要跑完整构建,但涉及配置和依赖的变更,必须跑。

6. 后续还能怎么扩展

“rea”现在已经在团队内部稳定跑了一段时间,但我觉得它还能继续往下深挖。

一个方向是接入微前端。团队业务会越来越多,如果所有系统都往一个仓库里堆,互相之间的依赖和应用隔离会变得非常麻烦。后续可以把“rea”作为其中一个子应用的载体,再把公共依赖抽出来做共享。这个方向的技术挑战不小,但收益也大,值得提前考虑。

另一个方向是优化开发调试体验。现在调试接口靠浏览器控制台看请求日志,虽然能用,但效率不高。加一组轻量级的内网调试面板,可以看到用户权限、请求记录、状态变更历史,排查线上问题会快很多。这种能力不需要特别复杂,关键是做出来能真正用得上。

还有一块可以在构建发布流程上继续深化。现在用的是最简单的构建加部署脚本,后续可以接入流水线,加自动化测试、视觉回归、灰度发布。这些能力对团队规模变大之后的稳定性提升非常有价值。

最后

写到这里,“rea”项目的全貌应该比较清楚了。坦白说,前端工程化这条路没有什么惊天动地的秘密,大多数方案都是社区里反复被验证过的成熟经验。“rea”的价值不在于它用了什么新技术,而在于它把这些经验真正落到了实处,并且在一堆“看着都会、做起来全是坑”的细节里趟平了路。

如果你正准备重构自己的React项目,或者希望为团队搭建一个靠谱的前端底座,可以照着这篇文章的目录和步骤去试。我强烈建议先把目录结构和规范约束确定下来,这比后面写任何业务代码都重要。那些看起来很琐碎的约定,恰恰是项目长期能维护下去的关键。

我个人还有一个小体会:工程化的落地过程中,队友的接受度往往比技术方案的优劣更重要。再好的方案,如果有人因为不理解而绕过,迟早会退化成纸上谈兵。“rea”项目之所以走得顺,很大程度上是因为从一开始就让每个成员参与了规范讨论,把规则变成了共识。给你的项目一点耐心,把方案讲透,让大家都觉得“这样改是对的”,推进起来就会快很多。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进