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
44 changes: 41 additions & 3 deletions crates/rspack_plugin_esm_library/src/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ use rspack_core::{
IdentCollector, MaybeDynamicTargetExportInfoHashKey, ModuleGraph, ModuleGraphCacheArtifact,
ModuleIdentifier, ModuleInfo, NAMESPACE_OBJECT_EXPORT, PathData, PrefetchExportsInfoMode,
RuntimeGlobals, SourceType, URLStaticMode, UsageState, UsedName, UsedNameItem, escape_name,
find_new_name, get_cached_readable_identifier, get_js_chunk_filename_template, property_access,
property_name, reserved_names::RESERVED_NAMES, rspack_sources::ReplaceSource,
split_readable_identifier, to_normal_comment,
find_new_name, get_cached_readable_identifier, get_js_chunk_filename_template,
get_module_directives, get_module_hashbang, property_access, property_name,
reserved_names::RESERVED_NAMES, rspack_sources::ReplaceSource, split_readable_identifier,
to_normal_comment,
};
use rspack_error::{Diagnostic, Result};
use rspack_javascript_compiler::ast::Ast;
Expand Down Expand Up @@ -1241,6 +1242,43 @@ var {} = {{}};
let entry_module_chunk = Self::get_module_chunk(entry_module, compilation);
entry_imports.entry(entry_module).or_default();

// NOTE: Similar hashbang and directives handling logic.
// See rspack_plugin_rslib/src/plugin.rs render() for why this duplication is necessary.
let hashbang = get_module_hashbang(module_graph, &entry_module);
let directives = get_module_directives(module_graph, &entry_module);

if let Some(hashbang) = &hashbang {
let entry_chunk_link = link.get_mut_unwrap(&entry_chunk_ukey);
entry_chunk_link.init_fragments.insert(
0,
Box::new(rspack_core::NormalInitFragment::new(
format!("{hashbang}\n"),
rspack_core::InitFragmentStage::StageConstants,
i32::MIN,
rspack_core::InitFragmentKey::unique(),
None,
)),
);
}

if let Some(directives) = directives {
let entry_module_chunk_link = link.get_mut_unwrap(&entry_module_chunk);

for (idx, directive) in directives.iter().enumerate() {
let insert_pos = if hashbang.is_some() { 1 + idx } else { idx };
entry_module_chunk_link.init_fragments.insert(
insert_pos,
Box::new(rspack_core::NormalInitFragment::new(
format!("{directive}\n"),
rspack_core::InitFragmentStage::StageConstants,
i32::MIN + 1 + idx as i32,
rspack_core::InitFragmentKey::unique(),
None,
)),
);
}
}

/*
entry module sometimes are splitted to whatever chunk user needs,
so the entry chunk maynot actually contains entry modules
Expand Down
44 changes: 1 addition & 43 deletions crates/rspack_plugin_esm_library/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rspack_core::{
AssetInfo, Chunk, ChunkGraph, ChunkRenderContext, ChunkUkey, CodeGenerationDataFilename,
Compilation, ConcatenatedModuleInfo, DependencyId, InitFragment, ModuleIdentifier, PathData,
PathInfo, RuntimeGlobals, RuntimeVariable, SourceType, get_js_chunk_filename_template,
get_module_directives, get_module_hashbang, get_undo_path, render_init_fragments,
get_undo_path, render_init_fragments,
rspack_sources::{ConcatSource, RawStringSource, ReplaceSource, Source, SourceExt},
};
use rspack_error::Result;
Expand Down Expand Up @@ -86,48 +86,6 @@ impl EsmLibraryPlugin {
let mut chunk_init_fragments: Vec<Box<dyn InitFragment<ChunkRenderContext> + 'static>> =
chunk_link.init_fragments.clone();

// NOTE: Similar hashbang and directives handling logic.
// See rspack_plugin_rslib/src/plugin.rs render() for why this duplication is necessary.
let entry_modules = compilation.chunk_graph.get_chunk_entry_modules(chunk_ukey);
for entry_module_id in &entry_modules {
let hashbang = get_module_hashbang(module_graph, entry_module_id);
let directives = get_module_directives(module_graph, entry_module_id);

if hashbang.is_none() && directives.is_none() {
continue;
}

if let Some(hashbang) = &hashbang {
chunk_init_fragments.insert(
0,
Box::new(rspack_core::NormalInitFragment::new(
format!("{hashbang}\n"),
rspack_core::InitFragmentStage::StageConstants,
i32::MIN,
rspack_core::InitFragmentKey::unique(),
None,
)),
);
}

if let Some(directives) = directives {
for (idx, directive) in directives.iter().enumerate() {
let insert_pos = if hashbang.is_some() { 1 + idx } else { idx };
chunk_init_fragments.insert(
insert_pos,
Box::new(rspack_core::NormalInitFragment::new(
format!("{directive}\n"),
rspack_core::InitFragmentStage::StageConstants,
i32::MIN + 1 + idx as i32,
rspack_core::InitFragmentKey::unique(),
None,
)),
);
}
}
break; // Only process the first entry module with hashbang/directives
}

let mut replace_auto_public_path = false;
let mut replace_static_url = false;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
```mjs title=main.mjs
#!/usr/bin/env node
import "./splitMain-index_js.mjs";


```

```mjs title=splitMain-index_js.mjs
import {fileURLToPath as __rspack_fileURLToPath} from "node:url";
import {dirname as __rspack_dirname} from "node:path";
import { createRequire as __rspack_createRequire } from "node:module";
const __rspack_createRequire_require = __rspack_createRequire(import.meta.url);
// ./index.js
var index_dirname = __rspack_dirname(__rspack_fileURLToPath(import.meta.url));
//


it('should have shebang in entry chunk', () => {
const fs = __rspack_createRequire_require('fs')
const path = __rspack_createRequire_require('path')

const code = fs.readFileSync(path.join(index_dirname, 'main.mjs'), 'utf-8')

expect(code.startsWith('#!')).toBeTruthy()
})

```
11 changes: 11 additions & 0 deletions tests/rspack-test/esmOutputCases/basic/shebang/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env node


it('should have shebang in entry chunk', () => {
const fs = __non_webpack_require__('fs')
const path = __non_webpack_require__('path')

const code = fs.readFileSync(path.join(__dirname, 'main.mjs'), 'utf-8')

expect(code.startsWith('#!')).toBeTruthy()
})
16 changes: 16 additions & 0 deletions tests/rspack-test/esmOutputCases/basic/shebang/rspack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const rspack = require('@rspack/core')

module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
splitMain: {
test: /index\.js/
}
}
}
},
plugins: [
new rspack.experiments.RslibPlugin()
]
}
Loading