Skip to content

Latest commit

 

History

History
128 lines (87 loc) · 5.18 KB

README.md

File metadata and controls

128 lines (87 loc) · 5.18 KB

Backstage extended with WebAssembly: 🥁 🎸 🎤 bigband

This repository contains examples and code to display a new pattern in developing backstage plugins -- integration with WebAssembly.

This experimental new technique relies on new standards and advanced features of WebAssembly, to take a WebAssembly binary built for $LANGUAGE, and converts that binary into the Javascript necessary

🎤 Looking for the BackstageCon 2024 slides?

Enjoyed the talk at BackstageCon 2024? Download the slides here

Dependencies

For the CLI, you'll need:

How it works

Assuming your favorite language (referred to as $LANGUAGE) has support for WebAssembly along with [WASI][wasi] preview1 (for example, in Rust this means the wasm32-wasi compilation target), you can build a WebAssembly binary that fulfills the WIT contract for the kind of plugin you care about.

1. Build a program that compiles to WebAssembly

For example, here's the WIT contract for a Backstage frontend plugin:

package backstage:plugins;

interface backstage-frontend-plugin {
  /// A representation of a node dependency (one that might be installed via `npm install`/`yarn add`)
  record node-dependency {
    /// Name of the dependency (ex. 'react')
    name: string,
    /// Version of the dependency
    version: option<string>,
    /// Whether this is a development-only dependency
    dev: bool,
  }

  // Get node dependencies that need to be installed
  get-node-deps: func() -> result<list<node-dependency>, string>;

  /// Files that make up React components to be used in in the frontend plugin
  record component-file {
    /// Path to the component file from the (root: `<project>/src/components`)
    /// ex. MyComponent/
    path: string,

    /// Whether this component is the root component for the plugin
    is-root: bool,

    /// Name of the component (used if this file represents a React component)
    /// This should be specified if is_root is specified
    component-class-name: option<string>,

    /// Contents of the
    contents: string,
  }

  /// Get the files that make up the frontend of the component
  get-component-files: func() -> result<list<component-file>, string>;
}

world plugin {
    export backstage-frontend-plugin;
}

As frontend plugins are essentially chunks of the Backstage frontend application, they primarily are concerned with packaging React components and related dependencies, so they can be installed/available when Backstage runs. Backend plugins are a little different (you can read that WIT definition as well).

For an example of how to build this, see the Examples section below.

Note

How you build your WebAssembly binary is inherently $LANGUAGE-specific!

For example, in Rust the primary way to build general WebAssembly binaries is with cargo component, but your language likely has different toolchain/requirements/setup.

2. Generate a Backstage plugin from your binary

Once you have a binary that fulfills the above contract, you can run it like so:

bigband generate \
    --plugin-type frontend \
    --plugin-id your-plugin \
    --wasm-binary path/to/your/plugin.wasm \
    --output-dir /tmp/output \
    --backstage-dir path/to/your/local/backstage/repository

Running the above command will take your WASM plugin built in $LANGUAGE, execute it to reveal important information/configuration, then generate a Backstage plugin. After generating the Backstage plugin it will actually modify your backstage repository in order to install that plugin.

To read the code for the CLI yourself, check out packages/cli.

3. Start Backstage

Assuming the installation command has executed successfully, you can run yarn dev from your local Backstage repository and view your new plugin.

For example, if your frontend plugin ID was new-plugin, you can visit localhost:3000/new-plugin to view the generated frontend.

Examples

To see how frontend and backend modules are implemented, jump to the relevant code for each:

Language Plugin Type Start here
Rust (🦀) Frontend ./examples/rust/frontend-plugin/src/lib.rs
Rust (🦀) Backend ./examples/rust/backend-plugin/src/lib.rs

Thanks

This project (bigband) works thanks to the help of pioneering projects and communities in the WebAssembly space: