@bleedingdev/modern-js-builder 3.2.0-ultramodern.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/cjs/createBuilder.js +94 -0
- package/dist/cjs/index.js +59 -0
- package/dist/cjs/plugins/devtools.js +47 -0
- package/dist/cjs/plugins/emitRouteFile.js +75 -0
- package/dist/cjs/plugins/environmentDefaults.js +100 -0
- package/dist/cjs/plugins/globalVars.js +55 -0
- package/dist/cjs/plugins/htmlMinify.js +115 -0
- package/dist/cjs/plugins/manifest.js +52 -0
- package/dist/cjs/plugins/postcss.js +162 -0
- package/dist/cjs/plugins/rscConfig.js +159 -0
- package/dist/cjs/plugins/rsdoctor.js +64 -0
- package/dist/cjs/plugins/runtimeChunk.js +55 -0
- package/dist/cjs/shared/devServer.js +87 -0
- package/dist/cjs/shared/getCssSupport.js +121 -0
- package/dist/cjs/shared/manifest.js +46 -0
- package/dist/cjs/shared/parseCommonConfig.js +210 -0
- package/dist/cjs/shared/rsc/rsc-server-entry-loader.js +41 -0
- package/dist/cjs/shared/rsc/rscClientBrowserFallback.js +64 -0
- package/dist/cjs/shared/rsc/rscEmptyModule.js +36 -0
- package/dist/cjs/shared/utils.js +115 -0
- package/dist/cjs/types.js +18 -0
- package/dist/esm/createBuilder.mjs +57 -0
- package/dist/esm/index.mjs +3 -0
- package/dist/esm/plugins/devtools.mjs +13 -0
- package/dist/esm/plugins/emitRouteFile.mjs +28 -0
- package/dist/esm/plugins/environmentDefaults.mjs +66 -0
- package/dist/esm/plugins/globalVars.mjs +21 -0
- package/dist/esm/plugins/htmlMinify.mjs +81 -0
- package/dist/esm/plugins/manifest.mjs +18 -0
- package/dist/esm/plugins/postcss.mjs +115 -0
- package/dist/esm/plugins/rscConfig.mjs +112 -0
- package/dist/esm/plugins/rsdoctor.mjs +30 -0
- package/dist/esm/plugins/runtimeChunk.mjs +21 -0
- package/dist/esm/shared/devServer.mjs +53 -0
- package/dist/esm/shared/getCssSupport.mjs +77 -0
- package/dist/esm/shared/manifest.mjs +12 -0
- package/dist/esm/shared/parseCommonConfig.mjs +173 -0
- package/dist/esm/shared/rsc/rsc-server-entry-loader.mjs +7 -0
- package/dist/esm/shared/rsc/rscClientBrowserFallback.mjs +20 -0
- package/dist/esm/shared/rsc/rscEmptyModule.mjs +2 -0
- package/dist/esm/shared/utils.mjs +53 -0
- package/dist/esm/types.mjs +0 -0
- package/dist/esm-node/createBuilder.mjs +58 -0
- package/dist/esm-node/index.mjs +4 -0
- package/dist/esm-node/plugins/devtools.mjs +14 -0
- package/dist/esm-node/plugins/emitRouteFile.mjs +29 -0
- package/dist/esm-node/plugins/environmentDefaults.mjs +67 -0
- package/dist/esm-node/plugins/globalVars.mjs +22 -0
- package/dist/esm-node/plugins/htmlMinify.mjs +82 -0
- package/dist/esm-node/plugins/manifest.mjs +19 -0
- package/dist/esm-node/plugins/postcss.mjs +116 -0
- package/dist/esm-node/plugins/rscConfig.mjs +117 -0
- package/dist/esm-node/plugins/rsdoctor.mjs +31 -0
- package/dist/esm-node/plugins/runtimeChunk.mjs +22 -0
- package/dist/esm-node/shared/devServer.mjs +54 -0
- package/dist/esm-node/shared/getCssSupport.mjs +78 -0
- package/dist/esm-node/shared/manifest.mjs +13 -0
- package/dist/esm-node/shared/parseCommonConfig.mjs +174 -0
- package/dist/esm-node/shared/rsc/rsc-server-entry-loader.mjs +8 -0
- package/dist/esm-node/shared/rsc/rscClientBrowserFallback.mjs +25 -0
- package/dist/esm-node/shared/rsc/rscEmptyModule.mjs +3 -0
- package/dist/esm-node/shared/utils.mjs +54 -0
- package/dist/esm-node/types.mjs +1 -0
- package/dist/types/createBuilder.d.ts +8 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/plugins/devtools.d.ts +4 -0
- package/dist/types/plugins/emitRouteFile.d.ts +6 -0
- package/dist/types/plugins/environmentDefaults.d.ts +3 -0
- package/dist/types/plugins/globalVars.d.ts +3 -0
- package/dist/types/plugins/htmlMinify.d.ts +2 -0
- package/dist/types/plugins/manifest.d.ts +2 -0
- package/dist/types/plugins/postcss.d.ts +6 -0
- package/dist/types/plugins/rscConfig.d.ts +18 -0
- package/dist/types/plugins/rsdoctor.d.ts +3 -0
- package/dist/types/plugins/runtimeChunk.d.ts +2 -0
- package/dist/types/shared/devServer.d.ts +6 -0
- package/dist/types/shared/getCssSupport.d.ts +1 -0
- package/dist/types/shared/manifest.d.ts +2 -0
- package/dist/types/shared/parseCommonConfig.d.ts +9 -0
- package/dist/types/shared/rsc/rsc-server-entry-loader.d.ts +5 -0
- package/dist/types/shared/rsc/rscClientBrowserFallback.d.ts +2 -0
- package/dist/types/shared/rsc/rscEmptyModule.d.ts +2 -0
- package/dist/types/shared/utils.d.ts +12 -0
- package/dist/types/types.d.ts +287 -0
- package/package.json +88 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { SERVICE_WORKER_ENVIRONMENT_NAME, getBrowserslistWithDefault } from "../shared/utils.mjs";
|
|
3
|
+
const pluginEnvironmentDefaults = (distPath = {})=>({
|
|
4
|
+
name: 'builder:environment-defaults-plugin',
|
|
5
|
+
setup (api) {
|
|
6
|
+
api.modifyRsbuildConfig((config, { mergeRsbuildConfig })=>{
|
|
7
|
+
const compatConfig = {};
|
|
8
|
+
if (config.environments?.[SERVICE_WORKER_ENVIRONMENT_NAME]) {
|
|
9
|
+
compatConfig.environments ??= {};
|
|
10
|
+
compatConfig.environments[SERVICE_WORKER_ENVIRONMENT_NAME] = {
|
|
11
|
+
output: {
|
|
12
|
+
polyfill: 'off',
|
|
13
|
+
distPath: {
|
|
14
|
+
root: join(distPath.root || 'dist', distPath.worker || 'worker'),
|
|
15
|
+
js: '',
|
|
16
|
+
css: '',
|
|
17
|
+
jsAsync: '',
|
|
18
|
+
cssAsync: ''
|
|
19
|
+
},
|
|
20
|
+
filename: {
|
|
21
|
+
js: '[name].js'
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (config.environments?.server) {
|
|
27
|
+
compatConfig.environments ??= {};
|
|
28
|
+
compatConfig.environments.server = {
|
|
29
|
+
output: {
|
|
30
|
+
emitAssets: false,
|
|
31
|
+
distPath: {
|
|
32
|
+
root: join(distPath.root || 'dist', distPath.server || 'bundles'),
|
|
33
|
+
js: '',
|
|
34
|
+
css: '',
|
|
35
|
+
jsAsync: '',
|
|
36
|
+
cssAsync: ''
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return compatConfig.environments ? mergeRsbuildConfig(compatConfig, config) : config;
|
|
42
|
+
});
|
|
43
|
+
api.modifyRsbuildConfig({
|
|
44
|
+
handler: (config)=>{
|
|
45
|
+
const environmentNameOrder = [
|
|
46
|
+
'client',
|
|
47
|
+
'server',
|
|
48
|
+
'workerSSR'
|
|
49
|
+
];
|
|
50
|
+
config.environments = Object.fromEntries(Object.entries(config.environments).sort((a1, a2)=>environmentNameOrder.includes(a1[0]) ? environmentNameOrder.indexOf(a1[0]) - environmentNameOrder.indexOf(a2[0]) : 1));
|
|
51
|
+
},
|
|
52
|
+
order: 'post'
|
|
53
|
+
});
|
|
54
|
+
api.modifyEnvironmentConfig(async (config, { name })=>{
|
|
55
|
+
config.output.overrideBrowserslist ??= await getBrowserslistWithDefault(api.context.rootPath, config, name === SERVICE_WORKER_ENVIRONMENT_NAME ? 'node' : config.output.target);
|
|
56
|
+
});
|
|
57
|
+
api.modifyBundlerChain(async (chain, { environment })=>{
|
|
58
|
+
const isServiceWorker = environment.name === SERVICE_WORKER_ENVIRONMENT_NAME;
|
|
59
|
+
if (isServiceWorker) chain.output.library({
|
|
60
|
+
...chain.output.get('library') || {},
|
|
61
|
+
type: 'commonjs2'
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
export { pluginEnvironmentDefaults };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { applyOptionsChain } from "@modern-js/utils";
|
|
2
|
+
const pluginGlobalVars = (options)=>({
|
|
3
|
+
name: 'builder:global-vars',
|
|
4
|
+
setup (api) {
|
|
5
|
+
api.modifyBundlerChain((chain, { env, target, bundler })=>{
|
|
6
|
+
if (!options) return;
|
|
7
|
+
const globalVars = applyOptionsChain({}, options, {
|
|
8
|
+
env,
|
|
9
|
+
target
|
|
10
|
+
});
|
|
11
|
+
const serializedVars = {};
|
|
12
|
+
Object.entries(globalVars).forEach(([key, value])=>{
|
|
13
|
+
serializedVars[key] = JSON.stringify(value) ?? 'undefined';
|
|
14
|
+
});
|
|
15
|
+
chain.plugin('globalVars').use(bundler.DefinePlugin, [
|
|
16
|
+
serializedVars
|
|
17
|
+
]);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
export { pluginGlobalVars };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { merge } from "ts-deepmerge";
|
|
2
|
+
function applyRemoveConsole(options, config) {
|
|
3
|
+
const { removeConsole } = config.performance;
|
|
4
|
+
const compressOptions = 'boolean' == typeof options.compress ? {} : options.compress || {};
|
|
5
|
+
if (true === removeConsole) options.compress = {
|
|
6
|
+
...compressOptions,
|
|
7
|
+
drop_console: true
|
|
8
|
+
};
|
|
9
|
+
else if (Array.isArray(removeConsole)) {
|
|
10
|
+
const pureFuncs = removeConsole.map((method)=>`console.${method}`);
|
|
11
|
+
options.compress = {
|
|
12
|
+
...compressOptions,
|
|
13
|
+
pure_funcs: pureFuncs
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return options;
|
|
17
|
+
}
|
|
18
|
+
function getTerserMinifyOptions(config) {
|
|
19
|
+
const options = {
|
|
20
|
+
mangle: {
|
|
21
|
+
safari10: true
|
|
22
|
+
},
|
|
23
|
+
format: {
|
|
24
|
+
ascii_only: 'ascii' === config.output.charset
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
if ('none' === config.output.legalComments) {
|
|
28
|
+
options.format ||= {};
|
|
29
|
+
options.format.comments = false;
|
|
30
|
+
}
|
|
31
|
+
const finalOptions = applyRemoveConsole(options, config);
|
|
32
|
+
return finalOptions;
|
|
33
|
+
}
|
|
34
|
+
function getMinifyOptions(config) {
|
|
35
|
+
const minifyJS = getTerserMinifyOptions(config);
|
|
36
|
+
return {
|
|
37
|
+
removeComments: false,
|
|
38
|
+
useShortDoctype: true,
|
|
39
|
+
keepClosingSlash: true,
|
|
40
|
+
collapseWhitespace: true,
|
|
41
|
+
removeRedundantAttributes: true,
|
|
42
|
+
removeScriptTypeAttributes: true,
|
|
43
|
+
removeStyleLinkTypeAttributes: true,
|
|
44
|
+
removeEmptyAttributes: true,
|
|
45
|
+
minifyJS,
|
|
46
|
+
minifyCSS: true,
|
|
47
|
+
minifyURLs: true
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const pluginHtmlMinifierTerser = ()=>({
|
|
51
|
+
name: 'builder:plugin-html-minifier-terser',
|
|
52
|
+
setup (api) {
|
|
53
|
+
api.modifyBundlerChain(async (chain, { isProd, environment })=>{
|
|
54
|
+
const { output, tools: { htmlPlugin } } = environment.config;
|
|
55
|
+
const disableHtmlMinify = !isProd || false === output.minify || false === htmlPlugin;
|
|
56
|
+
const { minify } = await import("html-minifier-terser");
|
|
57
|
+
const pluginRecord = chain.plugins.entries();
|
|
58
|
+
const minifyOptions = getMinifyOptions(environment.config);
|
|
59
|
+
for (const id of Object.keys(pluginRecord)){
|
|
60
|
+
if (!id.startsWith('html-')) continue;
|
|
61
|
+
const values = pluginRecord[id].values();
|
|
62
|
+
const isHtmlRspackPlugin = values.some((item)=>{
|
|
63
|
+
const name = item?.name || item.constructor?.name;
|
|
64
|
+
return 'HtmlRspackPlugin' === name;
|
|
65
|
+
});
|
|
66
|
+
if (isHtmlRspackPlugin && !disableHtmlMinify) {
|
|
67
|
+
chain.plugin(id).tap((options)=>{
|
|
68
|
+
if (!options.length) return options;
|
|
69
|
+
const userMinifyOption = options[0].minify;
|
|
70
|
+
if (false === userMinifyOption) return options;
|
|
71
|
+
const minifyFn = (html)=>minify(html, userMinifyOption ? merge(minifyOptions, userMinifyOption) : minifyOptions);
|
|
72
|
+
options[0].minify = minifyFn;
|
|
73
|
+
return options;
|
|
74
|
+
});
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
export { pluginHtmlMinifierTerser };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { generateManifest } from "../shared/manifest.mjs";
|
|
2
|
+
const pluginManifest = ()=>({
|
|
3
|
+
name: 'builder:manifest',
|
|
4
|
+
setup (api) {
|
|
5
|
+
api.modifyBundlerChain(async (chain, { target, CHAIN_ID })=>{
|
|
6
|
+
const { RspackManifestPlugin } = await import("rspack-manifest-plugin");
|
|
7
|
+
const publicPath = chain.output.get('publicPath');
|
|
8
|
+
chain.plugin(CHAIN_ID.PLUGIN.MANIFEST).use(RspackManifestPlugin, [
|
|
9
|
+
{
|
|
10
|
+
fileName: 'web' === target ? 'asset-manifest.json' : `asset-manifest-${target}.json`,
|
|
11
|
+
publicPath,
|
|
12
|
+
generate: generateManifest
|
|
13
|
+
}
|
|
14
|
+
]);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
export { pluginManifest };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import node_path from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
import { applyOptionsChain, isProd } from "@modern-js/utils";
|
|
5
|
+
import { logger } from "@rsbuild/core";
|
|
6
|
+
import { getCssSupport } from "../shared/getCssSupport.mjs";
|
|
7
|
+
const builderRequire = createRequire(import.meta.url);
|
|
8
|
+
const createRootRequire = (rootPath)=>createRequire(pathToFileURL(node_path.join(rootPath, 'package.json')).href);
|
|
9
|
+
const loadByResolver = (resolveWith, name)=>{
|
|
10
|
+
try {
|
|
11
|
+
return resolveWith(name);
|
|
12
|
+
} catch (error) {
|
|
13
|
+
const resolved = resolveWith.resolve(name);
|
|
14
|
+
return resolveWith(resolved);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const loadPostcssPlugin = (name, appRootPath)=>{
|
|
18
|
+
const resolvers = [
|
|
19
|
+
builderRequire,
|
|
20
|
+
createRootRequire(appRootPath),
|
|
21
|
+
createRootRequire(process.cwd())
|
|
22
|
+
];
|
|
23
|
+
let firstError = null;
|
|
24
|
+
for (const resolveWith of resolvers)try {
|
|
25
|
+
return loadByResolver(resolveWith, name);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
firstError ??= error;
|
|
28
|
+
}
|
|
29
|
+
throw firstError;
|
|
30
|
+
};
|
|
31
|
+
const importPostcssPlugin = (name, appRootPath)=>Promise.resolve(loadPostcssPlugin(name, appRootPath));
|
|
32
|
+
const clonePostCSSConfig = (config)=>({
|
|
33
|
+
...config,
|
|
34
|
+
plugins: config.plugins ? [
|
|
35
|
+
...config.plugins
|
|
36
|
+
] : void 0
|
|
37
|
+
});
|
|
38
|
+
const postcssLoadConfig = builderRequire('postcss-load-config');
|
|
39
|
+
const userPostcssrcCache = new Map();
|
|
40
|
+
const loadUserPostcssrc = async (root)=>{
|
|
41
|
+
const cached = userPostcssrcCache.get(root);
|
|
42
|
+
if (cached) return clonePostCSSConfig(await cached);
|
|
43
|
+
const promise = postcssLoadConfig({}, root).catch((err)=>{
|
|
44
|
+
if (err?.message?.includes('No PostCSS Config found')) return {};
|
|
45
|
+
throw err;
|
|
46
|
+
});
|
|
47
|
+
userPostcssrcCache.set(root, promise);
|
|
48
|
+
return promise.then((config)=>{
|
|
49
|
+
userPostcssrcCache.set(root, config);
|
|
50
|
+
return clonePostCSSConfig(config);
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const pluginPostcss = (options = {})=>({
|
|
54
|
+
name: 'builder:postcss-plugins',
|
|
55
|
+
pre: [
|
|
56
|
+
'builder:environment-defaults-plugin'
|
|
57
|
+
],
|
|
58
|
+
setup (api) {
|
|
59
|
+
const { autoprefixer } = options;
|
|
60
|
+
api.modifyEnvironmentConfig(async (config, { mergeEnvironmentConfig })=>{
|
|
61
|
+
if ('web' !== config.output.target) return config;
|
|
62
|
+
const cssSupport = getCssSupport(config.output.overrideBrowserslist);
|
|
63
|
+
const enableExtractCSS = !config.output?.injectStyles;
|
|
64
|
+
const enableCssMinify = !enableExtractCSS && isProd();
|
|
65
|
+
const cssnanoOptions = {
|
|
66
|
+
preset: [
|
|
67
|
+
'default',
|
|
68
|
+
{
|
|
69
|
+
mergeLonghand: false,
|
|
70
|
+
normalizeUrl: false
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
};
|
|
74
|
+
const plugins = await Promise.all([
|
|
75
|
+
importPostcssPlugin('postcss-flexbugs-fixes', api.context.rootPath),
|
|
76
|
+
!cssSupport.customProperties && importPostcssPlugin('postcss-custom-properties', api.context.rootPath),
|
|
77
|
+
!cssSupport.initial && importPostcssPlugin('postcss-initial', api.context.rootPath),
|
|
78
|
+
!cssSupport.pageBreak && importPostcssPlugin('postcss-page-break', api.context.rootPath),
|
|
79
|
+
!cssSupport.fontVariant && importPostcssPlugin('postcss-font-variant', api.context.rootPath),
|
|
80
|
+
!cssSupport.mediaMinmax && importPostcssPlugin('postcss-media-minmax', api.context.rootPath),
|
|
81
|
+
importPostcssPlugin('postcss-nesting', api.context.rootPath),
|
|
82
|
+
enableCssMinify && importPostcssPlugin('cssnano', api.context.rootPath).then((cssnano)=>cssnano(cssnanoOptions)),
|
|
83
|
+
importPostcssPlugin('autoprefixer', api.context.rootPath).then((autoprefixerPlugin)=>autoprefixerPlugin(applyOptionsChain({
|
|
84
|
+
flexbox: 'no-2009',
|
|
85
|
+
overrideBrowserslist: config.output.overrideBrowserslist
|
|
86
|
+
}, autoprefixer)))
|
|
87
|
+
]).then((results)=>results.filter(Boolean));
|
|
88
|
+
const userOptions = await loadUserPostcssrc(api.context.rootPath);
|
|
89
|
+
return mergeEnvironmentConfig({
|
|
90
|
+
tools: {
|
|
91
|
+
postcss: (opts)=>{
|
|
92
|
+
if ('function' == typeof opts.postcssOptions) {
|
|
93
|
+
logger.warn('unexpected function type postcssOptions, the default postcss plugins will not be applied.');
|
|
94
|
+
return opts;
|
|
95
|
+
}
|
|
96
|
+
const existingOptions = opts.postcssOptions ?? {};
|
|
97
|
+
const mergedOptions = {
|
|
98
|
+
...userOptions,
|
|
99
|
+
...existingOptions
|
|
100
|
+
};
|
|
101
|
+
const userPlugins = userOptions.plugins ?? [];
|
|
102
|
+
const existingPlugins = existingOptions.plugins ?? [];
|
|
103
|
+
mergedOptions.plugins = [
|
|
104
|
+
...userPlugins,
|
|
105
|
+
...existingPlugins,
|
|
106
|
+
...plugins
|
|
107
|
+
];
|
|
108
|
+
opts.postcssOptions = mergedOptions;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}, config);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
export { pluginPostcss };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
const ASYNC_STORAGE_PATTERN = /universal[/\\]async_storage/;
|
|
3
|
+
const RSC_COMMON_LAYER = 'rsc-common';
|
|
4
|
+
const ENTRY_NAME_VAR = '__MODERN_JS_ENTRY_NAME';
|
|
5
|
+
const createVirtualModule = (content)=>`data:text/javascript,${encodeURIComponent(content)}`;
|
|
6
|
+
const isAsyncStorageExclude = (exclude)=>{
|
|
7
|
+
if ('string' == typeof exclude) return ASYNC_STORAGE_PATTERN.test(exclude);
|
|
8
|
+
if (exclude instanceof RegExp) return exclude.test('universal/async_storage') || exclude.test('universal\\async_storage');
|
|
9
|
+
return false;
|
|
10
|
+
};
|
|
11
|
+
function pluginRscConfig() {
|
|
12
|
+
return {
|
|
13
|
+
name: 'builder:rsc-config',
|
|
14
|
+
setup (api) {
|
|
15
|
+
let layersCache = null;
|
|
16
|
+
const getLayers = async ()=>{
|
|
17
|
+
if (!layersCache) {
|
|
18
|
+
const { Layers } = await import("rsbuild-plugin-rsc");
|
|
19
|
+
layersCache = Layers;
|
|
20
|
+
}
|
|
21
|
+
return layersCache;
|
|
22
|
+
};
|
|
23
|
+
api.modifyBundlerChain({
|
|
24
|
+
handler: (chain, { isServer })=>{
|
|
25
|
+
if (isServer) {
|
|
26
|
+
const routeFilePattern = /[/\\]routes[/\\](?:.*[/\\])?(?:layout|page|\$)\.[tj]sx?$/;
|
|
27
|
+
const appFilePattern = /[/\\]App\.[tj]sx?$/;
|
|
28
|
+
const combinedPattern = new RegExp(`(${routeFilePattern.source}|${appFilePattern.source})`);
|
|
29
|
+
let loaderPath;
|
|
30
|
+
try {
|
|
31
|
+
loaderPath = require.resolve('../shared/rsc/rsc-server-entry-loader');
|
|
32
|
+
} catch {
|
|
33
|
+
loaderPath = path.resolve(__dirname, '../shared/rsc/rsc-server-entry-loader');
|
|
34
|
+
}
|
|
35
|
+
chain.module.rule('rsc-server-entry').test(/\.(tsx?|jsx?)$/).resource(combinedPattern).exclude.add(/node_modules/).end().use('rsc-server-entry-loader').loader(loaderPath).end();
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
order: 'pre'
|
|
39
|
+
});
|
|
40
|
+
api.modifyRspackConfig(async (config, utils)=>{
|
|
41
|
+
const isServer = 'node' === config.target || 'node' === utils.target || utils.environment?.name === 'server';
|
|
42
|
+
if (!isServer) return;
|
|
43
|
+
const Layers = await getLayers();
|
|
44
|
+
if (config.entry) {
|
|
45
|
+
const entries = config.entry;
|
|
46
|
+
const newEntries = {};
|
|
47
|
+
for (const [entryName, entryValue] of Object.entries(entries))if ('string' == typeof entryValue) newEntries[entryName] = {
|
|
48
|
+
import: entryValue,
|
|
49
|
+
layer: Layers.ssr
|
|
50
|
+
};
|
|
51
|
+
else if (Array.isArray(entryValue)) newEntries[entryName] = {
|
|
52
|
+
import: entryValue,
|
|
53
|
+
layer: Layers.ssr
|
|
54
|
+
};
|
|
55
|
+
else if ('object' == typeof entryValue && null !== entryValue) newEntries[entryName] = {
|
|
56
|
+
...entryValue,
|
|
57
|
+
layer: Layers.ssr
|
|
58
|
+
};
|
|
59
|
+
else newEntries[entryName] = entryValue;
|
|
60
|
+
config.entry = newEntries;
|
|
61
|
+
}
|
|
62
|
+
if (config.module?.rules) {
|
|
63
|
+
const rules = config.module.rules;
|
|
64
|
+
for (const rule of rules)if (rule.layer === Layers.rsc) {
|
|
65
|
+
if (rule.exclude) {
|
|
66
|
+
if (!Array.isArray(rule.exclude)) rule.exclude = [
|
|
67
|
+
rule.exclude
|
|
68
|
+
];
|
|
69
|
+
} else rule.exclude = [];
|
|
70
|
+
const hasExclude = rule.exclude.some(isAsyncStorageExclude);
|
|
71
|
+
if (!hasExclude) rule.exclude.push(ASYNC_STORAGE_PATTERN);
|
|
72
|
+
}
|
|
73
|
+
if (!Array.isArray(config.module.rules)) config.module.rules = [];
|
|
74
|
+
config.module.rules.push({
|
|
75
|
+
resource: ASYNC_STORAGE_PATTERN,
|
|
76
|
+
layer: RSC_COMMON_LAYER
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
api.modifyBundlerChain((chain, { isServer, isWebWorker })=>{
|
|
81
|
+
if (!isServer && !isWebWorker) {
|
|
82
|
+
const entries = chain.entryPoints.entries();
|
|
83
|
+
if (entries && 'object' == typeof entries) for (const entryName of Object.keys(entries)){
|
|
84
|
+
const entryPoint = chain.entry(entryName);
|
|
85
|
+
const code = `window.${ENTRY_NAME_VAR}="${entryName}";`;
|
|
86
|
+
entryPoint.add(createVirtualModule(code));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async function getRscPlugins(enableRsc, internalDirectory) {
|
|
94
|
+
if (enableRsc) {
|
|
95
|
+
const routesFileReg = new RegExp(`${internalDirectory.replace(/[/\\]/g, '[/\\\\]')}[/\\\\][^/\\\\]*[/\\\\]routes`);
|
|
96
|
+
const { pluginRSC } = await import("rsbuild-plugin-rsc");
|
|
97
|
+
return [
|
|
98
|
+
pluginRSC({
|
|
99
|
+
layers: {
|
|
100
|
+
rsc: [
|
|
101
|
+
/render[/\\].*[/\\]server[/\\]rsc/,
|
|
102
|
+
/AppProxy/,
|
|
103
|
+
routesFileReg
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
}),
|
|
107
|
+
pluginRscConfig()
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
export { getRscPlugins, pluginRscConfig };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const isRsdoctorEnabled = (config)=>{
|
|
2
|
+
if (void 0 === config) return false;
|
|
3
|
+
if ('boolean' == typeof config) return config;
|
|
4
|
+
if ('boolean' == typeof config?.enabled) return config.enabled;
|
|
5
|
+
return true;
|
|
6
|
+
};
|
|
7
|
+
const getRsdoctorPluginOptions = (config)=>{
|
|
8
|
+
if (config && 'object' == typeof config) return {
|
|
9
|
+
disableClientServer: config.disableClientServer ?? true
|
|
10
|
+
};
|
|
11
|
+
return {
|
|
12
|
+
disableClientServer: true
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
const pluginRsdoctor = (config)=>{
|
|
16
|
+
if (!isRsdoctorEnabled(config)) return null;
|
|
17
|
+
const pluginOptions = getRsdoctorPluginOptions(config);
|
|
18
|
+
return {
|
|
19
|
+
name: 'builder:rsdoctor',
|
|
20
|
+
setup (api) {
|
|
21
|
+
api.modifyBundlerChain(async (chain)=>{
|
|
22
|
+
const { RsdoctorRspackPlugin } = await import("@rsdoctor/rspack-plugin");
|
|
23
|
+
chain.plugin('rsdoctor').use(RsdoctorRspackPlugin, [
|
|
24
|
+
pluginOptions
|
|
25
|
+
]);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export { pluginRsdoctor };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RUNTIME_CHUNK_NAME, RUNTIME_CHUNK_REGEX } from "../shared/utils.mjs";
|
|
2
|
+
const pluginRuntimeChunk = (disableInlineRuntimeChunk)=>({
|
|
3
|
+
name: 'builder:runtime-chunk',
|
|
4
|
+
setup (api) {
|
|
5
|
+
api.modifyBundlerChain(async (chain, { target, environment })=>{
|
|
6
|
+
if ('web' !== target) return;
|
|
7
|
+
const { config } = environment;
|
|
8
|
+
const { chunkSplit } = config.performance;
|
|
9
|
+
if (chunkSplit?.strategy !== 'all-in-one' && false !== config.splitChunks) chain.optimization.runtimeChunk({
|
|
10
|
+
name: RUNTIME_CHUNK_NAME
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
api.modifyRsbuildConfig((config)=>{
|
|
14
|
+
config.output ||= {};
|
|
15
|
+
if (disableInlineRuntimeChunk) return;
|
|
16
|
+
const originalConfig = api.getRsbuildConfig('original');
|
|
17
|
+
if (originalConfig.output?.inlineScripts === void 0) config.output.inlineScripts = RUNTIME_CHUNK_REGEX;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
export { pluginRuntimeChunk };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { applyOptionsChain, isProd } from "@modern-js/utils";
|
|
2
|
+
import { merge } from "ts-deepmerge";
|
|
3
|
+
const defaultDevConfig = {
|
|
4
|
+
writeToDisk: (file)=>!file.includes('.hot-update.'),
|
|
5
|
+
hmr: true,
|
|
6
|
+
liveReload: true,
|
|
7
|
+
progressBar: true,
|
|
8
|
+
client: {
|
|
9
|
+
path: '/webpack-hmr',
|
|
10
|
+
overlay: false,
|
|
11
|
+
port: '<port>'
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const transformToRsbuildServerOptions = (dev, devServer, server)=>{
|
|
15
|
+
const { host = '0.0.0.0', https, startUrl, beforeStartUrl, server: devServerConfig, ...devConfig } = dev;
|
|
16
|
+
const port = process.env.PORT ? Number(process.env.PORT) : server?.port ?? 8080;
|
|
17
|
+
const rsbuildDev = merge(defaultDevConfig, devConfig);
|
|
18
|
+
delete rsbuildDev.setupMiddlewares;
|
|
19
|
+
const legacyServerConfig = applyOptionsChain({}, devServer, {}, merge);
|
|
20
|
+
const serverCofig = {
|
|
21
|
+
compress: devServerConfig?.compress ?? legacyServerConfig.compress,
|
|
22
|
+
headers: devServerConfig?.headers ?? legacyServerConfig.headers,
|
|
23
|
+
historyApiFallback: devServerConfig?.historyApiFallback ?? legacyServerConfig.historyApiFallback,
|
|
24
|
+
proxy: devServerConfig?.proxy ?? legacyServerConfig.proxy
|
|
25
|
+
};
|
|
26
|
+
const rsbuildServer = isProd() ? {
|
|
27
|
+
publicDir: false,
|
|
28
|
+
htmlFallback: false,
|
|
29
|
+
printUrls: false
|
|
30
|
+
} : {
|
|
31
|
+
publicDir: false,
|
|
32
|
+
htmlFallback: false,
|
|
33
|
+
printUrls: false,
|
|
34
|
+
compress: serverCofig.compress,
|
|
35
|
+
headers: serverCofig.headers,
|
|
36
|
+
historyApiFallback: serverCofig.historyApiFallback,
|
|
37
|
+
proxy: serverCofig.proxy,
|
|
38
|
+
host,
|
|
39
|
+
port,
|
|
40
|
+
https: https ? https : void 0,
|
|
41
|
+
middlewareMode: true,
|
|
42
|
+
cors: server?.cors
|
|
43
|
+
};
|
|
44
|
+
if (!isProd() && startUrl) rsbuildServer.open = beforeStartUrl ? {
|
|
45
|
+
target: true === startUrl ? '//localhost:<port>' : startUrl,
|
|
46
|
+
before: beforeStartUrl
|
|
47
|
+
} : startUrl;
|
|
48
|
+
return {
|
|
49
|
+
rsbuildDev,
|
|
50
|
+
rsbuildServer
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
export { transformToRsbuildServerOptions };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import browserslist from "browserslist";
|
|
2
|
+
const CSS_FEATURES_BROWSER = {
|
|
3
|
+
customProperties: {
|
|
4
|
+
and_chr: '49',
|
|
5
|
+
and_ff: '31',
|
|
6
|
+
android: '50',
|
|
7
|
+
chrome: '49',
|
|
8
|
+
edge: '15',
|
|
9
|
+
firefox: '31',
|
|
10
|
+
ios_saf: '9.3',
|
|
11
|
+
op_mob: '36',
|
|
12
|
+
opera: '36',
|
|
13
|
+
safari: '9.1',
|
|
14
|
+
samsung: '5.0'
|
|
15
|
+
},
|
|
16
|
+
initial: {
|
|
17
|
+
and_chr: '37',
|
|
18
|
+
and_ff: '27',
|
|
19
|
+
android: '37',
|
|
20
|
+
chrome: '37',
|
|
21
|
+
edge: '79',
|
|
22
|
+
firefox: '27',
|
|
23
|
+
ios_saf: '9.3',
|
|
24
|
+
op_mob: '24',
|
|
25
|
+
opera: '24',
|
|
26
|
+
safari: '9.1',
|
|
27
|
+
samsung: '3.0'
|
|
28
|
+
},
|
|
29
|
+
pageBreak: {
|
|
30
|
+
and_chr: '51',
|
|
31
|
+
and_ff: '92',
|
|
32
|
+
android: '51',
|
|
33
|
+
chrome: '51',
|
|
34
|
+
edge: '12',
|
|
35
|
+
firefox: '92',
|
|
36
|
+
ios_saf: '10',
|
|
37
|
+
op_mob: '37',
|
|
38
|
+
opera: '11.1',
|
|
39
|
+
safari: '10',
|
|
40
|
+
samsung: '5.0'
|
|
41
|
+
},
|
|
42
|
+
fontVariant: {
|
|
43
|
+
and_chr: '18',
|
|
44
|
+
and_ff: '34',
|
|
45
|
+
android: '4.4',
|
|
46
|
+
chrome: '1',
|
|
47
|
+
edge: '12',
|
|
48
|
+
firefox: '34',
|
|
49
|
+
ios_saf: '9.3',
|
|
50
|
+
op_mob: '12',
|
|
51
|
+
opera: '10',
|
|
52
|
+
safari: '9.1',
|
|
53
|
+
samsung: '1.0'
|
|
54
|
+
},
|
|
55
|
+
mediaMinmax: {
|
|
56
|
+
and_chr: '104',
|
|
57
|
+
and_ff: '109',
|
|
58
|
+
android: '104',
|
|
59
|
+
chrome: '104',
|
|
60
|
+
edge: '104',
|
|
61
|
+
firefox: '63',
|
|
62
|
+
opera: '91'
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const getCssFeatureBrowsers = (feature)=>{
|
|
66
|
+
const featureBrowsers = CSS_FEATURES_BROWSER[feature];
|
|
67
|
+
return browserslist(Object.entries(featureBrowsers).map(([key, value])=>`${key} >= ${value}`));
|
|
68
|
+
};
|
|
69
|
+
const isFeatureSupported = (projectBrowsers, featureBrowsers)=>projectBrowsers.every((item)=>featureBrowsers.includes(item));
|
|
70
|
+
function getCssSupport(projectBrowserslist) {
|
|
71
|
+
const projectBrowsers = browserslist(projectBrowserslist);
|
|
72
|
+
return Object.keys(CSS_FEATURES_BROWSER).reduce((acc, key)=>{
|
|
73
|
+
acc[key] = isFeatureSupported(projectBrowsers, getCssFeatureBrowsers(key));
|
|
74
|
+
return acc;
|
|
75
|
+
}, {});
|
|
76
|
+
}
|
|
77
|
+
export { getCssSupport };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const generateManifest = (seed, files, entries)=>{
|
|
2
|
+
const manifestFiles = files.reduce((manifest, file)=>{
|
|
3
|
+
manifest[file.name] = file.path;
|
|
4
|
+
return manifest;
|
|
5
|
+
}, seed);
|
|
6
|
+
const entrypointFiles = Object.keys(entries).reduce((previous, name)=>previous.concat(entries[name].filter((fileName)=>!fileName.endsWith('.map'))), []);
|
|
7
|
+
return {
|
|
8
|
+
files: manifestFiles,
|
|
9
|
+
entrypoints: entrypointFiles
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export { generateManifest };
|