diff --git a/packages/rspack/app-plugin.ts b/packages/rspack/app-plugin.ts new file mode 100644 index 0000000000000..03778d03524c1 --- /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 0000000000000..2cd9f7a8e6c82 --- /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 0000000000000..3c24652e4d8df --- /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 0000000000000..c6f2b7b5599ad --- /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 08b23cd982d38..b2a0a86af687f 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 0000000000000..4b2b24f28a4f1 --- /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 9bee83ae85100..b223ac9f71e90 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, };