Skip to content

Commit e246175

Browse files
committed
chore: update
1 parent c5016fb commit e246175

File tree

18 files changed

+289
-571
lines changed

18 files changed

+289
-571
lines changed

examples/react-component-bundle-false/rslib.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export default defineConfig({
3333
output: {
3434
target: 'web',
3535
assetPrefix: 'auto', // TODO: move this line to packages/core/src/asset/assetConfig.ts
36+
dataUriLimit: 4000
3637
},
3738
plugins: [pluginReact(), pluginSass()],
3839
});

examples/react-component-bundle-false/src/components/CounterButton/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type React from 'react';
2+
import logo from '../../assets/logo.svg';
23
import styles from './index.module.scss';
3-
import logo from '../../assets/logo.svg'
44

55
interface CounterButtonProps {
66
onClick: () => void;
@@ -12,7 +12,7 @@ export const CounterButton: React.FC<CounterButtonProps> = ({
1212
label,
1313
}) => (
1414
<button type="button" className={styles.button} onClick={onClick}>
15-
<img src={logo} alt='react'/>
15+
<img src={logo} alt="react" />
1616
{label}
1717
</button>
1818
);

examples/react-component-bundle/src/components/CounterButton/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type React from 'react';
2+
import logo from '../../assets/logo.svg';
23
import styles from './index.module.scss';
3-
import logo from '../../assets/logo.svg'
44

55
interface CounterButtonProps {
66
onClick: () => void;
@@ -12,7 +12,7 @@ export const CounterButton: React.FC<CounterButtonProps> = ({
1212
label,
1313
}) => (
1414
<button type="button" className={styles.button} onClick={onClick}>
15-
<img src={logo} alt='react'/>
15+
<img src={logo} alt="react" />
1616
{label}
1717
</button>
1818
);

package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,14 @@
6363
"pnpm": ">=9.0.0"
6464
},
6565
"pnpm": {
66+
"peerDependencyRules": {
67+
"allowAny": [
68+
"@rspack/*"
69+
]
70+
},
6671
"overrides": {
67-
"zx>@types/node": "-"
72+
"zx>@types/node": "-",
73+
"@rspack/core": "/Users/bytedance/Documents/codes/rspack/packages/rspack"
6874
}
6975
}
7076
}
Lines changed: 111 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,137 @@
1+
import assert from 'node:assert';
12
import { type Rspack, rspack } from '@rsbuild/core';
23
import { getUndoPath } from '../css/utils';
34

4-
type Options = {
5-
}
65
/**
76
* these codes is written according to
87
* https://github.com/web-infra-dev/rspack/blob/61f0cd2b4e313445a9d3329ca71240e99edfb352/crates/rspack_plugin_asset/src/lib.rs#L531
98
*/
10-
const pattern: RegExp = /__webpack_require__\.p\s\+\s["'](.+)["']/g;
11-
function extractAssetFilenames (content: string): string[] {
12-
console.log([...content.matchAll(pattern)])
13-
return [...content.matchAll(pattern)].map(i => {
14-
return i?.[1]
15-
}).filter(Boolean) as string[];
16-
}
179

10+
// 1. bundleless: single file
11+
const BUNDLELESS_ASSET_PATTERN: RegExp =
12+
/__webpack_require__\.p\s\+\s["'](.+)["']/g;
1813
const RSLIB_NAMESPACE_OBJECT = '__rslib_asset__';
19-
20-
const esmSingleFileTemplate = (url: string) => `import ${RSLIB_NAMESPACE_OBJECT} from '${url}';
14+
const esmSingleFileTemplate = (
15+
url: string,
16+
) => `import ${RSLIB_NAMESPACE_OBJECT} from '${url}';
2117
export default ${RSLIB_NAMESPACE_OBJECT};`;
18+
const cjsSingleFileTemplate = (url: string) =>
19+
`module.exports = require('${url}');`;
20+
21+
function extractAssetFilenames(content: string): string[] {
22+
return [...content.matchAll(BUNDLELESS_ASSET_PATTERN)]
23+
.map((i) => {
24+
return i?.[1];
25+
})
26+
.filter(Boolean) as string[];
27+
}
28+
29+
// 2. bundle: concatenated
30+
const CONCATENATED_PATTERN: RegExp =
31+
/(const|var) (\w+) = __webpack_require__\.p\s\+\s["'](.+)["']/g;
32+
const concatenatedEsmReplaceTemplate = (variableName: string, url: string) =>
33+
`import ${variableName} from '${url}';`;
34+
const concatenatedCjsReplaceTemplate = (
35+
declarationKind: string,
36+
variableName: string,
37+
url: string,
38+
) => `${declarationKind} ${variableName} = require('${url}');`;
2239

23-
const cjsSingleFileTemplate = (url: string) => `module.exports = require('${url}');`;
40+
// 3. bundle: not concatenated, in __webpack_require__.m
41+
const NOT_CONCATENATED_PATTERN: RegExp =
42+
/module\.exports = __webpack_require__\.p\s\+\s["'](.+)["']/g;
43+
const nonConcatenatedReplaceTemplate = (url: string) =>
44+
`module.exports = require('${url}');`;
2445

2546
const pluginName = 'LIB_ASSET_EXTRACT_PLUGIN';
2647

48+
type Options = {
49+
// just for perf, in bundleless we can replace the entire file
50+
bundle: boolean;
51+
};
52+
2753
class LibAssetExtractPlugin implements Rspack.RspackPluginInstance {
2854
readonly name: string = pluginName;
2955
options: Options;
30-
constructor(options?: Options) {
31-
this.options = options ?? {};
56+
constructor(options: Options) {
57+
this.options = options;
3258
}
3359

3460
apply(compiler: Rspack.Compiler): void {
3561
compiler.hooks.make.tap(pluginName, (compilation) => {
36-
compilation.hooks.processAssets.tap(pluginName, (assets) => {
37-
const chunkAsset = Object.keys(assets).filter((name) =>
38-
/js/.test(name),
39-
);
40-
for (const name of chunkAsset) {
41-
const isEsmFormat = compilation.options.output.module;
42-
const undoPath = getUndoPath(
43-
name,
44-
compilation.outputOptions.path!,
45-
true,
62+
compilation.hooks.processAssets.tap(pluginName, (assets) => {
63+
const chunkAsset = Object.keys(assets).filter((name) =>
64+
/js$/.test(name),
4665
);
47-
compilation.updateAsset(name, (old) => {
48-
const oldSource = old.source().toString();
49-
const assetFilenames = extractAssetFilenames(oldSource);
50-
51-
if (assetFilenames.length === 1) {
52-
const assetFilename = assetFilenames[0];
53-
let newSource: string = '';
54-
const url = `${undoPath}${assetFilename}`;
55-
56-
if(isEsmFormat) {
57-
newSource = esmSingleFileTemplate(url);
58-
} else {
59-
newSource = cjsSingleFileTemplate(url);
66+
for (const name of chunkAsset) {
67+
const isEsmFormat = compilation.options.output.module;
68+
const undoPath = getUndoPath(
69+
name,
70+
compilation.outputOptions.path!,
71+
true,
72+
);
73+
compilation.updateAsset(name, (old) => {
74+
const oldSource = old.source().toString();
75+
76+
// bundleless
77+
if (this.options.bundle === false) {
78+
const assetFilenames = extractAssetFilenames(oldSource);
79+
if (assetFilenames.length === 0) {
80+
return old;
81+
}
82+
assert(
83+
assetFilenames.length === 1,
84+
`in bundleless mode, each asset file should only generate one js module, but generated ${assetFilenames}, ${oldSource}`,
85+
);
86+
const assetFilename = assetFilenames[0];
87+
let newSource = '';
88+
const url = `${undoPath}${assetFilename}`;
89+
90+
if (isEsmFormat) {
91+
newSource = esmSingleFileTemplate(url);
92+
} else {
93+
newSource = cjsSingleFileTemplate(url);
94+
}
95+
return new rspack.sources.RawSource(newSource);
6096
}
61-
return new rspack.sources.RawSource(newSource);
62-
} else {
97+
98+
// bundle
6399
const newSource = new rspack.sources.ReplaceSource(old);
64-
assetFilenames.forEach(() => {
65-
})
100+
function replace(
101+
pattern: RegExp,
102+
replacer: (match: RegExpMatchArray) => string,
103+
) {
104+
const matches = oldSource.matchAll(pattern);
105+
for (const match of matches) {
106+
const replaced = replacer(match);
107+
newSource.replace(
108+
match.index,
109+
match.index + match[0].length - 1,
110+
replaced,
111+
);
112+
}
113+
}
114+
replace(CONCATENATED_PATTERN, (match) => {
115+
const declarationKind = match[1];
116+
const variableName = match[2];
117+
const url = `${undoPath}${match[3]}`;
118+
return isEsmFormat
119+
? concatenatedEsmReplaceTemplate(variableName!, url)
120+
: concatenatedCjsReplaceTemplate(
121+
declarationKind!,
122+
variableName!,
123+
url,
124+
);
125+
});
126+
replace(NOT_CONCATENATED_PATTERN, (match) => {
127+
const url = `${undoPath}${match[1]}`;
128+
return nonConcatenatedReplaceTemplate(url);
129+
});
66130
return newSource;
67-
}
68-
69-
});
70-
}
71-
})
72-
})}
131+
});
132+
}
133+
});
134+
});
135+
}
73136
}
74-
export { LibAssetExtractPlugin};
137+
export { LibAssetExtractPlugin };

packages/core/src/asset/assetConfig.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { EnvironmentConfig } from '@rsbuild/core';
22
import type { Format } from '../types';
33
import { LibAssetExtractPlugin } from './LibAssetExtractPlugin';
4+
LibAssetExtractPlugin;
45

56
// TODO: asset config document
67
export const composeAssetConfig = (
@@ -16,8 +17,7 @@ export const composeAssetConfig = (
1617
},
1718
tools: {
1819
rspack: {
19-
plugins: [new LibAssetExtractPlugin()]
20-
20+
// plugins: [new LibAssetExtractPlugin({ bundle: true })],
2121
},
2222
},
2323
};
@@ -30,8 +30,7 @@ export const composeAssetConfig = (
3030
},
3131
tools: {
3232
rspack: {
33-
plugins: [new LibAssetExtractPlugin()]
34-
33+
// plugins: [new LibAssetExtractPlugin({ bundle: false })],
3534
},
3635
},
3736
};

packages/core/src/config.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { composeAssetConfig } from './asset/assetConfig';
1717
import {
1818
DEFAULT_CONFIG_EXTENSIONS,
1919
DEFAULT_CONFIG_NAME,
20+
DTS_EXTENSIONS_PATTERN,
2021
JS_EXTENSIONS_PATTERN,
2122
RSLIB_ENTRY_QUERY,
2223
SWC_HELPERS,
@@ -974,7 +975,9 @@ const composeEntryConfig = async (
974975
});
975976

976977
// Filter the glob resolved entry files based on the allowed extensions
977-
const resolvedEntryFiles = globEntryFiles;
978+
const resolvedEntryFiles = globEntryFiles.filter((i) => {
979+
return !DTS_EXTENSIONS_PATTERN.test(i);
980+
});
978981

979982
if (resolvedEntryFiles.length === 0) {
980983
throw new Error(`Cannot find ${resolvedEntryFiles}`);
@@ -1121,7 +1124,7 @@ const composeBundlelessExternalConfig = (
11211124
styleRedirectPath,
11221125
styleRedirectExtension,
11231126
redirectPath,
1124-
issuer
1127+
issuer,
11251128
);
11261129

11271130
if (cssExternal !== false) {

packages/core/src/constant.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export const SHEBANG_REGEX: RegExp = /#!.*[\s\n\r]*$/;
1616
export const REACT_DIRECTIVE_REGEX: RegExp =
1717
/^['"]use (client|server)['"](;?)[\s\n\r]*$/;
1818

19+
const DTS_EXTENSIONS: string[] = ['d.ts', 'd.mts', 'd.cts'];
20+
1921
const JS_EXTENSIONS: string[] = [
2022
'js',
2123
'mjs',
@@ -33,11 +35,6 @@ const JS_EXTENSIONS: string[] = [
3335

3436
const CSS_EXTENSIONS: string[] = ['css', 'sass', 'scss', 'less'] as const;
3537

36-
const ENTRY_EXTENSIONS: string[] = [
37-
...JS_EXTENSIONS,
38-
...CSS_EXTENSIONS,
39-
] as const;
40-
4138
export const JS_EXTENSIONS_PATTERN: RegExp = new RegExp(
4239
`\\.(${JS_EXTENSIONS.join('|')})$`,
4340
);
@@ -46,6 +43,6 @@ export const CSS_EXTENSIONS_PATTERN: RegExp = new RegExp(
4643
`\\.(${CSS_EXTENSIONS.join('|')})$`,
4744
);
4845

49-
export const ENTRY_EXTENSIONS_PATTERN: RegExp = new RegExp(
50-
`\\.(${ENTRY_EXTENSIONS.join('|')})$`,
46+
export const DTS_EXTENSIONS_PATTERN: RegExp = new RegExp(
47+
`\\.(${DTS_EXTENSIONS.join('|')})$`,
5148
);

packages/core/tests/__snapshots__/config.test.ts.snap

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
88
"progressBar": false,
99
},
1010
"output": {
11+
"assetPrefix": "auto",
1112
"dataUriLimit": 0,
1213
"distPath": {
1314
"css": "./",
@@ -213,6 +214,16 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
213214
{
214215
"externalsType": "module-import",
215216
},
217+
{
218+
"plugins": [
219+
LibAssetExtractPlugin {
220+
"name": "LIB_ASSET_EXTRACT_PLUGIN",
221+
"options": {
222+
"bundle": true,
223+
},
224+
},
225+
],
226+
},
216227
{
217228
"plugins": [
218229
EntryChunkPlugin {
@@ -252,6 +263,7 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
252263
"progressBar": false,
253264
},
254265
"output": {
266+
"assetPrefix": "auto",
255267
"dataUriLimit": 0,
256268
"distPath": {
257269
"css": "./",
@@ -448,6 +460,16 @@ exports[`Should compose create Rsbuild config correctly > Merge Rsbuild config i
448460
{
449461
"externalsType": "commonjs-import",
450462
},
463+
{
464+
"plugins": [
465+
LibAssetExtractPlugin {
466+
"name": "LIB_ASSET_EXTRACT_PLUGIN",
467+
"options": {
468+
"bundle": true,
469+
},
470+
},
471+
],
472+
},
451473
{
452474
"plugins": [
453475
EntryChunkPlugin {

0 commit comments

Comments
 (0)