Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1830,3 +1830,4 @@ export interface ThreadsafeNodeFS {
mkdirp: (name: string) => Promise<string | void> | string | void
removeDirAll: (name: string) => Promise<string | void> | string | void
}

21 changes: 8 additions & 13 deletions crates/rspack_core/src/external_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,15 +345,13 @@ if(typeof {global} !== "undefined") return resolve();
fn get_module_import_type<'a>(&self, external_type: &'a ExternalType) -> &'a str {
match external_type.as_str() {
"module-import" => {
let external_type = self
.dependency_meta
.external_type
.as_ref()
.expect("should get \"module\" or \"import\" external type from dependency");

match external_type {
ExternalTypeEnum::Import => "import",
ExternalTypeEnum::Module => "module",
if let Some(external_type) = self.dependency_meta.external_type.as_ref() {
match external_type {
ExternalTypeEnum::Import => "import",
ExternalTypeEnum::Module => "module",
}
} else {
"module"
}
}
import_or_module => import_or_module,
Expand Down Expand Up @@ -479,10 +477,7 @@ impl Module for ExternalModule {
build_result.build_meta.has_top_level_await = true;
build_result.build_meta.exports_type = BuildMetaExportsType::Namespace;
}
r#type => panic!(
"Unhandled external type: {} in \"module-import\" type",
r#type
),
_ => {}
},
_ => build_result.build_meta.exports_type = BuildMetaExportsType::Dynamic,
}
Expand Down
6 changes: 6 additions & 0 deletions tests/webpack-test/configCases/externals/module-import/a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import external0 from "external0"; // module
const external1 = require("external1"); // module
const external2 = require("external2"); // node-commonjs
const external3 = import("external3"); // import

console.log(external0, external1, external2, external3);
10 changes: 10 additions & 0 deletions tests/webpack-test/configCases/externals/module-import/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const fs = require("fs");
const path = require("path");

it("module-import should correctly get fallback type", function() {
const content = fs.readFileSync(path.resolve(__dirname, "a.js"), "utf-8");
expect(content).toContain(`import * as __WEBPACK_EXTERNAL_MODULE_external0__ from "external0";`); // module
expect(content).toContain(`import * as __WEBPACK_EXTERNAL_MODULE_external1__ from "external1";`); // module
expect(content).toContain(`module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("external2");`); // node-commonjs
expect(content).toContain(`module.exports = import("external3");`); // import
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
findBundle: (i, options) => ["main.js"]
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/** @type {import("../../../../types").Configuration} */
module.exports = {
target: ["web", "es2020"],
node: {
__dirname: false,
__filename: false
},
output: {
module: true,
filename: "[name].js"
},
entry: {
a: "./a",
main: "./index"
},
optimization: {
concatenateModules: true
},
experiments: {
outputModule: true
},
externalsType: "module-import",
externals: [
function (
{ context, request, contextInfo, getResolve, dependencyType },
callback
) {
if (request === "external2") {
return callback(null, "node-commonjs external2");
}
callback();
},
{
external0: "external0",
external1: "external1",
external3: "external3",
fs: "commonjs fs",
path: "commonjs path"
}
]
};
18 changes: 18 additions & 0 deletions website/docs/en/config/externals.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,24 @@ async function foo() {

Note that there will be an `import` or `import()` statement in the output bundle.

When a module is not imported via `import` or `import()`, Rspack will use `"module"` externals type as fallback. If you want to use a different type of externals as fallback, you can specify it with a function in the `externals` option. For example:

```js title="rspack.config.js"
module.exports = {
externalsType: "module-import",
externals: [
function (
{ request, dependencyType },
callback
) {
if (dependencyType === "commonjs") {
return callback(null, `node-commonjs ${request}`);
}
callback();
},
]
```

### externalsType['node-commonjs']

Specify the default type of externals as `'node-commonjs'`. Rspack will import [`createRequire`](https://nodejs.org/api/module.html#module_module_createrequire_filename) from `'module'` to construct a require function for loading externals used in a module.
Expand Down
18 changes: 18 additions & 0 deletions website/docs/zh/config/externals.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,24 @@ async function foo() {

请注意,在输出产物中将有 `import` 或 `import()` 语句。

当一个模块没有通过 `import` 或 `import()` 导入时,Rspack 将使用 `"module"` externals type 作为回退。如果你想使用不同类型的 externals 作为回退,你可以在 `externals` 选项中指定一个函数。例如:

```js title="rspack.config.js"
module.exports = {
externalsType: "module-import",
externals: [
function (
{ request, dependencyType },
callback
) {
if (dependencyType === "commonjs") {
return callback(null, `node-commonjs ${request}`);
}
callback();
},
]
```

### externalsType['node-commonjs']

将 externals 类型设置为 `'node-commonjs'`,Rspack 将从 `module` 中导入 [`createRequire`](https://nodejs.org/api/module.html#module_module_createrequire_filename) 来构造一个 require 函数,用于加载模块中使用的外部对象。
Expand Down