Skip to content
Draft
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
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,10 @@
"engines": {
"node": ">=18.12.0",
"pnpm": ">=10.21.0"
},
"pnpm": {
"overrides": {
"@rspack/core": "link:../rspack/packages/rspack"
}
}
}
1 change: 1 addition & 0 deletions packages/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1830,6 +1830,7 @@ async function composeLibRsbuildConfig(
const assetConfig = composeAssetConfig(bundle, format);

const entryChunkConfig = composeEntryChunkConfig({
useLoader: advancedEsm !== true,
enabledImportMetaUrlShim: enabledShims.cjs['import.meta.url'],
contextToWatch: outBase,
});
Expand Down
198 changes: 100 additions & 98 deletions packages/core/src/plugins/EntryChunkPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { chmodSync } from 'node:fs';
// import { chmodSync } from 'node:fs';
import { createRequire } from 'node:module';
import {
type EnvironmentConfig,
Expand All @@ -8,9 +8,9 @@ import {
} from '@rsbuild/core';
import {
JS_EXTENSIONS_PATTERN,
REACT_DIRECTIVE_REGEX,
SHEBANG_PREFIX,
SHEBANG_REGEX,
// REACT_DIRECTIVE_REGEX,
// SHEBANG_PREFIX,
// SHEBANG_REGEX,
} from '../constant';

const require = createRequire(import.meta.url);
Expand All @@ -25,25 +25,25 @@ const IMPORT_META_URL_SHIM = `const __rslib_import_meta_url__ = /*#__PURE__*/ (f
})();
`;

const matchFirstLine = (source: string, regex: RegExp): string | false => {
const lineBreakPos = source.match(/(\r\n|\n)/);
const firstLineContent = source.slice(0, lineBreakPos?.index);
const matched = regex.exec(firstLineContent);
if (!matched) {
return false;
}
// const matchFirstLine = (source: string, regex: RegExp): string | false => {
// const lineBreakPos = source.match(/(\r\n|\n)/);
// const firstLineContent = source.slice(0, lineBreakPos?.index);
// const matched = regex.exec(firstLineContent);
// if (!matched) {
// return false;
// }

return matched[0];
};
// return matched[0];
// };

class EntryChunkPlugin {
private reactDirectives: Record<string, string> = {};
// private reactDirectives: Record<string, string> = {};

private shimsInjectedAssets: Set<string> = new Set();

private shebangChmod = 0o755;
private shebangEntries: Record<string, string> = {};
private shebangInjectedAssets: Set<string> = new Set();
// private shebangChmod = 0o755;
// private shebangEntries: Record<string, string> = {};
// private shebangInjectedAssets: Set<string> = new Set();

private enabledImportMetaUrlShim: boolean;
private contextToWatch: string | null = null;
Expand Down Expand Up @@ -71,58 +71,58 @@ class EntryChunkPlugin {
}
});

compiler.hooks.make.tap(PLUGIN_NAME, (compilation) => {
const entries: Record<string, string> = {};
for (const [key, value] of compilation.entries) {
const firstDep = value.dependencies[0];
if (firstDep?.request) {
entries[key] = firstDep.request;
}
}

for (const name in entries) {
const first = entries[name];
if (!first) continue;
const filename = first.split('?')[0]!;
const isJs = JS_EXTENSIONS_PATTERN.test(filename);
if (!isJs) continue;
const content = compiler.inputFileSystem!.readFileSync!(filename, {
encoding: 'utf-8',
});
// Shebang
if (content.startsWith(SHEBANG_PREFIX)) {
const shebangMatch = matchFirstLine(content, SHEBANG_REGEX);
if (shebangMatch) {
this.shebangEntries[name] = shebangMatch;
}
}
// React directive
const reactDirective = matchFirstLine(content, REACT_DIRECTIVE_REGEX);
if (reactDirective) {
this.reactDirectives[name] = reactDirective;
}
}
});
// compiler.hooks.make.tap(PLUGIN_NAME, (compilation) => {
// const entries: Record<string, string> = {};
// for (const [key, value] of compilation.entries) {
// const firstDep = value.dependencies[0];
// if (firstDep?.request) {
// entries[key] = firstDep.request;
// }
// }

// for (const name in entries) {
// const first = entries[name];
// if (!first) continue;
// const filename = first.split('?')[0]!;
// const isJs = JS_EXTENSIONS_PATTERN.test(filename);
// if (!isJs) continue;
// const content = compiler.inputFileSystem!.readFileSync!(filename, {
// encoding: 'utf-8',
// });
// // Shebang
// if (content.startsWith(SHEBANG_PREFIX)) {
// const shebangMatch = matchFirstLine(content, SHEBANG_REGEX);
// if (shebangMatch) {
// this.shebangEntries[name] = shebangMatch;
// }
// }
// // React directive
// const reactDirective = matchFirstLine(content, REACT_DIRECTIVE_REGEX);
// if (reactDirective) {
// this.reactDirectives[name] = reactDirective;
// }
// }
// });

compiler.hooks.make.tap(PLUGIN_NAME, (compilation) => {
compilation.hooks.chunkAsset.tap(PLUGIN_NAME, (chunk, filename) => {
compilation.hooks.chunkAsset.tap(PLUGIN_NAME, (_chunk, filename) => {
const isJs = JS_EXTENSIONS_PATTERN.test(filename);
if (!isJs) return;

this.shimsInjectedAssets.add(filename);

const name = chunk.name;
if (!name) return;
// const name = chunk.name;
// if (!name) return;

const shebangEntry = this.shebangEntries[name];
if (shebangEntry) {
this.shebangEntries[filename] = shebangEntry;
}
// const shebangEntry = this.shebangEntries[name];
// if (shebangEntry) {
// this.shebangEntries[filename] = shebangEntry;
// }

const reactDirective = this.reactDirectives[name];
if (reactDirective) {
this.reactDirectives[filename] = reactDirective;
}
// const reactDirective = this.reactDirectives[name];
// if (reactDirective) {
// this.reactDirectives[filename] = reactDirective;
// }
});
});

Expand Down Expand Up @@ -159,45 +159,45 @@ class EntryChunkPlugin {
}
});

compilation.hooks.processAssets.tap(
{
name: PLUGIN_NAME,
// Just after minify stage, to avoid from being minified.
stage: rspack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING - 1,
},
(assets) => {
const chunkAsset = Object.keys(assets);
for (const name of chunkAsset) {
const shebangValue = this.shebangEntries[name];
const reactDirectiveValue = this.reactDirectives[name];

if (shebangValue || reactDirectiveValue) {
compilation.updateAsset(name, (old) => {
const replaceSource = new rspack.sources.ReplaceSource(old);
// Shebang
if (shebangValue) {
replaceSource.insert(0, `${shebangValue}\n`);
this.shebangInjectedAssets.add(name);
}

// React directives
if (reactDirectiveValue) {
replaceSource.insert(0, `${reactDirectiveValue}\n`);
}

return replaceSource;
});
}
}
},
);
// compilation.hooks.processAssets.tap(
// {
// name: PLUGIN_NAME,
// // Just after minify stage, to avoid from being minified.
// stage: rspack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING - 1,
// },
// (assets) => {
// const chunkAsset = Object.keys(assets);
// for (const name of chunkAsset) {
// const shebangValue = this.shebangEntries[name];
// const reactDirectiveValue = this.reactDirectives[name];

// if (shebangValue || reactDirectiveValue) {
// compilation.updateAsset(name, (old) => {
// const replaceSource = new rspack.sources.ReplaceSource(old);
// // Shebang
// if (shebangValue) {
// replaceSource.insert(0, `${shebangValue}\n`);
// this.shebangInjectedAssets.add(name);
// }

// // React directives
// if (reactDirectiveValue) {
// replaceSource.insert(0, `${reactDirectiveValue}\n`);
// }

// return replaceSource;
// });
// }
// }
// },
// );
});

compiler.hooks.assetEmitted.tap(PLUGIN_NAME, (file, { targetPath }) => {
if (this.shebangInjectedAssets.has(file)) {
chmodSync(targetPath, this.shebangChmod);
}
});
// compiler.hooks.assetEmitted.tap(PLUGIN_NAME, (file, { targetPath }) => {
// if (this.shebangInjectedAssets.has(file)) {
// chmodSync(targetPath, this.shebangChmod);
// }
// });
}
}

Expand All @@ -217,13 +217,15 @@ const entryModuleLoaderRsbuildPlugin = (): RsbuildPlugin => ({

export const composeEntryChunkConfig = ({
enabledImportMetaUrlShim,
useLoader,
contextToWatch = null,
}: {
useLoader: boolean;
enabledImportMetaUrlShim: boolean;
contextToWatch: string | null;
}): EnvironmentConfig => {
return {
plugins: [entryModuleLoaderRsbuildPlugin()],
plugins: useLoader ? [entryModuleLoaderRsbuildPlugin()] : [],
tools: {
rspack: {
plugins: [
Expand Down
38 changes: 20 additions & 18 deletions packages/core/src/plugins/entryModuleLoader.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import type { Rspack } from '@rsbuild/core';
import { REACT_DIRECTIVE_REGEX, SHEBANG_REGEX } from '../constant';

function splitFromFirstLine(text: string): [string, string] {
const match = text.match(/(\r\n|\n)/);
if (!match) {
return [text, ''];
}
// import { REACT_DIRECTIVE_REGEX, SHEBANG_REGEX } from '../constant';

return [text.slice(0, match.index), text.slice(match.index)];
}
// function splitFromFirstLine(text: string): [string, string] {
// const match = text.match(/(\r\n|\n)/);
// if (!match) {
// return [text, ''];
// }

// return [text.slice(0, match.index), text.slice(match.index)];
// }

const loader: Rspack.LoaderDefinition = function loader(source) {
let result = source;
return source;
// let result = source;

const [firstLine1, rest] = splitFromFirstLine(result);
// const [firstLine1, rest] = splitFromFirstLine(result);

if (SHEBANG_REGEX.test(firstLine1)) {
result = rest;
}
// if (SHEBANG_REGEX.test(firstLine1)) {
// result = rest;
// }

const [firstLine2, rest2] = splitFromFirstLine(result);
if (REACT_DIRECTIVE_REGEX.test(firstLine2)) {
result = rest2;
}
// const [firstLine2, rest2] = splitFromFirstLine(result);
// if (REACT_DIRECTIVE_REGEX.test(firstLine2)) {
// result = rest2;
// }

return result;
// return result;
};

export default loader;
Loading