@bleedingdev/modern-js-builder 3.9.0-ultramodern.8 → 3.9.3-ultramodern.1

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.
@@ -56,14 +56,15 @@ const pluginEnvironmentDefaults = (distPath = {})=>({
56
56
  });
57
57
  api.modifyBundlerChain(async (chain, { environment })=>{
58
58
  const isServiceWorker = environment.name === SERVICE_WORKER_ENVIRONMENT_NAME;
59
- if (isServiceWorker && true === chain.output.get('module')) chain.output.library({
60
- ...chain.output.get('library') || {},
61
- type: 'module'
62
- });
63
- else if (isServiceWorker) chain.output.library({
64
- ...chain.output.get('library') || {},
65
- type: 'commonjs2'
66
- });
59
+ if (isServiceWorker) {
60
+ const library = chain.output.get('library');
61
+ chain.output.library({
62
+ ...'string' == typeof library || Array.isArray(library) ? {
63
+ name: library
64
+ } : library,
65
+ type: true === chain.output.get('module') ? 'module' : 'commonjs2'
66
+ });
67
+ }
67
68
  });
68
69
  }
69
70
  });
@@ -8,7 +8,9 @@ const pluginManifest = ()=>({
8
8
  chain.plugin(CHAIN_ID.PLUGIN.MANIFEST).use(RspackManifestPlugin, [
9
9
  {
10
10
  fileName: 'web' === target ? 'asset-manifest.json' : `asset-manifest-${target}.json`,
11
- publicPath,
11
+ ...'string' == typeof publicPath ? {
12
+ publicPath
13
+ } : {},
12
14
  generate: generateManifest
13
15
  }
14
16
  ]);
@@ -2,19 +2,26 @@ import path from "path";
2
2
  const ASYNC_STORAGE_PATTERN = /universal[/\\]async_storage/;
3
3
  const SERVER_LOADER_ENTRY_PATTERN = /[/\\](?:server-loader-combined|route-server-loaders)\.js$/;
4
4
  const RENDER_RSC_SOURCE_PATTERN = /render[/\\].*[/\\]server[/\\]rsc/;
5
- const RENDER_RSC_RSLIB_ENTRY_PATTERN = /render[/\\]dist[/\\]esm[/\\]rsc(?:Worker)?\.mjs$/;
6
- const RENDER_RSC_RUNTIME = '@modern-js/render/rsc';
7
- const RENDER_RSC_WORKER_RUNTIME = '@modern-js/render/rsc-worker';
5
+ const RENDER_RSC_RSLIB_ENTRY_PATTERN = /render[/\\]dist[/\\]esm[/\\]rsc(?:\.edge)?\.mjs$/;
8
6
  const RSC_COMMON_LAYER = 'rsc-common';
9
7
  const ENTRY_NAME_VAR = '__MODERN_JS_ENTRY_NAME';
10
8
  const ROUTE_DATA_FILE_PATTERN = /[/\\]routes[/\\](?:.*[/\\])?(?:layout|page|\$)\.(?:loader|data)\.[tj]sx?(?:\?.*)?$/;
11
9
  const createVirtualModule = (content)=>`data:text/javascript,${encodeURIComponent(content)}`;
10
+ const resolveRscEnvironments = (environments)=>{
11
+ const resolved = {
12
+ server: environments?.server ?? 'server',
13
+ client: environments?.client ?? 'client'
14
+ };
15
+ for (const [role, name] of Object.entries(resolved))if ('string' != typeof name || !name.trim()) throw new TypeError(`RSC ${role} environment must have a nonempty name`);
16
+ return resolved;
17
+ };
12
18
  const isAsyncStorageExclude = (exclude)=>{
13
19
  if ('string' == typeof exclude) return ASYNC_STORAGE_PATTERN.test(exclude);
14
20
  if (exclude instanceof RegExp) return exclude.test('universal/async_storage') || exclude.test('universal\\async_storage');
15
21
  return false;
16
22
  };
17
- function pluginRscConfig() {
23
+ function pluginRscConfig(environments, rscLayerMatchers = []) {
24
+ const serverEnvironment = resolveRscEnvironments(environments).server;
18
25
  return {
19
26
  name: 'builder:rsc-config',
20
27
  setup (api) {
@@ -27,9 +34,8 @@ function pluginRscConfig() {
27
34
  return layersCache;
28
35
  };
29
36
  api.modifyBundlerChain({
30
- handler: (chain, { isServer })=>{
31
- if (isServer) {
32
- chain.resolve.alias.set(`${RENDER_RSC_RUNTIME}$`, RENDER_RSC_WORKER_RUNTIME);
37
+ handler: (chain, { isServer, environment })=>{
38
+ if (isServer || environment.name === serverEnvironment) {
33
39
  let emptyModulePath;
34
40
  try {
35
41
  emptyModulePath = require.resolve('../shared/rsc/rscEmptyModule');
@@ -52,9 +58,25 @@ function pluginRscConfig() {
52
58
  order: 'pre'
53
59
  });
54
60
  api.modifyRspackConfig(async (config, utils)=>{
55
- const isServer = 'node' === config.target || 'node' === utils.target || utils.environment?.name === 'server';
61
+ const isServer = 'node' === config.target || 'node' === utils.target || utils.environment?.name === serverEnvironment;
56
62
  if (!isServer) return;
57
63
  const Layers = await getLayers();
64
+ if (utils.environment?.name !== serverEnvironment && rscLayerMatchers.length > 0) {
65
+ config.module ??= {};
66
+ config.module.rules ??= [];
67
+ config.module.rules.push({
68
+ test: rscLayerMatchers,
69
+ layer: Layers.rsc
70
+ }, {
71
+ issuerLayer: Layers.rsc,
72
+ resolve: {
73
+ conditionNames: [
74
+ 'react-server',
75
+ '...'
76
+ ]
77
+ }
78
+ });
79
+ }
58
80
  if (config.entry) {
59
81
  const entries = config.entry;
60
82
  const newEntries = {};
@@ -91,8 +113,8 @@ function pluginRscConfig() {
91
113
  });
92
114
  }
93
115
  });
94
- api.modifyBundlerChain((chain, { isServer, isWebWorker })=>{
95
- if (!isServer && !isWebWorker) {
116
+ api.modifyBundlerChain((chain, { isServer, isWebWorker, environment })=>{
117
+ if (!isServer && !isWebWorker && environment.name !== serverEnvironment) {
96
118
  const entries = chain.entryPoints.entries();
97
119
  if (entries && 'object' == typeof entries) for (const entryName of Object.keys(entries)){
98
120
  const entryPoint = chain.entry(entryName);
@@ -106,13 +128,12 @@ function pluginRscConfig() {
106
128
  }
107
129
  async function getRscPlugins(enableRsc, internalDirectory, environments) {
108
130
  if (enableRsc) {
131
+ const rscEnvironments = resolveRscEnvironments(environments);
109
132
  const rscLayerMatchers = createRscLayerMatchers(internalDirectory);
110
133
  const { pluginRSC } = await import("rsbuild-plugin-rsc");
111
134
  return [
112
135
  pluginRSC({
113
- ...environments ? {
114
- environments
115
- } : {},
136
+ environments: rscEnvironments,
116
137
  layers: {
117
138
  ssr: SERVER_LOADER_ENTRY_PATTERN,
118
139
  rsc: [
@@ -123,7 +144,7 @@ async function getRscPlugins(enableRsc, internalDirectory, environments) {
123
144
  ]
124
145
  }
125
146
  }),
126
- pluginRscConfig()
147
+ pluginRscConfig(rscEnvironments, rscLayerMatchers)
127
148
  ];
128
149
  }
129
150
  return [];
@@ -1,7 +1,6 @@
1
1
  import { mergeRsbuildConfig } from "@rsbuild/core";
2
2
  import { pluginCssMinimizer } from "@rsbuild/plugin-css-minimizer";
3
3
  import { pluginLess } from "@rsbuild/plugin-less";
4
- import { pluginReact } from "@rsbuild/plugin-react";
5
4
  import { pluginSass } from "@rsbuild/plugin-sass";
6
5
  import { pluginDevtool } from "../plugins/devtools.mjs";
7
6
  import { pluginEmitRouteFile } from "../plugins/emitRouteFile.mjs";
@@ -10,7 +9,9 @@ import { pluginGlobalVars } from "../plugins/globalVars.mjs";
10
9
  import { pluginHtmlMinifierTerser } from "../plugins/htmlMinify.mjs";
11
10
  import { pluginRuntimeChunk } from "../plugins/runtimeChunk.mjs";
12
11
  import { transformToRsbuildServerOptions } from "./devServer.mjs";
13
- import { NODE_MODULES_REGEX } from "./utils.mjs";
12
+ import { normalizeLessOptions, normalizeSassOptions, resolveSvgrOptions } from "./pluginOptions.mjs";
13
+ import { withTsgoDefaults } from "./tsgo.mjs";
14
+ import { NODE_MODULES_REGEX, SERVICE_WORKER_ENVIRONMENT_NAME } from "./utils.mjs";
14
15
  const CSS_MODULES_REGEX = /\.modules?\.\w+$/i;
15
16
  const GLOBAL_CSS_REGEX = /\.global\.\w+$/;
16
17
  const DEFAULT_CSS_MINIFIER_OPTIONS = {
@@ -36,7 +37,7 @@ function removeUndefinedKey(obj) {
36
37
  }
37
38
  async function parseCommonConfig(builderConfig, options) {
38
39
  const frameworkConfigPath = options?.frameworkConfigPath;
39
- const { plugins: [...plugins] = [], splitChunks, performance: { ...performanceConfig } = {}, output: { module = false, enableCssModuleTSDeclaration, disableCssModuleExtension, disableTsChecker, disableSvgr, svgDefaultExport, assetsRetry, enableAssetManifest, sourceMap, convertToRem, polyfill, dataUriLimit = 10000, distPath = {}, ...outputConfig } = {}, html: { outputStructure, appIcon, ...htmlConfig } = {}, source: { alias, globalVars, transformImport, reactCompiler, ...sourceConfig } = {}, dev = {}, server = {}, security: { checkSyntax, sri, ...securityConfig } = {}, tools: { devServer, tsChecker, minifyCss, less, sass, htmlPlugin, autoprefixer, ...toolsConfig } = {}, environments = {}, resolve = {} } = builderConfig;
40
+ const { plugins: [...plugins] = [], splitChunks, performance: { ...performanceConfig } = {}, output: { module = false, enableCssModuleTSDeclaration, disableCssModuleExtension, disableTsChecker, disableSvgr, svgDefaultExport, assetsRetry, enableAssetManifest, sourceMap, convertToRem, polyfill, dataUriLimit = 10000, distPath = {}, ...outputConfig } = {}, html: { outputStructure, appIcon, ...htmlConfig } = {}, source: { alias, globalVars, transformImport, reactCompiler, ...sourceConfig } = {}, dev = {}, server = {}, security: { checkSyntax, sri, ...securityConfig } = {}, tools: { devServer, tsChecker, minifyCss, less, sass, svgr, htmlPlugin, autoprefixer, ...toolsConfig } = {}, environments = {}, resolve = {} } = builderConfig;
40
41
  let combinedAlias;
41
42
  if (alias || resolve.alias) combinedAlias = [].concat(alias ?? []).concat(resolve.alias ?? []);
42
43
  const rsbuildConfig = {
@@ -119,12 +120,8 @@ async function parseCommonConfig(builderConfig, options) {
119
120
  sourceMap
120
121
  }),
121
122
  pluginEmitRouteFile(),
122
- pluginSass({
123
- sassLoaderOptions: sass
124
- }),
125
- pluginLess({
126
- lessLoaderOptions: less
127
- }),
123
+ pluginSass(normalizeSassOptions(sass)),
124
+ pluginLess(normalizeLessOptions(less)),
128
125
  pluginEnvironmentDefaults(distPath),
129
126
  pluginHtmlMinifierTerser()
130
127
  ];
@@ -135,7 +132,7 @@ async function parseCommonConfig(builderConfig, options) {
135
132
  if (!disableTsChecker) {
136
133
  const { pluginTypeCheck } = await import("@rsbuild/plugin-type-check");
137
134
  rsbuildPlugins.push(pluginTypeCheck({
138
- tsCheckerOptions: tsChecker
135
+ tsCheckerOptions: withTsgoDefaults(tsChecker, options?.cwd ?? process.cwd())
139
136
  }));
140
137
  }
141
138
  if (convertToRem) {
@@ -151,19 +148,44 @@ async function parseCommonConfig(builderConfig, options) {
151
148
  const { pluginSourceBuild } = await import("@rsbuild/plugin-source-build");
152
149
  rsbuildPlugins.push(pluginSourceBuild(true === sourceBuild ? {} : sourceBuild));
153
150
  }
154
- rsbuildPlugins.push(pluginReact(options?.disableReactCompiler || void 0 === reactCompiler ? {} : {
155
- reactCompiler
156
- }));
157
- if (!disableSvgr) {
158
- const { pluginSvgr } = await import("@rsbuild/plugin-svgr");
159
- rsbuildPlugins.push(pluginSvgr({
160
- mixedImport: true,
161
- parallel: true,
162
- svgrOptions: {
163
- exportType: 'component' === svgDefaultExport ? 'default' : 'named'
164
- }
165
- }));
166
- }
151
+ rsbuildPlugins.push({
152
+ name: 'rsbuild:react',
153
+ async setup (api) {
154
+ const { pluginReact } = await import("@rsbuild/plugin-react");
155
+ return pluginReact().setup(api);
156
+ }
157
+ });
158
+ if (!options?.disableReactCompiler && void 0 !== reactCompiler) rsbuildPlugins.push({
159
+ name: 'builder:react-compiler',
160
+ setup (api) {
161
+ api.modifyEnvironmentConfig((config, { name, mergeEnvironmentConfig })=>'web' === config.output.target && name !== SERVICE_WORKER_ENVIRONMENT_NAME ? mergeEnvironmentConfig({
162
+ tools: {
163
+ swc: {
164
+ jsc: {
165
+ transform: {
166
+ reactCompiler
167
+ }
168
+ }
169
+ }
170
+ }
171
+ }, config) : config);
172
+ }
173
+ });
174
+ const svgrOptions = resolveSvgrOptions({
175
+ svgr,
176
+ disableSvgr,
177
+ svgDefaultExport
178
+ });
179
+ if (false !== svgrOptions) rsbuildPlugins.push({
180
+ name: 'rsbuild:svgr',
181
+ pre: [
182
+ 'rsbuild:react'
183
+ ],
184
+ async setup (api) {
185
+ const { pluginSvgr } = await import("@rsbuild/plugin-svgr");
186
+ await pluginSvgr(svgrOptions).setup(api);
187
+ }
188
+ });
167
189
  if (assetsRetry) {
168
190
  const { pluginAssetsRetry } = await import("@rsbuild/plugin-assets-retry");
169
191
  rsbuildPlugins.push(pluginAssetsRetry(assetsRetry));
@@ -0,0 +1,75 @@
1
+ import { applyOptionsChain, isDevCommand, logger } from "@modern-js/utils";
2
+ const LESS_PLUGIN_KEYS = [
3
+ 'lessLoaderOptions',
4
+ 'include',
5
+ 'exclude',
6
+ 'parallel'
7
+ ];
8
+ const SASS_PLUGIN_KEYS = [
9
+ 'sassLoaderOptions',
10
+ 'include',
11
+ 'exclude',
12
+ 'rewriteUrls'
13
+ ];
14
+ const warned = new Set();
15
+ const resetPluginOptionsWarnings = ()=>{
16
+ warned.clear();
17
+ };
18
+ const warnOnceInDev = (key, message)=>{
19
+ if (!isDevCommand() || warned.has(key)) return;
20
+ warned.add(key);
21
+ logger.warn(message);
22
+ };
23
+ const isPlainObject = (value)=>'object' == typeof value && null !== value && !Array.isArray(value);
24
+ const isPluginLevelOptions = (value, pluginKeys)=>isPlainObject(value) && pluginKeys.some((key)=>key in value);
25
+ const isEmptyObject = (value)=>isPlainObject(value) && 0 === Object.keys(value).length;
26
+ const warnIgnoredKeys = (name, value, pluginKeys, loaderOptionsKey)=>{
27
+ const pluginLevel = Object.keys(value).filter((key)=>pluginKeys.includes(key));
28
+ const ignored = Object.keys(value).filter((key)=>!pluginKeys.includes(key));
29
+ if (0 === ignored.length) return;
30
+ warnOnceInDev(`${name}:mixed`, `\`${name}\` contains plugin-level options (${pluginLevel.join(', ')}) together with other keys (${ignored.join(', ')}). The whole object is passed to the plugin, so the other keys are ignored. Move loader options under \`${loaderOptionsKey}\`.`);
31
+ };
32
+ const normalizeLessOptions = (less)=>{
33
+ if (isPluginLevelOptions(less, LESS_PLUGIN_KEYS)) {
34
+ warnIgnoredKeys('tools.less', less, LESS_PLUGIN_KEYS, 'lessLoaderOptions');
35
+ return less;
36
+ }
37
+ if (void 0 !== less && !isEmptyObject(less)) warnOnceInDev('tools.less', "`tools.less` now accepts the full options of @rsbuild/plugin-less. Passing less-loader options directly is deprecated and will stop working in the next major version. Move them under `lessLoaderOptions`:\n before: tools: { less: { lessOptions: { javascriptEnabled: true } } }\n after: tools: { less: { lessLoaderOptions: { lessOptions: { javascriptEnabled: true } } } }");
38
+ return {
39
+ lessLoaderOptions: less
40
+ };
41
+ };
42
+ const normalizeSassOptions = (sass)=>{
43
+ if (isPluginLevelOptions(sass, SASS_PLUGIN_KEYS)) {
44
+ warnIgnoredKeys('tools.sass', sass, SASS_PLUGIN_KEYS, 'sassLoaderOptions');
45
+ return sass;
46
+ }
47
+ if (void 0 !== sass && !isEmptyObject(sass)) warnOnceInDev('tools.sass', "`tools.sass` now accepts the full options of @rsbuild/plugin-sass. Passing sass-loader options directly is deprecated and will stop working in the next major version. Move them under `sassLoaderOptions`:\n before: tools: { sass: { sassOptions: { quietDeps: true } } }\n after: tools: { sass: { sassLoaderOptions: { sassOptions: { quietDeps: true } } } }");
48
+ return {
49
+ sassLoaderOptions: sass
50
+ };
51
+ };
52
+ const mergeSvgrOptions = (target, source)=>{
53
+ const svgrOptions = source.svgrOptions ? {
54
+ ...target.svgrOptions,
55
+ ...source.svgrOptions
56
+ } : target.svgrOptions;
57
+ return Object.assign(target, source, {
58
+ svgrOptions
59
+ });
60
+ };
61
+ const resolveSvgrOptions = ({ svgr, disableSvgr, svgDefaultExport })=>{
62
+ if (void 0 !== disableSvgr) warnOnceInDev('output.disableSvgr', disableSvgr ? '`output.disableSvgr` is deprecated and will be removed in the next major version. Use `tools: { svgr: false }` instead.' : '`output.disableSvgr` is deprecated and will be removed in the next major version. SVGR is enabled by default, so `output.disableSvgr: false` can be removed (or use `tools: { svgr: {} }` to keep it explicit).');
63
+ if (void 0 !== svgDefaultExport) warnOnceInDev('output.svgDefaultExport', "`output.svgDefaultExport` is deprecated and will be removed in the next major version. Use `tools.svgr.svgrOptions.exportType` instead:\n before: output: { svgDefaultExport: 'component' }\n after: tools: { svgr: { svgrOptions: { exportType: 'default' } } }\n ('url' maps to exportType: 'named')");
64
+ if (false === svgr) return false;
65
+ if (void 0 === svgr && disableSvgr) return false;
66
+ const defaults = {
67
+ mixedImport: true,
68
+ parallel: true,
69
+ svgrOptions: {
70
+ exportType: 'component' === svgDefaultExport ? 'default' : 'named'
71
+ }
72
+ };
73
+ return applyOptionsChain(defaults, svgr, void 0, mergeSvgrOptions);
74
+ };
75
+ export { normalizeLessOptions, normalizeSassOptions, resetPluginOptionsWarnings, resolveSvgrOptions };
@@ -0,0 +1,198 @@
1
+ import { createHash } from "node:crypto";
2
+ import node_fs from "node:fs";
3
+ import { createRequire } from "node:module";
4
+ import node_path from "node:path";
5
+ import { json5 } from "@modern-js/utils";
6
+ const builderRequire = createRequire(import.meta.url);
7
+ const STABLE_TSGO_PACKAGE = "typescript/package.json";
8
+ const TSGO_CHECKER_DIR = node_path.join('.modern-js', 'tsgo');
9
+ const tryResolve = (request, rootPath)=>{
10
+ try {
11
+ return builderRequire.resolve(request, {
12
+ paths: [
13
+ rootPath
14
+ ]
15
+ });
16
+ } catch {
17
+ return;
18
+ }
19
+ };
20
+ const resolveTsgoPackagePath = (rootPath)=>{
21
+ const packageJsonPath = tryResolve(STABLE_TSGO_PACKAGE, rootPath) ?? builderRequire.resolve(STABLE_TSGO_PACKAGE);
22
+ const packageJson = JSON.parse(node_fs.readFileSync(packageJsonPath, 'utf8'));
23
+ if ("typescript" !== packageJson.name || '7.0.2' !== packageJson.version) throw new Error(`The native type checker requires typescript@7.0.2; found ${String(packageJson.name)}@${String(packageJson.version)} at ${packageJsonPath}.`);
24
+ return packageJsonPath;
25
+ };
26
+ const toPosixPath = (input)=>input.replaceAll(node_path.sep, '/');
27
+ const asTsConfigPath = (request)=>{
28
+ if (node_path.extname(request)) return [
29
+ request
30
+ ];
31
+ return [
32
+ request,
33
+ `${request}.json`
34
+ ];
35
+ };
36
+ const resolveExtends = (request, configDirectory)=>{
37
+ const configRequire = createRequire(node_path.join(configDirectory, 'tsconfig.json'));
38
+ for (const candidate of asTsConfigPath(request)){
39
+ if (candidate.startsWith('.') || node_path.isAbsolute(candidate)) {
40
+ const resolved = node_path.resolve(configDirectory, candidate);
41
+ if (node_fs.existsSync(resolved)) return resolved;
42
+ continue;
43
+ }
44
+ try {
45
+ return configRequire.resolve(candidate);
46
+ } catch {}
47
+ }
48
+ };
49
+ const PATH_COMPILER_OPTIONS = [
50
+ 'rootDir',
51
+ 'outDir',
52
+ 'declarationDir'
53
+ ];
54
+ const absolutiseConfigPaths = (compilerOptions, configDirectory)=>{
55
+ if (!compilerOptions) return {};
56
+ const resolved = {
57
+ ...compilerOptions
58
+ };
59
+ for (const option of PATH_COMPILER_OPTIONS){
60
+ const value = resolved[option];
61
+ if ('string' == typeof value && !node_path.isAbsolute(value)) resolved[option] = node_path.resolve(configDirectory, value);
62
+ }
63
+ return resolved;
64
+ };
65
+ const readTsConfig = (configFile, visited = new Set())=>{
66
+ if (visited.has(configFile) || !node_fs.existsSync(configFile)) return {};
67
+ visited.add(configFile);
68
+ const config = json5.parse(node_fs.readFileSync(configFile, 'utf8'));
69
+ const configDirectory = node_path.dirname(configFile);
70
+ const extendsList = Array.isArray(config.extends) ? config.extends : config.extends ? [
71
+ config.extends
72
+ ] : [];
73
+ const baseConfig = extendsList.reduce((merged, request)=>{
74
+ const resolved = resolveExtends(request, configDirectory);
75
+ if (!resolved) return merged;
76
+ const parentConfig = readTsConfig(resolved, visited);
77
+ return {
78
+ ...merged,
79
+ compilerOptions: {
80
+ ...merged.compilerOptions ?? {},
81
+ ...parentConfig.compilerOptions ?? {}
82
+ }
83
+ };
84
+ }, {});
85
+ return {
86
+ ...baseConfig,
87
+ compilerOptions: {
88
+ ...baseConfig.compilerOptions ?? {},
89
+ ...absolutiseConfigPaths(config.compilerOptions, configDirectory)
90
+ }
91
+ };
92
+ };
93
+ const readProjectReferences = (configFile)=>{
94
+ if (!node_fs.existsSync(configFile)) return [];
95
+ const config = json5.parse(node_fs.readFileSync(configFile, 'utf8'));
96
+ if (!Array.isArray(config.references)) return [];
97
+ const configDirectory = node_path.dirname(configFile);
98
+ return config.references.filter((reference)=>'string' == typeof reference?.path).map((reference)=>({
99
+ ...reference,
100
+ path: toPosixPath(node_path.resolve(configDirectory, reference.path))
101
+ }));
102
+ };
103
+ const toRelativeConfigPath = (fromDirectory, target)=>{
104
+ const relative = toPosixPath(node_path.relative(fromDirectory, target));
105
+ if (relative.startsWith('.')) return relative;
106
+ return `./${relative}`;
107
+ };
108
+ const writeFileIfChanged = (file, content)=>{
109
+ if (node_fs.existsSync(file) && node_fs.readFileSync(file, 'utf8') === content) return;
110
+ node_fs.writeFileSync(file, content);
111
+ };
112
+ const defaultTsgoCheckerConfigFile = (configFile)=>{
113
+ const hash = createHash('sha1').update(configFile).digest('hex').slice(0, 10);
114
+ return node_path.join(node_path.dirname(configFile), TSGO_CHECKER_DIR, `tsconfig.${hash}.json`);
115
+ };
116
+ const createTsgoCheckerConfig = (configFile, checkerConfigFile = defaultTsgoCheckerConfigFile(configFile))=>{
117
+ const configDirectory = node_path.dirname(configFile);
118
+ const checkerConfigDirectory = node_path.dirname(checkerConfigFile);
119
+ const tsConfig = readTsConfig(configFile);
120
+ const compilerOptions = {
121
+ baseUrl: null
122
+ };
123
+ const declaredRootDir = tsConfig.compilerOptions?.rootDir;
124
+ if ('string' == typeof declaredRootDir) compilerOptions.rootDir = toPosixPath(declaredRootDir);
125
+ else compilerOptions.rootDir = toPosixPath(configDirectory);
126
+ const moduleResolution = String(tsConfig.compilerOptions?.moduleResolution).toLowerCase();
127
+ if ([
128
+ 'node',
129
+ 'node10'
130
+ ].includes(moduleResolution)) compilerOptions.moduleResolution = null;
131
+ const references = readProjectReferences(configFile);
132
+ const checkerConfig = {
133
+ extends: toRelativeConfigPath(checkerConfigDirectory, configFile),
134
+ compilerOptions,
135
+ ...references.length > 0 ? {
136
+ references
137
+ } : {}
138
+ };
139
+ node_fs.mkdirSync(checkerConfigDirectory, {
140
+ recursive: true
141
+ });
142
+ writeFileIfChanged(checkerConfigFile, `${JSON.stringify(checkerConfig, null, 2)}\n`);
143
+ return checkerConfigFile;
144
+ };
145
+ const refreshTsgoCheckerConfig = (checkerConfigFile)=>{
146
+ const checkerConfigDirectory = node_path.dirname(checkerConfigFile);
147
+ if ('tsgo' !== node_path.basename(checkerConfigDirectory) || '.modern-js' !== node_path.basename(node_path.dirname(checkerConfigDirectory)) || !node_fs.existsSync(checkerConfigFile)) return;
148
+ let checkerConfig;
149
+ try {
150
+ checkerConfig = json5.parse(node_fs.readFileSync(checkerConfigFile, 'utf8'));
151
+ } catch {
152
+ return;
153
+ }
154
+ if ('string' != typeof checkerConfig.extends) return;
155
+ const projectConfigFile = node_path.resolve(checkerConfigDirectory, checkerConfig.extends);
156
+ if (node_fs.existsSync(projectConfigFile)) try {
157
+ createTsgoCheckerConfig(projectConfigFile, checkerConfigFile);
158
+ } catch {}
159
+ return projectConfigFile;
160
+ };
161
+ const normalizeTsgoConfig = (config, rootPath)=>{
162
+ const { typescript } = config;
163
+ if (typescript?.tsgo === false) return config;
164
+ const compilerOptions = {
165
+ ...typescript?.configOverwrite?.compilerOptions ?? {},
166
+ baseUrl: null
167
+ };
168
+ if ([
169
+ 'node',
170
+ 'node10'
171
+ ].includes(String(compilerOptions.moduleResolution).toLowerCase())) compilerOptions.moduleResolution = null;
172
+ config.typescript = {
173
+ ...typescript,
174
+ configOverwrite: {
175
+ ...typescript?.configOverwrite ?? {},
176
+ compilerOptions
177
+ }
178
+ };
179
+ if (typescript?.configFile) config.typescript.configFile = createTsgoCheckerConfig(node_path.resolve(rootPath, typescript.configFile));
180
+ return config;
181
+ };
182
+ const withTsgoDefaults = (userOptions, rootPath)=>{
183
+ const tsgoPath = resolveTsgoPackagePath(rootPath);
184
+ const userChain = userOptions ? Array.isArray(userOptions) ? userOptions : [
185
+ userOptions
186
+ ] : [];
187
+ return [
188
+ {
189
+ typescript: {
190
+ tsgo: true,
191
+ typescriptPath: tsgoPath
192
+ }
193
+ },
194
+ ...userChain,
195
+ (config)=>normalizeTsgoConfig(config, rootPath)
196
+ ];
197
+ };
198
+ export { refreshTsgoCheckerConfig, withTsgoDefaults };
@@ -1,4 +1,5 @@
1
1
  import "node:module";
2
2
  export { createRspackBuilder as createBuilder, parseConfig as parseRspackConfig } from "./createBuilder.mjs";
3
3
  export { logger } from "@rsbuild/core";
4
+ export { refreshTsgoCheckerConfig } from "./shared/tsgo.mjs";
4
5
  export { RUNTIME_CHUNK_NAME, RUNTIME_CHUNK_REGEX, SERVICE_WORKER_ENVIRONMENT_NAME, castArray, isHtmlDisabled } from "./shared/utils.mjs";
@@ -57,14 +57,15 @@ const pluginEnvironmentDefaults = (distPath = {})=>({
57
57
  });
58
58
  api.modifyBundlerChain(async (chain, { environment })=>{
59
59
  const isServiceWorker = environment.name === SERVICE_WORKER_ENVIRONMENT_NAME;
60
- if (isServiceWorker && true === chain.output.get('module')) chain.output.library({
61
- ...chain.output.get('library') || {},
62
- type: 'module'
63
- });
64
- else if (isServiceWorker) chain.output.library({
65
- ...chain.output.get('library') || {},
66
- type: 'commonjs2'
67
- });
60
+ if (isServiceWorker) {
61
+ const library = chain.output.get('library');
62
+ chain.output.library({
63
+ ...'string' == typeof library || Array.isArray(library) ? {
64
+ name: library
65
+ } : library,
66
+ type: true === chain.output.get('module') ? 'module' : 'commonjs2'
67
+ });
68
+ }
68
69
  });
69
70
  }
70
71
  });
@@ -9,7 +9,9 @@ const pluginManifest = ()=>({
9
9
  chain.plugin(CHAIN_ID.PLUGIN.MANIFEST).use(RspackManifestPlugin, [
10
10
  {
11
11
  fileName: 'web' === target ? 'asset-manifest.json' : `asset-manifest-${target}.json`,
12
- publicPath,
12
+ ...'string' == typeof publicPath ? {
13
+ publicPath
14
+ } : {},
13
15
  generate: generateManifest
14
16
  }
15
17
  ]);