From 01bee2f0ead9efd88773e5de4ebad5eda4433e67 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 9 Oct 2024 15:57:54 +0200 Subject: [PATCH] feat(rspack,webpack): add `rspack` builder (#29142) Co-authored-by: "yangjian.fe" Co-authored-by: underfin --- .github/workflows/ci.yml | 8 +- package.json | 2 + packages/kit/build.config.ts | 1 + packages/kit/package.json | 1 + packages/kit/src/build.ts | 51 ++- packages/kit/src/compatibility.ts | 1 + packages/kit/src/index.ts | 2 +- packages/nuxt/src/components/module.ts | 18 +- packages/nuxt/src/core/nitro.ts | 44 +- packages/nuxt/src/core/nuxt.ts | 2 + packages/rspack/build.config.ts | 18 + packages/rspack/builder.mjs | 5 + packages/rspack/package.json | 94 +++++ packages/schema/src/config/build.ts | 5 +- packages/schema/src/config/typescript.ts | 2 +- packages/schema/src/types/compatibility.ts | 2 +- packages/schema/src/types/config.ts | 2 +- packages/schema/src/types/hooks.ts | 49 +++ packages/webpack/build.config.ts | 1 + packages/webpack/builder.d.ts | 8 + packages/webpack/builder.mjs | 3 + packages/webpack/package.json | 7 +- packages/webpack/src/configs/client.ts | 2 +- packages/webpack/src/configs/server.ts | 2 +- packages/webpack/src/plugins/chunk.ts | 8 +- packages/webpack/src/plugins/vue/client.ts | 2 +- packages/webpack/src/plugins/vue/server.ts | 2 +- packages/webpack/src/presets/base.ts | 21 +- packages/webpack/src/presets/style.ts | 3 +- packages/webpack/src/presets/vue.ts | 8 +- packages/webpack/src/webpack.ts | 13 +- pnpm-lock.yaml | 399 +++++++++++++++--- test/basic.test.ts | 2 +- test/fixtures/basic-types/nuxt.config.ts | 2 +- test/fixtures/basic/nuxt.config.ts | 2 +- test/fixtures/basic/package.json | 1 + test/fixtures/runtime-compiler/nuxt.config.ts | 2 +- test/hmr.test.ts | 2 +- test/runtime-compiler.test.ts | 2 +- test/suspense.test.ts | 2 +- 40 files changed, 649 insertions(+), 152 deletions(-) create mode 100644 packages/rspack/build.config.ts create mode 100644 packages/rspack/builder.mjs create mode 100644 packages/rspack/package.json create mode 100644 packages/webpack/builder.d.ts create mode 100644 packages/webpack/builder.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cefda6475e..0ba6897c9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -191,7 +191,7 @@ jobs: matrix: os: [ubuntu-latest, windows-latest] env: ["dev", "built"] - builder: ["vite", "webpack"] + builder: ["vite", "rspack", "webpack"] context: ["async", "default"] manifest: ["manifest-on", "manifest-off"] payload: ["json", "js"] @@ -199,12 +199,18 @@ jobs: exclude: - builder: "webpack" payload: "js" + - builder: "rspack" + payload: "js" - manifest: "manifest-off" payload: "js" - context: "default" payload: "js" - os: windows-latest payload: "js" + - env: "dev" + builder: "rspack" + - manifest: "manifest-off" + builder: "rspack" - env: "dev" builder: "webpack" - manifest: "manifest-off" diff --git a/package.json b/package.json index db406a9547..9a0bc90c73 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ }, "resolutions": { "@nuxt/kit": "workspace:*", + "@nuxt/rspack-builder": "workspace:*", "@nuxt/schema": "workspace:*", "@nuxt/ui-templates": "workspace:*", "@nuxt/vite-builder": "workspace:*", @@ -63,6 +64,7 @@ "@eslint/js": "9.12.0", "@nuxt/eslint-config": "0.5.7", "@nuxt/kit": "workspace:*", + "@nuxt/rspack-builder": "workspace:*", "@nuxt/test-utils": "3.14.3", "@nuxt/webpack-builder": "workspace:*", "@testing-library/vue": "8.1.0", diff --git a/packages/kit/build.config.ts b/packages/kit/build.config.ts index 87a8ccb072..d2a1f7fa7d 100644 --- a/packages/kit/build.config.ts +++ b/packages/kit/build.config.ts @@ -6,6 +6,7 @@ export default defineBuildConfig({ 'src/index', ], externals: [ + '@rspack/core', '@nuxt/schema', 'nitropack', 'nitro', diff --git a/packages/kit/package.json b/packages/kit/package.json index f1143c8439..651056b852 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -48,6 +48,7 @@ "untyped": "^1.5.1" }, "devDependencies": { + "@rspack/core": "1.0.8", "@types/hash-sum": "1.0.2", "@types/semver": "7.5.8", "nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda", diff --git a/packages/kit/src/build.ts b/packages/kit/src/build.ts index fab8c45228..ba4a1d17ba 100644 --- a/packages/kit/src/build.ts +++ b/packages/kit/src/build.ts @@ -1,4 +1,5 @@ import type { Configuration as WebpackConfig, WebpackPluginInstance } from 'webpack' +import type { RspackPluginInstance } from '@rspack/core' import type { UserConfig as ViteConfig, Plugin as VitePlugin } from 'vite' import { useNuxt } from './context' import { toArray } from './utils' @@ -36,16 +37,7 @@ export interface ExtendWebpackConfigOptions extends ExtendConfigOptions {} // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface ExtendViteConfigOptions extends ExtendConfigOptions {} -/** - * Extend webpack config - * - * The fallback function might be called multiple times - * when applying to both client and server builds. - */ -export function extendWebpackConfig ( - fn: ((config: WebpackConfig) => void), - options: ExtendWebpackConfigOptions = {}, -) { +const extendWebpackCompatibleConfig = (builder: 'rspack' | 'webpack') => (fn: ((config: WebpackConfig) => void), options: ExtendWebpackConfigOptions = {}) => { const nuxt = useNuxt() if (options.dev === false && nuxt.options.dev) { @@ -55,7 +47,7 @@ export function extendWebpackConfig ( return } - nuxt.hook('webpack:config', (configs: WebpackConfig[]) => { + nuxt.hook(`${builder}:config`, (configs) => { if (options.server !== false) { const config = configs.find(i => i.name === 'server') if (config) { @@ -71,13 +63,25 @@ export function extendWebpackConfig ( }) } +/** + * Extend webpack config + * + * The fallback function might be called multiple times + * when applying to both client and server builds. + */ +export const extendWebpackConfig = extendWebpackCompatibleConfig('webpack') +/** + * Extend rspack config + * + * The fallback function might be called multiple times + * when applying to both client and server builds. + */ +export const extendRspackConfig = extendWebpackCompatibleConfig('rspack') + /** * Extend Vite config */ -export function extendViteConfig ( - fn: ((config: ViteConfig) => void), - options: ExtendViteConfigOptions = {}, -) { +export function extendViteConfig (fn: ((config: ViteConfig) => void), options: ExtendViteConfigOptions = {}) { const nuxt = useNuxt() if (options.dev === false && nuxt.options.dev) { @@ -114,6 +118,18 @@ export function addWebpackPlugin (pluginOrGetter: WebpackPluginInstance | Webpac config.plugins[method](...toArray(plugin)) }, options) } +/** + * Append rspack plugin to the config. + */ +export function addRspackPlugin (pluginOrGetter: RspackPluginInstance | RspackPluginInstance[] | (() => RspackPluginInstance | RspackPluginInstance[]), options?: ExtendWebpackConfigOptions) { + extendRspackConfig((config) => { + const method: 'push' | 'unshift' = options?.prepend ? 'unshift' : 'push' + const plugin = typeof pluginOrGetter === 'function' ? pluginOrGetter() : pluginOrGetter + + config.plugins = config.plugins || [] + config.plugins[method](...toArray(plugin)) + }, options) +} /** * Append Vite plugin to the config. @@ -131,6 +147,7 @@ export function addVitePlugin (pluginOrGetter: VitePlugin | VitePlugin[] | (() = interface AddBuildPluginFactory { vite?: () => VitePlugin | VitePlugin[] webpack?: () => WebpackPluginInstance | WebpackPluginInstance[] + rspack?: () => RspackPluginInstance | RspackPluginInstance[] } export function addBuildPlugin (pluginFactory: AddBuildPluginFactory, options?: ExtendConfigOptions) { @@ -141,4 +158,8 @@ export function addBuildPlugin (pluginFactory: AddBuildPluginFactory, options?: if (pluginFactory.webpack) { addWebpackPlugin(pluginFactory.webpack, options) } + + if (pluginFactory.rspack) { + addRspackPlugin(pluginFactory.rspack, options) + } } diff --git a/packages/kit/src/compatibility.ts b/packages/kit/src/compatibility.ts index 00ad74b67c..e2859e1812 100644 --- a/packages/kit/src/compatibility.ts +++ b/packages/kit/src/compatibility.ts @@ -8,6 +8,7 @@ export function normalizeSemanticVersion (version: string) { } const builderMap = { + '@nuxt/rspack-builder': 'rspack', '@nuxt/vite-builder': 'vite', '@nuxt/webpack-builder': 'webpack', } diff --git a/packages/kit/src/index.ts b/packages/kit/src/index.ts index bde038e6fb..c9b94204b0 100644 --- a/packages/kit/src/index.ts +++ b/packages/kit/src/index.ts @@ -13,7 +13,7 @@ export type { LoadNuxtOptions } from './loader/nuxt' // Utils export { addImports, addImportsDir, addImportsSources } from './imports' export { updateRuntimeConfig, useRuntimeConfig } from './runtime-config' -export { addBuildPlugin, addVitePlugin, addWebpackPlugin, extendViteConfig, extendWebpackConfig } from './build' +export { addBuildPlugin, addVitePlugin, addRspackPlugin, addWebpackPlugin, extendViteConfig, extendRspackConfig, extendWebpackConfig } from './build' export type { ExtendConfigOptions, ExtendViteConfigOptions, ExtendWebpackConfigOptions } from './build' export { assertNuxtCompatibility, checkNuxtCompatibility, getNuxtVersion, hasNuxtCompatibility, isNuxtMajorVersion, normalizeSemanticVersion, isNuxt2, isNuxt3 } from './compatibility' export { addComponent, addComponentsDir } from './components' diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index 98da026f2b..8f1589bb08 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -274,16 +274,18 @@ export default defineNuxtModule({ } }) - nuxt.hook('webpack:config', (configs) => { - configs.forEach((config) => { - const mode = config.name === 'client' ? 'client' : 'server' - config.plugins = config.plugins || [] + for (const key of ['rspack:config', 'webpack:config'] as const) { + nuxt.hook(key, (configs) => { + configs.forEach((config) => { + const mode = config.name === 'client' ? 'client' : 'server' + config.plugins = config.plugins || [] - if (mode !== 'server') { - writeFileSync(join(nuxt.options.buildDir, 'components-chunk.mjs'), 'export const paths = {}') - } + if (mode !== 'server') { + writeFileSync(join(nuxt.options.buildDir, 'components-chunk.mjs'), 'export const paths = {}') + } + }) }) - }) + } } }, }) diff --git a/packages/nuxt/src/core/nitro.ts b/packages/nuxt/src/core/nitro.ts index effcbd63cd..34f23fb75d 100644 --- a/packages/nuxt/src/core/nitro.ts +++ b/packages/nuxt/src/core/nitro.ts @@ -347,7 +347,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { } } - if (nuxt.options.builder === '@nuxt/webpack-builder' || nuxt.options.dev) { + if (nuxt.options.dev || nuxt.options.builder === '@nuxt/webpack-builder' || nuxt.options.builder === '@nuxt/rspack-builder') { nitroConfig.virtual!['#build/dist/server/styles.mjs'] = 'export default {}' // In case a non-normalized absolute path is called for on Windows if (process.platform === 'win32') { @@ -448,18 +448,20 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { } } }) - nuxt.hook('webpack:config', (configuration) => { - const clientConfig = configuration.find(config => config.name === 'client') - if (!clientConfig!.resolve) { clientConfig!.resolve!.alias = {} } - if (Array.isArray(clientConfig!.resolve!.alias)) { - clientConfig!.resolve!.alias.push({ - name: 'vue', - alias: 'vue/dist/vue.esm-bundler', - }) - } else { - clientConfig!.resolve!.alias!.vue = 'vue/dist/vue.esm-bundler' - } - }) + for (const hook of ['webpack:config', 'rspack:config'] as const) { + nuxt.hook(hook, (configuration) => { + const clientConfig = configuration.find(config => config.name === 'client') + if (!clientConfig!.resolve) { clientConfig!.resolve!.alias = {} } + if (Array.isArray(clientConfig!.resolve!.alias)) { + clientConfig!.resolve!.alias.push({ + name: 'vue', + alias: 'vue/dist/vue.esm-bundler', + }) + } else { + clientConfig!.resolve!.alias!.vue = 'vue/dist/vue.esm-bundler' + } + }) + } } // Setup handlers @@ -545,13 +547,15 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { // nuxt dev if (nuxt.options.dev) { - nuxt.hook('webpack:compile', ({ name, compiler }) => { - if (name === 'server') { - const memfs = compiler.outputFileSystem as typeof import('node:fs') - nitro.options.virtual['#build/dist/server/server.mjs'] = () => memfs.readFileSync(join(nuxt.options.buildDir, 'dist/server/server.mjs'), 'utf-8') - } - }) - nuxt.hook('webpack:compiled', () => { nuxt.server.reload() }) + for (const builder of ['webpack', 'rspack'] as const) { + nuxt.hook(`${builder}:compile`, ({ name, compiler }) => { + if (name === 'server') { + const memfs = compiler.outputFileSystem as typeof import('node:fs') + nitro.options.virtual['#build/dist/server/server.mjs'] = () => memfs.readFileSync(join(nuxt.options.buildDir, 'dist/server/server.mjs'), 'utf-8') + } + }) + nuxt.hook(`${builder}:compiled`, () => { nuxt.server.reload() }) + } nuxt.hook('vite:compiled', () => { nuxt.server.reload() }) nuxt.hook('server:devHandler', (h) => { devMiddlewareHandler.set(h) }) diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index 7daf4567ba..56ecd6f7c8 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -497,9 +497,11 @@ async function initNuxt (nuxt: Nuxt) { const envMap = { // defaults from `builder` based on package name + '@nuxt/rspack-builder': '@rspack/core/module', '@nuxt/vite-builder': 'vite/client', '@nuxt/webpack-builder': 'webpack/module', // simpler overrides from `typescript.builder` for better DX + 'rspack': '@rspack/core/module', 'vite': 'vite/client', 'webpack': 'webpack/module', // default 'merged' builder environment for module authors diff --git a/packages/rspack/build.config.ts b/packages/rspack/build.config.ts new file mode 100644 index 0000000000..c11f11a10c --- /dev/null +++ b/packages/rspack/build.config.ts @@ -0,0 +1,18 @@ +import { defineBuildConfig } from 'unbuild' +import config from '../webpack/build.config' + +export default defineBuildConfig({ + ...config[0], + externals: [ + '@rspack/core', + '#builder', + '@nuxt/schema', + ], + entries: [ + { + input: '../webpack/src/index', + name: 'index', + declaration: true, + }, + ], +}) diff --git a/packages/rspack/builder.mjs b/packages/rspack/builder.mjs new file mode 100644 index 0000000000..14b2475188 --- /dev/null +++ b/packages/rspack/builder.mjs @@ -0,0 +1,5 @@ +import webpack from '@rspack/core' + +export const builder = 'rspack' +export { webpack } +export const MiniCssExtractPlugin = webpack.CssExtractRspackPlugin diff --git a/packages/rspack/package.json b/packages/rspack/package.json new file mode 100644 index 0000000000..f689e1bbaa --- /dev/null +++ b/packages/rspack/package.json @@ -0,0 +1,94 @@ +{ + "name": "@nuxt/rspack-builder", + "version": "3.12.2", + "repository": { + "type": "git", + "url": "git+https://github.com/nuxt/nuxt.git", + "directory": "packages/rspack" + }, + "description": "rspack bundler for Nuxt", + "homepage": "https://nuxt.com", + "license": "MIT", + "type": "module", + "types": "./dist/index.d.ts", + "imports": { + "#builder": "./builder.mjs" + }, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs" + }, + "./dist/*": "./dist/*" + }, + "files": [ + "dist", + "builder.mjs" + ], + "scripts": { + "prepack": "unbuild" + }, + "dependencies": { + "@nuxt/friendly-errors-webpack-plugin": "^2.6.0", + "@nuxt/kit": "workspace:*", + "@rspack/core": "^1.0.8", + "autoprefixer": "^10.4.20", + "css-loader": "^7.1.2", + "css-minimizer-webpack-plugin": "^7.0.0", + "cssnano": "^7.0.6", + "defu": "^6.1.4", + "esbuild-loader": "^4.2.2", + "escape-string-regexp": "^5.0.0", + "estree-walker": "^3.0.3", + "file-loader": "^6.2.0", + "fork-ts-checker-webpack-plugin": "^9.0.2", + "globby": "^14.0.2", + "h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e", + "hash-sum": "^2.0.0", + "jiti": "^2.3.3", + "knitwork": "^1.1.0", + "lodash-es": "4.17.21", + "magic-string": "^0.30.11", + "memfs": "^4.13.0", + "mlly": "^1.7.2", + "ohash": "^1.1.4", + "pathe": "^1.1.2", + "pify": "^6.1.0", + "postcss": "^8.4.47", + "postcss-import": "^16.1.0", + "postcss-import-resolver": "^2.0.0", + "postcss-loader": "^8.1.1", + "postcss-url": "^10.1.3", + "pug-plain-loader": "^1.1.0", + "std-env": "^3.7.0", + "time-fix-plugin": "^2.0.7", + "ufo": "^1.5.4", + "unenv": "^1.10.0", + "unplugin": "^1.14.1", + "url-loader": "^4.1.1", + "vue-bundle-renderer": "^2.1.1", + "vue-loader": "^17.4.2", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-middleware": "^7.4.2", + "webpack-hot-middleware": "^2.26.1", + "webpack-virtual-modules": "^0.6.2", + "webpackbar": "^6.0.1" + }, + "devDependencies": { + "@nuxt/schema": "workspace:*", + "@types/hash-sum": "1.0.2", + "@types/lodash-es": "4.17.12", + "@types/pify": "5.0.4", + "@types/webpack-bundle-analyzer": "4.7.0", + "@types/webpack-hot-middleware": "2.25.9", + "rollup": "4.24.0", + "unbuild": "3.0.0-rc.11", + "vue": "3.5.11" + }, + "peerDependencies": { + "vue": "^3.3.4" + }, + "engines": { + "node": "^14.18.0 || >=16.10.0" + } +} diff --git a/packages/schema/src/config/build.ts b/packages/schema/src/config/build.ts index 6527a2aaa3..fbacf2dd79 100644 --- a/packages/schema/src/config/build.ts +++ b/packages/schema/src/config/build.ts @@ -7,14 +7,15 @@ import { consola } from 'consola' export default defineUntypedSchema({ /** * The builder to use for bundling the Vue part of your application. - * @type {'vite' | 'webpack' | { bundle: (nuxt: typeof import('../src/types/nuxt').Nuxt) => Promise }} + * @type {'vite' | 'webpack' | 'rspack' | { bundle: (nuxt: typeof import('../src/types/nuxt').Nuxt) => Promise }} */ builder: { - $resolve: async (val: 'vite' | 'webpack' | { bundle: (nuxt: unknown) => Promise } | undefined = 'vite', get) => { + $resolve: async (val: 'vite' | 'webpack' | 'rspack' | { bundle: (nuxt: unknown) => Promise } | undefined = 'vite', get) => { if (typeof val === 'object') { return val } const map: Record = { + rspack: '@nuxt/rspack-builder', vite: '@nuxt/vite-builder', webpack: '@nuxt/webpack-builder', } diff --git a/packages/schema/src/config/typescript.ts b/packages/schema/src/config/typescript.ts index 402cd007fd..742f5a20f9 100644 --- a/packages/schema/src/config/typescript.ts +++ b/packages/schema/src/config/typescript.ts @@ -20,7 +20,7 @@ export default defineUntypedSchema({ * builder environment types (with `false`) to handle this fully yourself, or opt for a 'shared' option. * * The 'shared' option is advised for module authors, who will want to support multiple possible builders. - * @type {'vite' | 'webpack' | 'shared' | false | undefined} + * @type {'vite' | 'webpack' | 'rspack' | 'shared' | false | undefined} */ builder: { $resolve: val => val ?? null, diff --git a/packages/schema/src/types/compatibility.ts b/packages/schema/src/types/compatibility.ts index 562b187cb0..209b373072 100644 --- a/packages/schema/src/types/compatibility.ts +++ b/packages/schema/src/types/compatibility.ts @@ -26,7 +26,7 @@ export interface NuxtCompatibility { * }) * ``` */ - builder?: Partial> + builder?: Partial> } export interface NuxtCompatibilityIssue { diff --git a/packages/schema/src/types/config.ts b/packages/schema/src/types/config.ts index 3de59b8493..805564bad6 100644 --- a/packages/schema/src/types/config.ts +++ b/packages/schema/src/types/config.ts @@ -81,7 +81,7 @@ export interface NuxtBuilder { export interface NuxtOptions extends Omit { vue: Omit & { config?: Partial> } sourcemap: Required> - builder: '@nuxt/vite-builder' | '@nuxt/webpack-builder' | NuxtBuilder + builder: '@nuxt/vite-builder' | '@nuxt/webpack-builder' | '@nuxt/rspack-builder' | NuxtBuilder postcss: Omit & { order: Exclude } webpack: ConfigSchema['webpack'] & { $client: ConfigSchema['webpack'] diff --git a/packages/schema/src/types/hooks.ts b/packages/schema/src/types/hooks.ts index 780b8b0614..7fd4b2aa5d 100644 --- a/packages/schema/src/types/hooks.ts +++ b/packages/schema/src/types/hooks.ts @@ -408,6 +408,55 @@ export interface NuxtHooks { * @returns void */ 'webpack:progress': (statesArray: any[]) => void + + // rspack + /** + * Called before configuring the webpack compiler. + * @param webpackConfigs Configs objects to be pushed to the compiler + * @returns Promise + */ + 'rspack:config': (webpackConfigs: Configuration[]) => HookResult + /** + * Allows to read the resolved webpack config + * @param webpackConfigs Configs objects to be pushed to the compiler + * @returns Promise + */ + 'rspack:configResolved': (webpackConfigs: Readonly[]) => HookResult + /** + * Called right before compilation. + * @param options The options to be added + * @returns Promise + */ + 'rspack:compile': (options: { name: string, compiler: Compiler }) => HookResult + /** + * Called after resources are loaded. + * @param options The compiler options + * @returns Promise + */ + 'rspack:compiled': (options: { name: string, compiler: Compiler, stats: Stats }) => HookResult + + /** + * Called on `change` on WebpackBar. + * @param shortPath the short path + * @returns void + */ + 'rspack:change': (shortPath: string) => void + /** + * Called on `done` if has errors on WebpackBar. + * @returns void + */ + 'rspack:error': () => void + /** + * Called on `allDone` on WebpackBar. + * @returns void + */ + 'rspack:done': () => void + /** + * Called on `progress` on WebpackBar. + * @param statesArray The array containing the states on progress + * @returns void + */ + 'rspack:progress': (statesArray: any[]) => void } export type NuxtHookName = keyof NuxtHooks diff --git a/packages/webpack/build.config.ts b/packages/webpack/build.config.ts index d9cd15d80a..e1567f1bb6 100644 --- a/packages/webpack/build.config.ts +++ b/packages/webpack/build.config.ts @@ -17,6 +17,7 @@ export default defineBuildConfig({ 'vue', ], externals: [ + '#builder', '@nuxt/schema', ], }) diff --git a/packages/webpack/builder.d.ts b/packages/webpack/builder.d.ts new file mode 100644 index 0000000000..a7924b945d --- /dev/null +++ b/packages/webpack/builder.d.ts @@ -0,0 +1,8 @@ +declare module '#builder' { + import type Webpack from 'webpack' + import type MiniCssExtractPlugin from 'mini-css-extract-plugin' + + export const webpack: typeof Webpack + export const MiniCssExtractPlugin: typeof MiniCssExtractPlugin + export const builder: 'webpack' | 'rspack' +} diff --git a/packages/webpack/builder.mjs b/packages/webpack/builder.mjs new file mode 100644 index 0000000000..4de1c41293 --- /dev/null +++ b/packages/webpack/builder.mjs @@ -0,0 +1,3 @@ +export const builder = 'webpack' +export { default as webpack } from 'webpack' +export { default as MiniCssExtractPlugin } from 'mini-css-extract-plugin' diff --git a/packages/webpack/package.json b/packages/webpack/package.json index 0c8588ca6d..3c99590c9f 100644 --- a/packages/webpack/package.json +++ b/packages/webpack/package.json @@ -11,6 +11,9 @@ "license": "MIT", "type": "module", "types": "./dist/index.d.ts", + "imports": { + "#builder": "./builder.mjs" + }, "exports": { ".": { "types": "./dist/index.d.ts", @@ -19,7 +22,8 @@ "./dist/*": "./dist/*" }, "files": [ - "dist" + "dist", + "builder.mjs" ], "scripts": { "prepack": "unbuild" @@ -72,6 +76,7 @@ }, "devDependencies": { "@nuxt/schema": "workspace:*", + "@rspack/core": "1.0.8", "@types/hash-sum": "1.0.2", "@types/lodash-es": "4.17.12", "@types/pify": "5.0.4", diff --git a/packages/webpack/src/configs/client.ts b/packages/webpack/src/configs/client.ts index e1bf00a5fd..f147745939 100644 --- a/packages/webpack/src/configs/client.ts +++ b/packages/webpack/src/configs/client.ts @@ -1,6 +1,5 @@ import querystring from 'node:querystring' import { resolve } from 'pathe' -import webpack from 'webpack' import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer' import { logger } from '@nuxt/kit' import { joinURL } from 'ufo' @@ -10,6 +9,7 @@ import { env, nodeless } from 'unenv' import type { WebpackConfigContext } from '../utils/config' import { applyPresets } from '../utils/config' import { nuxt } from '../presets/nuxt' +import { webpack } from '#builder' export async function client (ctx: WebpackConfigContext) { ctx.name = 'client' diff --git a/packages/webpack/src/configs/server.ts b/packages/webpack/src/configs/server.ts index e9a1738153..53370bef88 100644 --- a/packages/webpack/src/configs/server.ts +++ b/packages/webpack/src/configs/server.ts @@ -1,11 +1,11 @@ import { isAbsolute } from 'pathe' -import webpack from 'webpack' import ForkTSCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin' import { logger } from '@nuxt/kit' import type { WebpackConfigContext } from '../utils/config' import { applyPresets } from '../utils/config' import { nuxt } from '../presets/nuxt' import { node } from '../presets/node' +import { webpack } from '#builder' const assetPattern = /\.(?:css|s[ca]ss|png|jpe?g|gif|svg|woff2?|eot|ttf|otf|webp|webm|mp4|ogv)(?:\?.*)?$/i diff --git a/packages/webpack/src/plugins/chunk.ts b/packages/webpack/src/plugins/chunk.ts index 56edb4c2fc..999b83cbc7 100644 --- a/packages/webpack/src/plugins/chunk.ts +++ b/packages/webpack/src/plugins/chunk.ts @@ -1,9 +1,10 @@ import type { Compiler } from 'webpack' -import webpack from 'webpack' +import { webpack } from '#builder' const pluginName = 'ChunkErrorPlugin' -const script = ` +export class ChunkErrorPlugin { + script = ` if (typeof ${webpack.RuntimeGlobals.require} !== "undefined") { var _ensureChunk = ${webpack.RuntimeGlobals.ensureChunk}; ${webpack.RuntimeGlobals.ensureChunk} = function (chunkId) { @@ -16,12 +17,11 @@ if (typeof ${webpack.RuntimeGlobals.require} !== "undefined") { }; };` -export class ChunkErrorPlugin { apply (compiler: Compiler) { compiler.hooks.thisCompilation.tap(pluginName, compilation => compilation.mainTemplate.hooks.localVars.tap( { name: pluginName, stage: 1 }, - source => source + script, + source => source + this.script, ), ) } diff --git a/packages/webpack/src/plugins/vue/client.ts b/packages/webpack/src/plugins/vue/client.ts index 005afcf18e..3f217f3e1d 100644 --- a/packages/webpack/src/plugins/vue/client.ts +++ b/packages/webpack/src/plugins/vue/client.ts @@ -7,7 +7,7 @@ import { mkdir, writeFile } from 'node:fs/promises' import { normalizeWebpackManifest } from 'vue-bundle-renderer' import { dirname } from 'pathe' -import hash from 'hash-sum' +import { hash } from 'ohash' import type { Nuxt } from '@nuxt/schema' import type { Compilation, Compiler } from 'webpack' diff --git a/packages/webpack/src/plugins/vue/server.ts b/packages/webpack/src/plugins/vue/server.ts index 646589c601..29f3a1b74c 100644 --- a/packages/webpack/src/plugins/vue/server.ts +++ b/packages/webpack/src/plugins/vue/server.ts @@ -1,6 +1,6 @@ import type { Compilation, Compiler } from 'webpack' -import webpack from 'webpack' import { extractQueryPartJS, isJS, validate } from './util' +import { webpack } from '#builder' interface VueSSRServerPluginOptions { filename: string diff --git a/packages/webpack/src/presets/base.ts b/packages/webpack/src/presets/base.ts index 7e61613f2a..48ae42c14c 100644 --- a/packages/webpack/src/presets/base.ts +++ b/packages/webpack/src/presets/base.ts @@ -3,7 +3,6 @@ import { normalize, resolve } from 'pathe' import TimeFixPlugin from 'time-fix-plugin' import WebpackBar from 'webpackbar' import type { Configuration } from 'webpack' -import webpack from 'webpack' import { logger } from '@nuxt/kit' // @ts-expect-error missing types import FriendlyErrorsWebpackPlugin from '@nuxt/friendly-errors-webpack-plugin' @@ -16,6 +15,8 @@ import WarningIgnorePlugin from '../plugins/warning-ignore' import type { WebpackConfigContext } from '../utils/config' import { applyPresets, fileName } from '../utils/config' +import { builder, webpack } from '#builder' + export async function base (ctx: WebpackConfigContext) { await applyPresets(ctx, [ baseAlias, @@ -53,14 +54,18 @@ function basePlugins (ctx: WebpackConfigContext) { // Add timefix-plugin before other plugins if (ctx.options.dev) { - ctx.config.plugins.push(new TimeFixPlugin()) + if (ctx.nuxt.options.builder !== '@nuxt/rspack-builder') { + ctx.config.plugins.push(new TimeFixPlugin()) + } } // User plugins ctx.config.plugins.push(...(ctx.userConfig.plugins || [])) // Ignore empty warnings - ctx.config.plugins.push(new WarningIgnorePlugin(getWarningIgnoreFilter(ctx))) + if (ctx.nuxt.options.builder !== '@nuxt/rspack-builder') { + ctx.config.plugins.push(new WarningIgnorePlugin(getWarningIgnoreFilter(ctx))) + } // Provide env via DefinePlugin ctx.config.plugins.push(new webpack.DefinePlugin(getEnv(ctx))) @@ -93,21 +98,21 @@ function basePlugins (ctx: WebpackConfigContext) { reporter: { change: (_, { shortPath }) => { if (!ctx.isServer) { - ctx.nuxt.callHook('webpack:change', shortPath) + ctx.nuxt.callHook(`${builder}:change`, shortPath) } }, done: ({ state }) => { if (state.hasErrors) { - ctx.nuxt.callHook('webpack:error') + ctx.nuxt.callHook(`${builder}:error`) } else { logger.success(`${state.name} ${state.message}`) } }, allDone: () => { - ctx.nuxt.callHook('webpack:done') + ctx.nuxt.callHook(`${builder}:done`) }, progress ({ statesArray }) { - ctx.nuxt.callHook('webpack:progress', statesArray) + ctx.nuxt.callHook(`${builder}:progress`, statesArray) }, }, }, @@ -150,7 +155,7 @@ function baseTranspile (ctx: WebpackConfigContext) { /\.vue\.js/i, // include SFCs in node_modules /consola\/src/, /vue-demi/, - /(^|\/)nuxt\/(dist\/)?(app|[^/]+\/runtime)($|\/)/, + /(^|\/)nuxt\/(src\/|dist\/)?(app|[^/]+\/runtime)($|\/)/, ] for (let pattern of ctx.options.build.transpile) { diff --git a/packages/webpack/src/presets/style.ts b/packages/webpack/src/presets/style.ts index 90d1031885..fc44bd6157 100644 --- a/packages/webpack/src/presets/style.ts +++ b/packages/webpack/src/presets/style.ts @@ -1,9 +1,10 @@ -import MiniCssExtractPlugin from 'mini-css-extract-plugin' import CssMinimizerPlugin from 'css-minimizer-webpack-plugin' import type { WebpackConfigContext } from '../utils/config' import { applyPresets, fileName } from '../utils/config' import { getPostcssConfig } from '../utils/postcss' +import { MiniCssExtractPlugin } from '#builder' + export async function style (ctx: WebpackConfigContext) { await applyPresets(ctx, [ loaders, diff --git a/packages/webpack/src/presets/vue.ts b/packages/webpack/src/presets/vue.ts index 16acd3ca07..e14632a4fd 100644 --- a/packages/webpack/src/presets/vue.ts +++ b/packages/webpack/src/presets/vue.ts @@ -1,10 +1,11 @@ import { resolve } from 'pathe' import VueLoaderPlugin from 'vue-loader/dist/pluginWebpack5.js' -import webpack from 'webpack' import VueSSRClientPlugin from '../plugins/vue/client' import VueSSRServerPlugin from '../plugins/vue/server' import type { WebpackConfigContext } from '../utils/config' +import { webpack } from '#builder' + export function vue (ctx: WebpackConfigContext) { // @ts-expect-error de-default vue-loader ctx.config.plugins!.push(new (VueLoaderPlugin.default || VueLoaderPlugin)()) @@ -30,7 +31,8 @@ export function vue (ctx: WebpackConfigContext) { // https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags // TODO: Provide options to toggle ctx.config.plugins!.push(new webpack.DefinePlugin({ - __VUE_OPTIONS_API__: 'true', - __VUE_PROD_DEVTOOLS__: 'false', + '__VUE_OPTIONS_API__': 'true', + '__VUE_PROD_DEVTOOLS__': 'false', + '__VUE_PROD_HYDRATION_MISMATCH_DETAILS__': ctx.nuxt.options.debug, })) } diff --git a/packages/webpack/src/webpack.ts b/packages/webpack/src/webpack.ts index 1c9da4c3a2..f1b178af54 100644 --- a/packages/webpack/src/webpack.ts +++ b/packages/webpack/src/webpack.ts @@ -1,5 +1,4 @@ import pify from 'pify' -import webpack from 'webpack' import type { NodeMiddleware } from 'h3' import { resolve } from 'pathe' import { defineEventHandler, fromNodeMiddleware } from 'h3' @@ -21,6 +20,8 @@ import { client, server } from './configs' import { applyPresets, createWebpackConfigContext, getWebpackConfig } from './utils/config' import { dynamicRequire } from './nitro/plugins/dynamic-require' +import { builder, webpack } from '#builder' + // TODO: Support plugins // const plugins: string[] = [] @@ -52,7 +53,7 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => { prerenderRollupPlugins.push(dynamicRequirePlugin) rollupPlugins.push(dynamicRequirePlugin) - await nuxt.callHook('webpack:config', webpackConfigs) + await nuxt.callHook(`${builder}:config`, webpackConfigs) // Initialize shared MFS for dev const mfs = nuxt.options.dev ? createMFS() : null @@ -62,7 +63,7 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => { sourcemap: !!nuxt.options.sourcemap[config.name as 'client' | 'server'], })) // Emit chunk errors if the user has opted in to `experimental.emitRouteChunkError` - if (config.name === 'client' && nuxt.options.experimental.emitRouteChunkError) { + if (config.name === 'client' && nuxt.options.experimental.emitRouteChunkError && nuxt.options.builder !== '@nuxt/rspack-builder') { config.plugins!.push(new ChunkErrorPlugin()) } config.plugins!.push(composableKeysPlugin.webpack({ @@ -72,7 +73,7 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => { })) } - await nuxt.callHook('webpack:configResolved', webpackConfigs) + await nuxt.callHook(`${builder}:configResolved`, webpackConfigs) // Configure compilers const compilers = webpackConfigs.map((config) => { @@ -142,11 +143,11 @@ async function createDevMiddleware (compiler: Compiler) { async function compile (compiler: Compiler) { const nuxt = useNuxt() - await nuxt.callHook('webpack:compile', { name: compiler.options.name!, compiler }) + await nuxt.callHook(`${builder}:compile`, { name: compiler.options.name!, compiler }) // Load renderer resources after build compiler.hooks.done.tap('load-resources', async (stats) => { - await nuxt.callHook('webpack:compiled', { name: compiler.options.name!, compiler, stats }) + await nuxt.callHook(`${builder}:compiled`, { name: compiler.options.name!, compiler, stats }) }) // --- Dev Build --- diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8bd6d9c595..15b62e69e0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,6 +10,7 @@ overrides: '@nuxt/ui-templates': workspace:* '@nuxt/vite-builder': workspace:* '@nuxt/webpack-builder': workspace:* + '@nuxt/rspack-builder': workspace:* '@types/node': 20.16.11 '@vue/compiler-core': 3.5.11 '@vue/compiler-dom': 3.5.11 @@ -43,6 +44,9 @@ importers: '@nuxt/kit': specifier: workspace:* version: link:packages/kit + '@nuxt/rspack-builder': + specifier: workspace:* + version: link:packages/rspack '@nuxt/test-utils': specifier: 3.14.3 version: 3.14.3(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.11)(vue@3.5.11(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.7.4)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5)(webpack-sources@3.2.3))(playwright-core@1.48.0)(vite@5.4.8(@types/node@20.16.11)(sass@1.78.0)(terser@5.32.0))(vitest@2.1.2(@types/node@20.16.11)(happy-dom@15.7.4)(sass@1.78.0)(terser@5.32.0))(vue-router@4.4.5(vue@3.5.11(typescript@5.6.3)))(vue@3.5.11(typescript@5.6.3))(webpack-sources@3.2.3) @@ -245,6 +249,9 @@ importers: specifier: ^1.5.1 version: 1.5.1 devDependencies: + '@rspack/core': + specifier: 1.0.8 + version: 1.0.8 '@types/hash-sum': specifier: 1.0.2 version: 1.0.2 @@ -493,6 +500,169 @@ importers: specifier: 2.1.2 version: 2.1.2(@types/node@20.16.11)(happy-dom@15.7.4)(sass@1.78.0)(terser@5.32.0) + packages/rspack: + dependencies: + '@nuxt/friendly-errors-webpack-plugin': + specifier: ^2.6.0 + version: 2.6.0(webpack@5.95.0) + '@nuxt/kit': + specifier: workspace:* + version: link:../kit + '@rspack/core': + specifier: ^1.0.8 + version: 1.0.8 + autoprefixer: + specifier: ^10.4.20 + version: 10.4.20(postcss@8.4.47) + css-loader: + specifier: ^7.1.2 + version: 7.1.2(@rspack/core@1.0.8)(webpack@5.95.0) + css-minimizer-webpack-plugin: + specifier: ^7.0.0 + version: 7.0.0(webpack@5.95.0) + cssnano: + specifier: ^7.0.6 + version: 7.0.6(postcss@8.4.47) + defu: + specifier: ^6.1.4 + version: 6.1.4 + esbuild-loader: + specifier: ^4.2.2 + version: 4.2.2(webpack@5.95.0) + escape-string-regexp: + specifier: ^5.0.0 + version: 5.0.0 + estree-walker: + specifier: ^3.0.3 + version: 3.0.3 + file-loader: + specifier: ^6.2.0 + version: 6.2.0(webpack@5.95.0) + fork-ts-checker-webpack-plugin: + specifier: ^9.0.2 + version: 9.0.2(typescript@5.6.3)(webpack@5.95.0) + globby: + specifier: ^14.0.2 + version: 14.0.2 + h3: + specifier: npm:h3-nightly@2.0.0-1718872656.6765a6e + version: h3-nightly@2.0.0-1718872656.6765a6e + hash-sum: + specifier: ^2.0.0 + version: 2.0.0 + jiti: + specifier: 2.3.3 + version: 2.3.3 + knitwork: + specifier: ^1.1.0 + version: 1.1.0 + lodash-es: + specifier: 4.17.21 + version: 4.17.21 + magic-string: + specifier: ^0.30.11 + version: 0.30.11 + memfs: + specifier: ^4.13.0 + version: 4.13.0 + mlly: + specifier: ^1.7.2 + version: 1.7.2 + ohash: + specifier: 1.1.4 + version: 1.1.4 + pathe: + specifier: ^1.1.2 + version: 1.1.2 + pify: + specifier: ^6.1.0 + version: 6.1.0 + postcss: + specifier: 8.4.47 + version: 8.4.47 + postcss-import: + specifier: ^16.1.0 + version: 16.1.0(postcss@8.4.47) + postcss-import-resolver: + specifier: ^2.0.0 + version: 2.0.0 + postcss-loader: + specifier: ^8.1.1 + version: 8.1.1(@rspack/core@1.0.8)(postcss@8.4.47)(typescript@5.6.3)(webpack@5.95.0) + postcss-url: + specifier: ^10.1.3 + version: 10.1.3(postcss@8.4.47) + pug-plain-loader: + specifier: ^1.1.0 + version: 1.1.0(pug@3.0.3) + std-env: + specifier: ^3.7.0 + version: 3.7.0 + time-fix-plugin: + specifier: ^2.0.7 + version: 2.0.7(webpack@5.95.0) + ufo: + specifier: 1.5.4 + version: 1.5.4 + unenv: + specifier: ^1.10.0 + version: 1.10.0 + unplugin: + specifier: ^1.14.1 + version: 1.14.1(webpack-sources@3.2.3) + url-loader: + specifier: ^4.1.1 + version: 4.1.1(file-loader@6.2.0(webpack@5.95.0))(webpack@5.95.0) + vue-bundle-renderer: + specifier: ^2.1.1 + version: 2.1.1 + vue-loader: + specifier: ^17.4.2 + version: 17.4.2(@vue/compiler-sfc@3.5.11)(vue@3.5.11(typescript@5.6.3))(webpack@5.95.0) + webpack-bundle-analyzer: + specifier: ^4.10.2 + version: 4.10.2 + webpack-dev-middleware: + specifier: ^7.4.2 + version: 7.4.2(webpack@5.95.0) + webpack-hot-middleware: + specifier: ^2.26.1 + version: 2.26.1 + webpack-virtual-modules: + specifier: ^0.6.2 + version: 0.6.2 + webpackbar: + specifier: ^6.0.1 + version: 6.0.1(webpack@5.95.0) + devDependencies: + '@nuxt/schema': + specifier: workspace:* + version: link:../schema + '@types/hash-sum': + specifier: 1.0.2 + version: 1.0.2 + '@types/lodash-es': + specifier: 4.17.12 + version: 4.17.12 + '@types/pify': + specifier: 5.0.4 + version: 5.0.4 + '@types/webpack-bundle-analyzer': + specifier: 4.7.0 + version: 4.7.0 + '@types/webpack-hot-middleware': + specifier: 2.25.9 + version: 2.25.9 + rollup: + specifier: 4.24.0 + version: 4.24.0 + unbuild: + specifier: 3.0.0-rc.11 + version: 3.0.0-rc.11(sass@1.78.0)(typescript@5.6.3)(vue-tsc@2.1.6(typescript@5.6.3)) + vue: + specifier: 3.5.11 + version: 3.5.11(typescript@5.6.3) + packages/schema: dependencies: compatx: @@ -793,7 +963,7 @@ importers: version: 10.4.20(postcss@8.4.47) css-loader: specifier: ^7.1.2 - version: 7.1.2(webpack@5.95.0) + version: 7.1.2(@rspack/core@1.0.8)(webpack@5.95.0) css-minimizer-webpack-plugin: specifier: ^7.0.0 version: 7.0.0(webpack@5.95.0) @@ -868,7 +1038,7 @@ importers: version: 2.0.0 postcss-loader: specifier: ^8.1.1 - version: 8.1.1(postcss@8.4.47)(typescript@5.6.3)(webpack@5.95.0) + version: 8.1.1(@rspack/core@1.0.8)(postcss@8.4.47)(typescript@5.6.3)(webpack@5.95.0) postcss-url: specifier: ^10.1.3 version: 10.1.3(postcss@8.4.47) @@ -918,6 +1088,9 @@ importers: '@nuxt/schema': specifier: workspace:* version: link:../schema + '@rspack/core': + specifier: 1.0.8 + version: 1.0.8 '@types/hash-sum': specifier: 1.0.2 version: 1.0.2 @@ -951,6 +1124,9 @@ importers: test/fixtures/basic: dependencies: + '@nuxt/rspack-builder': + specifier: workspace:* + version: link:../../../packages/rspack '@nuxt/webpack-builder': specifier: workspace:* version: link:../../../packages/webpack @@ -1930,6 +2106,18 @@ packages: resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} hasBin: true + '@module-federation/runtime-tools@0.5.1': + resolution: {integrity: sha512-nfBedkoZ3/SWyO0hnmaxuz0R0iGPSikHZOAZ0N/dVSQaIzlffUo35B5nlC2wgWIc0JdMZfkwkjZRrnuuDIJbzg==} + + '@module-federation/runtime@0.5.1': + resolution: {integrity: sha512-xgiMUWwGLWDrvZc9JibuEbXIbhXg6z2oUkemogSvQ4LKvrl/n0kbqP1Blk669mXzyWbqtSp6PpvNdwaE1aN5xQ==} + + '@module-federation/sdk@0.5.1': + resolution: {integrity: sha512-exvchtjNURJJkpqjQ3/opdbfeT2wPKvrbnGnyRkrwW5o3FH1LaST1tkiNviT6OXTexGaVc2DahbdniQHVtQ7pA==} + + '@module-federation/webpack-bundler-runtime@0.5.1': + resolution: {integrity: sha512-mMhRFH0k2VjwHt3Jol9JkUsmI/4XlrAoBG3E0o7HoyoPYv1UFOWyqAflfANcUPgbYpvqmyLzDcO+3IT36LXnrA==} + '@netlify/functions@2.8.1': resolution: {integrity: sha512-+6wtYdoz0yE06dSa9XkP47tw5zm6g13QMeCwM3MmHx1vn8hzwFa51JtmfraprdkL7amvb7gaNM+OOhQU1h6T8A==} engines: {node: '>=14.0.0'} @@ -2338,6 +2526,67 @@ packages: cpu: [x64] os: [win32] + '@rspack/binding-darwin-arm64@1.0.8': + resolution: {integrity: sha512-1l8/eg3HNz53DHQO3fy5O5QKdYh8hSMZaWGtm3NR5IfdrTm2TaLL9tuR8oL2iHHtd87LEvVKHXdjlcuLV5IPNQ==} + cpu: [arm64] + os: [darwin] + + '@rspack/binding-darwin-x64@1.0.8': + resolution: {integrity: sha512-7BbG8gXVWjtqJegDpsObzM/B90Eig1piEtcahvPdvlC92uZz3/IwtKPpMaywGBrf5RSI3U0nQMSekwz0cO1SOw==} + cpu: [x64] + os: [darwin] + + '@rspack/binding-linux-arm64-gnu@1.0.8': + resolution: {integrity: sha512-QnqCL0wmwYqT/IFx5q0aw7DsIOr8oYUa4+7JI8iiqRf3RuuRJExesVW9VuWr0jS2UvChKgmb8PvRtDy/0tshFw==} + cpu: [arm64] + os: [linux] + + '@rspack/binding-linux-arm64-musl@1.0.8': + resolution: {integrity: sha512-Ns9TsE7zdUjimW5HURRW08BaMyAh16MDh97PPsGEMeRPx9plnRO9aXvuUG6t+0gy4KwlQdeq3BvUsbBpIo5Tow==} + cpu: [arm64] + os: [linux] + + '@rspack/binding-linux-x64-gnu@1.0.8': + resolution: {integrity: sha512-lfqUuKCoyRN/gGeokhX/oNYqB6OpbtgQb57b0QuD8IaiH2a1ee0TtEVvRbyQNEDwht6lW4RTNg0RfMYu52LgXg==} + cpu: [x64] + os: [linux] + + '@rspack/binding-linux-x64-musl@1.0.8': + resolution: {integrity: sha512-MgbHJWV5utVa1/U9skrXClydZ/eZw001++v4B6nb8myU6Ck1D02aMl9ESefb/sSA8TatLLxEXQ2VENG9stnPwQ==} + cpu: [x64] + os: [linux] + + '@rspack/binding-win32-arm64-msvc@1.0.8': + resolution: {integrity: sha512-3NN5VisnSOzhgqX77O/7NvcjPUueg1oIdMKoc5vElJCEu5FEXPqDhwZmr1PpBovaXshAcgExF3j54+20pwdg5g==} + cpu: [arm64] + os: [win32] + + '@rspack/binding-win32-ia32-msvc@1.0.8': + resolution: {integrity: sha512-17VQNC7PSygzsipSVoukDM/SOcVueVNsk9bZiB0Swl20BaqrlBts2Dvlmo+L+ZGsxOYI97WvA/zomMDv860usg==} + cpu: [ia32] + os: [win32] + + '@rspack/binding-win32-x64-msvc@1.0.8': + resolution: {integrity: sha512-Vtjt74Soh09XUsV5Nw0YjZVSk/qtsjtPnzbSZluncSAVUs8l+X1ALcM6n1Jrt3TLTfcqf7a+VIsWOXAMqkCGUg==} + cpu: [x64] + os: [win32] + + '@rspack/binding@1.0.8': + resolution: {integrity: sha512-abRirbrjobcllLAamyeiWxT6Rb0wELUnITynQdqRbSweWm2lvnhm9YBv4BcOjvJBzhJtvRJo5JBtbKXjDTarug==} + + '@rspack/core@1.0.8': + resolution: {integrity: sha512-pbXwXYb4WQwb0l35P5v3l/NpDJXy1WiVE4IcQ/6LxZYU5NyZuqtsK0trR88xIVRZb9qU0JUeCdQq7Xa6Q+c3Xw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@swc/helpers': '>=0.5.1' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@rspack/lite-tapable@1.0.1': + resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==} + engines: {node: '>=16.0.0'} + '@shikijs/core@1.17.0': resolution: {integrity: sha512-Mkk4Mp4bNnW1kytU8I7S5PK5teNSe0iKlfqxPss4sdwnlcU8a2N62Z3te2gVmZfU9t1HF6L3wyWuM43IvEeEsg==} @@ -2383,9 +2632,6 @@ packages: '@shikijs/vitepress-twoslash@1.17.0': resolution: {integrity: sha512-FcdZUtF1jL51fZfkITd1qEnmnVe/w8lnOGhEWptMqMNvMYzB8vxDv5y+E1zvE+rw0NbBuWtOmZea3WOah1nr6g==} - '@shikijs/vscode-textmate@9.2.2': - resolution: {integrity: sha512-TMp15K+GGYrWlZM8+Lnj9EaHEFmOen0WJBrfa17hF7taDOYthuPPV0GWzfd/9iMij0akS/8Yw2ikquH7uVi/fg==} - '@shikijs/vscode-textmate@9.3.0': resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} @@ -2651,32 +2897,18 @@ packages: '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@unhead/dom@1.11.6': - resolution: {integrity: sha512-FYU8Cu+XWcpbO4OvXdB6x7m6GTPcl6CW7igI8rNu6Kc0Ilxb+atxIvyFXdTGAyB7h/F0w3ex06ZVWJ65f3EW8A==} - '@unhead/dom@1.11.7': resolution: {integrity: sha512-Nj2ulnbY5lvIcxqXwdO5YfdvLm8EYLjcaOje2b2aQnfyPAyOIVeR8iB79DDKk/uZZAPEwkdhSnUdEh9Ny0b3lw==} - '@unhead/schema@1.11.6': - resolution: {integrity: sha512-Ava5+kQERaZ2fi66phgR9KZQr9SsheN1YhhKM8fCP2A4Jb5lHUssVQ19P0+89V6RX9iUg/Q27WdEbznm75LzhQ==} - '@unhead/schema@1.11.7': resolution: {integrity: sha512-j9uN7T63aUXrZ6yx2CfjVT7xZHjn0PZO7TPMaWqMFjneIH/NONKvDVCMEqDlXeqdSIERIYtk/xTHgCUMer5eyw==} - '@unhead/shared@1.11.6': - resolution: {integrity: sha512-aGrtzRCcFlVh9iru73fBS8FA1vpQskS190t5cCRRMpisOEunVv3ueqXN1F8CseQd0W4wyEr/ycDvdfKt+RPv5g==} - '@unhead/shared@1.11.7': resolution: {integrity: sha512-5v3PmV1LMyikGyQi/URYS5ilH8dg1Iomtja7iFWke990O8RBDEzAdagJqcsUE/fw+o7cXRSOamyx5wCf5Q1TrA==} '@unhead/ssr@1.11.7': resolution: {integrity: sha512-qI1zNFY8fU5S9EhroxlXSA5Q/XKbWAKXrVVNG+6bIh/IRrMOMJrPk4d1GmphF4gmNri3ARqly+OWx4VVaj0scA==} - '@unhead/vue@1.11.6': - resolution: {integrity: sha512-CMuDJGTi4n4wKdOp6/JmB9roGshjTdoFKF34PEkXu4+g97BiVFiZ9LvgY44+UlWCUzQHcqEPRQIzm9iKEqcfKw==} - peerDependencies: - vue: 3.5.11 - '@unhead/vue@1.11.7': resolution: {integrity: sha512-SLr0eQfznVp63iKi47L4s5Yz+oiQjDA82VBP4jlXi7dM9fSIn1ul1aKvBqle/ZxI2cqY8zVGz60EjhjWeu754A==} peerDependencies: @@ -6979,9 +7211,6 @@ packages: unenv@1.10.0: resolution: {integrity: sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ==} - unhead@1.11.6: - resolution: {integrity: sha512-TKTQGUzHKF925VZ4KZVbLfKFzTVTEWfPLaXKmkd/ptEY2FHEoJUF7xOpAWc3K7Jzy/ExS66TL7GnLLjtd4sISg==} - unhead@1.11.7: resolution: {integrity: sha512-aA0+JBRryLhDKUq6L2JhMDLZEG/ElyyDASyC9wiwDl6nvvsj9hD26LgPWgmAsSd+9HtMGM2N1gU27CWEMo16CQ==} @@ -8310,6 +8539,22 @@ snapshots: - encoding - supports-color + '@module-federation/runtime-tools@0.5.1': + dependencies: + '@module-federation/runtime': 0.5.1 + '@module-federation/webpack-bundler-runtime': 0.5.1 + + '@module-federation/runtime@0.5.1': + dependencies: + '@module-federation/sdk': 0.5.1 + + '@module-federation/sdk@0.5.1': {} + + '@module-federation/webpack-bundler-runtime@0.5.1': + dependencies: + '@module-federation/runtime': 0.5.1 + '@module-federation/sdk': 0.5.1 + '@netlify/functions@2.8.1': dependencies: '@netlify/serverless-functions-api': 1.19.1 @@ -8505,7 +8750,7 @@ snapshots: '@types/stripe-v3': 3.1.33 '@types/vimeo__player': 2.18.3 '@types/youtube': 0.1.0 - '@unhead/vue': 1.11.6(vue@3.5.11(typescript@5.6.3)) + '@unhead/vue': 1.11.7(vue@3.5.11(typescript@5.6.3)) '@vueuse/core': 11.1.0(vue@3.5.11(typescript@5.6.3)) consola: 3.2.3 defu: 6.1.4 @@ -8908,12 +9153,60 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.24.0': optional: true + '@rspack/binding-darwin-arm64@1.0.8': + optional: true + + '@rspack/binding-darwin-x64@1.0.8': + optional: true + + '@rspack/binding-linux-arm64-gnu@1.0.8': + optional: true + + '@rspack/binding-linux-arm64-musl@1.0.8': + optional: true + + '@rspack/binding-linux-x64-gnu@1.0.8': + optional: true + + '@rspack/binding-linux-x64-musl@1.0.8': + optional: true + + '@rspack/binding-win32-arm64-msvc@1.0.8': + optional: true + + '@rspack/binding-win32-ia32-msvc@1.0.8': + optional: true + + '@rspack/binding-win32-x64-msvc@1.0.8': + optional: true + + '@rspack/binding@1.0.8': + optionalDependencies: + '@rspack/binding-darwin-arm64': 1.0.8 + '@rspack/binding-darwin-x64': 1.0.8 + '@rspack/binding-linux-arm64-gnu': 1.0.8 + '@rspack/binding-linux-arm64-musl': 1.0.8 + '@rspack/binding-linux-x64-gnu': 1.0.8 + '@rspack/binding-linux-x64-musl': 1.0.8 + '@rspack/binding-win32-arm64-msvc': 1.0.8 + '@rspack/binding-win32-ia32-msvc': 1.0.8 + '@rspack/binding-win32-x64-msvc': 1.0.8 + + '@rspack/core@1.0.8': + dependencies: + '@module-federation/runtime-tools': 0.5.1 + '@rspack/binding': 1.0.8 + '@rspack/lite-tapable': 1.0.1 + caniuse-lite: 1.0.30001667 + + '@rspack/lite-tapable@1.0.1': {} + '@shikijs/core@1.17.0': dependencies: '@shikijs/engine-javascript': 1.17.0 '@shikijs/engine-oniguruma': 1.17.0 '@shikijs/types': 1.17.0 - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 hast-util-to-html: 9.0.3 @@ -8922,7 +9215,7 @@ snapshots: '@shikijs/engine-javascript': 1.20.0 '@shikijs/engine-oniguruma': 1.20.0 '@shikijs/types': 1.20.0 - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 hast-util-to-html: 9.0.3 @@ -8944,7 +9237,7 @@ snapshots: '@shikijs/engine-javascript@1.20.0': dependencies: '@shikijs/types': 1.20.0 - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/vscode-textmate': 9.3.0 oniguruma-to-js: 0.4.3 '@shikijs/engine-javascript@1.22.0': @@ -8956,12 +9249,12 @@ snapshots: '@shikijs/engine-oniguruma@1.17.0': dependencies: '@shikijs/types': 1.17.0 - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/vscode-textmate': 9.3.0 '@shikijs/engine-oniguruma@1.20.0': dependencies: '@shikijs/types': 1.20.0 - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/vscode-textmate': 9.3.0 '@shikijs/engine-oniguruma@1.22.0': dependencies: @@ -8983,12 +9276,12 @@ snapshots: '@shikijs/types@1.17.0': dependencies: - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 '@shikijs/types@1.20.0': dependencies: - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 '@shikijs/types@1.22.0': @@ -9004,7 +9297,7 @@ snapshots: mdast-util-gfm: 3.0.0 mdast-util-to-hast: 13.2.0 shiki: 1.17.0 - twoslash: 0.2.11(typescript@5.6.3) + twoslash: 0.2.12(typescript@5.6.3) twoslash-vue: 0.2.11(typescript@5.6.3) vue: 3.5.11(typescript@5.6.3) transitivePeerDependencies: @@ -9012,8 +9305,6 @@ snapshots: - supports-color - typescript - '@shikijs/vscode-textmate@9.2.2': {} - '@shikijs/vscode-textmate@9.3.0': {} '@sidvind/better-ajv-errors@3.0.1(ajv@8.17.1)': @@ -9340,30 +9631,16 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@unhead/dom@1.11.6': - dependencies: - '@unhead/schema': 1.11.6 - '@unhead/shared': 1.11.6 - '@unhead/dom@1.11.7': dependencies: '@unhead/schema': 1.11.7 '@unhead/shared': 1.11.7 - '@unhead/schema@1.11.6': - dependencies: - hookable: 5.5.3 - zhead: 2.2.4 - '@unhead/schema@1.11.7': dependencies: hookable: 5.5.3 zhead: 2.2.4 - '@unhead/shared@1.11.6': - dependencies: - '@unhead/schema': 1.11.6 - '@unhead/shared@1.11.7': dependencies: '@unhead/schema': 1.11.7 @@ -9373,15 +9650,6 @@ snapshots: '@unhead/schema': 1.11.7 '@unhead/shared': 1.11.7 - '@unhead/vue@1.11.6(vue@3.5.11(typescript@5.6.3))': - dependencies: - '@unhead/schema': 1.11.6 - '@unhead/shared': 1.11.6 - defu: 6.1.4 - hookable: 5.5.3 - unhead: 1.11.6 - vue: 3.5.11(typescript@5.6.3) - '@unhead/vue@1.11.7(vue@3.5.11(typescript@5.6.3))': dependencies: '@unhead/schema': 1.11.7 @@ -10689,7 +10957,7 @@ snapshots: dependencies: postcss: 8.4.47 - css-loader@7.1.2(webpack@5.95.0): + css-loader@7.1.2(@rspack/core@1.0.8)(webpack@5.95.0): dependencies: icss-utils: 5.1.0(postcss@8.4.47) postcss: 8.4.47 @@ -10700,6 +10968,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: + '@rspack/core': 1.0.8 webpack: 5.95.0 css-minimizer-webpack-plugin@7.0.0(webpack@5.95.0): @@ -13169,7 +13438,7 @@ snapshots: picocolors: 1.1.0 remark-parse: 11.0.0 shiki: 1.20.0 - twoslash: 0.2.11(typescript@5.6.3) + twoslash: 0.2.12(typescript@5.6.3) typescript: 5.6.3 unified: 11.0.5 unist-util-visit: 5.0.0 @@ -13456,13 +13725,14 @@ snapshots: read-cache: 1.0.0 resolve: 1.22.8 - postcss-loader@8.1.1(postcss@8.4.47)(typescript@5.6.3)(webpack@5.95.0): + postcss-loader@8.1.1(@rspack/core@1.0.8)(postcss@8.4.47)(typescript@5.6.3)(webpack@5.95.0): dependencies: cosmiconfig: 9.0.0(typescript@5.6.3) jiti: 2.3.3 postcss: 8.4.47 semver: 7.6.3 optionalDependencies: + '@rspack/core': 1.0.8 webpack: 5.95.0 transitivePeerDependencies: - typescript @@ -14178,7 +14448,7 @@ snapshots: dependencies: '@shikijs/core': 1.17.0 '@shikijs/types': 1.17.0 - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 shiki@1.20.0: @@ -14187,7 +14457,7 @@ snapshots: '@shikijs/engine-javascript': 1.20.0 '@shikijs/engine-oniguruma': 1.20.0 '@shikijs/types': 1.20.0 - '@shikijs/vscode-textmate': 9.2.2 + '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 side-channel@1.0.6: @@ -14634,13 +14904,6 @@ snapshots: node-fetch-native: 1.6.4 pathe: 1.1.2 - unhead@1.11.6: - dependencies: - '@unhead/dom': 1.11.6 - '@unhead/schema': 1.11.6 - '@unhead/shared': 1.11.6 - hookable: 5.5.3 - unhead@1.11.7: dependencies: '@unhead/dom': 1.11.7 diff --git a/test/basic.test.ts b/test/basic.test.ts index 8c70bdfda2..01a135223e 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -15,7 +15,7 @@ import type { NuxtIslandResponse } from '#app' // TODO: update @nuxt/test-utils const $fetch = _$fetch as import('nitro/types').$Fetch -const isWebpack = process.env.TEST_BUILDER === 'webpack' +const isWebpack = process.env.TEST_BUILDER === 'webpack' || process.env.TEST_BUILDER === 'rspack' const isTestingAppManifest = process.env.TEST_MANIFEST !== 'manifest-off' await setup({ diff --git a/test/fixtures/basic-types/nuxt.config.ts b/test/fixtures/basic-types/nuxt.config.ts index ffa2356e3a..ea5a0d9cf5 100644 --- a/test/fixtures/basic-types/nuxt.config.ts +++ b/test/fixtures/basic-types/nuxt.config.ts @@ -9,7 +9,7 @@ export default defineNuxtConfig({ future: { typescriptBundlerResolution: process.env.MODULE_RESOLUTION === 'bundler', }, - builder: process.env.TEST_BUILDER as 'webpack' | 'vite' ?? 'vite', + builder: process.env.TEST_BUILDER as 'webpack' | 'rspack' | 'vite' ?? 'vite', theme: './extends/bar', extends: [ './extends/node_modules/foo', diff --git a/test/fixtures/basic/nuxt.config.ts b/test/fixtures/basic/nuxt.config.ts index 75063b9cd7..3e41835bf2 100644 --- a/test/fixtures/basic/nuxt.config.ts +++ b/test/fixtures/basic/nuxt.config.ts @@ -31,7 +31,7 @@ export default defineNuxtConfig({ include: ['keepalive-in-config', 'not-keepalive-in-nuxtpage'], }, }, - builder: process.env.TEST_BUILDER as 'webpack' | 'vite' ?? 'vite', + builder: process.env.TEST_BUILDER as 'webpack' | 'rspack' | 'vite' ?? 'vite', appId: 'nuxt-app-basic', build: { transpile: [ diff --git a/test/fixtures/basic/package.json b/test/fixtures/basic/package.json index 5eceaeb30d..b4103147af 100644 --- a/test/fixtures/basic/package.json +++ b/test/fixtures/basic/package.json @@ -5,6 +5,7 @@ "build": "nuxi build" }, "dependencies": { + "@nuxt/rspack-builder": "workspace:*", "@nuxt/webpack-builder": "workspace:*", "nuxt": "workspace:*" }, diff --git a/test/fixtures/runtime-compiler/nuxt.config.ts b/test/fixtures/runtime-compiler/nuxt.config.ts index b61d642360..202a2e6630 100644 --- a/test/fixtures/runtime-compiler/nuxt.config.ts +++ b/test/fixtures/runtime-compiler/nuxt.config.ts @@ -7,5 +7,5 @@ export default defineNuxtConfig({ vue: { runtimeCompiler: true, }, - builder: process.env.TEST_BUILDER as 'webpack' | 'vite' ?? 'vite', + builder: process.env.TEST_BUILDER as 'webpack' | 'rspack' | 'vite' ?? 'vite', }) diff --git a/test/hmr.test.ts b/test/hmr.test.ts index d313ac5fc6..ff2783cb66 100644 --- a/test/hmr.test.ts +++ b/test/hmr.test.ts @@ -10,7 +10,7 @@ import { expectWithPolling, renderPage } from './utils' // TODO: update @nuxt/test-utils const $fetch = _$fetch as import('nitro/types').$Fetch -const isWebpack = process.env.TEST_BUILDER === 'webpack' +const isWebpack = process.env.TEST_BUILDER === 'webpack' || process.env.TEST_BUILDER === 'rspack' // TODO: fix HMR on Windows if (process.env.TEST_ENV !== 'built' && !isWindows) { diff --git a/test/runtime-compiler.test.ts b/test/runtime-compiler.test.ts index 7ab8944d09..d90b618d2e 100644 --- a/test/runtime-compiler.test.ts +++ b/test/runtime-compiler.test.ts @@ -4,7 +4,7 @@ import { $fetch, createPage, setup } from '@nuxt/test-utils/e2e' import { isWindows } from 'std-env' import { expectNoClientErrors } from './utils' -const isWebpack = process.env.TEST_BUILDER === 'webpack' +const isWebpack = process.env.TEST_BUILDER === 'webpack' || process.env.TEST_BUILDER === 'rspack' await setup({ rootDir: fileURLToPath(new URL('./fixtures/runtime-compiler', import.meta.url)), diff --git a/test/suspense.test.ts b/test/suspense.test.ts index 859a934817..6fb55edc7c 100644 --- a/test/suspense.test.ts +++ b/test/suspense.test.ts @@ -4,7 +4,7 @@ import { isWindows } from 'std-env' import { setup } from '@nuxt/test-utils' import { renderPage } from './utils' -const isWebpack = process.env.TEST_BUILDER === 'webpack' +const isWebpack = process.env.TEST_BUILDER === 'webpack' || process.env.TEST_BUILDER === 'rspack' await setup({ rootDir: fileURLToPath(new URL('./fixtures/suspense', import.meta.url)),