前端开发工具【免费下载链接】relayRelay is a JavaScript framework for building>项目地址https://gitcode.com/gh_mirrors/relay29/relay点击查看免费下载导读本文围绕 Relay 19 数据驱动依赖Data Driven Dependencies简称 3D的配置环节展开完整解读 Relay Compiler 配置文件中moduleImportConfig字段的结构、子字段语义与各模式示例。读完本文你将掌握如何在不改动代码的前提下自动启用 Server 3D以及如何通过dynamicModuleProvider与surface两个字段为 OSS 项目开启 Client 3D并能从源码与测试用例层面理解每个配置项在编译期的真实作用。一、从零配置开始Server 3D 的自动启用在 Relay 中Server 3D即 3D 组件所需数据全部由 GraphQL 服务端解析是默认自动启用的无需对 Relay Compiler 配置做任何改动Server 3D is automatically enabled without any changes to your configuration.这意味着只要你的 GraphQL 片段中使用了match/module指令Relay Compiler 就会在编译产物中生成对应的模块加载逻辑运行时按需下载匹配到的那一个具体类型的组件与数据。与 Server 3D 相对的是Client 3D——所有渲染数据由客户端侧的 Relay Resolvers 解析——这类场景必须显式地在 Relay Compiler 配置文件中新增一个moduleImportConfig字段才能开启。两者更完整的背景可参见 3D 系列引言。二、moduleImportConfig字段总览在 OSS开源项目中开启 Client 3D 的方式是在 relay compiler 的配置文件中追加moduleImportConfig。该字段在 Relay 19 的编译配置中实际上包含三个子字段两个常用 一个内部扩展子字段说明是否 OSS 必填dynamicModuleProvider定义 3D 组件在运行时如何被动态导入必填surface定义启用 Client 3D 的作用面surface必填operationModuleProvider定义生成在NormalizationModuleImport节点上的导入语句用于 exec-time Client 3D一般省略这一结构在仓库的 Rust 配置类型中有精确对应。在 compiler/crates/relay-config/src/module_import_config.rs 中pub struct ModuleImportConfig { /// Defines the custom import statement to be generated on the /// ModuleImport node in ASTs, used for dynamically loading /// components at runtime. pub dynamic_module_provider: OptionModuleProvider, /// Defines the custom import statement to be generated for the /// operationModuleProvider function on the NormalizationModuleImport /// node in ASTs. Used in exec time client 3D. pub operation_module_provider: OptionModuleProvider, /// Defines the surface upon which module is enabled. pub surface: OptionSurface, }同时relay-compiler-config-schema.json 给出了该字段的 JSON Schema 约束additionalProperties: false即不认识的子字段会被直接拒绝moduleImportConfig: { description: Configuration for module., type: object, properties: { dynamicModuleProvider: { description: Defines the custom import statement to be generated on the\nModuleImport node in ASTs, used for dynamically loading\ncomponents at runtime. }, operationModuleProvider: { description: Defines the custom import statement to be generated for the\noperationModuleProvider function on the NormalizationModuleImport\nnode in ASTs. Used in exec time client 3D. }, surface: { description: Defines the surface upon which module is enabled. } }, additionalProperties: false }需要注意moduleImportConfig在整个配置中的默认值为{ dynamicModuleProvider: null, operationModuleProvider: null, surface: null }见同一 schema 文件第 126–130 行因此不写这个字段时行为等价于未启用 Client 3D——这与Server 3D 自动开启的设计是一致的。三、dynamicModuleProvider3D 组件如何被导入dynamicModuleProvider决定 Relay Compiler 为 3D 组件生成怎样的动态导入语句。它由mode与statement两个子字段构成其中mode有两种取值3.1 模式一JSResourceMeta 内部使用将mode设为JSResource表示告知 Relay Compiler3D 组件应以JSResource一种可动态加载的 JavaScript 模块的方式导入。此时可以完全省略statement子字段moduleImportConfig: { dynamicModuleProvider: { mode: JSResource } }从 Rust 类型定义可以看到ModuleProvider是一个以mode为标签tag的枚举JSResource分支不携带任何额外数据module_import_config.rs#[serde(tag mode)] pub enum ModuleProvider { /// Generates a module provider using JSResource JSResource, /// Generates a custom JS import, Use $module as the placeholder /// for the actual module. e.g. () import($module) Custom { statement: StringKey }, }3.2 模式二CustomOSS 推荐将mode设为Custom表示你希望编写自定义的 import 语句来加载 3D 组件。此时必须填写statement子字段并在语句中使用占位符$module代替实际的 3D 组件名。编译时 Relay Compiler 会把$module替换成module(name: ...)指令中指定的组件名。moduleImportConfig: { dynamicModuleProvider: { mode: Custom, statement: function() { var JSResource require(JSResource); return JSResource(m#$module); } } }上面是 Meta 内部常用的写法经JSResource(m#模块名)动态加载。而在 OSS 项目中statement可以是你需要的任何导入方式例如基于 CommonJS 的相对路径 requiremoduleImportConfig: { dynamicModuleProvider: { mode: Custom, statement: () require(./.$module) }, surface: resolvers }仓库的编译测试夹具中也有同款配置query-with-module-directive-custom-import.graphql%project_config% { moduleImportConfig: { dynamicModuleProvider: { mode: Custom, statement: () import($module) } }, language: flow }对应的 JSResource 模式夹具见 query-with-module-directive-jsresource-import.graphql两个夹具使用完全相同的module(name: MarkdownUserNameRenderer.react)片段仅靠moduleImportConfig的差异来验证两种模式下生成的导入代码不同——这直观说明dynamicModuleProvider只影响如何导入不影响 3D 的语义。四、surfaceClient 3D 的作用范围surface用于声明 Client 3D 在哪些场景下生效。在 Meta 内部存在三种取值而在 OSS 中只有一种正确用法。4.1resolversOSS 唯一选项resolvers表示 Client 3D 仅对完全由客户端 Relay Resolvers 决定的字段生效可视为最纯正的 Client 3D 用法moduleImportConfig: { dynamicModuleProvider: { mode: JSResource, }, surface: resolvers }在 OSS 中surface应固定设置为resolvers。这与 Relay Resolvers 在开源生态中的定位一致OSS 项目使用 Client 3D 的前提正是数据来自客户端 resolver。仓库的集成测试夹具 client-3D-resolvers-enabled-server-3D-fragment.graphql 展示了一个同时使用match与surface: resolvers的混合用例%project_config% { moduleImportConfig: { dynamicModuleProvider: { mode: JSResource }, surface: resolvers }, language: flow }4.2None省略该字段Meta 内部场景不写surface字段即表示该值。这是 xplat 中大多数项目的现状属于Server 3D 的一种特殊变体3D 组件的模块信息由 Relay Compiler 保存在客户端一侧而不再随数据从服务端下发。需要特别说明的是这种变体相对 Server 3D 没有任何性能收益它诞生的初衷是为了支持 xplat 与 WWW 之间的代码共享。本文前述两个dynamicModuleProvider示例JSResource 与 Custom在不配置surface时都属于这一None场景。4.3all两者兼用all表示resolvers与None两种场景同时启用moduleImportConfig: { dynamicModuleProvider: { mode: JSResource, }, surface: all }从 JSON Schema 的Surface定义可以看到合法取值实际上只有resolvers与all两个relay-compiler-config-schema.jsonSurface: { type: string, enum: [ resolvers, all ] }对应的 Rust 枚举module_import_config.rs同样只有Resolvers与All两个变体None 在类型系统中正是surface: None的 Rust 表达。五、一份可落地的 OSS 完整配置将以上内容汇总一份开启 Client 3D 的 OSS Relay Compiler 配置如下以 JSON 形式追加到你的 compiler 配置文件中的项目级配置里moduleImportConfig: { dynamicModuleProvider: { mode: Custom, statement: () require(./.$module) }, surface: resolvers }要点回顾mode固定为Customstatement按你的模块系统自由定制占位符$module会被编译期替换为真实组件名surface固定为resolvers若你的项目使用 ES Module可将statement改为() import($module)仓库测试夹具即采用此写法。关于配置文件本身的写法可以参考仓库自带的示例 compiler/test-project/relay.config.json其中演示了root、sources、projects等外层结构的组织方式moduleImportConfig即作为projects.name下的一个属性存在。配置完成后通过 Relay Compiler 重新生成产物即可在客户端使用moduleMatchContainer渲染由 Relay Resolvers 驱动的 3D 组件具体组件侧写法参见 Client 3D 使用指南。六、源码级验证配置如何驱动编译行为moduleImportConfig并非摆设它直接参与 Relay 编译流水线。从测试代码可见其调用关系compiler/crates/relay-transforms/tests/generate_data_driven_dependency_metadata.rs 将ModuleImportConfig { dynamic_module_provider: JSResource, surface: Resolvers }传入transform_match转换再交给generate_data_driven_dependency_metadata生成 3D 元数据let module_import_config ModuleImportConfig { dynamic_module_provider: Some(ModuleProvider::JSResource), operation_module_provider: None, surface: Some(Surface::Resolvers), }; apply_transform_for_test(fixture, |program| { let flags FeatureFlags::default(); let program transform_match(program, flags, module_import_config, Default::default())?; let program generate_data_driven_dependency_metadata(program); Ok(program) })从源码结构看transform_matchcompiler/crates/relay-transforms/src/match_/match_transform.rs会在编译期处理match/module指令并生成ModuleImportAST 节点而dynamicModuleProvider中mode的不同取值JSResource/Custom会决定该节点上importStatement的最终文本形态surface则控制该转换在哪些场景resolver 驱动 / 普通 Server 3D / 两者兼有被应用。配置与实现一一对应这也解释了为什么错误配置例如statement缺少$module占位符、或mode拼写错误会在编译阶段被 schema 校验拦截。七、配置注意事项小结Server 3D 无需配置只要不写moduleImportConfigmatch/module依旧按 Server 3D 工作Client 3D 必须配置缺dynamicModuleProvider或surface都不会启用 resolver 驱动的 3D$module占位符不可省略Custom模式的statement中若没有该占位符编译器无法把语句绑定到具体组件名区分surface语义OSS 使用resolversall与省略字段None 场景主要用于 Meta 内部 xplat 的代码共享诉求OSS 项目中按需选用即可schema 兜底additionalProperties: false与严格的枚举约束意味着配置错误会在编译期尽早暴露而不是留到运行时。至此你已完整掌握 Relay 19 中 3D 功能的配置面既清楚 Server 3D 的零配置默认行为也明白 Client 3D 的moduleImportConfig从字段到源码实现的完整链路。赞分享前端开发工具【免费下载链接】relayRelay is a JavaScript framework for building>项目地址https://gitcode.com/gh_mirrors/relay29/relay点击查看免费下载相关推荐Apache DolphinScheduler StarRocks 数据源接入指南表单配置、驱动依赖与 JDBC 安全参数源码解析Apache DolphinScheduler StarRocks 数据源接入指南表单配置、驱动依赖与 JDBC 安全参数源码解析 StarRocks 是当前任务调度数据编排工作流自动化后端大数据Relay 19 useQueryLoader 完全指南以事件驱动的方式预取查询数据Relay 19 useQueryLoader 完全指南以事件驱动的方式预取查询数据 useQueryLoader 是 React Relay 中用于实现 r前端开发工具ESP-IDF 构建系统 v2 组件依赖配置完全指南从 REQUIRES/PRIV_REQUIRES 到配置驱动依赖ESP IDF 构建系统 v2 组件依赖配置完全指南从 REQUIRES/PRIV_REQUIRES 到配置驱动依赖 本指南以 docs/en/api gui物联网嵌入式创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
