从零搭个现代前端项目,我踩过的坑都给你标红了

后端说没问题
2025-12-26 02:29
阅读 786

今天早上八点刚到公司,泡了杯速溶咖啡(别笑,三线城市没那么多精品咖啡店),打开电脑发现昨晚刷 LeetCode 的时候把终端关了——又白跑了一次力扣。不过还好,今天不用赶着改产品提的“小需求”(你懂的,就是那种“就加个按钮,五分钟搞定”的需求)。趁着晨会前这段安静时间,我想写点实在的东西:怎么从零开始搭一个现代化的前端项目

为什么突然想写这个?上周五我们团队接了个新项目,要给本地一家制造企业做内部管理系统。产品经理画完原型图甩过来一句:“这次用新技术吧,显得我们有实力。” 我心里苦笑——嘴上说着“新技术”,预算和工期却比双11大促还紧。但没办法,既然要做,那就得做得像样点。正好我也在准备跳槽,简历上总不能只写“熟练使用 jQuery 吧”。


别再从 create-react-app 无脑开始了

很多人一说新建项目,直接 npx create-react-app my-app,完事。这在 2018 年没问题,但现在?真不够看了。

现代前端项目不只是“能跑就行”,还得考虑:

  • 开发体验:热更新快不快?报错提示友好吗?
  • 构建性能:CI/CD 能不能跑得动?打包体积压得住吗?
  • 可维护性:半年后新人接手会不会骂娘?
  • 扩展性:以后要加微前端、SSR、PWA 怎么办?

所以我们这次没用 CRA,而是基于 Vite + TypeScript + PNPM + ESLint + Prettier + Husky 搭了一套脚手架。听起来花里胡哨?其实配置起来也就半小时,而且后续省下的时间远超这点投入。


初始化:用 Vite 真香

pnpm create vite@latest my-project -- --template react-ts
cd my-project
pnpm install

为啥选 Vite?两个字:。本地开发启动从 CRA 的 15 秒降到 300 毡秒,HMR(热更新)几乎无感。对于我们这种经常被产品经理临时叫去改 UI 的苦命人来说,省下的每一秒都是生命。

而且 Vite 原生支持 TS、CSS Modules、JSON 导入,连 Webpack 配置都不用碰——终于不用再和 webpack.config.js 死磕到凌晨三点了。


代码规范:别让队友在 PR 里吵架

以前我们团队因为缩进是 2 还是 4 空格吵过三次,最后决定:工具说了算

我们在项目根目录加了这几个文件:

  • .eslintrc.cjs:ESLint 规则,用了 @typescript-eslint/recommended
  • .prettierrc:统一格式化风格
  • .editorconfig:让不同编辑器行为一致
  • husky + lint-staged:提交前自动 lint 和 format

关键配置片段:

// .prettierrc
{
  "semi": false,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "es5"
}
// lint-staged.config.js
export default {
  '*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'],
  '*.{css,scss,json,md}': ['prettier --write']
}

现在谁要是提交一堆格式问题,Git hooks 直接拦住,根本推不上 GitHub。产品再急,也得等代码干净了再说。


Git 提交规范:别再写 “fix bug” 了

说到 GitHub,我们强制要求 Conventional Commits。不是为了装,是真的有用。

以前看 Git log 是这样的:

fix bug
update
done
ok

现在是这样的:

feat(auth): add login page
fix(api): handle 401 redirect
chore(deps): update axios to v1.6

配合 commitlint@commitlint/config-conventional,提交信息不符合规范直接不让 commit。虽然一开始大家骂骂咧咧,但三个月后回溯问题时,所有人都闭嘴了——因为能精准定位到哪个 commit 引入了问题。

而且,自动生成 CHANGELOG 和语义化版本号也成了可能。虽然我们是内部系统用不上,但跳槽面试的时候,这套流程写进简历绝对加分。


组件设计:别重复造轮子,但也别乱引依赖

我们用了 shadcn/ui 而不是 Ant Design 或 Element Plus。原因很简单:按需引入 + 完全可控

shadcn/ui 不是 npm 包,而是把组件代码直接 copy 到你项目里。听起来反直觉?但好处巨大:

  • 样式可以随意改,不用覆盖一堆 CSS
  • 不会因为某个 UI 库升级导致整个页面崩掉
  • 打包体积只包含你用到的部分

比如一个按钮:

// components/ui/button.tsx
import { cn } from '@/lib/utils'

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: 'default' | 'outline'
}

export function Button({ className, variant = 'default', ...props }: ButtonProps) {
  return (
    <button
      className={cn(
        'px-4 py-2 rounded-md',
        variant === 'default' && 'bg-blue-500 text-white',
        variant === 'outline' && 'border border-blue-500 text-blue-500',
        className
      )}
      {...props}
    />
  )
}

完全透明,想加 loading 状态?直接改就行。再也不用去看 UI 库源码找哪个 prop 叫 loadingIndicator 了。


测试:不是可有可无的摆设

我知道,很多中小公司根本不管测试。但我们这次咬牙上了 Vitest + Testing Library

为什么?因为上个月上线一个报表功能,因为没处理空数据,导致整个页面白屏。运维半夜打电话,我当时真的想砸电脑。

现在核心组件都有快照测试和交互测试:

// __tests__/Button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react'
import { Button } from '@/components/ui/button'

test('calls onClick when clicked', () => {
  const handleClick = vi.fn()
  render(<Button onClick={handleClick}>Click me</Button>)
  
  fireEvent.click(screen.getByText('Click me'))
  expect(handleClick).toHaveBeenCalled()
})

CI 里跑一遍,确保不会因为改个样式把功能搞挂。虽然多花点时间,但比起线上事故,这成本太低了。


部署:一键发布到 GitHub Pages

因为是内部系统,客户没给服务器,只能先放 GitHub Pages 凑合用(别笑,三线城市客户真就这么干)。

Vite 打包后,一行命令搞定:

pnpm build
gh-pages -d dist

配合 GitHub Actions,每次 push 到 main 分支自动部署:

# .github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v2
      - run: pnpm install
      - run: pnpm build
      - uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./dist

第二天早上客户就能看到最新版本,再也不用我们手动发 zip 包了。


最后一点真心话

说实话,作为一个三线城市的“技术负责人”(其实就是最老的前端),我深知资源有限、人力紧张。但我们不能因此就放弃工程化。现代化前端不是炫技,而是用工具减少重复劳动、降低出错概率、提升交付质量

这套架子搭完后,新同事入职第一天就能跑起来项目,改个页面不用问“这个变量在哪定义的”。上周五加班到九点,但因为有完善的类型检查和测试,上线一次过——回家路上还能刷两道算法题,为跳槽做准备。

如果你也在小公司挣扎,别觉得“我们项目小,没必要”。恰恰是因为小,才更需要靠工具和规范来弥补人力的不足。

对了,所有代码我都放 GitHub 上了,欢迎 star(不是为了流量,是真的希望帮到同行): https://github.com/yourname/modern-frontend-boilerplate

(当然,链接是假的,真项目不能公开 😅)


写完这篇已经是中午十二点,产品又在群里@我:“那个筛选条件能不能加个‘全部’选项?”
我深吸一口气,回了个“OK”,然后默默打开了项目代码——幸好昨天配好了 Git hooks,至少格式不会乱。

评论 0

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