ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

使用 Turborepo 构建 React Native Web 跨端 Monorepo:Expo + Next.js + 共享 UI 全指南

使用 Turborepo 构建 React Native Web 跨端 Monorepo:Expo + Next.js + 共享 UI 全指南 使用 Turborepo 构建 React Native Web 跨端 MonorepoExpo Next.js 共享 UI 全指南【免费下载链接】turboBuild system optimized for JavaScript and TypeScript, written in Rust项目地址: https://gitcode.com/gh_mirrors/tu/turbo导读本指南基于 Turborepo 官方仓库中的with-react-native-web社区示例系统讲解如何在同一个 monorepo 中同时管理 React NativeExpo原生应用与 React Native WebNext.jsWeb 应用并借助共享的 React Native 组件库实现真正的一次编写、多端运行。读完本文你将掌握该示例的完整目录结构、每个应用与包的职责划分、Turbo 任务的管道配置方式以及如何从零创建和运行这套跨端工程。示例概览一个仓库两端应用一套组件with-react-native-web是一个由社区维护maintainedByCoreTeam: false见 meta.json的 Turborepo 示例核心思路是native基于 Expo 的 React Native 应用用于 iOS / Android 原生开发web基于 Next.js 的 Web 应用通过 react-native-web 在浏览器中渲染 React Native 组件repo/ui一个存根stubReact Native 组件库被web与native两个应用共享repo/typescript-config整个 monorepo 统一使用的tsconfig.json配置集合。示例中所有应用与包均 100% 使用 TypeScript 编写见 README从而实现同一套 UI 代码在原生端与 Web 端的一致体验。使用 create-turbo 快速初始化与仓库内其他示例一致创建本项目只需一条命令npx create-turbolatest -e with-react-native-webcreate-turbo会拉取该示例的模板并基于当前 Turbo 版本初始化。初始化完成后仓库根目录的 package.json 使用 Yarn Workspacesapps/*与packages/*组织包并声明turbo: 2.9.6、node 18的环境要求。根目录统一暴露以下脚本{ scripts: { dev: turbo run dev, build: turbo run build, clean: turbo run clean rm -rf node_modules, format: prettier --write \**/*.{ts,tsx,js,jsx,json,md}\ --ignore-path .gitignore } }目录结构与各模块职责with-react-native-web/ ├── apps/ │ ├── native/ # Expo 驱动的 React Native 应用 │ └── web/ # Next.js react-native-web 应用 ├── packages/ │ ├── typescript-config/ # 共享的 tsconfig 配置 │ └── ui/ # 共享的 React Native 组件库Button ├── turbo.json # Turbo 任务管道配置 ├── package.json # workspace 根配置 └── yarn.locknativeExpo 原生应用native/package.json 是标准的 Expo Router 项目关键依赖为expo ^55.0.4、react-native 0.83.2、react 19.2.0并包含expo-router、expo-status-bar、react-native-safe-area-context、react-native-screens等配套库。它提供的脚本有{ scripts: { dev: expo start --web, android: expo run:android, ios: expo run:ios, web: expo start --web, eject: expo eject } }入口为 index.js页面代码位于app/目录Expo Router 文件路由。应用级配置集中在 app.json其中值得注意的字段包括scheme: com.turbo.example与 Android 的package、iOS 的 bundle 标识web.bundler: metro即 Web 端同样使用 Metro 打包plugins: [expo-router]启用文件路由assets/下的icon.png、splash.png、adaptive-icon.png、favicon.png分别用于应用图标、启动屏、Android 自适应图标与 Web favicon。在 app/index.tsx 中页面通过View、Text、StyleSheet渲染并从repo/ui引入共享的Button组件import { StyleSheet, Text, View } from react-native; import { StatusBar } from expo-status-bar; import { Button } from repo/ui; export default function Native() { return ( View style{styles.container} Text style{styles.header}Native/Text Button onClick{() { console.log(Pressed!); alert(Pressed!); }} textBoop / StatusBar styleauto / /View ); }webNext.js react-native-webweb/package.json 是一个 Next.js 16 应用next 16.3.0除常规依赖外显式引入react-native-web ^0.21.0并在开发依赖中声明babel-plugin-react-native-web ^0.19.10以支持 Babel 层的组件转换。脚本为标准的next dev/next build/next start/next lint。首页 app/page.tsx 同样直接消费repo/ui的Buttonuse client; import { Button } from repo/ui; import styles from ../styles/index.module.css; export default function Web() { return ( div className{styles.container} h1Web/h1 Button onClick{() console.log(Pressed!)} textBoop / /div ); }由于组件库是 React Native 风格实现PressableStyleSheet在 Web 端正是依赖 react-native-web 将其编译为原生 DOM 元素与 CSS实现同一组件在两端的真实复用。repo/ui共享 React Native 组件库组件库的入口 src/index.tsx 导出Button核心实现 src/button.tsx 使用 React Native 的Pressable、Text与StyleSheet编写import * as React from react; import { StyleSheet, GestureResponderEvent, Text, Pressable, } from react-native; export interface ButtonProps { text: string; onClick?: (event: GestureResponderEvent) void; } export function Button({ text, onClick }: ButtonProps) { return ( Pressable style{styles.button} onPress{onClick} Text style{styles.text}{text}/Text /Pressable ); } const styles StyleSheet.create({ button: { maxWidth: 200, textAlign: center, borderRadius: 10, paddingTop: 14, paddingBottom: 14, paddingLeft: 30, paddingRight: 30, fontSize: 15, backgroundColor: #2f80ed, }, text: { color: white, }, });其构建由 tsup.config.ts 驱动关键配置包括entry指向src/index.tsx输出 CJS 与 ESM 两种格式banner.js: use client确保组件在 Next.js App Router 下被正确视为客户端组件external: [react]将 react 排除在打包产物之外自动生成.d.ts类型声明dts配置。包清单 package.json 声明main: ./dist/index.js、types: ./dist/index.d.ts因此应用侧通过repo/ui包名直接引用构建产物这正是 monorepo 内部包共享的关键机制。repo/typescript-config统一类型配置该包提供三份可继承的配置base.json、nextjs.json与react-native-library.json。react-native-library.json 面向 React Native 组件库开启allowJs、jsx: react、lib: [DOM, ESNext]、noEmit: true等选项repo/ui的 tsconfig.json 即通过extends: repo/typescript-config/react-native-library.json继承之并额外开启strict: true。Turbo 任务管道让两端构建协同调度根目录 turbo.json 定义了整个仓库的任务编排是理解为什么一条turbo run build就能串起全部应用的关键{ $schema: https://turborepo.dev/schema.json, ui: tui, tasks: { build: { inputs: [$TURBO_DEFAULT$, .env*], outputs: [dist/**, .next/**, !.next/cache/**, !.next/dev/**], dependsOn: [^build] }, dev: { cache: false, persistent: true }, lint: {}, clean: { cache: false } } }各任务的工程含义builddependsOn: [^build]表示先构建所有依赖方即repo/ui再并行构建web与nativeinputs声明参与哈希计算的输入默认文件加.env*outputs声明产物目录dist/**、.next/**其中!.next/cache/**与!.next/dev/**用于排除不应纳入缓存的 Next.js 缓存与开发产物。devpersistent: true声明其为长驻进程如expo start、next devcache: false关闭缓存避免长期运行的开发服务器污染缓存。lint空配置即采用 Turborepo 默认行为对声明了lint脚本的包并行执行。cleancache: false确保清理任务总是真实执行。这种管道设计使得新增一个应用或包时无需修改根配置只要包内声明对应 scriptTurbo 便会自动纳入依赖图调度并利用缓存加速构建。运行与验证在示例根目录依次执行yarn install # 安装全部 workspace 依赖 yarn dev # 等价于 turbo run dev并行启动两端开发服务器 yarn build # 先构建 repo/ui再构建 web/native yarn clean # 清理各包构建产物并移除 node_modules开发模式下native端可通过 Expo 的 Web 模式expo start --web在浏览器中预览也可用yarn ios/yarn android启动原生模拟器web端运行在 Next.js 默认端口。两端页面共享同一个Button点击后原生端弹出alert(Pressed!)Web 端则在控制台输出Pressed!直观验证了组件复用、行为按平台定制的跨端模式。小结with-react-native-web示例展示了 Turborepo 在跨端场景下的典型用法Expo 与 Next.js 共存于一个 workspaceReact Native 组件库通过 tsup 打包后在两端复用统一的turbo.json管道则负责依赖排序、产物缓存与长驻开发进程管理。对于希望以最小成本实现 iOS / Android / Web 三端覆盖的团队这是一个可以直接作为起点的工程模板更完整的跨端与微前端组合方案可进一步参考仓库中的 with-microfrontends 与 with-vite-module-federation 等示例。【免费下载链接】turboBuild system optimized for JavaScript and TypeScript, written in Rust项目地址: https://gitcode.com/gh_mirrors/tu/turbo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表