The demo app can be built and launched from the command line with bazel:
bazel build //docs/site:site
bazel run //docs/site:siteAdding a new plugin is simple using predefined macros for BUILD.bazel files.
Core plugins provide shared functionality, usable on all platforms i.e. as Player Core runs on every platform, any core Player plugin will also run on every platform which allows for shared functionality to be authored once and shared across every platform.
React plugins add react specific functionality.
All plugins follow a common structure:
The basic structure is as follows:
plugins/example
├── react
│ ├── BUILD.bazel
│ ├── src
│ │ ├── index.tsx
│ │ └── __tests__
│ │ └── index.test.tsx
│ └── package.json
└── core
├── BUILD.bazel
├── src
│ ├── index.ts
│ └── __tests__
│ └── index.test.ts
└── package.jsonTo scaffold your plugin, create a new core or react folder in the appropriate plugin directory, with the appropriate folders, a package.json and a blank BUILD.bazel:
For core plugins:
mkdir -p plugins/example-plugin/core/src
cd plugins/example-plugin/core
pnpm init
touch BUILD.bazelFor react plugins:
mkdir -p plugins/example-plugin/react/src
cd plugins/example-plugin/react
pnpm init
touch BUILD.bazelSet the name, version, and entry point of the package in the package.json:
For core plugins:
{
"name": "@player-ui/example-plugin-core",
"version": "0.0.0-PLACEHOLDER",
"main": "src/index.ts",
}For react plugins:
{
"name": "@player-ui/example-plugin-react",
"version": "0.0.0-PLACEHOLDER",
"main": "src/index.tsx",
}Note
The package follows a naming convemtion of @player-ui/{description}-plugin-{platform}.
The js_pipeline macro will handle the full build:
load("@rules_player//javascript:defs.bzl", "js_pipeline")
js_pipeline(package_name = "@player-ui/example-plugin-core")In order to use the tsup bundler, add tsup_config to the BUILD.bazel file. This is done by loading the tsup_config helper from the tools package and calling it within BUILD.bazel:
load("//tools:defs.bzl", "tsup_config")
tsup_config(name = "tsup_config")All plugins leverage vitest for testing. To use vitest, add vitest_config to the BUILD.bazel file. This is done by loading the vitest_config helper from the tools package and calling it within BUILD.bazel:
load("//tools:defs.bzl", "...", "vitest_config")
vitest_config(name = "vitest_config")Since each package can have different external dependencies, they each need to have their own node_modules. pnpm supports a single lock file for multiple packages by setting up a pnpm-workspace.yaml. The resulting lock file can be used by rules_js to set up a Bazel workspace with multiple packages that each get their own node_modules folder in the bin tree. The npm_link_all_packages rule will automatically set up the correct node_modules folder based on the Bazel package name and the pnpm-lock.yaml. Add the following to your BUILD.bazel file.
load("@npm//:defs.bzl", "npm_link_all_packages")
npm_link_all_packages(name = "node_modules")js_pipeline takes deps, test_deps, and peer_deps to allow specifying dependencies:
js_pipeline(
package_name = "@player-ui/example-plugin-core",
peer_deps = [
"//:node_modules/react",
],
deps = [
":node_modules/@player-ui/react-subscribe",
],
test_deps = [
":node_modules/@player-ui/common-types-plugin",
],
)Note
External dependencies are specified as such //:node_modules/... with the leading //, while internal dependencies are specified as such :node_modules/... without the leading //.
Internal dependencies also need to be added to the package.json either as a dependency, dev dependency, or peer dependency:
{
...
"dependencies": {
"@player-ui/react-subscribe": "workspace:*",
},
"devDependencies": {
"@player-ui/common-types-plugin": "workspace:*",
}
...
}Add the new package's node_modules directory to .bazelignore:
plugins/example-plugin/core/node_modules