cli: auto detect frontend plugins

Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Jonathan Roebuck <jroebu14@users.noreply.github.com>
Co-authored-by: Jack Palmer <UsainBloot@users.noreply.github.com>
Co-authored-by: Philipp Hugenroth <philipph@spotify.com>
Signed-off-by: Vincenzo Scamporlino <vincenzos@spotify.com>
This commit is contained in:
Vincenzo Scamporlino
2023-07-14 12:11:18 +02:00
committed by Patrik Oldsberg
parent fd7bcf9ab2
commit 08e36cdab3
7 changed files with 54 additions and 81 deletions
+1
View File
@@ -133,6 +133,7 @@
"webpack": "^5.70.0",
"webpack-dev-server": "^4.7.3",
"webpack-node-externals": "^3.0.0",
"webpack-virtual-modules": "^0.5.0",
"yaml": "^2.0.0",
"yml-loader": "^2.1.0",
"yn": "^4.0.0",
+17 -14
View File
@@ -22,6 +22,7 @@ import ModuleScopePlugin from 'react-dev-utils/ModuleScopePlugin';
import { RunScriptWebpackPlugin } from 'run-script-webpack-plugin';
import webpack, { ProvidePlugin } from 'webpack';
import nodeExternals from 'webpack-node-externals';
import VirtualModulesPlugin from 'webpack-virtual-modules';
import { isChildPath } from '@backstage/cli-common';
import { getPackages } from '@manypkg/get-packages';
import { optimization } from './optimization';
@@ -39,6 +40,7 @@ import pickBy from 'lodash/pickBy';
import yn from 'yn';
import { readEntryPoints } from '../entryPoints';
const PACKAGES_GLOBAL = '__backstage_detected_packages__';
const BUILD_CACHE_ENV_VAR = 'BACKSTAGE_CLI_EXPERIMENTAL_BUILD_CACHE';
export function resolveBaseUrl(config: Config): URL {
@@ -84,7 +86,7 @@ export async function createConfig(
paths: BundlingPaths,
options: BundlingOptions,
): Promise<webpack.Configuration> {
const { checksEnabled, isDev, frontendConfig, extraPackages } = options;
const { checksEnabled, isDev, frontendConfig, extraPackages = [] } = options;
const { plugins, loaders } = transforms(options);
// Any package that is part of the monorepo but outside the monorepo root dir need
@@ -127,19 +129,17 @@ export async function createConfig(
}),
);
plugins.push(
new ProvidePlugin(
Object.fromEntries(
extraPackages?.map(name => [
`__backstageLoadedPackage_${name}`,
name,
]) ?? [],
),
),
);
if (extraPackages.length > 0) {
const requirePackageScript = extraPackages
?.map(pkg => `require('${pkg}')`)
.join(',');
// In browser
// const packageKeys = Object.keys(window).filter(key => key.startsWith('__backstageLoadedPackage_'))
plugins.push(
new VirtualModulesPlugin({
[`node_modules/${PACKAGES_GLOBAL}.js`]: `window['${PACKAGES_GLOBAL}'] = { modules: [${requirePackageScript}] }`,
}),
);
}
const buildInfo = await readBuildInfo();
plugins.push(
@@ -177,7 +177,10 @@ export async function createConfig(
},
devtool: isDev ? 'eval-cheap-module-source-map' : 'source-map',
context: paths.targetPath,
entry: [paths.targetEntry, ...(extraPackages ?? [])],
entry: [
...(extraPackages.length > 0 ? [`${PACKAGES_GLOBAL}.js`] : []),
paths.targetEntry,
],
resolve: {
extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx', '.json', '.wasm'],
mainFields: ['browser', 'module', 'main'],
+26 -4
View File
@@ -33,8 +33,34 @@ import {
forbiddenDuplicatesFilter,
includedFilter,
} from '../../commands/versions/lint';
import { BackstagePackageJson } from '@backstage/cli-node';
export async function serveBundle(options: ServeOptions) {
const paths = resolveBundlingPaths(options);
const pkgPath = paths.targetPackageJson;
const pkg: BackstagePackageJson = await fs.readJson(pkgPath);
// TODO: proper
// Assumption for config string based on https://github.com/backstage/backstage/issues/18372 ^
const packageDetectionMode = options.fullConfig.getOptionalString(
'app.experimental.packages',
);
const extraPackages = [];
if (packageDetectionMode === 'all') {
for (const depName of Object.keys(pkg.dependencies ?? {})) {
const depPackageJson: BackstagePackageJson = require(require.resolve(
`${depName}/package.json`,
{ paths: [paths.targetPath] },
));
if (
['frontend-plugin', 'frontend-plugin-module'].includes(
depPackageJson.backstage?.role || '',
)
) {
extraPackages.push(depName);
}
}
}
if (options.verifyVersions) {
const lockfile = await Lockfile.load(
libPaths.resolveTargetRoot('yarn.lock'),
@@ -107,7 +133,6 @@ export async function serveBundle(options: ServeOptions) {
const { frontendConfig, fullConfig } = cliConfig;
// TODO: proper
const extraPackages = ['@backstage/plugin-org'];
const url = resolveBaseUrl(frontendConfig);
const host =
@@ -117,9 +142,6 @@ export async function serveBundle(options: ServeOptions) {
Number(url.port) ||
(url.protocol === 'https:' ? 443 : 80);
const paths = resolveBundlingPaths(options);
const pkgPath = paths.targetPackageJson;
const pkg = await fs.readJson(pkgPath);
const config = await createConfig(paths, {
...options,
checksEnabled: options.checksEnabled,
@@ -98,7 +98,5 @@ export function createPlugin<
>(
config: PluginConfig<Routes, ExternalRoutes, PluginInputOptions>,
): BackstagePlugin<Routes, ExternalRoutes, PluginInputOptions> {
const plugin = new PluginImpl(config);
window.allPlugins.push(plugin);
return plugin;
return new PluginImpl(config);
}
+1 -58
View File
@@ -28,65 +28,8 @@ import {
graphQlBrowseApiRef,
GraphiQLPage,
} from '../src';
// import * as orgPlugin from '@backstage/plugin-org';
// console.log(`DEBUG: orgPlugin=`, orgPlugin);
// // (process.env.EXTRA_PACKAGE_IMPORTS as string[]).map(name => require(name))
// console.log(
// `DEBUG: process.env.EXTRA_PACKAGE_IMPORTS=`,
// process.env.EXTRA_PACKAGE_IMPORTS,
// );
// require.ensure(process.env.EXTRA_PACKAGE_IMPORTS as string[], innerRequire => {
// console.log(`DEBUG: innerRequire=`, innerRequire);
// const path3 = require.resolve('@backstage/plugin-org');
// console.log(`DEBUG: path3=`, path3);
// const loadedModules = (process.env.EXTRA_PACKAGE_IMPORTS as string[]).map(
// name => console.log('require', name) || require(name),
// );
// console.log(`DEBUG: loadedModules=`, loadedModules);
// });
console.log(process.env);
console.log(
`DEBUG: process.env.EXTRA_PACKAGE_IMPORTS=`,
process.env.EXTRA_PACKAGE_IMPORTS,
);
// const orgPlugin = require([
// '@backstage/plugin-org',
// '@backstage/plugin-todo',
// ], modules => {
// console.log(`DEBUG: modules=`, modules);
// });
// require.ensure(
// process.env.EXTRA_PACKAGE_IMPORTS,
// innerRequire => {
// console.log(
// `DEBUG: module1=`,
// require(process.env.EXTRA_PACKAGE_IMPORTS[0]),
// );
// // console.log(
// // `DEBUG: module2=`,
// // innerRequire(require.resolve('@backstage/plugin-todo')),
// // );
// },
// err => console.error('ERROR CALLBACK: ', err),
// );
// console.log(`DEBUG: orgPlugin=`, orgPlugin);
// const orgPlugin2 = require(process.env.EXTRA_PACKAGE_IMPORTS, modules => {
// console.log(`DEBUG: modules=`, modules);
// });
// console.log(`DEBUG: orgPlugin2=`, orgPlugin2);
// __webpack_require__(
// process.env.EXTRA_PACKAGE_IMPORTS as string[],
// loadedModules => {
// console.log(`DEBUG: loadedModules=`, loadedModules);
// },
// );
// require.context()
console.log('modules', window.__backstage_detected_packages__.modules);
createDevApp()
.registerPlugin(graphiqlPlugin)
-2
View File
@@ -27,8 +27,6 @@ export const orgPlugin = createPlugin({
},
});
window.iAmTheOrgPlugin = orgPlugin;
/** @public */
export const EntityGroupProfileCard = orgPlugin.provide(
createComponentExtension({
+8
View File
@@ -3882,6 +3882,7 @@ __metadata:
webpack: ^5.70.0
webpack-dev-server: ^4.7.3
webpack-node-externals: ^3.0.0
webpack-virtual-modules: ^0.5.0
yaml: ^2.0.0
yml-loader: ^2.1.0
yn: ^4.0.0
@@ -42801,6 +42802,13 @@ __metadata:
languageName: node
linkType: hard
"webpack-virtual-modules@npm:^0.5.0":
version: 0.5.0
resolution: "webpack-virtual-modules@npm:0.5.0"
checksum: 22b59257b55c89d11ae295b588b683ee9fdf3aeb591bc7b6f88ac1d69cb63f4fcb507666ea986866dfae161a1fa534ad6fb4e2ea91bbcd0a6d454368d7d4c64b
languageName: node
linkType: hard
"webpack@npm:^5, webpack@npm:^5.70.0":
version: 5.88.2
resolution: "webpack@npm:5.88.2"