From 09a01eb30cb00e244077662e88844b1a64a70200 Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Tue, 19 Nov 2024 21:01:10 +0000 Subject: [PATCH] feat(rspack): add NxAppRspackPlugin and NxReactRspackPlugin (#28987) - feat(rspack): add NxAppRspackPlugin - feat(rspack): add NxReactRspackPlugin ## Current Behavior We currently do not have rspack plugins to encapsulate our app, web and react support for Rspack. This leads to issues with defining configs that are supported by Crystal ## Expected Behavior Add and expose two plugins, `NxAppRspackPlugin` and `NxReactRspackPlugin`, to support building configs that are supported by crystal ## Related Issue(s) Fixes # --- packages/rspack/app-plugin.ts | 2 + packages/rspack/react-plugin.ts | 1 + .../nx-app-rspack-plugin.ts | 56 +++++++++++++++++++ .../nx-react-rspack-plugin.ts | 10 ++++ .../src/plugins/utils/apply-web-config.ts | 5 +- .../src/plugins/utils/delete-output-path.ts | 14 +++++ .../utils/plugins/normalize-options.ts | 2 +- 7 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 packages/rspack/app-plugin.ts create mode 100644 packages/rspack/react-plugin.ts create mode 100644 packages/rspack/src/plugins/nx-app-rspack-plugin/nx-app-rspack-plugin.ts create mode 100644 packages/rspack/src/plugins/nx-react-rspack-plugin/nx-react-rspack-plugin.ts create mode 100644 packages/rspack/src/plugins/utils/delete-output-path.ts diff --git a/packages/rspack/app-plugin.ts b/packages/rspack/app-plugin.ts new file mode 100644 index 0000000000..03778d0352 --- /dev/null +++ b/packages/rspack/app-plugin.ts @@ -0,0 +1,2 @@ +export { NxAppRspackPlugin } from './src/plugins/nx-app-rspack-plugin/nx-app-rspack-plugin'; +export type { NxAppRspackPluginOptions } from './src/plugins/utils/models'; diff --git a/packages/rspack/react-plugin.ts b/packages/rspack/react-plugin.ts new file mode 100644 index 0000000000..2cd9f7a8e6 --- /dev/null +++ b/packages/rspack/react-plugin.ts @@ -0,0 +1 @@ +export { NxReactRspackPlugin } from './src/plugins/nx-react-rspack-plugin/nx-react-rspack-plugin'; diff --git a/packages/rspack/src/plugins/nx-app-rspack-plugin/nx-app-rspack-plugin.ts b/packages/rspack/src/plugins/nx-app-rspack-plugin/nx-app-rspack-plugin.ts new file mode 100644 index 0000000000..3c24652e4d --- /dev/null +++ b/packages/rspack/src/plugins/nx-app-rspack-plugin/nx-app-rspack-plugin.ts @@ -0,0 +1,56 @@ +import type { Compiler } from '@rspack/core'; +import type { + NormalizedNxAppRspackPluginOptions, + NxAppRspackPluginOptions, +} from '../utils/models'; +import { normalizeOptions } from '../utils/plugins/normalize-options'; +import { applyBaseConfig } from '../utils/apply-base-config'; +import { applyWebConfig } from '../utils/apply-web-config'; +import { deleteOutputDir } from '../utils/delete-output-path'; + +/** + * This plugin provides features to build Node and Web applications. + * - TS Support (including tsconfig paths + * - Assets handling + * - Stylesheets handling + * - index.html and package.json generation + * + * Web-only features, such as stylesheets and images, are only supported when `target` is `web` or `webworker`. + */ +export class NxAppRspackPlugin { + private readonly options: NormalizedNxAppRspackPluginOptions; + + constructor(options: NxAppRspackPluginOptions = {}) { + // If we're building inferred targets, skip normalizing the build options + if (!global.NX_GRAPH_CREATION) { + this.options = normalizeOptions(options); + } + } + + apply(compiler: Compiler) { + // Default's to web + const target = this.options.target ?? compiler.options.target; + this.options.outputPath ??= compiler.options.output?.path; + if (typeof target === 'string') { + this.options.target = target; + } + + applyBaseConfig(this.options, compiler.options, { + useNormalizedEntry: true, + }); + + if (compiler.options.target) { + this.options.target = compiler.options.target; + } + + if (this.options.target === 'web' || this.options.target === 'webworker') { + applyWebConfig(this.options, compiler.options, { + useNormalizedEntry: true, + }); + } + + if (this.options.deleteOutputPath) { + deleteOutputDir(this.options.root, this.options.outputPath); + } + } +} diff --git a/packages/rspack/src/plugins/nx-react-rspack-plugin/nx-react-rspack-plugin.ts b/packages/rspack/src/plugins/nx-react-rspack-plugin/nx-react-rspack-plugin.ts new file mode 100644 index 0000000000..c6f2b7b559 --- /dev/null +++ b/packages/rspack/src/plugins/nx-react-rspack-plugin/nx-react-rspack-plugin.ts @@ -0,0 +1,10 @@ +import type { Compiler } from '@rspack/core'; +import { applyReactConfig } from '../utils/apply-react-config'; + +export class NxReactRspackPlugin { + constructor(private options: { svgr?: boolean } = {}) {} + + apply(compiler: Compiler) { + applyReactConfig(this.options, compiler.options); + } +} diff --git a/packages/rspack/src/plugins/utils/apply-web-config.ts b/packages/rspack/src/plugins/utils/apply-web-config.ts index 08b23cd982..b2a0a86af6 100644 --- a/packages/rspack/src/plugins/utils/apply-web-config.ts +++ b/packages/rspack/src/plugins/utils/apply-web-config.ts @@ -7,6 +7,7 @@ import { HtmlRspackPlugin, CssExtractRspackPlugin, EnvironmentPlugin, + RspackOptionsNormalized, } from '@rspack/core'; import { instantiateScriptPlugins } from './instantiate-script-plugins'; import { join, resolve } from 'path'; @@ -21,7 +22,7 @@ import { NormalizedNxAppRspackPluginOptions } from './models'; export function applyWebConfig( options: NormalizedNxAppRspackPluginOptions, - config: Configuration = {}, + config: Partial = {}, { useNormalizedEntry, }: { @@ -351,7 +352,7 @@ export function applyWebConfig( }); config.optimization = !isProd - ? undefined + ? {} : { ...(config.optimization ?? {}), minimizer: [...(config.optimization?.minimizer ?? []), ...minimizer], diff --git a/packages/rspack/src/plugins/utils/delete-output-path.ts b/packages/rspack/src/plugins/utils/delete-output-path.ts new file mode 100644 index 0000000000..4b2b24f28a --- /dev/null +++ b/packages/rspack/src/plugins/utils/delete-output-path.ts @@ -0,0 +1,14 @@ +import { rmSync } from 'fs'; +import { resolve } from 'path'; + +/** + * Delete an output directory, but error out if it's the root of the project. + */ +export function deleteOutputDir(root: string, outputPath: string) { + const resolvedOutputPath = resolve(root, outputPath); + if (resolvedOutputPath === root) { + throw new Error('Output path MUST not be project root directory!'); + } + + rmSync(resolvedOutputPath, { recursive: true, force: true }); +} diff --git a/packages/rspack/src/plugins/utils/plugins/normalize-options.ts b/packages/rspack/src/plugins/utils/plugins/normalize-options.ts index 9bee83ae85..b223ac9f71 100644 --- a/packages/rspack/src/plugins/utils/plugins/normalize-options.ts +++ b/packages/rspack/src/plugins/utils/plugins/normalize-options.ts @@ -124,7 +124,7 @@ export function normalizeOptions( sourceMap: combinedPluginAndMaybeExecutorOptions.sourceMap ?? !isProd, sourceRoot, styles: combinedPluginAndMaybeExecutorOptions.styles ?? [], - target: combinedPluginAndMaybeExecutorOptions.target, + target: combinedPluginAndMaybeExecutorOptions.target ?? 'web', targetName, vendorChunk: combinedPluginAndMaybeExecutorOptions.vendorChunk ?? !isProd, };