Skip to content

Commit 71b1c2e

Browse files
committed
fix(modern-module): compat with more export cases
1 parent a6b1ca2 commit 71b1c2e

File tree

7 files changed

+142
-40
lines changed

7 files changed

+142
-40
lines changed

crates/rspack_plugin_library/src/modern_module_library_plugin.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use std::hash::Hash;
22

33
use rspack_core::rspack_sources::{ConcatSource, RawSource, SourceExt};
44
use rspack_core::{
5-
merge_runtime, ApplyContext, ChunkUkey, CodeGenerationExportsFinalNames, Compilation,
6-
CompilationOptimizeChunkModules, CompilationParams, CompilerCompilation, CompilerOptions,
7-
ConcatenatedModule, ConcatenatedModuleExportsDefinitions, LibraryOptions, ModuleIdentifier,
8-
Plugin, PluginContext,
5+
merge_runtime, to_identifier, ApplyContext, ChunkUkey, CodeGenerationExportsFinalNames,
6+
Compilation, CompilationOptimizeChunkModules, CompilationParams, CompilerCompilation,
7+
CompilerOptions, ConcatenatedModule, ConcatenatedModuleExportsDefinitions, LibraryOptions,
8+
ModuleIdentifier, Plugin, PluginContext,
99
};
1010
use rspack_error::{error_bail, Result};
1111
use rspack_hash::RspackHash;
@@ -74,6 +74,14 @@ impl ModernModuleLibraryPlugin {
7474
let unconcatenated_module_ids = module_ids
7575
.iter()
7676
.filter(|id| !concatenated_module_ids.contains(id))
77+
.filter(|id| {
78+
let module = module_graph
79+
.module_by_identifier(id)
80+
.expect("should have module");
81+
module
82+
.get_concatenation_bailout_reason(&module_graph, &compilation.chunk_graph)
83+
.is_none()
84+
})
7785
.collect::<HashSet<_>>();
7886

7987
for module_id in unconcatenated_module_ids.into_iter() {
@@ -114,6 +122,7 @@ fn render_startup(
114122
.get(module_id, Some(&chunk.runtime));
115123

116124
let mut exports = vec![];
125+
let mut exports_with_property_access = vec![];
117126

118127
let Some(_) = self.get_options_for_chunk(compilation, chunk_ukey)? else {
119128
return Ok(());
@@ -136,14 +145,29 @@ fn render_startup(
136145
.expect("name can't be empty");
137146

138147
let final_name = exports_final_names.get(used_name.as_str());
148+
139149
if let Some(final_name) = final_name {
140-
if info_name == final_name {
150+
// Currently, there's not way to determine if a final_name contains a property access.
151+
if final_name.contains('.') || final_name.contains("()") {
152+
exports_with_property_access.push((final_name, info_name));
153+
} else if info_name == final_name {
141154
exports.push(info_name.to_string());
142155
} else {
143156
exports.push(format!("{} as {}", final_name, info_name));
144157
}
145158
}
146159
}
160+
161+
for (final_name, info_name) in exports_with_property_access.iter() {
162+
let var_name = format!("__webpack_exports__{}", to_identifier(info_name));
163+
164+
source.add(RawSource::from(format!(
165+
"var {var_name} = {};\n",
166+
final_name
167+
)));
168+
169+
exports.push(format!("{} as {}", var_name, info_name));
170+
}
147171
}
148172

149173
if !exports.is_empty() {

packages/rspack-test-tools/tests/__snapshots__/Config.test.js.snap

Lines changed: 99 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -327,20 +327,9 @@ div {
327327
head{--webpack--120:&_13;}"
328328
`;
329329
330-
exports[`config config/library/modern-module-force-concaten step should pass 1`] = `
331-
"
332-
;// CONCATENATED MODULE: ./a.js
333-
const a = 'a'
334-
335-
export { a };
336-
"
337-
`;
338-
339-
exports[`config config/library/modern-module-force-concaten step should pass 2`] = `
330+
exports[`config config/library/modern-module-force-concaten step should pass: .cjs should bail out 1`] = `
340331
"var __webpack_modules__ = ({
341-
\\"772\\": (function (module) {
342-
343-
;// CONCATENATED MODULE: ./b.cjs
332+
\\"851\\": (function (module) {
344333
module.exports = 'b'
345334
346335
}),
@@ -374,23 +363,113 @@ return module.exports;
374363
// startup
375364
// Load entry module and return exports
376365
// This entry module is referenced by other modules so it can't be inlined
377-
var __webpack_exports__ = __webpack_require__(\\"772\\");
366+
var __webpack_exports__ = __webpack_require__(\\"851\\");
378367
"
379368
`;
380369
381-
exports[`config config/library/modern-module-force-concaten step should pass 3`] = `
382-
"
383-
;// CONCATENATED MODULE: ./c.js
384-
const c = 'c'
370+
exports[`config config/library/modern-module-force-concaten step should pass: .cjs should bail out when bundling 1`] = `
371+
"var __webpack_modules__ = ({
372+
\\"997\\": (function (module) {
373+
module.exports = 'bar'
374+
375+
}),
376+
377+
});
378+
/************************************************************************/
379+
// The module cache
380+
var __webpack_module_cache__ = {};
381+
382+
// The require function
383+
function __webpack_require__(moduleId) {
385384
385+
// Check if module is in cache
386+
var cachedModule = __webpack_module_cache__[moduleId];
387+
if (cachedModule !== undefined) {
388+
return cachedModule.exports;
389+
}
390+
// Create a new module (and put it into the cache)
391+
var module = (__webpack_module_cache__[moduleId] = {
392+
exports: {}
393+
});
394+
// Execute the module function
395+
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
396+
397+
// Return the exports of the module
398+
return module.exports;
399+
400+
}
401+
402+
/************************************************************************/
403+
// webpack/runtime/compat_get_default_export
404+
(() => {
405+
// getDefaultExport function for compatibility with non-harmony modules
406+
__webpack_require__.n = function (module) {
407+
var getter = module && module.__esModule ?
408+
function () { return module['default']; } :
409+
function () { return module; };
410+
__webpack_require__.d(getter, { a: getter });
411+
return getter;
412+
};
413+
414+
415+
416+
417+
})();
418+
// webpack/runtime/define_property_getters
419+
(() => {
420+
__webpack_require__.d = function(exports, definition) {
421+
for(var key in definition) {
422+
if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
423+
Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
424+
}
425+
}
426+
};
427+
})();
428+
// webpack/runtime/has_own_property
429+
(() => {
430+
__webpack_require__.o = function (obj, prop) {
431+
return Object.prototype.hasOwnProperty.call(obj, prop);
432+
};
433+
434+
})();
435+
/************************************************************************/
436+
437+
;// CONCATENATED MODULE: ./e/foo.js
438+
const foo = 'foo'
439+
440+
// EXTERNAL MODULE: ./e/bar.cjs
441+
var bar = __webpack_require__(\\"997\\");
442+
var bar_default = /*#__PURE__*/__webpack_require__.n(bar);
443+
;// CONCATENATED MODULE: ./e/index.js
444+
445+
446+
447+
448+
449+
var __webpack_exports__bar = (bar_default());
450+
export { foo, __webpack_exports__bar as bar };
386451
"
387452
`;
388453
389-
exports[`config config/library/modern-module-force-concaten step should pass 4`] = `
454+
exports[`config config/library/modern-module-force-concaten step should pass: .mjs should concat 1`] = `
390455
"
391456
;// CONCATENATED MODULE: ./d.mjs
392457
const d = 'd'
393-
export { d };
458+
"
459+
`;
460+
461+
exports[`config config/library/modern-module-force-concaten step should pass: harmony export should concat 1`] = `
462+
"
463+
;// CONCATENATED MODULE: ./a.js
464+
const a = 'a'
465+
466+
export { a };
467+
"
468+
`;
469+
470+
exports[`config config/library/modern-module-force-concaten step should pass: unambiguous should bail out 1`] = `
471+
"const c = 'c'
472+
394473
"
395474
`;
396475
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export const d = 'd'
1+
const d = 'd'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = 'bar'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const foo = 'foo'
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { foo } from './foo.js'
2+
import bar from './bar.cjs'
3+
4+
export { foo, bar }

packages/rspack-test-tools/tests/configCases/library/modern-module-force-concaten/rspack.config.js

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ module.exports = {
44
"a": "./a.js",
55
"b": "./b.cjs",
66
"c": "./c.js",
7-
"d": "./d.mjs"
7+
"d": "./d.mjs",
8+
"e": "./e/index.js"
89
},
910
output: {
1011
filename: `[name].js`,
@@ -13,15 +14,6 @@ module.exports = {
1314
iife: false,
1415
chunkFormat: "module",
1516
},
16-
externalsType: "module",
17-
externals: [
18-
(data, callback) => {
19-
if (data.contextInfo.issuer) {
20-
return callback(null, data.request)
21-
}
22-
callback()
23-
},
24-
],
2517
experiments: {
2618
outputModule: true
2719
},
@@ -37,10 +29,11 @@ module.exports = {
3729
*/
3830
const handler = compilation => {
3931
compilation.hooks.afterProcessAssets.tap("testcase", assets => {
40-
expect(assets['a.js']._value).toMatchSnapshot();
41-
expect(assets['b.js']._value).toMatchSnapshot();
42-
expect(assets['c.js']._value).toMatchSnapshot();
43-
expect(assets['d.js']._value).toMatchSnapshot();
32+
expect(assets['a.js']._value).toMatchSnapshot("harmony export should concat");
33+
expect(assets['b.js']._value).toMatchSnapshot(".cjs should bail out");
34+
expect(assets['c.js']._value).toMatchSnapshot("unambiguous should bail out");
35+
expect(assets['d.js']._value).toMatchSnapshot(".mjs should concat");
36+
expect(assets['e.js']._value).toMatchSnapshot(".cjs should bail out when bundling");
4437
});
4538
};
4639
this.hooks.compilation.tap("testcase", handler);

0 commit comments

Comments
 (0)