3. 移动端项目初始化:从零搭建你的React移动端工程

好,咱们直接进入正题。项目初始化这事儿,看着简单,但坑其实不少。我见过太多同学一上来就 npx create-react-app my-app,然后就开始写代码,结果到后面发现配置改不动、打包体积大、热更新慢……说白了,就是一开始没选对工具。

今天我就带你走一遍,从脚手架选择到目录规划,再到配置文件详解,把移动端项目的底子打扎实。

3.1 选哪个?Create React App 还是 Vite?

这个问题我经常被问到。我的建议很直接:新项目首选 Vite

为什么?你想想看,CRA(Create React App)当年确实是神器,但它的开发服务器启动慢,热更新也慢。尤其是移动端项目,你经常要改一点样式就刷新看效果,CRA 那几秒钟的等待真的很磨人。

Vite 就不一样了。它基于 ES Module,开发时按需编译,启动速度几乎是秒开。我在一个中型移动端项目里做过对比,CRA 冷启动要 8 秒,Vite 只要 1.2 秒。这差距,你感受一下。

我的选择建议:
  • Vite:新项目、追求开发体验、需要快速迭代 → 首选
  • CRA:老项目维护、团队习惯 CRA、需要零配置 → 可以保留
  • 自己搭 Webpack:除非你有特殊需求,否则别折腾

嗯,这里要注意一点:Vite 对 Node.js 版本有要求,建议 16+。我之前有个同事用 Node 14 跑 Vite,报了一堆错,查了半天才发现是版本问题。

3.2 用 Vite 初始化项目

咱们直接上手。打开终端,执行:

npm create vite@latest my-mobile-app -- --template react-ts

这里我用了 TypeScript 模板。为什么?移动端项目逻辑复杂,类型系统能帮你省掉很多调试时间。我个人习惯是,只要不是特别小的 demo,都用 TS。

初始化完成后,进入目录安装依赖:

cd my-mobile-app
npm install

然后启动:

npm run dev

看到终端里出现 Local: http://localhost:5173,就说明成功了。

小技巧:Vite 默认端口是 5173,如果你想改成 3000(跟 CRA 保持一致),可以在 vite.config.ts 里加 server: { port: 3000 }

3.3 目录结构规划:移动端项目的骨架

项目初始化完了,但目录结构还是空的。我见过很多项目,一开始不规划目录,写到后面就变成一锅粥。组件、工具函数、页面全混在一起,找文件得靠猜。

下面是我在多个移动端项目中沉淀下来的目录结构,你可以直接拿来用:

src/
├── assets/          # 静态资源(图片、字体、SVG)
│   ├── images/
│   └── fonts/
├── components/      # 通用组件
│   ├── common/      # 基础组件(Button、Input、Modal)
│   └── business/    # 业务组件(ProductCard、UserAvatar)
├── hooks/           # 自定义 Hooks
│   ├── useDebounce.ts
│   ├── useThrottle.ts
│   └── useViewport.ts
├── pages/           # 页面组件
│   ├── Home/
│   ├── Detail/
│   └── User/
├── router/          # 路由配置
│   └── index.tsx
├── store/           # 状态管理
│   └── index.ts
├── styles/          # 全局样式
│   ├── reset.css
│   ├── variables.css
│   └── mixins.css
├── utils/           # 工具函数
│   ├── request.ts   # 网络请求封装
│   ├── format.ts    # 格式化函数
│   └── storage.ts   # 本地存储封装
├── types/           # TypeScript 类型定义
│   └── index.d.ts
├── App.tsx
└── main.tsx

这个结构有几个好处:

  • 职责清晰:每个文件夹只做一件事,不会互相污染
  • 便于扩展:新页面来了,直接在 pages 下加文件夹就行
  • 团队协作友好:大家知道什么东西该放哪里,不用问来问去

我曾经在一个项目里看到有人把网络请求直接写在组件里,结果换了个页面想复用,只能复制粘贴。后来我强制要求所有请求都封装到 utils/request.ts 里,代码质量瞬间提升。

3.4 移动端项目配置文件详解

好,目录结构搭好了,接下来咱们看看几个关键的配置文件。这些文件决定了你的项目能不能在移动端跑得顺畅。

3.4.1 vite.config.ts:Vite 的核心配置

这个文件是 Vite 的入口配置。对于移动端项目,有几个配置项特别重要:

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

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  },
  server: {
    port: 3000,
    host: '0.0.0.0',  // 允许局域网访问,方便真机调试
    proxy: {
      '/api': {
        target: 'http://your-api-server.com',
        changeOrigin: true
      }
    }
  },
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          ui: ['antd-mobile']
        }
      }
    }
  }
})

这里我重点说几个:

  • resolve.alias:配置路径别名,以后写 @/components/Button../../components/Button 舒服多了
  • server.host: '0.0.0.0':这个一定要开!不然你手机连不上电脑的本地服务,没法真机调试
  • build.rollupOptions.output.manualChunks:把第三方库拆成独立 chunk,这样用户访问时可以利用浏览器缓存,不用每次都下载 React 全家桶
注意:生产环境记得关掉 server.host,或者用环境变量控制。我之前有个项目忘了关,上线后 API 地址暴露了,还好及时发现。

3.4.2 tsconfig.json:TypeScript 配置

移动端项目用 TypeScript,配置上要特别注意路径别名和严格模式:

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "include": ["src"]
}

这里 paths 要和 vite.config.ts 里的 alias 保持一致,不然 IDE 会报错说找不到模块。

3.4.3 postcss.config.js:移动端适配的关键

移动端适配,说白了就是让页面在不同屏幕尺寸下都能正常显示。我推荐用 postcss-px-to-viewport 这个插件,它能把 px 自动转成 vw 单位:

export default {
  plugins: {
    'postcss-px-to-viewport': {
      viewportWidth: 375,  // 设计稿宽度(iPhone 6/7/8)
      unitPrecision: 5,    // 转换后保留的小数位数
      viewportUnit: 'vw',  // 转换后的单位
      selectorBlackList: ['.ignore', '.hairlines'],  // 不转换的类名
      minPixelValue: 1,    // 小于 1px 不转换
      mediaQuery: false    // 是否允许在媒体查询中转换
    }
  }
}

为什么用 375?因为大多数移动端设计稿都是基于 iPhone 6/7/8 的 375px 宽度。你写 width: 100px,它会自动转成 width: 26.66667vw,在不同屏幕上都按比例缩放。

避坑指南:我曾经在项目里用了 1px 的边框,结果 postcss-px-to-viewport 把它转成了 0.26667vw,在有些手机上边框直接消失了。后来我在 selectorBlackList 里加了 '.hairlines',专门处理 1px 边框的场景。

3.4.4 .env 文件:环境变量管理

移动端项目通常有开发、测试、生产三个环境,环境变量要分开管理:

// .env.development
VITE_API_BASE_URL=http://localhost:3000/api
VITE_APP_TITLE=移动端项目(开发环境)

// .env.production
VITE_API_BASE_URL=https://api.your-domain.com
VITE_APP_TITLE=移动端项目

在代码里用 import.meta.env.VITE_API_BASE_URL 就能拿到对应的值。注意 Vite 的环境变量必须以 VITE_ 开头,不然不会暴露给前端代码。

3.5 初始化后的第一件事:验证移动端适配

项目搭好了,配置写完了,别急着写业务代码。先验证一下移动端适配是否生效:

  1. App.tsx 里写一个 div,宽度设为 375px
  2. 启动项目,用 Chrome DevTools 模拟 iPhone 6/7/8
  3. 检查元素,看宽度是不是变成了 100vw
  4. 切换到 iPhone X(375px 宽度),看布局是否正常
  5. 用手机真机访问,看效果是否一致

这一步走通了,后面写页面就只管按设计稿写 px,剩下的交给 postcss 去处理。

总结一下:
  • 新项目用 Vite,开发体验好太多
  • 目录结构提前规划,别等代码多了再重构
  • 配置文件要理解每个选项的作用,别照抄
  • 移动端适配用 postcss-px-to-viewport,省心省力

好了,项目初始化就到这里。下一章咱们会深入移动端适配的细节,包括 rem、vw、媒体查询这些方案的对比,以及我在实际项目中踩过的坑。到时候见。