@bleedingdev/modern-js-app-tools-extensions 3.8.3-ultramodern.2

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.
Files changed (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -0
  3. package/dist/cjs/cloudflare/artifacts.js +127 -0
  4. package/dist/cjs/cloudflare/constants.js +141 -0
  5. package/dist/cjs/cloudflare/delivery-unit.js +161 -0
  6. package/dist/cjs/cloudflare/i18n-worker.js +135 -0
  7. package/dist/cjs/cloudflare/index.js +156 -0
  8. package/dist/cjs/cloudflare/security-policies.js +205 -0
  9. package/dist/cjs/cloudflare/types.js +18 -0
  10. package/dist/cjs/cloudflare/utils.js +66 -0
  11. package/dist/cjs/cloudflare/worker-manifest.js +239 -0
  12. package/dist/cjs/cloudflare/wrangler-config.js +205 -0
  13. package/dist/cjs/cloudflare-builder.js +394 -0
  14. package/dist/cjs/cloudflare-output-contract.js +108 -0
  15. package/dist/cjs/cloudflare-output-plan.js +93 -0
  16. package/dist/cjs/cloudflare-output-verifier/identity.js +92 -0
  17. package/dist/cjs/cloudflare-output-verifier/index.js +188 -0
  18. package/dist/cjs/cloudflare-output-verifier/issues.js +54 -0
  19. package/dist/cjs/cloudflare-output-verifier/manifest.js +89 -0
  20. package/dist/cjs/cloudflare-output-verifier/mutation-policy.js +151 -0
  21. package/dist/cjs/cloudflare-output-verifier/worker-bundles.js +378 -0
  22. package/dist/cjs/config.js +18 -0
  23. package/dist/cjs/css-extract-runtime-plugin.js +74 -0
  24. package/dist/cjs/index.js +125 -0
  25. package/dist/cjs/read-template.js +56 -0
  26. package/dist/cjs/release-envelope/canonical.js +68 -0
  27. package/dist/cjs/release-envelope/framework-output.js +649 -0
  28. package/dist/cjs/release-envelope/index.js +399 -0
  29. package/dist/cjs/release-envelope/plugin.js +102 -0
  30. package/dist/cjs/release-envelope/types.js +51 -0
  31. package/dist/cjs/release-identity.js +110 -0
  32. package/dist/cjs/templates/cloudflare-entry.001-bootstrap-security.mjs +251 -0
  33. package/dist/cjs/templates/cloudflare-entry.002-assets-routes.mjs +191 -0
  34. package/dist/cjs/templates/cloudflare-entry.003-i18n-locales.mjs +514 -0
  35. package/dist/cjs/templates/cloudflare-entry.004-rendering-css.mjs +1194 -0
  36. package/dist/cjs/templates/cloudflare-entry.005-worker-dispatch.mjs +421 -0
  37. package/dist/cjs/templates/cloudflare-entry.006-fetch-handler.mjs +93 -0
  38. package/dist/cjs/templates/cloudflare-worker-fs-promises.mjs +11 -0
  39. package/dist/cjs/templates/cloudflare-worker-loadable-server.mjs +281 -0
  40. package/dist/cjs/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +14 -0
  41. package/dist/cjs/templates/cloudflare-worker-path.mjs +98 -0
  42. package/dist/esm/cloudflare/artifacts.mjs +64 -0
  43. package/dist/esm/cloudflare/constants.mjs +34 -0
  44. package/dist/esm/cloudflare/delivery-unit.mjs +110 -0
  45. package/dist/esm/cloudflare/i18n-worker.mjs +97 -0
  46. package/dist/esm/cloudflare/index.mjs +108 -0
  47. package/dist/esm/cloudflare/security-policies.mjs +167 -0
  48. package/dist/esm/cloudflare/types.mjs +0 -0
  49. package/dist/esm/cloudflare/utils.mjs +12 -0
  50. package/dist/esm/cloudflare/worker-manifest.mjs +179 -0
  51. package/dist/esm/cloudflare/wrangler-config.mjs +151 -0
  52. package/dist/esm/cloudflare-builder.mjs +327 -0
  53. package/dist/esm/cloudflare-output-contract.mjs +31 -0
  54. package/dist/esm/cloudflare-output-plan.mjs +45 -0
  55. package/dist/esm/cloudflare-output-verifier/identity.mjs +54 -0
  56. package/dist/esm/cloudflare-output-verifier/index.mjs +133 -0
  57. package/dist/esm/cloudflare-output-verifier/issues.mjs +10 -0
  58. package/dist/esm/cloudflare-output-verifier/manifest.mjs +51 -0
  59. package/dist/esm/cloudflare-output-verifier/mutation-policy.mjs +99 -0
  60. package/dist/esm/cloudflare-output-verifier/worker-bundles.mjs +313 -0
  61. package/dist/esm/config.mjs +0 -0
  62. package/dist/esm/css-extract-runtime-plugin.mjs +32 -0
  63. package/dist/esm/index.mjs +10 -0
  64. package/dist/esm/read-template.mjs +5 -0
  65. package/dist/esm/release-envelope/canonical.mjs +21 -0
  66. package/dist/esm/release-envelope/framework-output.mjs +573 -0
  67. package/dist/esm/release-envelope/index.mjs +335 -0
  68. package/dist/esm/release-envelope/plugin.mjs +54 -0
  69. package/dist/esm/release-envelope/types.mjs +7 -0
  70. package/dist/esm/release-identity.mjs +66 -0
  71. package/dist/esm/templates/cloudflare-entry.001-bootstrap-security.mjs +251 -0
  72. package/dist/esm/templates/cloudflare-entry.002-assets-routes.mjs +191 -0
  73. package/dist/esm/templates/cloudflare-entry.003-i18n-locales.mjs +514 -0
  74. package/dist/esm/templates/cloudflare-entry.004-rendering-css.mjs +1194 -0
  75. package/dist/esm/templates/cloudflare-entry.005-worker-dispatch.mjs +421 -0
  76. package/dist/esm/templates/cloudflare-entry.006-fetch-handler.mjs +93 -0
  77. package/dist/esm/templates/cloudflare-worker-fs-promises.mjs +11 -0
  78. package/dist/esm/templates/cloudflare-worker-loadable-server.mjs +281 -0
  79. package/dist/esm/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +14 -0
  80. package/dist/esm/templates/cloudflare-worker-path.mjs +98 -0
  81. package/dist/esm-node/cloudflare/artifacts.mjs +65 -0
  82. package/dist/esm-node/cloudflare/constants.mjs +35 -0
  83. package/dist/esm-node/cloudflare/delivery-unit.mjs +111 -0
  84. package/dist/esm-node/cloudflare/i18n-worker.mjs +98 -0
  85. package/dist/esm-node/cloudflare/index.mjs +109 -0
  86. package/dist/esm-node/cloudflare/security-policies.mjs +168 -0
  87. package/dist/esm-node/cloudflare/types.mjs +1 -0
  88. package/dist/esm-node/cloudflare/utils.mjs +13 -0
  89. package/dist/esm-node/cloudflare/worker-manifest.mjs +180 -0
  90. package/dist/esm-node/cloudflare/wrangler-config.mjs +152 -0
  91. package/dist/esm-node/cloudflare-builder.mjs +328 -0
  92. package/dist/esm-node/cloudflare-output-contract.mjs +32 -0
  93. package/dist/esm-node/cloudflare-output-plan.mjs +46 -0
  94. package/dist/esm-node/cloudflare-output-verifier/identity.mjs +55 -0
  95. package/dist/esm-node/cloudflare-output-verifier/index.mjs +134 -0
  96. package/dist/esm-node/cloudflare-output-verifier/issues.mjs +11 -0
  97. package/dist/esm-node/cloudflare-output-verifier/manifest.mjs +52 -0
  98. package/dist/esm-node/cloudflare-output-verifier/mutation-policy.mjs +100 -0
  99. package/dist/esm-node/cloudflare-output-verifier/worker-bundles.mjs +314 -0
  100. package/dist/esm-node/config.mjs +1 -0
  101. package/dist/esm-node/css-extract-runtime-plugin.mjs +33 -0
  102. package/dist/esm-node/index.mjs +11 -0
  103. package/dist/esm-node/read-template.mjs +9 -0
  104. package/dist/esm-node/release-envelope/canonical.mjs +22 -0
  105. package/dist/esm-node/release-envelope/framework-output.mjs +574 -0
  106. package/dist/esm-node/release-envelope/index.mjs +336 -0
  107. package/dist/esm-node/release-envelope/plugin.mjs +55 -0
  108. package/dist/esm-node/release-envelope/types.mjs +8 -0
  109. package/dist/esm-node/release-identity.mjs +67 -0
  110. package/dist/esm-node/templates/cloudflare-entry.001-bootstrap-security.mjs +251 -0
  111. package/dist/esm-node/templates/cloudflare-entry.002-assets-routes.mjs +191 -0
  112. package/dist/esm-node/templates/cloudflare-entry.003-i18n-locales.mjs +514 -0
  113. package/dist/esm-node/templates/cloudflare-entry.004-rendering-css.mjs +1194 -0
  114. package/dist/esm-node/templates/cloudflare-entry.005-worker-dispatch.mjs +421 -0
  115. package/dist/esm-node/templates/cloudflare-entry.006-fetch-handler.mjs +93 -0
  116. package/dist/esm-node/templates/cloudflare-worker-fs-promises.mjs +11 -0
  117. package/dist/esm-node/templates/cloudflare-worker-loadable-server.mjs +281 -0
  118. package/dist/esm-node/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +14 -0
  119. package/dist/esm-node/templates/cloudflare-worker-path.mjs +98 -0
  120. package/dist/types/cloudflare/artifacts.d.ts +15 -0
  121. package/dist/types/cloudflare/constants.d.ts +24 -0
  122. package/dist/types/cloudflare/delivery-unit.d.ts +23 -0
  123. package/dist/types/cloudflare/i18n-worker.d.ts +22 -0
  124. package/dist/types/cloudflare/index.d.ts +2 -0
  125. package/dist/types/cloudflare/security-policies.d.ts +52 -0
  126. package/dist/types/cloudflare/types.d.ts +28 -0
  127. package/dist/types/cloudflare/utils.d.ts +6 -0
  128. package/dist/types/cloudflare/worker-manifest.d.ts +149 -0
  129. package/dist/types/cloudflare/wrangler-config.d.ts +51 -0
  130. package/dist/types/cloudflare-builder.d.ts +59 -0
  131. package/dist/types/cloudflare-output-contract.d.ts +14 -0
  132. package/dist/types/cloudflare-output-plan.d.ts +34 -0
  133. package/dist/types/cloudflare-output-verifier/identity.d.ts +8 -0
  134. package/dist/types/cloudflare-output-verifier/index.d.ts +18 -0
  135. package/dist/types/cloudflare-output-verifier/issues.d.ts +14 -0
  136. package/dist/types/cloudflare-output-verifier/manifest.d.ts +2 -0
  137. package/dist/types/cloudflare-output-verifier/mutation-policy.d.ts +14 -0
  138. package/dist/types/cloudflare-output-verifier/worker-bundles.d.ts +20 -0
  139. package/dist/types/config.d.ts +175 -0
  140. package/dist/types/css-extract-runtime-plugin.d.ts +6 -0
  141. package/dist/types/index.d.ts +10 -0
  142. package/dist/types/read-template.d.ts +2 -0
  143. package/dist/types/release-envelope/canonical.d.ts +5 -0
  144. package/dist/types/release-envelope/framework-output.d.ts +32 -0
  145. package/dist/types/release-envelope/index.d.ts +6 -0
  146. package/dist/types/release-envelope/plugin.d.ts +30 -0
  147. package/dist/types/release-envelope/types.d.ts +62 -0
  148. package/dist/types/release-identity.d.ts +16 -0
  149. package/dist/types/templates/cloudflare-entry.001-bootstrap-security.d.mts +1 -0
  150. package/dist/types/templates/cloudflare-entry.002-assets-routes.d.mts +1 -0
  151. package/dist/types/templates/cloudflare-entry.003-i18n-locales.d.mts +1 -0
  152. package/dist/types/templates/cloudflare-entry.004-rendering-css.d.mts +1 -0
  153. package/dist/types/templates/cloudflare-entry.005-worker-dispatch.d.mts +1 -0
  154. package/dist/types/templates/cloudflare-entry.006-fetch-handler.d.mts +4 -0
  155. package/dist/types/templates/cloudflare-worker-fs-promises.d.mts +5 -0
  156. package/dist/types/templates/cloudflare-worker-loadable-server.d.mts +48 -0
  157. package/dist/types/templates/cloudflare-worker-mf-ssr-runtime-plugin.d.mts +13 -0
  158. package/dist/types/templates/cloudflare-worker-path.d.mts +21 -0
  159. package/package.json +131 -0
  160. package/src/cloudflare/artifacts.ts +165 -0
  161. package/src/cloudflare/constants.ts +50 -0
  162. package/src/cloudflare/delivery-unit.ts +195 -0
  163. package/src/cloudflare/i18n-worker.ts +197 -0
  164. package/src/cloudflare/index.ts +259 -0
  165. package/src/cloudflare/security-policies.ts +194 -0
  166. package/src/cloudflare/types.ts +33 -0
  167. package/src/cloudflare/utils.ts +40 -0
  168. package/src/cloudflare/worker-manifest.ts +313 -0
  169. package/src/cloudflare/wrangler-config.ts +338 -0
  170. package/src/cloudflare-builder.ts +653 -0
  171. package/src/cloudflare-output-contract.ts +30 -0
  172. package/src/cloudflare-output-plan.ts +108 -0
  173. package/src/cloudflare-output-verifier/identity.ts +87 -0
  174. package/src/cloudflare-output-verifier/index.ts +277 -0
  175. package/src/cloudflare-output-verifier/issues.ts +54 -0
  176. package/src/cloudflare-output-verifier/manifest.ts +76 -0
  177. package/src/cloudflare-output-verifier/mutation-policy.ts +159 -0
  178. package/src/cloudflare-output-verifier/worker-bundles.ts +664 -0
  179. package/src/config.ts +196 -0
  180. package/src/css-extract-runtime-plugin.ts +70 -0
  181. package/src/index.ts +10 -0
  182. package/src/read-template.ts +8 -0
  183. package/src/release-envelope/canonical.ts +58 -0
  184. package/src/release-envelope/framework-output.ts +1121 -0
  185. package/src/release-envelope/index.ts +656 -0
  186. package/src/release-envelope/plugin.ts +125 -0
  187. package/src/release-envelope/types.ts +83 -0
  188. package/src/release-identity.ts +134 -0
  189. package/src/templates/cloudflare-entry.001-bootstrap-security.mjs +251 -0
  190. package/src/templates/cloudflare-entry.002-assets-routes.mjs +191 -0
  191. package/src/templates/cloudflare-entry.003-i18n-locales.mjs +514 -0
  192. package/src/templates/cloudflare-entry.004-rendering-css.mjs +1194 -0
  193. package/src/templates/cloudflare-entry.005-worker-dispatch.mjs +421 -0
  194. package/src/templates/cloudflare-entry.006-fetch-handler.mjs +93 -0
  195. package/src/templates/cloudflare-worker-fs-promises.mjs +11 -0
  196. package/src/templates/cloudflare-worker-loadable-server.mjs +281 -0
  197. package/src/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +14 -0
  198. package/src/templates/cloudflare-worker-path.mjs +98 -0
@@ -0,0 +1,653 @@
1
+ import fs from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import path from 'node:path';
4
+ import { SERVICE_WORKER_ENVIRONMENT_NAME } from '@modern-js/builder';
5
+ import type { BffUserConfig } from '@modern-js/server-core';
6
+ import { isProd } from '@modern-js/utils';
7
+ import type {
8
+ EnvironmentConfig,
9
+ ModifyBundlerChainFn,
10
+ RsbuildEntry,
11
+ RsbuildEntryDescription,
12
+ } from '@rsbuild/core';
13
+ import { provider } from 'std-env';
14
+ import { CLOUDFLARE_WORKER_NODE_BUILTINS } from './cloudflare-output-contract';
15
+ import { getTemplatePath } from './read-template';
16
+
17
+ const moduleRequire = createRequire(import.meta.url);
18
+ const BFF_EFFECT_WORKER_ENTRY_NAME = '__modern_bff_effect';
19
+ const BFF_EFFECT_WORKER_RUNTIME_QUERY = 'modern-bff-runtime';
20
+ const MF_SSR_DATA_FETCH_RUNTIME_PLUGIN =
21
+ '@module-federation/modern-js-v3/ssr-inject-data-fetch-function-plugin';
22
+ const MF_SSR_DEV_RUNTIME_PLUGIN =
23
+ '@module-federation/modern-js-v3/ssr-dev-plugin';
24
+ const JS_OR_TS_EXTENSIONS = new Set([
25
+ '.js',
26
+ '.jsx',
27
+ '.ts',
28
+ '.tsx',
29
+ '.mjs',
30
+ '.mts',
31
+ '.cjs',
32
+ '.cts',
33
+ ]);
34
+
35
+ export interface CloudflareBuilderNormalizedConfig {
36
+ bff?: BffUserConfig;
37
+ deploy?: { target?: string };
38
+ }
39
+
40
+ export interface CloudflareBuilderAppContext {
41
+ apiDirectory: string;
42
+ appDirectory: string;
43
+ }
44
+
45
+ export interface CloudflareBuilderEnvironmentsOptions {
46
+ appContext: CloudflareBuilderAppContext;
47
+ environments: Record<string, EnvironmentConfig>;
48
+ normalizedConfig: CloudflareBuilderNormalizedConfig;
49
+ resolveDeployProvider?: ResolveCloudflareDeployProvider;
50
+ }
51
+
52
+ export type ResolveCloudflareDeployProvider = () => string | undefined;
53
+
54
+ export interface CloudflareWorkerRspackConfig {
55
+ externals: Record<string, string>;
56
+ externalsType: 'module-import';
57
+ module: {
58
+ parser: {
59
+ javascript: {
60
+ dynamicImportMode: 'eager';
61
+ };
62
+ };
63
+ };
64
+ optimization: {
65
+ runtimeChunk: { name: string };
66
+ splitChunks: {
67
+ chunks: 'all';
68
+ minSize: 0;
69
+ name: string;
70
+ };
71
+ };
72
+ }
73
+
74
+ export type CloudflareBuilderEnvironmentsResult = {
75
+ environments: Record<string, EnvironmentConfig>;
76
+ };
77
+
78
+ export type ModifyCloudflareBuilderEnvironments = (
79
+ input: CloudflareBuilderEnvironmentsResult,
80
+ ) =>
81
+ | CloudflareBuilderEnvironmentsResult
82
+ | Promise<CloudflareBuilderEnvironmentsResult>;
83
+
84
+ export interface CloudflareBuilderPluginApi {
85
+ getAppContext(): Readonly<CloudflareBuilderAppContext>;
86
+ getNormalizedConfig(): Readonly<CloudflareBuilderNormalizedConfig>;
87
+ modifyBuilderEnvironments(handler: ModifyCloudflareBuilderEnvironments): void;
88
+ }
89
+
90
+ export interface CloudflareBuilderPlugin {
91
+ name: string;
92
+ setup(api: CloudflareBuilderPluginApi): void;
93
+ }
94
+
95
+ const findExistingFile = (candidates: string[]) =>
96
+ candidates.find(candidate => fs.existsSync(candidate));
97
+
98
+ const resolveJsOrTsEntry = (entryWithoutOrWithExtension: string) => {
99
+ if (JS_OR_TS_EXTENSIONS.has(path.extname(entryWithoutOrWithExtension))) {
100
+ return fs.existsSync(entryWithoutOrWithExtension)
101
+ ? entryWithoutOrWithExtension
102
+ : undefined;
103
+ }
104
+
105
+ return findExistingFile(
106
+ [...JS_OR_TS_EXTENSIONS].map(
107
+ extension => `${entryWithoutOrWithExtension}${extension}`,
108
+ ),
109
+ );
110
+ };
111
+
112
+ const resolvePackageEntry = (packageName: string, paths: string[]) => {
113
+ try {
114
+ return fs.realpathSync(moduleRequire.resolve(packageName, { paths }));
115
+ } catch {
116
+ return undefined;
117
+ }
118
+ };
119
+
120
+ const findPackageRoot = (entryFile: string, packageName: string) => {
121
+ let directory = path.dirname(entryFile);
122
+
123
+ while (directory !== path.dirname(directory)) {
124
+ const packageJsonPath = path.join(directory, 'package.json');
125
+
126
+ try {
127
+ const packageJson: unknown = JSON.parse(
128
+ fs.readFileSync(packageJsonPath, 'utf-8'),
129
+ );
130
+ if (
131
+ typeof packageJson === 'object' &&
132
+ packageJson !== null &&
133
+ 'name' in packageJson &&
134
+ packageJson.name === packageName
135
+ ) {
136
+ return directory;
137
+ }
138
+ } catch {}
139
+
140
+ directory = path.dirname(directory);
141
+ }
142
+
143
+ return undefined;
144
+ };
145
+
146
+ const resolvePackageFile = (
147
+ packageName: string,
148
+ filePath: string,
149
+ paths: string[],
150
+ ) => {
151
+ try {
152
+ return fs.realpathSync(
153
+ moduleRequire.resolve(`${packageName}/${filePath}`, { paths }),
154
+ );
155
+ } catch {
156
+ try {
157
+ const packageJsonPath = moduleRequire.resolve(
158
+ `${packageName}/package.json`,
159
+ { paths },
160
+ );
161
+ const packageFile = path.join(path.dirname(packageJsonPath), filePath);
162
+
163
+ if (fs.existsSync(packageFile)) {
164
+ return fs.realpathSync(packageFile);
165
+ }
166
+ } catch {}
167
+
168
+ const packageEntry = resolvePackageEntry(packageName, paths);
169
+ const packageRoot = packageEntry
170
+ ? findPackageRoot(packageEntry, packageName)
171
+ : undefined;
172
+ const packageFile = packageRoot
173
+ ? path.join(packageRoot, filePath)
174
+ : undefined;
175
+
176
+ return packageFile && fs.existsSync(packageFile)
177
+ ? fs.realpathSync(packageFile)
178
+ : undefined;
179
+ }
180
+ };
181
+
182
+ const setAliasIfPresent = (
183
+ alias: { set(name: string, value: string): unknown },
184
+ name: string,
185
+ value: string | undefined,
186
+ ) => {
187
+ if (value) {
188
+ alias.set(name, value);
189
+ }
190
+ };
191
+
192
+ const getCloudflareWorkerNodeExternals = () =>
193
+ Object.fromEntries(
194
+ CLOUDFLARE_WORKER_NODE_BUILTINS.flatMap(builtin => {
195
+ const nodeBuiltin = `node:${builtin}`;
196
+ return [
197
+ [builtin, `module-import ${nodeBuiltin}`],
198
+ [nodeBuiltin, `module-import ${nodeBuiltin}`],
199
+ ];
200
+ }),
201
+ );
202
+
203
+ const normalizeWorkerOutputName = (name: string) =>
204
+ path.posix.normalize(name.replace(/\\/gu, '/')).toLowerCase();
205
+
206
+ const reserveWorkerChunkName = (
207
+ baseName: string,
208
+ reservedOutputNames: ReadonlySet<string>,
209
+ ) => {
210
+ let name = baseName;
211
+ while (reservedOutputNames.has(normalizeWorkerOutputName(name))) {
212
+ name = `${name}_`;
213
+ }
214
+ return name;
215
+ };
216
+
217
+ export function getCloudflareWorkerRspackConfig(
218
+ workerEntryNames: Iterable<string>,
219
+ ): CloudflareWorkerRspackConfig {
220
+ const entryNames = [...workerEntryNames];
221
+ for (const entryName of entryNames) {
222
+ const slashName = entryName.replace(/\\/gu, '/');
223
+ const normalizedName = path.posix.normalize(slashName);
224
+ if (
225
+ entryName !== slashName ||
226
+ normalizedName !== slashName ||
227
+ normalizedName === '.' ||
228
+ normalizedName.startsWith('../') ||
229
+ path.posix.isAbsolute(normalizedName) ||
230
+ path.win32.isAbsolute(slashName) ||
231
+ /^[A-Za-z]:/u.test(slashName)
232
+ ) {
233
+ throw new Error(
234
+ `Cloudflare worker entry name "${entryName}" must be a canonical relative output path without dot segments or backslashes.`,
235
+ );
236
+ }
237
+ }
238
+
239
+ const reservedNames = new Set(entryNames.map(normalizeWorkerOutputName));
240
+ const runtimeName = reserveWorkerChunkName(
241
+ '__modern_worker_runtime',
242
+ reservedNames,
243
+ );
244
+ reservedNames.add(normalizeWorkerOutputName(runtimeName));
245
+ const sharedName = reserveWorkerChunkName(
246
+ '__modern_worker_shared',
247
+ reservedNames,
248
+ );
249
+
250
+ return {
251
+ externals: getCloudflareWorkerNodeExternals(),
252
+ externalsType: 'module-import',
253
+ module: {
254
+ parser: {
255
+ javascript: {
256
+ dynamicImportMode: 'eager',
257
+ },
258
+ },
259
+ },
260
+ optimization: {
261
+ runtimeChunk: { name: runtimeName },
262
+ splitChunks: {
263
+ chunks: 'all',
264
+ minSize: 0,
265
+ name: sharedName,
266
+ },
267
+ },
268
+ };
269
+ }
270
+
271
+ export function applyCloudflareWorkerRspackConfig(
272
+ chain: Parameters<ModifyBundlerChainFn>[0],
273
+ workerEntryNames: Iterable<string>,
274
+ ) {
275
+ const config = getCloudflareWorkerRspackConfig(workerEntryNames);
276
+
277
+ chain.externals(config.externals);
278
+ chain.externalsType(config.externalsType);
279
+ chain.module.parser.merge(config.module.parser);
280
+ chain.optimization.runtimeChunk(config.optimization.runtimeChunk);
281
+ chain.optimization.splitChunks(config.optimization.splitChunks);
282
+ }
283
+
284
+ export function applyCloudflareWorkerMfRuntimeBoundary(
285
+ chain: Parameters<ModifyBundlerChainFn>[0],
286
+ ) {
287
+ const runtimePlugin = getTemplatePath(
288
+ 'cloudflare-worker-mf-ssr-runtime-plugin.mjs',
289
+ );
290
+ chain.plugins.delete('plugin-module-federation');
291
+ chain.resolve.alias.set(
292
+ `${MF_SSR_DATA_FETCH_RUNTIME_PLUGIN}$`,
293
+ runtimePlugin,
294
+ );
295
+ chain.resolve.alias.set(`${MF_SSR_DEV_RUNTIME_PLUGIN}$`, runtimePlugin);
296
+ }
297
+
298
+ const getEffectBffEntry = (
299
+ normalizedConfig: CloudflareBuilderNormalizedConfig,
300
+ appContext: CloudflareBuilderAppContext,
301
+ ) => {
302
+ if (
303
+ !normalizedConfig.bff ||
304
+ normalizedConfig.bff.runtimeFramework === 'hono'
305
+ ) {
306
+ return undefined;
307
+ }
308
+
309
+ const configuredEntry = normalizedConfig.bff.effect?.entry;
310
+ if (configuredEntry) {
311
+ const entryWithoutOrWithExtension = path.isAbsolute(configuredEntry)
312
+ ? configuredEntry
313
+ : path.resolve(appContext.appDirectory, configuredEntry);
314
+ return resolveJsOrTsEntry(entryWithoutOrWithExtension);
315
+ }
316
+
317
+ return resolveJsOrTsEntry(path.resolve(appContext.apiDirectory, 'index'));
318
+ };
319
+
320
+ const CLOUDFLARE_DEPLOY_PROVIDERS = new Set([
321
+ 'cloudflare',
322
+ 'cloudflare_pages',
323
+ 'cloudflare_workers',
324
+ ]);
325
+
326
+ const resolveStdEnvDeployProvider: ResolveCloudflareDeployProvider = () =>
327
+ provider;
328
+
329
+ const isCloudflareWorkerDeploy = (
330
+ normalizedConfig: CloudflareBuilderNormalizedConfig,
331
+ resolveDeployProvider: ResolveCloudflareDeployProvider,
332
+ ) => {
333
+ const explicitTarget =
334
+ normalizedConfig.deploy?.target || process.env.MODERNJS_DEPLOY;
335
+ if (explicitTarget) {
336
+ return explicitTarget === 'cloudflare';
337
+ }
338
+
339
+ const detectedProvider = resolveDeployProvider();
340
+ return detectedProvider
341
+ ? CLOUDFLARE_DEPLOY_PROVIDERS.has(detectedProvider)
342
+ : false;
343
+ };
344
+
345
+ const rewriteWorkerEntryPath = (entry: string) =>
346
+ entry
347
+ .replace('index.jsx', 'index.server.jsx')
348
+ .replace('bootstrap.server.jsx', 'index.server.jsx')
349
+ .replace('bootstrap.jsx', 'index.server.jsx');
350
+
351
+ const rewriteWorkerEntryDescription = (
352
+ description: RsbuildEntryDescription,
353
+ ): RsbuildEntryDescription => {
354
+ const entryImport = description.import;
355
+ if (typeof entryImport === 'string') {
356
+ return { ...description, import: rewriteWorkerEntryPath(entryImport) };
357
+ }
358
+ if (Array.isArray(entryImport)) {
359
+ return {
360
+ ...description,
361
+ import: entryImport.map(rewriteWorkerEntryPath),
362
+ };
363
+ }
364
+ return description;
365
+ };
366
+
367
+ const rewriteWorkerEntries = (entries: RsbuildEntry): RsbuildEntry =>
368
+ Object.fromEntries(
369
+ Object.entries(entries).map(([name, value]) => {
370
+ if (typeof value === 'string') {
371
+ return [name, rewriteWorkerEntryPath(value)];
372
+ }
373
+ if (Array.isArray(value)) {
374
+ return [name, value.map(rewriteWorkerEntryPath)];
375
+ }
376
+ return [name, rewriteWorkerEntryDescription(value)];
377
+ }),
378
+ );
379
+
380
+ const prependBundlerChain = (
381
+ environment: EnvironmentConfig,
382
+ handler: ModifyBundlerChainFn,
383
+ ): EnvironmentConfig => {
384
+ const bundlerChain = environment.tools?.bundlerChain;
385
+ return {
386
+ ...environment,
387
+ tools: {
388
+ ...environment.tools,
389
+ htmlPlugin: false,
390
+ bundlerChain: bundlerChain
391
+ ? Array.isArray(bundlerChain)
392
+ ? [handler, ...bundlerChain]
393
+ : [handler, bundlerChain]
394
+ : handler,
395
+ },
396
+ };
397
+ };
398
+
399
+ const getWorkerEntries = (
400
+ environment: EnvironmentConfig,
401
+ normalizedConfig: CloudflareBuilderNormalizedConfig,
402
+ appContext: CloudflareBuilderAppContext,
403
+ ) => {
404
+ const configuredEntries = environment.source?.entry;
405
+ if (!configuredEntries) {
406
+ return undefined;
407
+ }
408
+
409
+ const entries = rewriteWorkerEntries(configuredEntries);
410
+ const effectApiEntry = getEffectBffEntry(normalizedConfig, appContext);
411
+ return effectApiEntry
412
+ ? {
413
+ ...entries,
414
+ [BFF_EFFECT_WORKER_ENTRY_NAME]: [
415
+ `${effectApiEntry}?${BFF_EFFECT_WORKER_RUNTIME_QUERY}`,
416
+ ],
417
+ }
418
+ : entries;
419
+ };
420
+
421
+ const createCloudflareBundlerChain = (
422
+ appContext: CloudflareBuilderAppContext,
423
+ workerEntryNames: Iterable<string>,
424
+ ): ModifyBundlerChainFn => {
425
+ const resolvePaths = [appContext.appDirectory, process.cwd()];
426
+ const tanstackRouterSsrServerFile = resolvePackageFile(
427
+ '@tanstack/router-core',
428
+ 'dist/esm/ssr/ssr-server.js',
429
+ resolvePaths,
430
+ );
431
+ const runtimeRscWorkerFile = resolvePackageFile(
432
+ '@modern-js/runtime',
433
+ 'dist/esm/rsc/server.worker.mjs',
434
+ resolvePaths,
435
+ );
436
+ const renderRscWorkerFile = resolvePackageFile(
437
+ '@modern-js/render',
438
+ 'dist/esm/rscWorker.mjs',
439
+ resolvePaths,
440
+ );
441
+ const reactFile = resolvePackageFile('react', 'index.js', resolvePaths);
442
+ const reactJsxRuntimeFile = resolvePackageFile(
443
+ 'react',
444
+ 'jsx-runtime.js',
445
+ resolvePaths,
446
+ );
447
+ const reactJsxDevRuntimeFile = resolvePackageFile(
448
+ 'react',
449
+ 'jsx-dev-runtime.js',
450
+ resolvePaths,
451
+ );
452
+ const reactDomFile = resolvePackageFile(
453
+ 'react-dom',
454
+ 'index.js',
455
+ resolvePaths,
456
+ );
457
+ const reactDomServerEdgeFile = resolvePackageFile(
458
+ 'react-dom',
459
+ 'server.edge.js',
460
+ resolvePaths,
461
+ );
462
+ const loadableComponentFile = resolvePackageFile(
463
+ '@loadable/component',
464
+ 'dist/esm/loadable.esm.mjs',
465
+ [...resolvePaths, getTemplatePath('')],
466
+ );
467
+ const loadableServerWorkerFile = getTemplatePath(
468
+ 'cloudflare-worker-loadable-server.mjs',
469
+ );
470
+ const fsPromisesWorkerFile = getTemplatePath(
471
+ 'cloudflare-worker-fs-promises.mjs',
472
+ );
473
+ const pathWorkerFile = getTemplatePath('cloudflare-worker-path.mjs');
474
+ const entryNames = [...workerEntryNames];
475
+
476
+ return chain => {
477
+ applyCloudflareWorkerRspackConfig(chain, entryNames);
478
+ chain.output
479
+ .module(true)
480
+ .library({ type: 'module' })
481
+ .publicPath('/')
482
+ .chunkFormat('module')
483
+ .chunkLoading('import')
484
+ .workerChunkLoading('import');
485
+
486
+ for (const condition of [
487
+ 'workerd',
488
+ 'worker',
489
+ 'webpack',
490
+ isProd() ? 'production' : 'development',
491
+ 'import',
492
+ 'require',
493
+ 'module',
494
+ ]) {
495
+ chain.resolve.conditionNames.add(condition);
496
+ }
497
+
498
+ applyCloudflareWorkerMfRuntimeBoundary(chain);
499
+ if (tanstackRouterSsrServerFile) {
500
+ chain.resolve.alias.set(
501
+ '@tanstack/router-core/ssr/server$',
502
+ tanstackRouterSsrServerFile,
503
+ );
504
+ chain.resolve.alias.set(
505
+ '@tanstack/router-core/ssr/server',
506
+ tanstackRouterSsrServerFile,
507
+ );
508
+ }
509
+ if (runtimeRscWorkerFile) {
510
+ chain.resolve.alias.set(
511
+ '@modern-js/runtime/rsc/server$',
512
+ runtimeRscWorkerFile,
513
+ );
514
+ chain.resolve.alias.set(
515
+ '@modern-js/runtime/rsc/server',
516
+ runtimeRscWorkerFile,
517
+ );
518
+ }
519
+ if (renderRscWorkerFile) {
520
+ chain.resolve.alias.set('@modern-js/render/rsc$', renderRscWorkerFile);
521
+ chain.resolve.alias.set('@modern-js/render/rsc', renderRscWorkerFile);
522
+ chain.resolve.alias.set(
523
+ '@modern-js/render/rsc-worker$',
524
+ renderRscWorkerFile,
525
+ );
526
+ }
527
+ setAliasIfPresent(chain.resolve.alias, 'react$', reactFile);
528
+ setAliasIfPresent(
529
+ chain.resolve.alias,
530
+ 'react/jsx-runtime$',
531
+ reactJsxRuntimeFile,
532
+ );
533
+ setAliasIfPresent(
534
+ chain.resolve.alias,
535
+ 'react/jsx-dev-runtime$',
536
+ reactJsxDevRuntimeFile,
537
+ );
538
+ setAliasIfPresent(chain.resolve.alias, 'react-dom$', reactDomFile);
539
+ setAliasIfPresent(
540
+ chain.resolve.alias,
541
+ 'react-dom/server.edge$',
542
+ reactDomServerEdgeFile,
543
+ );
544
+ setAliasIfPresent(
545
+ chain.resolve.alias,
546
+ '@loadable/component$',
547
+ loadableComponentFile,
548
+ );
549
+ setAliasIfPresent(
550
+ chain.resolve.alias,
551
+ '@loadable/server$',
552
+ loadableServerWorkerFile,
553
+ );
554
+ setAliasIfPresent(
555
+ chain.resolve.alias,
556
+ 'fs/promises$',
557
+ fsPromisesWorkerFile,
558
+ );
559
+ setAliasIfPresent(
560
+ chain.resolve.alias,
561
+ 'node:fs/promises$',
562
+ fsPromisesWorkerFile,
563
+ );
564
+ setAliasIfPresent(chain.resolve.alias, 'path$', pathWorkerFile);
565
+ setAliasIfPresent(chain.resolve.alias, 'node:path$', pathWorkerFile);
566
+ chain.resolve.alias.set(
567
+ 'react-server-dom-rspack/server.node$',
568
+ 'react-server-dom-rspack/server.edge',
569
+ );
570
+ chain.resolve.alias.set(
571
+ 'react-server-dom-rspack/server.node',
572
+ 'react-server-dom-rspack/server.edge',
573
+ );
574
+ chain.resolve.alias.set(
575
+ 'react-server-dom-rspack/client.node$',
576
+ 'react-server-dom-rspack/client.edge',
577
+ );
578
+ chain.resolve.alias.set(
579
+ 'react-server-dom-rspack/client.node',
580
+ 'react-server-dom-rspack/client.edge',
581
+ );
582
+ chain.resolve.fallback.set('fs', false);
583
+ chain.resolve.fallback.set('node:fs', false);
584
+ };
585
+ };
586
+
587
+ export function getCloudflareBuilderEnvironments({
588
+ appContext,
589
+ environments,
590
+ normalizedConfig,
591
+ resolveDeployProvider = resolveStdEnvDeployProvider,
592
+ }: CloudflareBuilderEnvironmentsOptions): Record<string, EnvironmentConfig> {
593
+ if (!isCloudflareWorkerDeploy(normalizedConfig, resolveDeployProvider)) {
594
+ return environments;
595
+ }
596
+
597
+ const workerEnvironment = environments[SERVICE_WORKER_ENVIRONMENT_NAME];
598
+ if (!workerEnvironment) {
599
+ return environments;
600
+ }
601
+
602
+ const workerEntries = getWorkerEntries(
603
+ workerEnvironment,
604
+ normalizedConfig,
605
+ appContext,
606
+ );
607
+ if (!workerEntries) {
608
+ return environments;
609
+ }
610
+
611
+ const cloudflareWorkerEnvironment = prependBundlerChain(
612
+ {
613
+ ...workerEnvironment,
614
+ output: {
615
+ ...workerEnvironment.output,
616
+ module: true,
617
+ target: 'web',
618
+ },
619
+ source: {
620
+ ...workerEnvironment.source,
621
+ entry: workerEntries,
622
+ },
623
+ },
624
+ createCloudflareBundlerChain(appContext, Object.keys(workerEntries)),
625
+ );
626
+
627
+ return {
628
+ ...environments,
629
+ [SERVICE_WORKER_ENVIRONMENT_NAME]: cloudflareWorkerEnvironment,
630
+ };
631
+ }
632
+
633
+ export function applyCloudflareBuilderEnvironments(
634
+ options: CloudflareBuilderEnvironmentsOptions,
635
+ ): CloudflareBuilderEnvironmentsResult {
636
+ return { environments: getCloudflareBuilderEnvironments(options) };
637
+ }
638
+
639
+ export const createCloudflareBuilderPlugin = (
640
+ resolveDeployProvider = resolveStdEnvDeployProvider,
641
+ ): CloudflareBuilderPlugin => ({
642
+ name: '@modern-js/cloudflare-builder',
643
+ setup(api) {
644
+ api.modifyBuilderEnvironments(({ environments }) =>
645
+ applyCloudflareBuilderEnvironments({
646
+ appContext: api.getAppContext(),
647
+ environments,
648
+ normalizedConfig: api.getNormalizedConfig(),
649
+ resolveDeployProvider,
650
+ }),
651
+ );
652
+ },
653
+ });
@@ -0,0 +1,30 @@
1
+ export const CLOUDFLARE_WORKER_ENTRY = 'server/index.mjs';
2
+ export const CLOUDFLARE_WORKER_MANIFEST = 'server/modern-worker-manifest.json';
3
+ export const CLOUDFLARE_WRANGLER_CONFIG_FILE = 'wrangler.json';
4
+ export const CLOUDFLARE_OUTPUT_PACKAGE_FILE = 'package.json';
5
+ export const CLOUDFLARE_WORKER_PACKAGE_FILE = 'worker/package.json';
6
+ export const CLOUDFLARE_ASSETS_BINDING = 'ASSETS';
7
+ export const CLOUDFLARE_PUBLIC_ASSETS_DIRECTORY = 'public';
8
+ export const CLOUDFLARE_WORKER_BUNDLE_DIRECTORY = 'worker';
9
+ export const CLOUDFLARE_RUNTIME_TYPE = 'cloudflare-module-worker';
10
+ export const CLOUDFLARE_OUTPUT_PACKAGE_TYPE = 'module';
11
+ export const CLOUDFLARE_WORKER_PACKAGE_TYPE = 'commonjs';
12
+ export const CLOUDFLARE_WORKER_BUNDLE_FORMAT = 'commonjs';
13
+ export const CLOUDFLARE_WORKER_NODE_BUILTINS = [
14
+ 'async_hooks',
15
+ 'buffer',
16
+ 'crypto',
17
+ 'events',
18
+ 'fs/promises',
19
+ 'module',
20
+ 'path',
21
+ 'process',
22
+ 'stream',
23
+ 'string_decoder',
24
+ 'url',
25
+ 'util',
26
+ ] as const;
27
+ export const CLOUDFLARE_REQUIRED_COMPATIBILITY_FLAGS = [
28
+ 'nodejs_compat',
29
+ 'global_fetch_strictly_public',
30
+ ] as const;