Skip to content

Commit 65c39cf

Browse files
committed
fix: use native plugin to handle hashbang and react directives
1 parent 06563fd commit 65c39cf

File tree

9 files changed

+461
-558
lines changed

9 files changed

+461
-558
lines changed

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,10 @@
6565
"engines": {
6666
"node": ">=18.12.0",
6767
"pnpm": ">=10.21.0"
68+
},
69+
"pnpm": {
70+
"overrides": {
71+
"@rspack/core": "link:../rspack/packages/rspack"
72+
}
6873
}
6974
}

packages/core/src/plugins/EntryChunkPlugin.ts

Lines changed: 97 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { chmodSync } from 'node:fs';
1+
// import { chmodSync } from 'node:fs';
22
import { createRequire } from 'node:module';
33
import {
44
type EnvironmentConfig,
@@ -8,9 +8,9 @@ import {
88
} from '@rsbuild/core';
99
import {
1010
JS_EXTENSIONS_PATTERN,
11-
REACT_DIRECTIVE_REGEX,
12-
SHEBANG_PREFIX,
13-
SHEBANG_REGEX,
11+
// REACT_DIRECTIVE_REGEX,
12+
// SHEBANG_PREFIX,
13+
// SHEBANG_REGEX,
1414
} from '../constant';
1515

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

28-
const matchFirstLine = (source: string, regex: RegExp): string | false => {
29-
const lineBreakPos = source.match(/(\r\n|\n)/);
30-
const firstLineContent = source.slice(0, lineBreakPos?.index);
31-
const matched = regex.exec(firstLineContent);
32-
if (!matched) {
33-
return false;
34-
}
28+
// const matchFirstLine = (source: string, regex: RegExp): string | false => {
29+
// const lineBreakPos = source.match(/(\r\n|\n)/);
30+
// const firstLineContent = source.slice(0, lineBreakPos?.index);
31+
// const matched = regex.exec(firstLineContent);
32+
// if (!matched) {
33+
// return false;
34+
// }
3535

36-
return matched[0];
37-
};
36+
// return matched[0];
37+
// };
3838

3939
class EntryChunkPlugin {
40-
private reactDirectives: Record<string, string> = {};
40+
// private reactDirectives: Record<string, string> = {};
4141

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

44-
private shebangChmod = 0o755;
45-
private shebangEntries: Record<string, string> = {};
46-
private shebangInjectedAssets: Set<string> = new Set();
44+
// private shebangChmod = 0o755;
45+
// private shebangEntries: Record<string, string> = {};
46+
// private shebangInjectedAssets: Set<string> = new Set();
4747

4848
private enabledImportMetaUrlShim: boolean;
4949
private contextToWatch: string | null = null;
@@ -71,58 +71,58 @@ class EntryChunkPlugin {
7171
}
7272
});
7373

74-
compiler.hooks.make.tap(PLUGIN_NAME, (compilation) => {
75-
const entries: Record<string, string> = {};
76-
for (const [key, value] of compilation.entries) {
77-
const firstDep = value.dependencies[0];
78-
if (firstDep?.request) {
79-
entries[key] = firstDep.request;
80-
}
81-
}
82-
83-
for (const name in entries) {
84-
const first = entries[name];
85-
if (!first) continue;
86-
const filename = first.split('?')[0]!;
87-
const isJs = JS_EXTENSIONS_PATTERN.test(filename);
88-
if (!isJs) continue;
89-
const content = compiler.inputFileSystem!.readFileSync!(filename, {
90-
encoding: 'utf-8',
91-
});
92-
// Shebang
93-
if (content.startsWith(SHEBANG_PREFIX)) {
94-
const shebangMatch = matchFirstLine(content, SHEBANG_REGEX);
95-
if (shebangMatch) {
96-
this.shebangEntries[name] = shebangMatch;
97-
}
98-
}
99-
// React directive
100-
const reactDirective = matchFirstLine(content, REACT_DIRECTIVE_REGEX);
101-
if (reactDirective) {
102-
this.reactDirectives[name] = reactDirective;
103-
}
104-
}
105-
});
74+
// compiler.hooks.make.tap(PLUGIN_NAME, (compilation) => {
75+
// const entries: Record<string, string> = {};
76+
// for (const [key, value] of compilation.entries) {
77+
// const firstDep = value.dependencies[0];
78+
// if (firstDep?.request) {
79+
// entries[key] = firstDep.request;
80+
// }
81+
// }
82+
83+
// for (const name in entries) {
84+
// const first = entries[name];
85+
// if (!first) continue;
86+
// const filename = first.split('?')[0]!;
87+
// const isJs = JS_EXTENSIONS_PATTERN.test(filename);
88+
// if (!isJs) continue;
89+
// const content = compiler.inputFileSystem!.readFileSync!(filename, {
90+
// encoding: 'utf-8',
91+
// });
92+
// // Shebang
93+
// if (content.startsWith(SHEBANG_PREFIX)) {
94+
// const shebangMatch = matchFirstLine(content, SHEBANG_REGEX);
95+
// if (shebangMatch) {
96+
// this.shebangEntries[name] = shebangMatch;
97+
// }
98+
// }
99+
// // React directive
100+
// const reactDirective = matchFirstLine(content, REACT_DIRECTIVE_REGEX);
101+
// if (reactDirective) {
102+
// this.reactDirectives[name] = reactDirective;
103+
// }
104+
// }
105+
// });
106106

107107
compiler.hooks.make.tap(PLUGIN_NAME, (compilation) => {
108-
compilation.hooks.chunkAsset.tap(PLUGIN_NAME, (chunk, filename) => {
108+
compilation.hooks.chunkAsset.tap(PLUGIN_NAME, (_chunk, filename) => {
109109
const isJs = JS_EXTENSIONS_PATTERN.test(filename);
110110
if (!isJs) return;
111111

112112
this.shimsInjectedAssets.add(filename);
113113

114-
const name = chunk.name;
115-
if (!name) return;
114+
// const name = chunk.name;
115+
// if (!name) return;
116116

117-
const shebangEntry = this.shebangEntries[name];
118-
if (shebangEntry) {
119-
this.shebangEntries[filename] = shebangEntry;
120-
}
117+
// const shebangEntry = this.shebangEntries[name];
118+
// if (shebangEntry) {
119+
// this.shebangEntries[filename] = shebangEntry;
120+
// }
121121

122-
const reactDirective = this.reactDirectives[name];
123-
if (reactDirective) {
124-
this.reactDirectives[filename] = reactDirective;
125-
}
122+
// const reactDirective = this.reactDirectives[name];
123+
// if (reactDirective) {
124+
// this.reactDirectives[filename] = reactDirective;
125+
// }
126126
});
127127
});
128128

@@ -159,45 +159,45 @@ class EntryChunkPlugin {
159159
}
160160
});
161161

162-
compilation.hooks.processAssets.tap(
163-
{
164-
name: PLUGIN_NAME,
165-
// Just after minify stage, to avoid from being minified.
166-
stage: rspack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING - 1,
167-
},
168-
(assets) => {
169-
const chunkAsset = Object.keys(assets);
170-
for (const name of chunkAsset) {
171-
const shebangValue = this.shebangEntries[name];
172-
const reactDirectiveValue = this.reactDirectives[name];
173-
174-
if (shebangValue || reactDirectiveValue) {
175-
compilation.updateAsset(name, (old) => {
176-
const replaceSource = new rspack.sources.ReplaceSource(old);
177-
// Shebang
178-
if (shebangValue) {
179-
replaceSource.insert(0, `${shebangValue}\n`);
180-
this.shebangInjectedAssets.add(name);
181-
}
182-
183-
// React directives
184-
if (reactDirectiveValue) {
185-
replaceSource.insert(0, `${reactDirectiveValue}\n`);
186-
}
187-
188-
return replaceSource;
189-
});
190-
}
191-
}
192-
},
193-
);
162+
// compilation.hooks.processAssets.tap(
163+
// {
164+
// name: PLUGIN_NAME,
165+
// // Just after minify stage, to avoid from being minified.
166+
// stage: rspack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING - 1,
167+
// },
168+
// (assets) => {
169+
// const chunkAsset = Object.keys(assets);
170+
// for (const name of chunkAsset) {
171+
// const shebangValue = this.shebangEntries[name];
172+
// const reactDirectiveValue = this.reactDirectives[name];
173+
174+
// if (shebangValue || reactDirectiveValue) {
175+
// compilation.updateAsset(name, (old) => {
176+
// const replaceSource = new rspack.sources.ReplaceSource(old);
177+
// // Shebang
178+
// if (shebangValue) {
179+
// replaceSource.insert(0, `${shebangValue}\n`);
180+
// this.shebangInjectedAssets.add(name);
181+
// }
182+
183+
// // React directives
184+
// if (reactDirectiveValue) {
185+
// replaceSource.insert(0, `${reactDirectiveValue}\n`);
186+
// }
187+
188+
// return replaceSource;
189+
// });
190+
// }
191+
// }
192+
// },
193+
// );
194194
});
195195

196-
compiler.hooks.assetEmitted.tap(PLUGIN_NAME, (file, { targetPath }) => {
197-
if (this.shebangInjectedAssets.has(file)) {
198-
chmodSync(targetPath, this.shebangChmod);
199-
}
200-
});
196+
// compiler.hooks.assetEmitted.tap(PLUGIN_NAME, (file, { targetPath }) => {
197+
// if (this.shebangInjectedAssets.has(file)) {
198+
// chmodSync(targetPath, this.shebangChmod);
199+
// }
200+
// });
201201
}
202202
}
203203

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,32 @@
11
import type { Rspack } from '@rsbuild/core';
2-
import { REACT_DIRECTIVE_REGEX, SHEBANG_REGEX } from '../constant';
32

4-
function splitFromFirstLine(text: string): [string, string] {
5-
const match = text.match(/(\r\n|\n)/);
6-
if (!match) {
7-
return [text, ''];
8-
}
3+
// import { REACT_DIRECTIVE_REGEX, SHEBANG_REGEX } from '../constant';
94

10-
return [text.slice(0, match.index), text.slice(match.index)];
11-
}
5+
// function splitFromFirstLine(text: string): [string, string] {
6+
// const match = text.match(/(\r\n|\n)/);
7+
// if (!match) {
8+
// return [text, ''];
9+
// }
10+
11+
// return [text.slice(0, match.index), text.slice(match.index)];
12+
// }
1213

1314
const loader: Rspack.LoaderDefinition = function loader(source) {
14-
let result = source;
15+
return source;
16+
// let result = source;
1517

16-
const [firstLine1, rest] = splitFromFirstLine(result);
18+
// const [firstLine1, rest] = splitFromFirstLine(result);
1719

18-
if (SHEBANG_REGEX.test(firstLine1)) {
19-
result = rest;
20-
}
20+
// if (SHEBANG_REGEX.test(firstLine1)) {
21+
// result = rest;
22+
// }
2123

22-
const [firstLine2, rest2] = splitFromFirstLine(result);
23-
if (REACT_DIRECTIVE_REGEX.test(firstLine2)) {
24-
result = rest2;
25-
}
24+
// const [firstLine2, rest2] = splitFromFirstLine(result);
25+
// if (REACT_DIRECTIVE_REGEX.test(firstLine2)) {
26+
// result = rest2;
27+
// }
2628

27-
return result;
29+
// return result;
2830
};
2931

3032
export default loader;

0 commit comments

Comments
 (0)