ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Redwood 4.x 项目文件结构全解析:api / web / scripts 三大 side 的目录职责与实战指南

Redwood 4.x 项目文件结构全解析:api / web / scripts 三大 side 的目录职责与实战指南 Redwood 4.x 项目文件结构全解析api / web / scripts 三大 side 的目录职责与实战指南【免费下载链接】redwoodRedwoodGraphQL项目地址: https://gitcode.com/gh_mirrors/re/redwood导读本指南以 Redwood 官方教程version-4.x第一章《Redwood File Structure》为骨架逐层拆解一个新创建的 Redwood 应用为何会生成api、web、scripts三大顶层目录以及每个目录下各文件的职责边界。读完本文你将能在一分钟内读懂任意 Redwood 项目的目录树知道新增数据库表、GraphQL 接口、页面、组件时分别该把代码放进哪里并能对照本仓库中的真实空项目 fixture 验证每一种约定。顶层结构总览api、web、scripts 三足鼎立Redwood 在项目最顶层划分出三个目录文档以 v4.x 的新建应用为例省略了各类配置文件├── api ├── scripts └── web这三个目录背后是 Redwood 的核心设计理念按关注点分离前后端。后端api与前端web分别拥有独立的路径、独立的package.json依赖树和独立的构建流程。这种结构直接借鉴了 Yarn 的workspaces工作区机制而在 Redwood 的术语里每个 workspace 被称作一个side侧。用 yarn workspace 管理依赖正因为前后端是独立的 workspace后续安装 npm 包时必须明确指出要装到哪一侧。官方文档给出的命令语法如下此处仅演示语法无需真正执行yarn workspace web add marked yarn workspace api add better-fsyarn workspace web add pkg把前端组件库、工具库安装到 web 侧yarn workspace api add pkg把服务端依赖数据库驱动、鉴权库等安装到 api 侧。同时 Redwood 也提供yarn rw命令体系如yarn rw dev用于跨 side 的日常开发操作具体命令可参考仓库文档 cli-commands.md。一份目录两种语言形态Redwood 同时支持 JavaScript 与 TypeScript两种形态的目录结构完全一致仅文件扩展名不同。官方文档分别给出了两份目录树这里是 TypeScript 版本的完整形态├── api │ ├── db │ │ └── schema.prisma │ ├── dist │ ├── src │ │ ├── directives │ │ │ ├── requireAuth │ │ │ └── skipAuth │ │ ├── functions │ │ │ └── graphql.ts │ │ ├── graphql │ │ ├── lib │ │ │ ├── auth.ts │ │ │ ├── db.ts │ │ │ └── logger.ts │ │ └── services │ └── types │ ├── scripts │ └── seed.ts │ └── web ├── public │ ├── favicon.png │ ├── README.md │ └── robots.txt └── src ├── components ├── layouts ├── pages │ ├── FatalErrorPage │ │ └── FatalErrorPage.tsx │ └── NotFoundPage │ └── NotFoundPage.tsx ├── App.tsx ├── index.css ├── index.html └── Routes.tsxJS 形态与之完全一一对应graphql.ts→graphql.js、App.tsx→App.js、Routes.tsx→Routes.js等。初次见到几十个文件确实令人望而生畏但正如文档所说这背后是一套非常清晰的组织约定后续教程会逐一涉及。下面我们按目录逐个深入。scripts与业务侧无关的命令行脚本scripts目录用于存放那些既不属于 api 侧、也不属于 web 侧的 Node 脚本——即你需要在命令行手动运行的杂项工具脚本。新建应用中它只包含一个文件seed.{js,ts}数据库种子脚本用于为应用写入跑起来就必须存在的基础数据比如管理员账号、站点配置。在本仓库的 空项目 fixture 中可以看到它的真实形态默认导出async函数通过api/src/lib/db引入 Prisma 客户端。注释明确说明了两条触发路径首次运行yarn rw prisma migrate dev时自动执行每次运行yarn rw prisma migrate reset时自动执行也可手动通过yarn rw prisma db seed触发。默认种子脚本是一个空实现只在控制台打印提示信息真正的数据写入逻辑如示例中的db.user.createMany({ data: users })由开发者补充。数据库种子机制更完整的说明见仓库文档 database-seeds.md。api 侧后端服务的四层目录api目录下共有四个目录职责各不相同db、dist、src、types。db数据库的管线层api/db只负责一件事——描述并演进数据库schema.prisma用 Prisma Schema 语言定义数据库的表与列。以本仓库 空项目 fixture 的 schema.prisma 为例新建应用默认是 SQLitedatasource db { provider sqlite url env(DATABASE_URL) directUrl env(DIRECT_URL) } generator client { provider prisma-client-js binaryTargets native } // Define your own datamodels here and run yarn redwood prisma migrate dev // to create migrations for them and apply to your dev DB. // TODO: Please remove the following example: model UserExample { id Int id default(autoincrement()) email String unique name String? }在添加第一张表之后api/db下还会自动生成两个东西dev.dbSQLite 本地开发数据库文件migrations/数据库 schema 随时间变化的快照集合每一份迁移文件记录了某次结构变更保证团队成员与各环境间的数据库结构可追溯、可回放。dist编译产物开发时可忽略api/dist存放 api 侧的编译输出属于构建产物不需要也不应该手工编辑开发时直接忽略。src全部后端源码所在api/src包含五个子目录它们共同构成了 Redwood 服务端的骨架directivesGraphQL schema 指令directives用于定义 GraphQL schema 指令schema directives典型用途是控制查询访问权限和转换字段值。新建应用自带两个指令requireAuth要求访问者已认证可选附带角色校验skipAuth显式放行允许公开访问。以 fixture 中的 requireAuth.ts 为例它通过createValidatorDirective注册一个requireAuth(roles: [String])指令validate阶段调用src/lib/auth中的applicationRequireAuth完成校验skipAuth.ts 的validate则直接空实现放行。每个指令目录下还附带同名测试文件如requireAuth.test.ts供后续教程实践测试驱动开发。functionsServerless 函数functions存放应用需要的 lambda 函数Redwood 的服务端模型基于 Serverless Functions。其中graphql.{js,ts}是 Redwood 自动生成、接入 GraphQL API 所必需的文件不要删除。fixture 中的 graphql.ts 展示了它的真实实现——通过createGraphQLHandler组装整套 GraphQL 服务import { createGraphQLHandler } from redwoodjs/graphql-server import directives from src/directives/**/*.{js,ts} import sdls from src/graphql/**/*.sdl.{js,ts} import services from src/services/**/*.{js,ts} import { db } from src/lib/db import { logger } from src/lib/logger export const handler createGraphQLHandler({ loggerConfig: { logger, options: {} }, directives, sdls, services, onException: () { // Disconnect from your database with an unhandled exception. db.$disconnect() }, })可以看到GraphQL handler 通过 glob 模式自动收集directives、graphqlSDL 文件与services三个目录并注入db与logger。这意味着你新增的 SDL 和 service 文件会被自动发现并挂载无需手工注册。graphqlGraphQL Schema 定义层graphql目录存放以 Schema Definition LanguageSDL编写的 GraphQL schema文件以.sdl.{js,ts}结尾如post.sdl.ts。SDL 文件定义查询、变更queries/mutations的类型与字段签名真正取数逻辑则在services中实现。lib后端公共工具库lib目录集中存放 api 侧的基础设施代码。新建应用自带三个文件auth.{js,ts}鉴权功能的占位实现。fixture 中的 auth.ts 默认isAuthenticated()直接返回true模拟已登录用户、hasRole与requireAuth为占位逻辑供services中的调用先有东西可检查接入真实鉴权后替换实现即可db.{js,ts}实例化 Prisma 数据库客户端。fixture 中的 db.ts 创建PrismaClient并配置日志级别[info, warn, error]再通过handlePrismaLogging把 Prisma 日志接入统一 loggerexport const db new PrismaClient({ log: emitLogLevels([info, warn, error]), }) handlePrismaLogging({ db, logger, logLevels: [info, warn, error], })logger.{js,ts}基于 pino 的日志配置。fixture 中的 logger.ts 通过createLogger({})创建日志器其注释详细说明了RedwoodLoggerOptions的三个可选项options定义如何记录如 redaction 与 format、destination输出到文件或 transport stream、showConfig是否在初始化时打印配置。此外任何api 侧公共、又不好归入上述分类的代码官方建议都放进lib。services业务逻辑与数据操作services存放与数据相关的业务逻辑。当你在 GraphQL 中查询或变更数据时真正执行的resolver代码就写在这里——但它的组织方式使其可被应用其他位置复用而不只是 GraphQL 专用。新增 service 文件同样会被graphql.ts中的src/services/**/*.{js,ts}glob 自动收集。types自动编译的 GraphQL 类型api/types存放自动编译生成的 GraphQL 类型由 Redwood 在生成/构建时产出开发过程中无需手工维护可安全忽略。以上就是 Redwood 后端的全部组织方式。web 侧前端的两个分区web目录分为public与src两大部分。public不经 React 处理的静态资源public存放不被 React 组件引用的静态资源构建时它们会被原样复制到最终应用的根目录对应 Webpack 构建产物的dist目录。新建应用包含三个文件favicon.png浏览器标签页图标新应用默认使用 RedwoodJS 的 logoREADME.md说明public目录的用法与最佳实践详见下文robots.txt控制搜索引擎爬虫的抓取规则。关于静态资源的使用策略web/public/README.md 给出了两条关键约定public目录应克制使用由于该目录下的资源绕过 JavaScript 模块系统只适合放 favicon、robots.txt、manifest、与 Webpack 不兼容的第三方库等少数资产。背后实现依赖 Webpack 的copy-webpack-plugin组件内引用资源应直接 import将图片等资源直接 import 进模板、页面或组件让 Webpack 的file-loader/url-loader小于 10kb 的文件参与打包从而获得路径校验、错误检查与正确的产物路径处理import React from react import logo from ./my-logo.jpg function Header() { return img src{logo} altLogo / }src前端源码区web/src是前端代码的核心包含以下目录与文件componentsReact 组件与 Cellscomponents存放传统的 React 组件以及 Redwood 特有的Cells按约定文件名如ArticleCell.js组织负责获取数据 → 渲染加载/空/失败/成功态的声明式数据组件。后续教程会详细展开 Cells 的用法更完整的参考见仓库文档 cells.md。layouts跨页面共享的布局layouts存放包裹页面内容、并在多个Pages之间共享的 HTML/组件结构如导航栏 内容区的组合布局。布局本身也是 React 组件只是职责定位为页面容器。pagesURL 与页面的映射对象pages存放页面组件页面可可选地被包裹在 Layout 中是某个 URL 的着陆页——例如 URL/articles/hello-world映射到一个页面/contact-us映射到另一个页面。约定是每个页面一个同名目录目录内放同名组件文件如HomePage/HomePage.tsx。新建应用自带两个特殊页面NotFoundPage.{js,tsx}当没有任何路由匹配当前 URL 时展示。fixture 中的 NotFoundPage.tsx 渲染一个内联样式的 404 Page Not Found 页面FatalErrorPage.{js,tsx}当发生无法捕获、无法恢复的错误否则应用会渲染白屏时展示。fixture 中的 FatalErrorPage.tsx 有一个值得注意的实现细节——开发环境下它加载redwoodjs/web的DevFatalErrorPage展示详细报错生产构建则回退到简洁的 Something went wrong 页面避免把内部错误细节暴露给用户。App.tsx应用启动引导代码App.{js,tsx}是 Redwood 应用的引导bootstrap代码。fixture 中的 App.tsx 展示了完整的启动链路import { FatalErrorBoundary, RedwoodProvider } from redwoodjs/web import { RedwoodApolloProvider } from redwoodjs/web/apollo import FatalErrorPage from src/pages/FatalErrorPage import Routes from src/Routes import ./index.css const App ({ children }) ( FatalErrorBoundary page{FatalErrorPage} RedwoodProvider titleTemplate%PageTitle | %AppTitle RedwoodApolloProvider {children ? children : Routes /} /RedwoodApolloProvider /RedwoodProvider /FatalErrorBoundary ) export default AppFatalErrorBoundary错误边界出错时渲染FatalErrorPageRedwoodProvider提供标题模板等全局配置%PageTitle | %AppTitle决定浏览器标签页标题格式RedwoodApolloProvider注入 Apollo GraphQL 客户端。index.css自定义样式的起点index.css是编写自定义 CSS 的起始位置。当然样式方案选择很多官方文档点名推荐 TailwindCSS——在它的加持下你甚至可能整个应用生命周期都不需要手写多少自定义 CSS。index.html标准的 React 入口 HTMLindex.html是应用的 HTML 挂载点。fixture 中的 index.html 包含div idredwood-app挂载节点并保留了一行特殊注释!-- Please keep the line below for prerender support. --配合% prerenderPlaceholder %为预渲染Prerender功能留位。Routes.tsxURL 到页面的路由定义Routes.{js,tsx}定义应用的全部路由把 URL 映射到对应 Page。fixture 中的 Routes.tsx 是新建应用的最小形态import { Router, Route } from redwoodjs/router const Routes () { return ( Router Route notfound page{NotFoundPage} / /Router ) } export default Routes文件头部的注释还揭示了 Redwood 的一个约定src/pages下的所有 Page 组件会被自动导入支持嵌套目录且目录名必须大写嵌套目录名会拼接到组件名前缀上例如src/pages/Admin/BooksPage/BooksPage.js对应组件AdminBooksPage。路由机制的完整能力见仓库文档 router.md。对照真实仓库验证empty-project fixture 与 redwood.toml本文所述结构并非抽象描述——本仓库的 empty-project fixture 就是与 v4.x 教程形态一致的真实空项目TypeScript 版你可以在仓库中逐文件对照api/db/schema.prisma、api/src/functions/graphql.ts、api/src/lib/{auth,db,logger}.ts、web/src/App.tsx、web/src/Routes.tsx等都与上文完全对应。另外虽然本指南开头省略了配置文件但有一份配置文件值得提前了解——redwood.toml它是让 Redwood 应用成为 Redwood 应用的关键删除后yarn rw dev会直接报错。它同时定义了 web 与 api 两侧的开发端口与 API 路径[web] title Redwood App port 8910 apiUrl /.redwood/functions # you can customise graphql and dbauth urls individually too includeEnvironmentVariables [] # any ENV vars that should be available to the web side [api] port 8911 [browser] open true其中apiUrl /.redwood/functions是 web 侧调用 api 侧 serverless 函数的统一前缀。完整的配置项清单见仓库文档 app-configuration-redwood-toml.md。小结一张目录职责速查表目录/文件职责典型使用场景scripts/seed.ts数据库种子脚本写入管理员账号、站点配置等基础数据api/db/schema.prisma数据库 schema定义表结构后运行prisma migrate devapi/src/directivesGraphQL 权限指令新增requireAuth/skipAuth式指令api/src/functionsServerless 函数graphql.ts是 GraphQL API 入口也可添加自定义函数api/src/graphqlSDL 定义文件新增.sdl.ts描述查询/变更类型api/src/lib后端公共代码鉴权、数据库客户端、日志等基础设施api/src/services业务逻辑 / resolvers编写查询与变更的真实取数逻辑web/public静态资源favicon、robots.txt 等无需模块化处理的资产web/src/componentsReact 组件与 Cells可复用 UI 与声明式数据组件web/src/layouts跨页面布局导航栏、页脚等共享结构web/src/pagesURL 着陆页一个 URL 对应一个页面web/src/App.tsx应用引导全局 Provider 与错误边界装配web/src/Routes.tsx路由定义URL 与 Page 的映射Redwood 的文件结构看似繁多但规律高度一致后端按db / src / types分层、src内按职责分子目录前端按public / src分区、页面/组件/布局各归其位。后续教程中我们会在这套骨架之上创建新的页面、布局、SDL、service 与组件——到那时每一段代码该放在哪里都将水到渠成。【免费下载链接】redwoodRedwoodGraphQL项目地址: https://gitcode.com/gh_mirrors/re/redwood创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表