Merge pull request #4307 from backstage/rugvip/devres
cli,config-loader,app-backend: fixes for module resolution and config loading
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Fixed module resolution of external libraries during backend development. Modules used to be resolved relative to the backend entrypoint, but are now resolved relative to each individual module.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/config-loader': patch
|
||||
---
|
||||
|
||||
Each piece of the configuration schema is now validated upfront, in order to produce more informative errors.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-app-backend': patch
|
||||
---
|
||||
|
||||
Failures to load the frontend configuration schema now throws an error that includes more context and instructions for how to fix the issue.
|
||||
@@ -219,7 +219,7 @@ export async function createBackendConfig(
|
||||
}
|
||||
: {}),
|
||||
externals: [
|
||||
nodeExternals({
|
||||
nodeExternalsWithResolve({
|
||||
modulesDir: paths.rootNodeModules,
|
||||
additionalModuleDirs: moduleDirs,
|
||||
allowlist: ['webpack/hot/poll?100', ...localPackageNames],
|
||||
@@ -296,3 +296,32 @@ export async function createBackendConfig(
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
// This makes the module resolution happen from the context of each non-external module, rather
|
||||
// than the main entrypoint. This fixes a bug where dependencies would be resolved from the backend
|
||||
// package rather than each individual backend package and plugin.
|
||||
//
|
||||
// TODO(Rugvip): Feature suggestion/contribute this to webpack-externals
|
||||
function nodeExternalsWithResolve(
|
||||
options: Parameters<typeof nodeExternals>[0],
|
||||
) {
|
||||
let currentContext: string;
|
||||
const externals = nodeExternals({
|
||||
...options,
|
||||
importType(request) {
|
||||
const resolved = require.resolve(request, {
|
||||
paths: [currentContext],
|
||||
});
|
||||
return `commonjs ${resolved}`;
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
context: string,
|
||||
request: string,
|
||||
callback: webpack.ExternalsFunctionCallback,
|
||||
) => {
|
||||
currentContext = context;
|
||||
return externals(context, request, callback);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -69,6 +69,14 @@ export function compileConfigSchemas(
|
||||
},
|
||||
});
|
||||
|
||||
for (const schema of schemas) {
|
||||
try {
|
||||
ajv.compile(schema.value);
|
||||
} catch (error) {
|
||||
throw new Error(`Schema at ${schema.path} is invalid, ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
const merged = mergeAllOf(
|
||||
{ allOf: schemas.map(_ => _.value) },
|
||||
{
|
||||
|
||||
@@ -84,13 +84,21 @@ export async function readConfigs(options: ReadOptions): Promise<AppConfig[]> {
|
||||
const schemaPath = resolvePath(appDistDir, '.config-schema.json');
|
||||
if (await fs.pathExists(schemaPath)) {
|
||||
const serializedSchema = await fs.readJson(schemaPath);
|
||||
const schema = await loadConfigSchema({ serialized: serializedSchema });
|
||||
|
||||
const frontendConfigs = await schema.process(
|
||||
[{ data: config.get() as JsonObject, context: 'app' }],
|
||||
{ visibility: ['frontend'] },
|
||||
);
|
||||
appConfigs.push(...frontendConfigs);
|
||||
try {
|
||||
const schema = await loadConfigSchema({ serialized: serializedSchema });
|
||||
|
||||
const frontendConfigs = await schema.process(
|
||||
[{ data: config.get() as JsonObject, context: 'app' }],
|
||||
{ visibility: ['frontend'] },
|
||||
);
|
||||
appConfigs.push(...frontendConfigs);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
'Invalid schema embedded in the app bundle, to fix this issue you need ' +
|
||||
`to correct the schema and then rebuild the app bundle. ${error}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return appConfigs;
|
||||
|
||||
Reference in New Issue
Block a user