Apollo 编译器插件
编译器插件目前在 Apollo Kotlin 中使用 实验性。如果您对这些插件有任何反馈,请通过以下方式告诉我们GitHub 问题或Kotlin Slack 社区。
Apollo 编译器支持广泛选项。对于这些选项不足以满足需求的情况,您可以使用 Apollo 编译器插件来修改编译器的行为。
Apollo 编译器插件允许
- 更改生成源代码的布局(类名、包名、大小写规则)。
- 更改持久查询的 ID。
- 转换 JavaPoet/KotlinPoet 模型。
- 转换 Apollo IR。
实现编译器插件
在此示例中,我们将实现一个插件,该插件使用了在您的后端注册的自定义持久查询 ID。
Apollo 编译器使用ServiceLoader API在运行时加载插件。插件需要实现为一个独立模块,并将其添加到类路径中。
首先,创建一个新的 Gradle 模块并将其apollo-compiler
作为依赖项添加到build.gradle[.kts]
文件中。在此示例中,我们将使用apollo-compiler-plugin
作为模块名称:
// apollo-compiler-plugin/build.gradle.ktsplugins {id("org.jetbrains.kotlin.jvm")}dependencies {// Add apollo-compiler as a dependencyimplementation("com.apollographql.apollo:apollo-compiler:4.0.0")}
接下来,在 src/main/kotlin/mypackage/MyPlugin
文件中创建你的插件:
package mypackageimport com.apollographql.apollo.compiler.OperationOutputGeneratorimport com.apollographql.apollo.compiler.ApolloCompilerPluginimport com.apollographql.apollo.compiler.operationoutput.OperationDescriptorimport com.apollographql.apollo.compiler.operationoutput.OperationIdclass MyPlugin: ApolloCompilerPlugin {override fun operationIds(descriptors: List<OperationDescriptor>): List<OperationId> {// This assumes the returned ids are in the same order as the descriptorsreturn registerOperations(descriptors).withIndex().map { OperationId(it.value, descriptors[it.index].name) }}/*** Send operations to a remote server and return the server persisted ids*/fun registerOperations(descriptors: List<OperationDescriptor>): List<String> {// ...}}
接下来,创建一个 ApolloCompilerPluginProvider
,这是编译插件的人口点。它通过 ServiceLoader API 载入的。
class MyPluginProvider: ApolloCompilerPluginProvider {override fun create(environment: ApolloCompilerPluginEnvironment): ApolloCompilerPlugin {return MyPlugin()}}
通过在 ServiceLoader 中添加一个资源来让插件可发现:
mypackage.MyPluginProvider
ⓘ 注意
资源文件的名称很重要。它必须是 com.apollographql.apollo.compiler.ApolloCompilerPluginProvider
并位于 META-INF/services
文件夹中。这是 ServiceLoader
在运行时搜索插件的方式。
将插件添加到 Apollo 编译器类路径
使用 Service.plugin()
Gradle 方法将插件添加到 Apollo 编译器类路径:
// app/build.gradle.ktsplugins {id("org.jetbrains.kotlin.jvm")id("com.apollographql.apollo")}apollo {service("service") {packageName.set("com.example")// Add your plugin to the Apollo compiler classpathplugin(project(":apollo-compiler-plugin"))}}
插件代码将在下次调用编译器时被调用。
向 Apollo 编译器插件传递参数
由于编译插件在隔离的类路径上运行,因此您无法使用主构建逻辑类路径中的类或数据。
为了将构建时 参数传递给 Apollo 编译器插件,请使用 argument()
函数:
apollo {service("service") {packageName.set("com.example")// Add your plugin to the Apollo compiler classpathplugin(project(":apollo-compiler-plugin")) {argument("token", token)}}}
参数在 ApolloCompilerPluginEnvironment.arguments 中可用:
class MyPluginProvider: ApolloCompilerPluginProvider {override fun create(environment: ApolloCompilerPluginEnvironment): ApolloCompilerPlugin {return MyPlugin(environment.arguments.get("token") as String)}}
参数必须是可序列化的,并且是可从引导类加载器访问的类的实例。在实际应用中,支持内置类型和集合。
限制
因为在使用编译器插件时,codegen是在单独的类加载器中运行的,因此无法同时使用 packageNameGenerator
、operationIdGenerator
或operationOutputGenerator
。如果您想使用它们,您必须:
- 使用
ApolloCompilerPlugin.layout()
而不是packageNameGenerator
- 使用
ApolloCompilerPlugin.operationIds()
而不是operationIdGenerator
和operationOutputGenerator
其他参考资料
有关其他像布局、IR、JavaPoet和KotlinPoet转换之类的插件API,请参阅ApolloCompilerPlugin API 文档
有关更多示例,请查看集成测试。