当前仓库是一个 monorepo(基于 pnpm 的 workspace)
- Expo 代码在 client 目录,Express.js 代码在 server 目录
- 本模板默认无 Tab Bar,可按需改造
├── client/ # React Native 前端代码 │ ├── app/ # Expo Router 路由目录(仅路由配置) │ │ ├── _layout.tsx # 根布局文件(必需,务必阅读) │ │ └── index.tsx # 首页 │ ├── screens/ # 页面实现目录(与 app/ 路由对应) │ │ └── demo/ # 示例页面 │ │ └── index.tsx │ ├── components/ # 可复用组件 │ │ └── Screen.tsx # 页面容器组件(必用) │ ├── hooks/ # 自定义 Hooks │ ├── contexts/ # React Context 代码 │ ├── utils/ # 工具函数 │ ├── assets/ # 静态资源 | └── package.json # Expo 应用 package.json ├── server/ # 服务端代码根目录 (Express.js) | ├── src/ │ │ └── index.ts # 服务端入口文件 | └── package.json # 服务端 package.json ├── package.json ├── .cozeproj # 预置脚手架脚本(禁止修改) └── .coze # 配置文件(禁止修改)
基于 tailwindcss 进行样式开发(底层基于 Uniwind)
写法示例:
<View className="flex-1 bg-white dark:bg-gray-900 p-4"></View><Text
className="text-lg font-bold text-gray-900 dark:text-white"
selectionColorClassName="accent-blue-500"
>
Hello World
</Text>Uniwind 官方文档:https://docs.uniwind.dev/llms.txt
# 对 client 和 server 目录同时进行校验
pnpm -w lint:all
# 对 client 目录进行校验
pnpm -w lint:client
# 对 server 目录进行校验
pnpm -w lint:server默认为跟随系统,如果用户明确指定为“暗色”或“亮色”,需要修改 client/components/ColorSchemeUpdater.tsx 的 DEFAULT_THEME 变量为合适的值
当前项目的设计系统基于 tailwindcss 实现,核心入口文件为 client/global.css,如果需要定制主题,应该阅读并修改 client/global.css 文件
适用于线性流程应用,采用简化的目录结构:
client/app/
├── _layout.tsx # 根布局(Stack 导航配置)
├── index.tsx # 应用入口
├── detail.tsx # 详情页(通过 params 传递数据)
└── +not-found.tsx # 404 页面
根布局配置 client/app/_layout.tsx:
以下仅为代码片段供写法参考
<Stack screenOptions={{ headerShown: false }}>
<Stack.Screen name="index" />
<Stack.Screen name="detail" />
</Stack>应用入口 client/app/index.tsx:
export { default } from "@/screens/home";禁止事项:无 Tab Bar 场景下,不得创建
(tabs)目录。
采用路由分组实现底部导航栏:
client/app/
├── _layout.tsx # 根布局
├── (tabs)/
│ ├── _layout.tsx # Tab 导航配置
│ ├── index.tsx # 默认 Tab(必须存在)
│ ├── discover.tsx # 发现页
│ └── profile.tsx # 个人中心
├── detail.tsx # Tab 外的独立页面(通过 params 传递数据)
└── +not-found.tsx
⚠️ [CRITICAL]:app/index.tsx优先级高于(tabs)/index.tsx,会导致首页无 Tab Bar。当有(tabs)/index.tsx时必须删除app/index.tsx。
根布局配置 client/app/_layout.tsx:
以下仅为代码片段供写法参考
<Stack screenOptions={{ headerShown: false }}>
<Stack.Screen name="(tabs)" />
<Stack.Screen name="detail" />
</Stack>应用入口 client/app/(tabs)/index.tsx:
export { default } from "@/screens/home";Tab 布局配置 client/app/(tabs)/_layout.tsx:
import { Tabs } from 'expo-router';
import { Platform } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { FontAwesome6 } from '@expo/vector-icons';
import { useCSSVariable } from 'uniwind';
export default function TabLayout() {
const insets = useSafeAreaInsets();
const [background, muted, accent, border] = useCSSVariable([
'--color-background',
'--color-muted',
'--color-accent',
'--color-border',
]) as string[];
return (
<Tabs
screenOptions={{
headerShown: false,
tabBarStyle: {
backgroundColor: background,
borderTopWidth: 1,
borderTopColor: border,
// 通过固定宽度 55 来修正 Web 上的表现
height: Platform.OS === 'web' ? 55 : 50 + insets.bottom,
},
tabBarActiveTintColor: accent,
tabBarInactiveTintColor: muted,
}}
>
{/* name 必须与文件名完全一致 */}
<Tabs.Screen
name="index"
options={{
title: '首页',
tabBarIcon: ({ color }) => (
<FontAwesome6 name="house" size={20} color={color} />
),
}}
/>
<Tabs.Screen
name="discover"
options={{
title: '发现',
tabBarIcon: ({ color }) => (
<FontAwesome6 name="compass" size={20} color={color} />
),
}}
/>
<Tabs.Screen
name="profile"
options={{
title: '我的',
tabBarIcon: ({ color }) => (
<FontAwesome6 name="user" size={20} color={color} />
),
}}
/>
</Tabs>
);
}Tab 页面文件 client/app/(tabs)/index.tsx:
export { default } from "@/screens/home";在改动 client/app/_layout.tsx 前,必须先阅读该文件,再进行修改操作
以下是需要保留的重要逻辑
- 保留 global.css 引入(tailwindcss 生效的关键)
- 保留 Provider 的使用
禁止使用 npm 或 yarn,按目录区分安装命令:
| 目录 | 安装命令 | 说明 |
|---|---|---|
client/ |
npx expo install <package> |
Expo 会自动选择与 SDK 兼容的版本 |
server/ |
pnpm add <package> |
使用 pnpm 管理后端依赖 |
# client 目录(Expo 项目)
cd client && npx expo install expo-camera expo-image-picker
# server 目录(Express 项目)
cd server && pnpm add axios cors网络问题处理:npx expo install 可能因网络原因失败,失败时重试 2 次,仍失败则改用 pnpm add 安装
Expo 配置了 @/ 路径别名指向 client/ 目录:
// 正确
import { Screen } from '@/components/Screen';
// 避免相对路径
import { Screen } from '../../../components/Screen';coze dev:用来首次启动前后端服务,也可以用来重启前后端服务(该命令会先尝试杀掉占用端口的进程,再启动服务)