fix: enable requireAsExpression by default again and not to throw warning when requireAlias is disabled#12998
Conversation
4a9b2b4 to
de501f1
Compare
Deploying rspack with
|
| Latest commit: |
ba2c2b7
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://02da3b22.rspack-v2.pages.dev |
| Branch Preview URL: | https://fix-umd-require-error.rspack-v2.pages.dev |
There was a problem hiding this comment.
Pull request overview
This PR restores requireAsExpression to be enabled by default to avoid runtime require is not defined errors in patterns like typeof require === "function" && require, and adjusts CommonJS parsing to suppress the “critical dependency” warning specifically when require is being renamed while requireAlias is disabled.
Changes:
- Enable
module.parser.javascript.requireAsExpressionby default and update docs to reflect the new default. - Add parser state to suppress the “unknown context critical” warning during
requirerenaming whenrequireAliasisfalse. - Update/add test cases and snapshots to cover both
requireAliasenabled/disabled behaviors under the new default.
Reviewed changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| website/docs/zh/config/module.mdx | Updates Chinese docs to show requireAsExpression default is true and how to disable it. |
| website/docs/en/config/module.mdx | Updates English docs to show requireAsExpression default is true and how to disable it. |
| packages/rspack/src/config/defaults.ts | Changes JS-side default parser option requireAsExpression to true. |
| crates/rspack/src/builder/mod.rs | Aligns Rust builder defaults for require_as_expression (and require_alias) with expected defaults. |
| crates/rspack_plugin_javascript/src/visitors/dependency/parser/mod.rs | Adds parser state to track when a rename is in progress. |
| crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs | Suppresses “critical dependency” warning for require when it is being renamed and requireAlias is disabled. |
| tests/rspack-test/statsOutputCases/async-commons-chunk/snapshots/stats.txt | Updates stats snapshot to reflect new warning output. |
| tests/rspack-test/defaultsCases/default/base.js | Updates expected defaults to show requireAsExpression: true. |
| tests/rspack-test/configCases/parsing/require-alias-enabled/rspack.config.js | New fixture for requireAlias: true. |
| tests/rspack-test/configCases/parsing/require-alias-enabled/index.js | New test validating alias behavior when requireAlias is enabled. |
| tests/rspack-test/configCases/parsing/require-alias-enabled/file.js | New fixture module for require-alias-enabled case. |
| tests/rspack-test/configCases/parsing/require-alias-enabled/warnings.js | New expected warning patterns for require-alias-enabled case. |
| tests/rspack-test/configCases/parsing/require-alias-disabled/rspack.config.js | Removes explicit requireAsExpression: false since default is now true. |
| tests/rspack-test/configCases/parsing/require-alias-disabled/index.js | Adjusts assertions for output under new default requireAsExpression. |
| tests/rspack-test/configCases/parsing/require-alias-disabled/file.js | New fixture module for require-alias-disabled case. |
| tests/rspack-test/configCases/parsing/require-alias-disabled/warnings.js | New expected warning patterns for require-alias-disabled case. |
| crates/rspack/tests/snapshots/defaults__default_options.snap.new | Adds a new snapshot artifact file reflecting updated defaults. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
📦 Binary Size-limit
🎉 Size decreased by 19.63KB from 48.65MB to 48.63MB (⬇️0.04%) |
Rsdoctor Bundle Diff Analysis
Found 5 projects in monorepo, 0 projects with changes. 📊 Quick Summary
Generated by Rsdoctor GitHub Action |
CodSpeed Performance ReportMerging this PR will degrade performance by 10.92%Comparing Summary
Performance Changes
Footnotes
|
de501f1 to
ba2c2b7
Compare
There was a problem hiding this comment.
reviewed by Codex locally on my device, is the warning expected here?
- Problem location:
crates/rspack_plugin_javascript/src/parser_plugin/common_js_imports_parse_plugin.rs:442andcrates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs:933 - Specific reason:
rename()will firstparser.walk_expression(expr)and then returnSome(true)whenrequireAlias: false; however,get_var_namein_walk_iifewill executeparser.walk_expression(expr)again in therename == truebranch, so the same require is walked twice. - Direct consequences:
- An extra CommonJsRequireContextDependency will be created;
- The warning suppressed by
is_renamingin the first pass will "leak out" in the second pass (is_renaminghas been restored), so Critical dependency warning may still occur in the IIFE scenario.
- Suggested fix: In
get_var_nameof_walk_iife, treatrename == trueas "already processed", return directly, and avoid extrawalk_expression.
a minimal reproduction:
// source
(function (r) {})(require);// config
const path = require("node:path");
/** @type {import("@rspack/core").Configuration} */
module.exports = {
mode: "development",
context: __dirname,
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
module: {
parser: {
javascript: {
requireAlias: false,
requireAsExpression: true,
unknownContextCritical: true
}
}
},
infrastructureLogging: {
level: "none"
},
stats: {
preset: "errors-warnings",
errorDetails: true
}
};result
WARNING in ./src/index.js 1:19-26
⚠ Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
╭────
1 │ (function (r) {})(require);
· ───────
╰────
Rspack compiled with 1 warning
and the fix
diff --git a/crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs b/crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs
index 30217bc8a3..96900d966a 100644
--- a/crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs
+++ b/crates/rspack_plugin_javascript/src/visitors/dependency/parser/walk.rs
@@ -932,15 +932,18 @@ impl JavascriptParser<'_> {
&& rename_identifier
.call_hooks_name(parser, |this, for_name| drive.can_rename(this, for_name))
.unwrap_or_default()
- && !rename_identifier
+ {
+ if !rename_identifier
.call_hooks_name(parser, |this, for_name| drive.rename(this, expr, for_name))
.unwrap_or_default()
- {
- let variable = parser
- .get_variable_info(&rename_identifier)
- .map(|info| ExportedVariableInfo::VariableInfo(info.id()))
- .unwrap_or(ExportedVariableInfo::Name(rename_identifier));
- return Some(variable);
+ {
+ let variable = parser
+ .get_variable_info(&rename_identifier)
+ .map(|info| ExportedVariableInfo::VariableInfo(info.id()))
+ .unwrap_or(ExportedVariableInfo::Name(rename_identifier));
+ return Some(variable);
+ }
+ return None;
}
parser.walk_expression(expr);
None
Seems to be a bug of parser before, i'll fix it |
Summary
If the
requireAsExpressionis disabled by default, thetypeof require === "function" && requirewill not be convert totrue && requireand throw an error ofrequire is not definedin runtime. But we can not just convert alltypeof require === "function"tofalsebecausetypeof require === "function" && require("./a")need it to be true. So we can only enable requireAsExpression by default.Meanwhile, if requireAlias is disabled, the require which in
var cjs = requirewill throw an warning. So we just need to prevent generating this warning by adding a flag to parser and if the renaming happens torequirethen skip the warning.Related links
Checklist