-
Notifications
You must be signed in to change notification settings - Fork 4
Protobuf JS Plugin
This guide explains the usage of the Spine Protobuf JS Gradle plugin.
The Protobuf JS Plugin performs enhancement of JavaScript files generated by Protobuf compiler.
In general, all the enhancements are performed for the features needed by Spine Web. The framework users should not interact with the enhanced API. However, those enhancements are required for the Spine Web library to function properly.
The plugin can be applied as follows:
apply plugin: 'io.spine.tools.proto-js-plugin'
The plugin configuration is performed via the protoJs
extension and also requires configuring of the Protobuf compiler.
The minimal working configuration is following:
/**
* Compiles Protobuf sources into JavaScript.
*
* <p>This is a lifecycle task. It performs no action but triggers all the tasks which perform
* the compilation.
*/
task compileProtoToJs {
}
protobuf {
generatedFilesBaseDir = "${projectDir}/generated"
protoc {...}
generateProtoTasks {
all().each { final task ->
task.builtins {
js {
// Currently, the Proto JS plugin supports only Common JS imports.
option "import_style=commonjs"
}
task.generateDescriptorSet = true
task.descriptorSetOptions.path = "${projectDir}/build/descriptors/${task.sourceSet.name}/known_types.desc"
}
compileProtoToJs.dependsOn task
}
}
}
protoJs {
generateParsersTask().dependsOn compileProtoToJs
// There is no need to configure paths to generated Protobufs
// since the compiler uses default paths.
}
You can configure the paths where to put generated Protobuf files and the descriptor set file as follows:
// The example omits configuration which is not related to paths.
ext {
genProtoBaseDir = projectDir
genProtoSubDir = "proto"
genProtoMain = "$genProtoBaseDir/main/$genProtoSubDir"
}
protobuf {
generatedFilesBaseDir = genProtoBaseDir
generateProtoTasks {
all().each { final task ->
task.builtins {
js {
outputSubDir = genProtoSubDir
option "import_style=commonjs"
}
task.generateDescriptorSet = true
task.descriptorSetOptions.path = "${projectDir}/custom/${task.sourceSet.name}/known_types.desc"
}
}
}
}
protoJs {
mainGenProtoDir = genProtoMain
mainDescriptorSetPath = "$projectDir/custom/main/known_types.desc"
// The same for test files.
}
Currently, Protobuf compiler generates relative imports for dependencies of a file.
So, for a .proto
file with the following snippet:
package spine.base;
import "spine/options.proto";
The compiler generates:
var spine_options_pb = require('../../spine/options_pb.js');
In this case, you need to generate the options file by itself. Though, the plugin makes it possible to adjust import paths.
By default, the plugin handles imports of some Protobufs provided by Spine. See Extension.predefinedModules()
for the details.
So the import above is adjusted to:
var spine_options_pb = require('spine-web/proto/spine/options_pb.js');
The spine-web is an artifact published to NPM, so your project needs to have it as a dependency.
You can also specify custom modules and directories they provide. So the plugin will replace relative imports by imports of module files.
An example:
protoJs {
modules = [
// The module provides `company/client` directory (not including subdirectories).
// So, an import path like {@code ../company/client/file.js}
// becomes {@code client/company/client/file.js}.
'client' : ['company/client'],
// The module provides `company/server` directory (including subdirectories).
// So, an import path like {@code ../company/server/nested/file.js}
// becomes {@code server/company/server/nested/file.js}.
'server' : ['company/server/*'],
// The module provides 'proto/company` directory.
// So, an import pah like {@code ../company/file.js}
// becomes {@code common-types/proto/company/file.js}.
'common-types' : ['proto/company']
]
}
In the configuration above, the modules
property is a map. A key is a name of an NPM module and a value is a list of patterns describing directories provided by the module. The patterns are used to match and resolve imports.