feat(angular): support esbuild middleware functions (#21048)

This commit is contained in:
Dmitriy Stepanenko 2024-01-22 19:34:02 +02:00 committed by GitHub
parent cb5eeb7475
commit c1238aad5e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 52 additions and 2 deletions

View File

@ -109,6 +109,14 @@
"type": "boolean", "type": "boolean",
"description": "Read buildable libraries from source instead of building them separately. If not set, it will take the value specified in the `browserTarget` options, or it will default to `true` if it's also not set in the `browserTarget` options.", "description": "Read buildable libraries from source instead of building them separately. If not set, it will take the value specified in the `browserTarget` options, or it will default to `true` if it's also not set in the `browserTarget` options.",
"x-priority": "important" "x-priority": "important"
},
"esbuildMiddleware": {
"description": "A list of HTTP request middleware functions. _Note: this is only supported in Angular versions >= 17.0.0_.",
"type": "array",
"items": {
"type": "string",
"description": "The path to the middleware function. Relative to the workspace root."
}
} }
}, },
"additionalProperties": false, "additionalProperties": false,

View File

@ -45,6 +45,7 @@
"ignoredDependencies": [ "ignoredDependencies": [
"nx", "nx",
"eslint", "eslint",
"vite",
"rxjs", "rxjs",
"semver", "semver",
// These are installed by ensurePackage so missing in package.json // These are installed by ensurePackage so missing in package.json

View File

@ -10,8 +10,8 @@ import {
normalizePath, normalizePath,
parseTargetString, parseTargetString,
readCachedProjectGraph, readCachedProjectGraph,
stripIndents,
type Target, type Target,
targetToTargetString,
} from '@nx/devkit'; } from '@nx/devkit';
import { getRootTsConfigPath } from '@nx/js'; import { getRootTsConfigPath } from '@nx/js';
import type { DependentBuildableProjectNode } from '@nx/js/src/utils/buildable-libs-utils'; import type { DependentBuildableProjectNode } from '@nx/js/src/utils/buildable-libs-utils';
@ -24,6 +24,7 @@ import { combineLatest, from } from 'rxjs';
import { switchMap } from 'rxjs/operators'; import { switchMap } from 'rxjs/operators';
import { getInstalledAngularVersionInfo } from '../../executors/utilities/angular-version-utils'; import { getInstalledAngularVersionInfo } from '../../executors/utilities/angular-version-utils';
import { import {
loadMiddleware,
loadPlugins, loadPlugins,
type PluginSpec, type PluginSpec,
} from '../../executors/utilities/esbuild-extensions'; } from '../../executors/utilities/esbuild-extensions';
@ -45,12 +46,22 @@ type BuildTargetOptions = {
customWebpackConfig?: { path?: string }; customWebpackConfig?: { path?: string };
indexFileTransformer?: string; indexFileTransformer?: string;
plugins?: string[] | PluginSpec[]; plugins?: string[] | PluginSpec[];
esbuildMiddleware?: string[];
}; };
export function executeDevServerBuilder( export function executeDevServerBuilder(
rawOptions: Schema, rawOptions: Schema,
context: import('@angular-devkit/architect').BuilderContext context: import('@angular-devkit/architect').BuilderContext
) { ) {
if (rawOptions.esbuildMiddleware) {
const { major: angularMajorVersion, version: angularVersion } =
getInstalledAngularVersionInfo();
if (angularMajorVersion < 17) {
throw new Error(stripIndents`The "esbuildMiddleware" option is only supported in Angular >= 17.0.0. You are currently using "${angularVersion}".
You can resolve this error by removing the "esbuildMiddleware" option or by migrating to Angular 17.0.0.`);
}
}
process.env.NX_TSCONFIG_PATH = getRootTsConfigPath(); process.env.NX_TSCONFIG_PATH = getRootTsConfigPath();
const options = normalizeOptions(rawOptions); const options = normalizeOptions(rawOptions);
@ -164,8 +175,11 @@ export function executeDevServerBuilder(
return combineLatest([ return combineLatest([
from(import('@angular-devkit/build-angular')), from(import('@angular-devkit/build-angular')),
from(loadPlugins(buildTargetOptions.plugins, buildTargetOptions.tsConfig)), from(loadPlugins(buildTargetOptions.plugins, buildTargetOptions.tsConfig)),
from(
loadMiddleware(options.esbuildMiddleware, buildTargetOptions.tsConfig)
),
]).pipe( ]).pipe(
switchMap(([{ executeDevServerBuilder }, plugins]) => switchMap(([{ executeDevServerBuilder }, plugins, middleware]) =>
executeDevServerBuilder( executeDevServerBuilder(
delegateBuilderOptions, delegateBuilderOptions,
context, context,
@ -217,6 +231,7 @@ export function executeDevServerBuilder(
}, },
{ {
buildPlugins: plugins, buildPlugins: plugins,
middleware,
} }
) )
) )

View File

@ -17,6 +17,7 @@ interface BaseSchema {
watch?: boolean; watch?: boolean;
poll?: number; poll?: number;
buildLibsFromSource?: boolean; buildLibsFromSource?: boolean;
esbuildMiddleware?: string[];
} }
export type SchemaWithBrowserTarget = BaseSchema & { export type SchemaWithBrowserTarget = BaseSchema & {

View File

@ -115,6 +115,14 @@
"type": "boolean", "type": "boolean",
"description": "Read buildable libraries from source instead of building them separately. If not set, it will take the value specified in the `browserTarget` options, or it will default to `true` if it's also not set in the `browserTarget` options.", "description": "Read buildable libraries from source instead of building them separately. If not set, it will take the value specified in the `browserTarget` options, or it will default to `true` if it's also not set in the `browserTarget` options.",
"x-priority": "important" "x-priority": "important"
},
"esbuildMiddleware": {
"description": "A list of HTTP request middleware functions. _Note: this is only supported in Angular versions >= 17.0.0_.",
"type": "array",
"items": {
"type": "string",
"description": "The path to the middleware function. Relative to the workspace root."
}
} }
}, },
"additionalProperties": false, "additionalProperties": false,

View File

@ -1,5 +1,6 @@
import { registerTsProject } from '@nx/js/src/internal'; import { registerTsProject } from '@nx/js/src/internal';
import type { Plugin } from 'esbuild'; import type { Plugin } from 'esbuild';
import type { Connect } from 'vite';
import { loadModule } from './module-loader'; import { loadModule } from './module-loader';
export type PluginSpec = { export type PluginSpec = {
@ -39,3 +40,19 @@ async function loadPlugin(pluginSpec: string | PluginSpec): Promise<Plugin> {
return plugin; return plugin;
} }
export async function loadMiddleware(
middlewareFns: string[] | undefined,
tsConfig: string
): Promise<Connect.NextHandleFunction[]> {
if (!middlewareFns?.length) {
return [];
}
const cleanupTranspiler = registerTsProject(tsConfig);
try {
return await Promise.all(middlewareFns.map((fnPath) => loadModule(fnPath)));
} finally {
cleanupTranspiler();
}
}