|
| 1 | +[id="proc-export-third-party-plugins-rhdh_{context}"] |
| 2 | += Exporting third-party plugins in {product} |
| 3 | + |
| 4 | +To use plugins in {product}, you can export plugins as derived dynamic plugin packages. These packages contain the plugin code and dependencies, ready for dynamic plugin integration into {product-short}. |
| 5 | + |
| 6 | +.Prerequisites |
| 7 | +* The `@janus-idp/cli` package is installed. Use the latest version (`@latest` tag) for compatibility with the most recent features and fixes. |
| 8 | +* Node.js and NPM is installed and configured. |
| 9 | +* The third-party plugin is compatible with your {product} version. For more information, see link:https://github.com/janus-idp/backstage-showcase/blob/main/docs/dynamic-plugins/versions.md[Version compatibility matrix]. |
| 10 | +* The third-party plugin must have a valid `package.json` file in its root directory, containing all required metadata and dependencies. |
| 11 | ++ |
| 12 | +-- |
| 13 | +Backend plugins:: |
| 14 | ++ |
| 15 | +To ensure compatibility with the dynamic plugin support and enable their use as dynamic plugins, existing backend plugins must be compatible with the new Backstage backend system. Additionally, these plugins must be rebuilt using a dedicated CLI command. |
| 16 | ++ |
| 17 | +The new Backstage backend system entry point (created using `createBackendPlugin()` or `createBackendModule()`) must be exported as the default export from either the main package or an `alpha` package (if the plugin instance support is still provided using `alpha` APIs). This doesn't add any additional requirement on top of the standard plugin development guidelines of the plugin instance. |
| 18 | ++ |
| 19 | +The dynamic export mechanism identifies private dependencies and sets the `bundleDependencies` field in the `package.json` file. This export mechanism ensures that the dynamic plugin package is published as a self-contained package, with its private dependencies bundled in a private `node_modules` folder. |
| 20 | ++ |
| 21 | +Certain plugin dependencies require specific handling in the derived packages, such as: |
| 22 | ++ |
| 23 | +* *Shared dependencies* are provided by the {product-very-short} application and listed as `peerDependencies` in `package.json` file, not bundled in the dynamic plugin package. For example, by default, all `@backstage` scoped packages are shared. |
| 24 | ++ |
| 25 | +You can use the `--shared-package` flag to specify shared dependencies, that are expected to be provided by {product} application and not bundled in the dynamic plugin package. |
| 26 | ++ |
| 27 | +To treat a `@backstage` package as private, use the negation prefix (`!`). For example, when a plugin depends on the package in `@backstage` that is not provided by the {product} application. |
| 28 | + |
| 29 | +* *Embedded dependencies* are bundled into the dynamic plugin package with their dependencies hoisted to the top level. By default, packages with `-node` or `-common` suffixes are embedded. |
| 30 | ++ |
| 31 | +You can use the `--embed-package` flag to specify additional embedded packages. For example, packages from the same workspace that do not follow the default naming convention. |
| 32 | ++ |
| 33 | +The following is an example of exporting a dynamic plugin with shared and embedded packages: |
| 34 | ++ |
| 35 | +.Example dynamic plugin export with shared and embedded packages |
| 36 | +[source,terminal] |
| 37 | +---- |
| 38 | +npx @janus-idp/cli@latest export-dynamic-plugin --shared-package '!/@backstage/plugin-notifications/' <1> --embed-package @backstage/plugin-notifications-backend <2> |
| 39 | +---- |
| 40 | ++ |
| 41 | +<1> `@backstage/plugin-notifications` package is treated as a private dependency and is bundled in the dynamic plugin package, despite being in the `@backstage` scope. |
| 42 | +<2> `@backstage/plugin-notifications-backend` package is marked as an embedded dependency and is bundled in the dynamic plugin package. |
| 43 | + |
| 44 | +Front-end plugins:: |
| 45 | ++ |
| 46 | +Front-end plugins can use `scalprum` for configuration, which the CLI can generate automatically during the export process. The generated default configuration is logged when running the following command: |
| 47 | ++ |
| 48 | +.Example command to log the default configuration |
| 49 | +[source,terminal] |
| 50 | +---- |
| 51 | +npx @janus-idp/cli@latest export-dynamic |
| 52 | +---- |
| 53 | ++ |
| 54 | +The following is an example of default `scalprum` configuration: |
| 55 | ++ |
| 56 | +.Default `scalprum` configuration |
| 57 | +[source,json] |
| 58 | +---- |
| 59 | +"scalprum": { |
| 60 | + "name": "<package_name>", // The Webpack container name matches the NPM package name, with "@" replaced by "." and "/" removed. |
| 61 | + "exposedModules": { |
| 62 | + "PluginRoot": "./src/index.ts" // The default module name is "PluginRoot" and doesn't need explicit specification in the app-config.yaml file. |
| 63 | + } |
| 64 | +} |
| 65 | +---- |
| 66 | ++ |
| 67 | +You can add a `scalprum` section to the `package.json` file. For example: |
| 68 | ++ |
| 69 | +.Example `scalprum` customization |
| 70 | +[source,json] |
| 71 | +---- |
| 72 | +"scalprum": { |
| 73 | + "name": "custom-package-name", |
| 74 | + "exposedModules": { |
| 75 | + "FooModuleName": "./src/foo.ts", |
| 76 | + "BarModuleName": "./src/bar.ts" |
| 77 | + // Define multiple modules here, with each exposed as a separate entry point in the Webpack container. |
| 78 | + } |
| 79 | +} |
| 80 | +---- |
| 81 | ++ |
| 82 | +Dynamic plugins might need adjustments for {product-short} needs, such as static JSX for mountpoints or dynamic routes. These changes are optional but might be incompatible with static plugins. |
| 83 | ++ |
| 84 | +To include static JSX, define an additional export and use it as the dynamic plugin's `importName`. For example: |
| 85 | ++ |
| 86 | +.Example static and dynamic plugin export |
| 87 | +[source,tsx] |
| 88 | +---- |
| 89 | +// For a static plugin |
| 90 | +export const EntityTechdocsContent = () => {...} |
| 91 | +
|
| 92 | +// For a dynamic plugin |
| 93 | +export const DynamicEntityTechdocsContent = { |
| 94 | + element: EntityTechdocsContent, |
| 95 | + staticJSXContent: ( |
| 96 | + <TechDocsAddons> |
| 97 | + <ReportIssue /> |
| 98 | + </TechDocsAddons> |
| 99 | + ), |
| 100 | +}; |
| 101 | +---- |
| 102 | +-- |
| 103 | + |
| 104 | +.Procedure |
| 105 | +* Use the `package export-dynamic-plugin` command from the `@janus-idp/cli` package to export the plugin: |
| 106 | ++ |
| 107 | +-- |
| 108 | +.Example command to export a third-party plugin |
| 109 | +[source,terminal] |
| 110 | +---- |
| 111 | +npx @janus-idp/cli@latest package export-dynamic-plugin |
| 112 | +---- |
| 113 | + |
| 114 | +Ensure that you execute the previous command in the root directory of the plugin's JavaScript package (containing `package.json` file). |
| 115 | + |
| 116 | +The resulting derived package will be located in the `dist-dynamic` subfolder. The exported package name consists of the original plugin name with `-dynamic` appended. |
| 117 | + |
| 118 | +[WARNING] |
| 119 | +==== |
| 120 | +The derived dynamic plugin JavaScript packages must not be published to the public NPM registry. For more appropriate packaging options, see xref:assembly-package-publish-third-party-dynamic-plugin[]. If you must publish to the NPM registry, use a private registry. |
| 121 | +==== |
| 122 | +-- |
| 123 | + |
| 124 | + |
0 commit comments