-
Notifications
You must be signed in to change notification settings - Fork 149
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(docs): installing external plugins and dynamic-plugins doc clea…
…nup (#1895) * chode(docs): installing external plugins * chore(docs): cleanup, better wording * chore(docs): improve wording and formatting in external plugins installation guide * chore(docs): remove TOC, when rendered using techdocs it is generated automaticaly * docs: break dynamic-plugins.md file
- Loading branch information
Showing
8 changed files
with
1,044 additions
and
1,116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
|
||
# Debugging Dynamic Plugins | ||
|
||
## Backend Dynamic Plugins Local Debug | ||
|
||
For local debugging of Dynamic Plugins you need to clone `backstage-showcase`, run it with debugging enabled and attach your IDE debugger to the backend process. First it is required to build and copy the dynamic plugin: | ||
|
||
* Build your plugin and export the dynamic package | ||
|
||
``` | ||
cd ${pluginRootDir} | ||
yarn build && yarn run export-dynamic | ||
``` | ||
|
||
* Copy the resulting `dist-dynamic` directory to dynamic-plugins-root/${plugin-id} | ||
|
||
Once the plugin is built and deployed, it is time to prepare the showcase to run it debug mode: | ||
|
||
* Go to `backstage-showcase` root directory; | ||
* Run `yarn workspace backend start --inspect` | ||
* In logs you should see something like the following: | ||
|
||
``` | ||
Debugger listening on ws://127.0.0.1:9229/9299bb26-3c32-4781-9488-7759b8781db5 | ||
``` | ||
|
||
* The application will be acessible from `http://localhost:7007`. You may start the front end by running the following command from the root directory: `yarn start --filter=app`. It will be available in `http://localhost:3000` | ||
* Attach your IDE debugger to the backend process. This step may depend on the IDE that you are using. For example, if you are using VSCode you may want to check [Node.js debugging in VS Code](https://code.visualstudio.com/docs/nodejs/nodejs-debugging) | ||
* Add Breakpoints to the files in folder `dynamic-plugins-root/${plugin-id}`. Optionally you can configure your IDE to add the source maps for the plugin so you can debug the TypeScript code directly and not the compiled Javascript files | ||
|
||
## Backend Dynamic Plugins Container Debug | ||
|
||
It is possible to run RHDH on a container and debug plugins that are running on it. In this case you don't need to clone the `backstage-showcase` code locally, instead you must make sure that the running container has the [Node JS debug](https://nodejs.org/en/learn/getting-started/debugging) port open and exposed to the host machine. These are the steps to debug backend dynamic plugins on a container: | ||
|
||
* Create directory `dynamic-plugins-root` | ||
* Build your plugin and copy the folder `dist-dynamic` to `dynamic-plugins-root` | ||
|
||
``` | ||
$ yarn build && yarn export-dynamic | ||
$ cp ${yourPluginRootDir}/dist-dynamic ./dynamic-plugins-root/${pluginID} | ||
``` | ||
|
||
* Start the container and make sure to share the plugins directory with it, allow inspect and open the debug port. Here's a sample command tested on RHDH container image version 1.3: | ||
|
||
``` | ||
podman run \ | ||
-v ./dynamic-plugins-root:/opt/app-root/src/dynamic-plugins-root:Z \ | ||
-v ./app-config.local.yaml:/opt/app-root/src/app-config.local.yaml:Z \ | ||
-p 7007:7007 \ | ||
-p 9229:9229 \ | ||
-e NODE_OPTIONS=--no-node-snapshot \ | ||
--entrypoint='["node", "--inspect=0.0.0.0:9229", "packages/backend", "--config", "app-config.yaml", "--config", "app-config.example.yaml", "--config", "app-config.local.yaml"]' \ | ||
quay.io/rhdh/rhdh-hub-rhel9:1.3 | ||
``` | ||
|
||
You should be able to debug from your IDE by attaching it to the process running on port `9229` or selecting it from a list of processes detected by the IDE. | ||
|
||
## Frontend Dynamic Plugins Debug | ||
|
||
Front end plugins can be debugged directly on your browser, just make sure to export the sources map. When running the plugin on the browser open the Developer Tools and you should be able to visualize the source code and place breakpoints. |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
# Export Derived Dynamic Plugin Package | ||
|
||
In order to be able to use dynamic plugins in the RHDH, they need to be exported as a separate package. Which is than used by the RHDH to load the plugin. | ||
Exporting a dynamic plugin package is a process of creating a new package that contains the plugin code and its dependencies, and is ready to be used as a dynamic plugin in the RHDH. | ||
|
||
This document describes how to export a dynamic plugin package from an existing Backstage plugin. | ||
|
||
The exporting is done using the `package export-dynamic-plugin` command from the `@janus-idp/cli` package. | ||
The most convenient way to run the command is to use `npx`: | ||
|
||
```bash | ||
npx @janus-idp/cli@latest package export-dynamic-plugin | ||
``` | ||
|
||
This command needs to be executed in the root folder of the JavaScript package (with `package.json`) of the plugin that you want to export as a dynamic plugin. | ||
|
||
The resulting package will be located in the `dist-dynamic` sub-folder. The name of the exported packaged is modified by adding the `-dynamic` suffix to the plugin name. | ||
|
||
This allows packing it with `npm pack`, or publishing it to npm registry. See [Packaging Dynamic Plugins](packaging-dynamic-plugins.md) for more information on how to package and distribute dynamic plugins. | ||
|
||
> [!NOTE] | ||
> The derived dynamic plugin JavaScript packages should **not** be pushed to the public npm registry. They should only be published to a private npm registry. | ||
This documentation uses `@latest` tag to ensure that the latest version of the `@janus-idp/cli` package is used. | ||
But you need to make sure that you are using the version of the `@janus-idp/cli` package that is compatible with your RHDH version. | ||
You can find the compatible versions in the [Version Matrix](./versions.md). | ||
|
||
If you are developing your own plugin that is going to be used as a dynamic plugin, it might be useful to add the `export-dynamic-plugin` command to the `package.json` file as a script: | ||
|
||
```json | ||
{ | ||
"scripts": { | ||
"export-dynamic": "janus-cli package package export-dynamic-plugin" | ||
}, | ||
"devDependencies": { | ||
"@janus-idp/cli": "^1.18.0" | ||
} | ||
} | ||
``` | ||
|
||
## Backend plugins | ||
|
||
To be compatible with the showcase dynamic plugin support, and used as dynamic plugins, existing plugins must be based on, or compatible with, the new backend system, as well as rebuilt with a dedicated CLI command. | ||
|
||
The new backend system standard entry point (created using `createBackendPlugin()` or `createBackendModule()`) should be exported as the default export of either the main package or of an `alpha` package (if the new backend support is still provided as `alpha` APIs). This doesn't add any additional requirement on top of the standard plugin development guidelines of the new backend system. | ||
For a practical example of a dynamic plugin entry point built upon the new backend system, please refer to the [Janus plugins repository](https://github.com/janus-idp/backstage-plugins/blob/main/plugins/aap-backend/src/module.ts#L25). | ||
|
||
The dynamic export mechanism identifies private, non-backstage dependencies, and sets the `bundleDependencies` field in the `package.json` file for them, so that the dynamic plugin package can be published as a self-contained package, along with its private dependencies bundled in a private `node_modules` folder. | ||
|
||
### Shared dependencies | ||
|
||
During the exporting process some dependencies are marked as shared dependencies, and are expected to be provided by the main Backstage application. These dependencies are not bundled in the dynamic plugin package, but are marked as `peerDependencies` in the `package.json` file. | ||
By default all the `@backstage`-scoped packages are considered shared packages. | ||
|
||
Using `--shared-package` flag you can control which packages are considered shared packages. | ||
Shared packages are expected to be provided by the main Backstage application, and are not bundled in the dynamic plugin package. | ||
The `--shared-package` flag can be used multiple times to specify multiple shared packages. | ||
|
||
If plugin depends on a package that is in the `@backstage` scope, but is not provided by the main Backstage application, you can use the negation prefix `!` to specify that it should be considered as a private dependency of the dynamic plugin. | ||
|
||
### Embedded dependencies | ||
|
||
During the exporting process some dependencies are marked as embedded dependencies, and are bundled in the dynamic plugin package. | ||
Embedded packages are merged into the dynamic plugin package, and their dependencies are hoisted to the top level of the dynamic plugin package. | ||
By default, all packages with `-node` or `-common` suffix are automatically embedded in the exported plugin package. | ||
|
||
Using `--embed-package` flag you can control which packages are embedded in the dynamic plugin package. | ||
The `--embed-package` flag can be used multiple times to specify multiple embedded packages. | ||
|
||
If plugin depends on another package that is in the same monorepo workspace and it doesn't follow stadart naming convention (`-node`, or `-common`), you can use the `--embed-package` flag to embed it in the dynamic plugin package. | ||
|
||
Example of exporting a dynamic plugin with shared and embedded packages: | ||
|
||
```bash | ||
npx @janus-idp/cli@latest export-dynamic-plugin --shared-package '!/@backstage/plugin-notifications/' --embed-package @backstage/plugin-notifications-backend | ||
``` | ||
|
||
In this example, the `@backstage/plugin-notifications` package is marked as a private dependency (not shared) and it will be bundled in the dynamic plugin package, even though it is in the `@backstage` scope. | ||
The `@backstage/plugin-notifications-backend` package is marked as an embedded dependency, and it will be bundled in the dynamic plugin package. | ||
|
||
## Frontend plugins | ||
|
||
Our CLI can generate the default configuration for Scalprum on the fly. For generated defaults see logs when running `npx @janus-idp/cli@latest export-dynamic`. We default to the following configuration: | ||
|
||
```json | ||
... | ||
"scalprum": { | ||
"name": "<package_name>", // Webpack container name is the same as NPM package name without "@" symbol and "/" replaced with "." | ||
"exposedModules": { | ||
"PluginRoot": "./src/index.ts" // PluginRoot module name is the default, therefore it doesn't have to be explicitly specified later in the app-config.yaml file | ||
} | ||
}, | ||
... | ||
``` | ||
|
||
//TODO document how to use a separate file for the Scalprum configuration which should be a preferred way to customize Scalprum's behavior. | ||
|
||
However if you want to customize Scalprum's behavior, you can do so by including additional section to the `package.json` under `scalprum` key: | ||
|
||
```json | ||
... | ||
"scalprum": { | ||
"name": "custom-package-name", | ||
"exposedModules": { | ||
"FooModuleName": "./src/foo.ts", | ||
"BarModuleName": "./src/bar.ts", | ||
... | ||
// You can export multiple modules here. Each module will be exposed as a separate entrypoint in the Webpack container. | ||
} | ||
}, | ||
... | ||
``` | ||
|
||
Dynamic plugins may also need to adopt to specific Backstage needs like static JSX children for mountpoints and dynamic routes. These changes are strictly optional and exported symbols are incompatible with static plugins. | ||
|
||
To include static JSX as element children with your dynamically imported component, please define an additional export as follows and use that as your dynamic plugin `importName`: | ||
|
||
```tsx | ||
// Used by a static plugin | ||
export const EntityTechdocsContent = () => {...} | ||
|
||
// Used by a dynamic plugin | ||
export const DynamicEntityTechdocsContent = { | ||
element: EntityTechdocsContent, | ||
staticJSXContent: ( | ||
<TechDocsAddons> | ||
<ReportIssue /> | ||
</TechDocsAddons> | ||
), | ||
}; | ||
``` | ||
|
||
Important part of the frontend dynamic plugins is its layout configuration (bindings and routes). For more information on how to configure bindings and routes, see [Layout Configuration](layoud-configuration.md). |
Oops, something went wrong.