Skip to content

Commit

Permalink
refactor(cli): new --in-place/--no-in-place option to the `export…
Browse files Browse the repository at this point in the history
…-dynamic-plugin` CLI command to allow exporting to `dist-dynamic` (when value is `false`). (#1584)

refactor(cli): New `--in-place`/`--no-in-place` option to the `export-dynamic-plugin` CLI command to allow exporting to `dist-dynamic` (when value is `false`).

Signed-off-by: David Festal <[email protected]>
  • Loading branch information
davidfestal authored Apr 30, 2024
1 parent f868a85 commit 4b5cc40
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ function checkWorkspacePackageVersion(
);
}

function customizeForDynamicUse(options: {
export function customizeForDynamicUse(options: {
embedded: ResolvedEmbedded[];
monoRepoPackages: Packages | undefined;
sharedPackages?: SharedPackagesRules | undefined;
Expand Down
10 changes: 6 additions & 4 deletions packages/cli/src/commands/export-dynamic-plugin/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import chalk from 'chalk';
import { OptionValues } from 'commander';
import fs from 'fs-extra';

import path from 'path';

import { paths } from '../../lib/paths';
import { getConfigSchema } from '../../lib/schema/collect';
import { Task } from '../../lib/tasks';
Expand All @@ -28,9 +30,9 @@ import { backend as backendEmbedAsDependencies } from './backend-embed-as-depend
import { applyDevOptions } from './dev';
import { frontend } from './frontend';

const saveSchema = async (packageName: string, path: string) => {
const saveSchema = async (packageName: string, destination: string) => {
const configSchema = await getConfigSchema(packageName);
await fs.writeJson(paths.resolveTarget(path), configSchema, {
await fs.writeJson(paths.resolveTarget(destination), configSchema, {
encoding: 'utf8',
spaces: 2,
});
Expand All @@ -53,10 +55,10 @@ export async function command(opts: OptionValues): Promise<void> {
} else {
targetPath = await backendEmbedAsCode(roleInfo, opts);
}
configSchemaPath = 'dist-dynamic/dist/configSchema.json';
configSchemaPath = path.join(targetPath, 'dist/configSchema.json');
} else if (role === 'frontend-plugin') {
targetPath = await frontend(roleInfo, opts);
configSchemaPath = 'dist-scalprum/configSchema.json';
configSchemaPath = path.join(targetPath, 'dist-scalprum/configSchema.json');
} else {
throw new Error(
'Only packages with the "backend-plugin", "backend-plugin-module" or "frontend-plugin" roles can be exported as dynamic backend plugins',
Expand Down
71 changes: 68 additions & 3 deletions packages/cli/src/commands/export-dynamic-plugin/frontend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,28 @@

import { PackageRoleInfo } from '@backstage/cli-node';

import { getPackages } from '@manypkg/get-packages';
import chalk from 'chalk';
import { OptionValues } from 'commander';
import fs from 'fs-extra';

import path from 'path';

import { buildScalprumPlugin } from '../../lib/builder/buildScalprumPlugin';
import { productionPack } from '../../lib/packager/productionPack';
import { paths } from '../../lib/paths';
import { Task } from '../../lib/tasks';
import { customizeForDynamicUse } from './backend-embed-as-dependencies';

export async function frontend(
_: PackageRoleInfo,
__: OptionValues,
opts: OptionValues,
): Promise<string> {
const {
name,
version,
scalprum: scalprumExternal,
files,
} = await fs.readJson(paths.resolveTarget('package.json'));

let scalprum = scalprumExternal;
Expand All @@ -54,7 +62,63 @@ export async function frontend(
);
}

await fs.remove(paths.resolveTarget('dist-scalprum'));
const distDynamicRelativePath = 'dist-dynamic';
const target = opts.inPlace
? path.resolve(paths.targetDir)
: path.resolve(paths.targetDir, distDynamicRelativePath);

if (!opts.inPlace) {
Task.log(
`Packing main package to ${chalk.cyan(
path.join(distDynamicRelativePath, 'package.json'),
)}`,
);

if (opts.clean) {
await fs.remove(target);
}

await fs.mkdirs(target);

await productionPack({
packageDir: paths.targetDir,
targetDir: target,
});

Task.log(
`Customizing main package in ${chalk.cyan(
path.join(distDynamicRelativePath, 'package.json'),
)} for dynamic loading`,
);
if (files && Array.isArray(files) && !files.includes('dist-scalprum')) {
files.push('dist-scalprum');
}
const monoRepoPackages = await getPackages(paths.targetDir);
await customizeForDynamicUse({
embedded: [],
monoRepoPackages,
overridding: {
name: `${name}-dynamic`,
// We remove scripts, because they do not make sense for this derived package.
// They even bring errors, especially the pre-pack and post-pack ones:
// we want to be able to use npm pack on this derived package to distribute it as a dynamic plugin,
// and obviously this should not trigger the backstage pre-pack or post-pack actions
// which are related to the packaging of the original static package.
scripts: {},
files,
},
})(path.resolve(target, 'package.json'));
}

const resolvedScalprumDistPath = path.join(target, 'dist-scalprum');

Task.log(
`Generating dynamic frontend plugin assets in ${chalk.cyan(
resolvedScalprumDistPath,
)}`,
);

await fs.remove(resolvedScalprumDistPath);

await buildScalprumPlugin({
writeStats: false,
Expand All @@ -65,7 +129,8 @@ export async function frontend(
version,
},
fromPackage: name,
resolvedScalprumDistPath,
});

return paths.targetDir;
return target;
}
10 changes: 9 additions & 1 deletion packages/cli/src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,16 @@ export function registerScriptCommand(program: Command) {
)
.option(
'--embed-as-dependencies',
'Include embedded packages as private dependencies, instead of merging the with the generated code. Experimental for now, but expected to become the default.',
'Include embedded packages as private dependencies of backend plugins, instead of merging them with the generated code. Experimental for now, but expected to become the default.',
false,
)
.option('--no-embed-as-dependencies', undefined, true)
.option(
'--in-place',
'Adds the frontend dynamic plugin assets to the `dist-scalprum` folder of the original plugin package. When value is `false` (using `--no-in-place`), it produces the assets in a distinct package located in the `dist-dynamic` sub-folder, as for backend plugins. `true` by default for now, it is expected to become `false` by default.',
true,
)
.option('--no-in-place', undefined, false)
.action(lazy(() => import('./export-dynamic-plugin').then(m => m.command)));

command
Expand Down
5 changes: 4 additions & 1 deletion packages/cli/src/lib/builder/buildScalprumPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ interface BuildScalprumPluginOptions {
configPaths: string[];
pluginMetadata: PluginBuildMetadata;
fromPackage: string;
resolvedScalprumDistPath: string;
}

export async function buildScalprumPlugin(options: BuildScalprumPluginOptions) {
const { targetDir, pluginMetadata, fromPackage } = options;
const { targetDir, pluginMetadata, fromPackage, resolvedScalprumDistPath } =
options;
await buildScalprumBundle({
targetDir,
entry: 'src/index',
Expand All @@ -23,5 +25,6 @@ export async function buildScalprumPlugin(options: BuildScalprumPluginOptions) {
args: [],
fromPackage,
})),
resolvedScalprumDistPath,
});
}
32 changes: 22 additions & 10 deletions packages/cli/src/lib/bundler/bundlePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,35 @@ function applyContextToError(error: string, moduleName: string): string {
}

export async function buildScalprumBundle(
options: BundlingPathsOptions & DynamicPluginOptions,
options: BundlingPathsOptions &
DynamicPluginOptions & {
resolvedScalprumDistPath: string;
},
) {
const paths = resolveBundlingPaths(options);
const config = await createScalprumConfig(paths, {
...options,
checksEnabled: false,
isDev: false,
baseUrl: resolveBaseUrl(options.frontendConfig),
});
const config = await createScalprumConfig(
{
targetScalprumDist: options.resolvedScalprumDistPath,
...paths,
},
{
...options,
checksEnabled: false,
isDev: false,
baseUrl: resolveBaseUrl(options.frontendConfig),
},
);

const isCi = yn(process.env.CI, { default: false });

const previousFileSizes = await measureFileSizesBeforeBuild(
paths.targetScalprumDist,
options.resolvedScalprumDistPath,
);
await fs.emptyDir(paths.targetScalprumDist);
await fs.emptyDir(options.resolvedScalprumDistPath);

// TODO(davidfestal): ask @tumido or @Hyperkid123if this still makes sense here for dynamic plugins.
// That seems strange since the public assets are not copied to `dist-scalprum`,
// which is the place from where the dynamic plugin assets will be served
if (paths.targetPublic) {
await fs.copy(paths.targetPublic, paths.targetDist, {
dereference: true,
Expand All @@ -56,7 +68,7 @@ export async function buildScalprumBundle(
printFileSizesAfterBuild(
stats,
previousFileSizes,
paths.targetScalprumDist,
options.resolvedScalprumDistPath,
WARN_AFTER_BUNDLE_GZIP_SIZE,
WARN_AFTER_CHUNK_GZIP_SIZE,
);
Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/lib/bundler/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ export function resolveBundlingPaths(options: BundlingPathsOptions) {
targetPath: resolvePath(targetDir, '.'),
targetRunFile: runFileExists ? targetRunFile : undefined,
targetDist: resolvePath(targetDir, 'dist'),
targetScalprumDist: resolvePath(targetDir, 'dist-scalprum'),
targetAssets: resolvePath(targetDir, 'assets'),
targetSrc: resolvePath(targetDir, 'src'),
targetDev: resolvePath(targetDir, 'dev'),
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/lib/bundler/scalprumConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const sharedModules = {
};

export async function createScalprumConfig(
paths: BundlingPaths,
paths: BundlingPaths & { targetScalprumDist: string },
options: DynamicPluginOptions,
): Promise<webpack.Configuration> {
const { checksEnabled, isDev } = options;
Expand Down

0 comments on commit 4b5cc40

Please sign in to comment.