从零开始构建一个现代化前端项目:试用期菜鸟的血泪踩坑实录

调皮猴
2025-12-14 14:19
阅读 314

大家好,我是小林,刚入职杭州一家中型互联网公司不到一个月,目前还在试用期瑟瑟发抖中。之前在一家传统软件公司混了两年,技术栈基本停留在 jQuery + Bootstrap 的“上古时代”。来这边面试的时候,HR说我们团队技术氛围浓厚、拥抱前沿,我以为就是客套话——结果入职第一天,看到同事都在聊 Vite、TypeScript、微前端、Web Vitals,我当场瞳孔地震。

上周五,我的 mentor(带教导师)老张丢给我一个任务:“下周三前,搭个新项目的脚手架,要能跑起来,还要符合咱们团队的规范。” 我内心OS:不是有 create-react-app 吗?直接开干不就完了?结果老张微微一笑:“CRA?那是2018年的玩具了,现在谁还用那个?”

行吧,被现实狠狠教育了。为了保住这份离阿里网易都很近、薪资还不错的工作(毕竟杭州房租真不便宜),我硬着头皮从零开始搞起了这个“现代化前端项目”。今天这篇教程,就是记录我这三天踩过的坑、熬过的夜、以及差点被产品经理气到砸 Mac 的瞬间。如果你也刚入行,或者像我一样技术有点落伍,希望这篇能帮你少走点弯路。


起因:为什么不能直接用现成的脚手架?

其实一开始我也想偷懒。但老张说,现在大厂(包括我们这种“准大厂”)对前端工程化要求很高,光会写组件不够,得懂整个构建流程、性能监控、CI/CD 集成。而且我们项目要支持 SSR(服务端渲染)和 PWA(渐进式 Web 应用),CRA 根本搞不定。

更扎心的是,他说:“你要是连基础配置都看不懂,以后怎么 debug 构建问题?线上白屏了怎么办?等着运维大哥半夜打电话骂你吗?”

好吧,道理我都懂。那就从 npm init 开始吧!


第一步:初始化项目 & 选择核心工具链

首先,我新建了一个空文件夹:

mkdir modern-frontend-starter
cd modern-frontend-starter
npm init -y

然后安装几个核心依赖。这里我参考了团队内部的文档(其实是偷偷看了隔壁组的 GitHub 仓库):

  • Vite:新一代构建工具,快如闪电,开发服务器秒启动
  • React 18:团队主技术栈(虽然我个人更喜欢 Vue,但人在屋檐下……)
  • TypeScript:必须上!JS 写大型项目太容易翻车
  • ESLint + Prettier:代码风格统一,避免 PR 时被同事喷
  • Husky + lint-staged:提交前自动格式化,杜绝脏代码入库
npm install -D vite @vitejs/plugin-react typescript @types/react @types/react-dom
npm install react react-dom
npm install -D eslint prettier husky lint-staged

💡 小贴士:-D--save-dev 的简写,只在开发环境用。

接着,我创建了 vite.config.ts

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    port: 3000,
    open: true // 自动打开浏览器
  },
  build: {
    outDir: 'dist'
  }
})

简单吧?但别小看这几行,它背后是 Webpack 时代几十行配置的简化版。Vite 利用原生 ES 模块(ESM)直接在浏览器运行代码,开发时几乎零编译,真的香!


第二步:配置 TypeScript 和代码规范

为了让 TS 正常工作,我加了 tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": ["src"]
}

然后是 ESLint + Prettier 联合配置。这里我踩了个大坑:两个工具默认规则冲突,导致保存时格式化完,ESLint 又报错。最后用了社区推荐的 .eslintrc.cjs + .prettierrc 组合:

// .eslintrc.cjs
module.exports = {
  env: {
    browser: true,
    es2021: true
  },
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended'
  ],
  parser: '@typescript-eslint/parser',
  plugins: ['react', '@typescript-eslint'],
  rules: {
    'react/react-in-jsx-scope': 'off' // React 17+ 不需要显式导入
  },
  settings: {
    react: {
      version: 'detect'
    }
  }
}
// .prettierrc
{
  "semi": false,
  "tabWidth": 2,
  "singleQuote": true,
  "printWidth": 80,
  "trailingComma": "es5"
}

最后用 Husky 搞个 pre-commit 钩子:

npx husky-init && npm install
npx husky add .husky/pre-commit "npx lint-staged"

并在 package.json 中添加:

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

搞定!现在每次 git commit,代码都会自动格式化 + 检查。再也不用担心被 code review 时被嘲讽“缩进不对”了 😅


第三步:目录结构 & 基础页面搭建

我们团队有个不成文的规定:src 目录必须清晰分层。于是我按以下结构组织:

src/
├── assets/          # 静态资源
├── components/      # 通用组件
├── hooks/           # 自定义 Hook
├── pages/           # 页面级组件
├── utils/           # 工具函数
├── App.tsx
└── main.tsx

写了个超简单的首页:

// src/pages/Home.tsx
import React from 'react'

const Home = () => {
  return (
    <div className="container">
      <h1>欢迎来到现代化前端世界!</h1>
      <p>当前时间:{new Date().toLocaleTimeString()}</p>
    </div>
  )
}

export default Home

然后在 App.tsx 里引入。注意:虽然现在没用路由,但提前按页面拆分,以后加 React Router 也方便。


第四步:性能优化 & 用户体验细节

作为“用户体验至上”的团队,老张特别强调:首屏加载速度必须快,交互必须流畅

1. 资源压缩与缓存

Vite 默认在 build 时做代码分割和压缩。但我们加了额外配置:

// vite.config.ts
import { splitVendorChunkPlugin } from 'vite'

export default defineConfig({
  plugins: [
    react(),
    splitVendorChunkZone() // 将 node_modules 拆成 vendor chunk
  ],
  build: {
    sourcemap: true, // 生产环境也保留 sourcemap,方便排查线上错误
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom']
        }
      }
    }
  }
})

2. 浏览器兼容性

我们目标用户主要是移动端,所以最低支持到 iOS 12 / Android 10。Vite 默认使用现代浏览器特性,但通过 @vitejs/plugin-legacy 可以生成兼容版本:

npm install -D @vitejs/plugin-legacy
// vite.config.ts
import legacy from '@vitejs/plugin-legacy'

export default defineConfig({
  plugins: [
    react(),
    legacy({
      targets: ['iOS >= 12', 'Android >= 10']
    })
  ]
})

这样构建后会多出 legacy-polyfill-*.js 和对应的 HTML 文件,老设备也能跑。

3. Lighthouse 评分优化

我在本地跑 Lighthouse,发现“最佳实践”只有 70 分。原因有几个:

  • 缺少 <meta name="viewport">
  • 没有设置 lang 属性
  • 图片没加 alt

于是赶紧补全 index.html

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Modern Frontend Starter</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

再跑一次,92 分!老张看了直点头:“不错,有产品sense。”


第五步:集成 GitHub Actions 实现自动化

既然是现代化项目,怎么能少了 CI/CD?我们用 GitHub 托管代码,所以自然选 GitHub Actions。

我在 .github/workflows/ci.yml 里写了:

name: CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test-and-build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      - run: npm ci
      - run: npm run lint
      - run: npm run build

对应 package.json 脚本:

{
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
  }
}

现在每次 push 到 main 或提 PR,GitHub 都会自动跑 lint 和 build。如果失败,PR 会被 block —— 再也不用担心有人把 console.log 提到生产环境了(说的就是上周那个实习生……)。


踩坑总结:那些让我想砸 Mac 的瞬间

  1. TSX 文件被 ESLint 忽略
    原因:.eslintignore 里误加了 *.tsx。删掉就好。

  2. Vite 开发服务器 HTTPS 报错
    因为公司内网要求所有服务走 HTTPS。解决方案:在 server 配置里加 https: true,并生成自签名证书(或让运维给个测试证书)。

  3. PWA 离线缓存失效
    一开始用 workbox 配置错了,缓存策略没生效。后来改用 vite-plugin-pwa,一行配置搞定。

  4. Mac 和 Windows 路径大小写问题
    我在 Mac 上写 import MyComponent from './mycomponent',但实际文件叫 MyComponent.tsx。Mac 不区分大小写能跑,但 Windows 测试机直接崩。从此养成严格命名习惯。


最终效果 & 心得体会

周三早上,我把项目链接发到群里。老张试了一下,说:“加载速度不错,Lighthouse 90+,代码也规范,可以 merge 了。” 那一刻,我感觉试用期稳了!

这个项目虽然简单,但它让我真正理解了“现代化前端”不只是用新框架,而是工程化思维 + 用户体验 + 自动化流程的结合。以前我觉得这些是“花架子”,现在明白:没有这些,项目大了就是灾难。

顺便,我把整个项目开源到了 GitHub:github.com/lin-coder/modern-frontend-starter(名字是我瞎起的)。里面有详细注释和 README,新手可以直接 clone 下来玩。欢迎 star & 提 issue!


给新手的建议

事项 推荐做法 避坑提醒
构建工具 优先选 Vite Webpack 配置复杂,新手慎入
语言 TypeScript 必上 JS 在大型项目维护成本高
代码规范 ESLint + Prettier + Git Hooks 不要等到项目大了才加
性能 从第一天关注 Lighthouse 别等上线了用户投诉才优化
自动化 尽早集成 CI/CD 手动部署迟早出事

最后,送一句我们团队墙上的话:“前端不止是切图仔,更是用户体验的守门人。

共勉!下次再分享如何接入微前端和埋点监控。对了,如果你们公司也在招人(坐标杭州,偏爱 Mac 用户),可以私信我~(试用期结束前先给自己留条后路,狗头保命)


本文纯属个人经验分享,如有雷同,那说明你也正在经历试用期的煎熬。加油,打工人!

评论 0

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