diff --git a/packages/rspack/src/Compiler.ts b/packages/rspack/src/Compiler.ts index 8eafd94f8ef..51f4592db9a 100644 --- a/packages/rspack/src/Compiler.ts +++ b/packages/rspack/src/Compiler.ts @@ -403,7 +403,9 @@ class Compiler { childCompiler.root = this.root; if (Array.isArray(plugins)) { for (const plugin of plugins) { - plugin.apply(childCompiler); + if (plugin) { + plugin.apply(childCompiler); + } } } for (const name in this.hooks) { diff --git a/packages/rspack/src/config/zod.ts b/packages/rspack/src/config/zod.ts index fb103845981..3fee24c6215 100644 --- a/packages/rspack/src/config/zod.ts +++ b/packages/rspack/src/config/zod.ts @@ -26,6 +26,18 @@ const mode = z.enum(["development", "production", "none"]); export type Mode = z.infer; //#endregion +//#region Falsy +const falsy = z.union([ + z.literal(false), + z.literal(0), + z.literal(""), + z.null(), + z.undefined() +]); + +export type Falsy = z.infer; +//#endregion + //#region Entry const rawPublicPath = z.string(); export type RawPublicPath = z.infer; @@ -459,7 +471,7 @@ const ruleSetRule: z.ZodType = baseRuleSetRule.extend({ rules: z.lazy(() => ruleSetRule.array()).optional() }); -const ruleSetRules = z.array(z.literal("...").or(ruleSetRule)); +const ruleSetRules = z.array(z.literal("...").or(ruleSetRule).or(falsy)); export type RuleSetRules = z.infer; const assetParserDataUrlOptions = z.strictObject({ @@ -888,7 +900,8 @@ export type RspackPluginFunction = (this: Compiler, compiler: Compiler) => void; const plugin = z.union([ z.custom(), - z.custom() + z.custom(), + falsy, ]); const plugins = plugin.array(); export type Plugins = z.infer; @@ -1062,9 +1075,9 @@ const experiments = z.strictObject({ val )}' has been deprecated, please switch to 'experiments.newSplitChunks = true' to use webpack's behavior. See the discussion ${termlink( - "here", - "https://github.com/web-infra-dev/rspack/discussions/4168" - )}` + "here", + "https://github.com/web-infra-dev/rspack/discussions/4168" + )}` ); } return true; diff --git a/packages/rspack/src/rspack.ts b/packages/rspack/src/rspack.ts index 2ee3d658475..2e892f06c5d 100644 --- a/packages/rspack/src/rspack.ts +++ b/packages/rspack/src/rspack.ts @@ -70,7 +70,7 @@ function createCompiler(userOptions: RspackOptions): Compiler { for (const plugin of options.plugins) { if (typeof plugin === "function") { (plugin as RspackPluginFunction).call(compiler, compiler); - } else { + } else if (plugin) { plugin.apply(compiler); } } @@ -148,8 +148,10 @@ function rspack( } else { const { compiler, watch } = create(); if (watch) { - util.deprecate(() => {}, - "A 'callback' argument needs to be provided to the 'rspack(options, callback)' function when the 'watch' option is set. There is no way to handle the 'watch' option without a callback.")(); + util.deprecate( + () => { }, + "A 'callback' argument needs to be provided to the 'rspack(options, callback)' function when the 'watch' option is set. There is no way to handle the 'watch' option without a callback." + )(); } return compiler; } diff --git a/packages/rspack/src/rspackOptionsApply.ts b/packages/rspack/src/rspackOptionsApply.ts index a3be3998ecb..0c97297ca6f 100644 --- a/packages/rspack/src/rspackOptionsApply.ts +++ b/packages/rspack/src/rspackOptionsApply.ts @@ -149,7 +149,7 @@ export function optionsApply_compat( } export class RspackOptionsApply { - constructor() {} + constructor() { } process(options: RspackOptionsNormalized, compiler: Compiler) { assert( options.output.path, @@ -182,7 +182,7 @@ export class RspackOptionsApply { for (const item of minimizer) { if (typeof item === "function") { (item as RspackPluginFunction).call(compiler, compiler); - } else if (item !== "...") { + } else if (item !== "..." && item) { item.apply(compiler); } } diff --git a/packages/rspack/tests/configCases/plugins/plugins-falsy/a.js b/packages/rspack/tests/configCases/plugins/plugins-falsy/a.js new file mode 100644 index 00000000000..58c57157d36 --- /dev/null +++ b/packages/rspack/tests/configCases/plugins/plugins-falsy/a.js @@ -0,0 +1 @@ +export default "test"; diff --git a/packages/rspack/tests/configCases/plugins/plugins-falsy/index.js b/packages/rspack/tests/configCases/plugins/plugins-falsy/index.js new file mode 100644 index 00000000000..f2944e9172d --- /dev/null +++ b/packages/rspack/tests/configCases/plugins/plugins-falsy/index.js @@ -0,0 +1,5 @@ +const test = require("./a"); + +it("should work with falsy plugins", function () { + expect(test.default).toBe("test"); +}); diff --git a/packages/rspack/tests/configCases/plugins/plugins-falsy/webpack.config.js b/packages/rspack/tests/configCases/plugins/plugins-falsy/webpack.config.js new file mode 100644 index 00000000000..60669738df4 --- /dev/null +++ b/packages/rspack/tests/configCases/plugins/plugins-falsy/webpack.config.js @@ -0,0 +1,22 @@ +const nullValue = null; +const undefinedValue = undefined; +const falseValue = false; +const zeroValue = 0; +const emptyStringValue = ""; + +class FailPlugin { + apply() { + throw new Error("FailedPlugin"); + } +} + +/** @type {import("../../../../src/index").RspackOptions} */ +module.exports = { + plugins: [ + undefinedValue && new FailPlugin(), + nullValue && new FailPlugin(), + falseValue && new FailPlugin(), + zeroValue && new FailPlugin(), + emptyStringValue && new FailPlugin() + ] +};