dinou 4.0.7 → 4.0.9

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 (34) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dinou/core/babel-esm-loader.js +1 -4
  3. package/dinou/core/build-static-pages.js +37 -40
  4. package/dinou/core/css-require-hook.js +64 -0
  5. package/dinou/core/generating-isg.js +2 -3
  6. package/dinou/core/get-error-jsx.js +1 -3
  7. package/dinou/core/get-file-path-and-dynamic-params.js +0 -1
  8. package/dinou/core/get-jsx.js +1 -3
  9. package/dinou/core/get-ssg-jsx-or-jsx.js +2 -2
  10. package/dinou/core/render-app-to-html.js +1 -5
  11. package/dinou/core/render-html.js +24 -29
  12. package/dinou/core/server-function-proxy-webpack.js +2 -3
  13. package/dinou/core/server.js +21 -68
  14. package/dinou/esbuild/helpers-esbuild/get-config-esbuild-prod.mjs +0 -1
  15. package/dinou/esbuild/helpers-esbuild/get-config-esbuild.mjs +0 -1
  16. package/dinou/esbuild/helpers-esbuild/get-esbuild-entries.mjs +8 -8
  17. package/dinou/esbuild/helpers-esbuild/write.mjs +6 -6
  18. package/dinou/esbuild/plugins-esbuild/assets-plugin.mjs +17 -17
  19. package/dinou/esbuild/plugins-esbuild/babel-react-compiler-plugin.mjs +11 -11
  20. package/dinou/esbuild/plugins-esbuild/server-functions-plugin.mjs +5 -5
  21. package/dinou/esbuild/plugins-esbuild/stable-chunk-names-and-maps-plugin.mjs +12 -12
  22. package/dinou/esbuild/plugins-postcss/postcss-extract-plugin.js +3 -3
  23. package/dinou/esbuild/react-refresh/esm-hmr-plugin.mjs +12 -39
  24. package/dinou/esbuild/react-refresh/react-refresh-runtime.mjs +1 -2
  25. package/dinou/package.json +4 -6
  26. package/dinou/rollup/rollup-plugins/rollup-plugin-react-client-manifest.js +4 -4
  27. package/dinou/rollup/rollup-plugins/rollup-plugin-server-functions.js +5 -5
  28. package/dinou/rollup/rollup.config.js +30 -58
  29. package/dinou/webpack/helpers/get-webpack-entries.js +7 -31
  30. package/dinou/webpack/loaders/server-functions-loader.js +4 -5
  31. package/dinou/webpack/plugins/manifest-generator-plugin.js +6 -6
  32. package/dinou/webpack/plugins/server-functions-plugin.js +7 -12
  33. package/dinou/webpack/webpack.config.js +21 -36
  34. package/package.json +3 -5
@@ -23,9 +23,7 @@ babelRegister({
23
23
  extensions: [".js", ".jsx", ".ts", ".tsx"],
24
24
  });
25
25
  const createScopedName = require("./createScopedName");
26
- require("css-modules-require-hook")({
27
- generateScopedName: createScopedName,
28
- });
26
+ require("./css-require-hook.js")();
29
27
  addHook({
30
28
  extensions,
31
29
  name: function (localName, filepath) {
@@ -220,13 +218,11 @@ if (isDevelopment) {
220
218
  isInitial = true;
221
219
  currentManifest = {};
222
220
  });
223
- // manifestWatcher.on("all", (event) => console.log("event", event));
224
221
  manifestWatcher.on("change", onManifestChange);
225
222
  }
226
223
  startManifestWatcher();
227
224
  }
228
225
  let serverFunctionsManifest = null;
229
- // const devCache = new Map(); // For dev: Map<absolutePath, Set<exports>>
230
226
 
231
227
  if (!isDevelopment) {
232
228
  // In prod/build: load generated manifest
@@ -328,14 +324,6 @@ function getContext(req, res) {
328
324
 
329
325
  // 4. REDIRECT (Your existing smart wrapper)
330
326
  redirect: (...args) => safeResCall("redirect", ...args),
331
- // redirect: (...args) => {
332
- // if (res.headersSent) {
333
- // // Do nothing on res object.
334
- // // We trust that your Server Function will return <ClientRedirect />
335
- // return;
336
- // }
337
- // res.redirect.apply(res, args);
338
- // },
339
327
  },
340
328
  };
341
329
  return context;
@@ -515,12 +503,7 @@ async function serveRSCPayload(req, res, isOld = false, isStatic = false) {
515
503
  // isStatic,
516
504
  // reqPath
517
505
  // );
518
- if (
519
- (!isDevelopment &&
520
- /*Object.keys({ ...req.query }).length === 0 &&*/
521
- !dynamicState.value) ||
522
- isStatic
523
- ) {
506
+ if ((!isDevelopment && !dynamicState.value) || isStatic) {
524
507
  const payloadPath = path.resolve(
525
508
  "dist2",
526
509
  reqPath.replace(/^\//, ""),
@@ -538,16 +521,6 @@ async function serveRSCPayload(req, res, isOld = false, isStatic = false) {
538
521
  console.error("Error reading RSC file:", err);
539
522
  res.status(500).end();
540
523
  });
541
- // readStream.on("end", () => {
542
- // if (!regenerating.has(reqPath)) {
543
- // // Regeneration has finished, delete the old one
544
- // try {
545
- // unlinkSync(payloadPathOld);
546
- // } catch (err) {
547
- // console.error("Error deleting old RSC file:", err);
548
- // }
549
- // }
550
- // });
551
524
  return readStream.pipe(res);
552
525
  }
553
526
  }
@@ -562,16 +535,16 @@ async function serveRSCPayload(req, res, isOld = false, isStatic = false) {
562
535
  );
563
536
  const manifest = isDevelopment
564
537
  ? JSON.parse(
565
- readFileSync(
566
- path.resolve(
567
- process.cwd(),
568
- isWebpack
569
- ? `${outputFolder}/react-client-manifest.json`
570
- : `react_client_manifest/react-client-manifest.json`,
571
- ),
572
- "utf8",
538
+ readFileSync(
539
+ path.resolve(
540
+ process.cwd(),
541
+ isWebpack
542
+ ? `${outputFolder}/react-client-manifest.json`
543
+ : `react_client_manifest/react-client-manifest.json`,
573
544
  ),
574
- )
545
+ "utf8",
546
+ ),
547
+ )
575
548
  : cachedClientManifest;
576
549
 
577
550
  const { pipe } = renderToPipeableStream(jsx, manifest);
@@ -612,16 +585,16 @@ app.post(/^\/____rsc_payload_error____\/.*\/?$/, async (req, res) => {
612
585
  );
613
586
  const manifest = isDevelopment
614
587
  ? JSON.parse(
615
- readFileSync(
616
- path.resolve(
617
- process.cwd(),
618
- isWebpack
619
- ? `${outputFolder}/react-client-manifest.json`
620
- : `react_client_manifest/react-client-manifest.json`,
621
- ),
622
- "utf8",
588
+ readFileSync(
589
+ path.resolve(
590
+ process.cwd(),
591
+ isWebpack
592
+ ? `${outputFolder}/react-client-manifest.json`
593
+ : `react_client_manifest/react-client-manifest.json`,
623
594
  ),
624
- )
595
+ "utf8",
596
+ ),
597
+ )
625
598
  : cachedClientManifest;
626
599
  const { pipe } = renderToPipeableStream(jsx, manifest);
627
600
  pipe(res);
@@ -644,11 +617,7 @@ app.get(/^\/.*\/?$/, (req, res) => {
644
617
  // Get reference to the mutable object
645
618
  const dynamicState = isDynamic.get(reqPath);
646
619
  // console.log("dynamicState.value", dynamicState.value);
647
- if (
648
- !isDevelopment &&
649
- /*Object.keys({ ...req.query }).length === 0 &&*/
650
- !dynamicState.value
651
- ) {
620
+ if (!isDevelopment && !dynamicState.value) {
652
621
  revalidating(reqPath, dynamicState);
653
622
  let htmlPathOld;
654
623
  if (regenerating.has(reqPath)) {
@@ -688,16 +657,6 @@ app.get(/^\/.*\/?$/, (req, res) => {
688
657
 
689
658
  // 4. Manually close the response (now we do)
690
659
  res.end();
691
-
692
- // // 5. Optional cleanup logic (async to avoid blocking)
693
- // if (htmlPathOld && !regenerating.has(reqPath)) {
694
- // // It is better to use fs.promises to avoid blocking the event loop
695
- // require("fs")
696
- // .promises.unlink(htmlPathOld)
697
- // .catch((err) => {
698
- // console.error("Error deleting old HTML file:", err);
699
- // });
700
- // }
701
660
  });
702
661
 
703
662
  return; // The stream is already flowing
@@ -763,7 +722,6 @@ app.get(/^\/.*\/?$/, (req, res) => {
763
722
  appHtmlStream.on("end", resolve);
764
723
  appHtmlStream.on("error", (error) => {
765
724
  console.error("Stream error:", error);
766
- // resolve(); // ⚠️ WATCH OUT: If you resolve here and then try to send status 500, it might fail if headers sent
767
725
  if (!res.headersSent) res.status(500).send("Internal Server Error");
768
726
  resolve(); // Better resolve at the end
769
727
  });
@@ -923,9 +881,6 @@ app.post("/____server_function____", async (req, res) => {
923
881
  // Prod: use manifest (relativePath is already normalized)
924
882
  allowedExports = serverFunctionsManifest[relativePath];
925
883
  } else {
926
- // Dev: use cache or verify file
927
- // allowedExports = devCache.get(absolutePath);
928
- // if (!allowedExports) {
929
884
  const fileContent = readFileSync(absolutePath, "utf8"); // Reads only once
930
885
  if (!useServerRegex.test(fileContent)) {
931
886
  return res
@@ -935,8 +890,6 @@ app.post("/____server_function____", async (req, res) => {
935
890
  // Parse exports (you need to implement parseExports on server if not present)
936
891
  const exports = parseExports(fileContent); // Assume you move parseExports to a shared util
937
892
  allowedExports = new Set(exports);
938
- // devCache.set(absolutePath, allowedExports);
939
- // }
940
893
  }
941
894
 
942
895
  // Validate exportName against allowedExports
@@ -61,7 +61,6 @@ export default function getConfigEsbuildProd({
61
61
  "/serverFunctionProxy.js",
62
62
  "/__hmr_client__.js",
63
63
  "/react-refresh-entry.js",
64
- // "dinou",
65
64
  ],
66
65
  plugins,
67
66
  };
@@ -58,7 +58,6 @@ export default function getConfigEsbuild({
58
58
  "/serverFunctionProxy.js",
59
59
  "/__hmr_client__.js",
60
60
  "/react-refresh-entry.js",
61
- // "dinou",
62
61
  ],
63
62
  plugins,
64
63
  };
@@ -68,7 +68,7 @@ export default async function getEsbuildEntries({
68
68
  continue;
69
69
  }
70
70
 
71
- // Leer el archivo UNA sola vez
71
+ // Read the file ONLY once
72
72
  let importedCode;
73
73
  try {
74
74
  importedCode = readFileSync(absImportPathWithExt, "utf8");
@@ -81,12 +81,12 @@ export default async function getEsbuildEntries({
81
81
  }
82
82
 
83
83
  if (!isTopLevelClientComponent) {
84
- // Verificar si es un client component
84
+ // Verify if it is a client component
85
85
  const isImportedFileClient = useClientRegex.test(importedCode.trim());
86
86
 
87
- // Si es client component, NO procesar recursivamente
87
+ // If it is a client component, DO NOT process recursively
88
88
  if (isImportedFileClient) {
89
- continue; // No procesar recursivamente client components
89
+ continue; // Do not recursively process client components
90
90
  }
91
91
  } else {
92
92
  const isImportedFileServer = useServerRegex.test(importedCode.trim());
@@ -96,7 +96,7 @@ export default async function getEsbuildEntries({
96
96
  }
97
97
  }
98
98
 
99
- // Para módulos no-client, procesar normalmente
99
+ // For non-client modules, process normally
100
100
  if (
101
101
  absImportPathWithExt.endsWith(".css") ||
102
102
  absImportPathWithExt.endsWith(".scss") ||
@@ -111,15 +111,15 @@ export default async function getEsbuildEntries({
111
111
  continue;
112
112
  }
113
113
 
114
- // 🚨 LA SOLUCIÓN: Si es un JSON, lo añadimos pero NO lo parseamos con Babel
114
+ // 🚨 THE SOLUTION: If it is a JSON file, add it but DO NOT parse it with Babel
115
115
  if (absImportPathWithExt.endsWith(".json")) {
116
116
  imports.add(absImportPathWithExt);
117
- continue; // Esto evita que pase a la recursividad de Babel
117
+ continue; // This prevents it from entering Babel recursion
118
118
  }
119
119
 
120
120
  imports.add(absImportPathWithExt);
121
121
 
122
- // Procesar imports recursivamente para módulos no-client
122
+ // Process imports recursively for non-client modules
123
123
  try {
124
124
  const nested = await getImportsAndAssetsAndCsss(
125
125
  importedCode,
@@ -16,31 +16,31 @@ export default async function write(result) {
16
16
  entryPointNormalized = entryPointNormalized.replace("dinou-asset:", "");
17
17
  }
18
18
  const inputKeys = Object.keys(info.inputs);
19
- // Lógica para assets
19
+ // Logic for assets
20
20
  if (
21
21
  regex.test(entryPointNormalized) &&
22
22
  inputKeys.length === 1 &&
23
23
  inputKeys[0] === info.entryPoint
24
24
  ) {
25
- // Saltar el .js inútil
25
+ // Skip the useless .js file
26
26
  const normalizedPath = normalizeRel(relPath);
27
27
  skipSet.add(normalizedPath);
28
- // Saltar el .map correspondiente si existe
28
+ // Skip the corresponding .map file if it exists
29
29
  const mapRelPath = relPath.replace(/\.js$/, ".js.map");
30
30
  if (result.metafile.outputs[mapRelPath]) {
31
31
  skipSet.add(normalizeRel(mapRelPath));
32
32
  }
33
33
  }
34
- // Lógica para CSS
34
+ // Logic for CSS
35
35
  if (
36
36
  cssRegex.test(info.entryPoint) &&
37
37
  ((inputKeys.length === 1 && inputKeys[0] === info.entryPoint) ||
38
38
  inputKeys.length === 0)
39
39
  ) {
40
- // Saltar el .js inútil
40
+ // Skip the useless .js file
41
41
  const normalizedPath = normalizeRel(relPath);
42
42
  skipSet.add(normalizedPath);
43
- // Saltar el .map correspondiente si existe
43
+ // Skip the corresponding .map file if it exists
44
44
  const mapRelPath = relPath + ".map";
45
45
  if (result.metafile.outputs[mapRelPath]) {
46
46
  skipSet.add(normalizeRel(mapRelPath));
@@ -18,7 +18,7 @@ export default function assetsPlugin({ include = regex } = {}) {
18
18
 
19
19
  build.initialOptions.assetNames = "assets/[name]-[hash]";
20
20
 
21
- // Manejar la carga de assets con namespaces diferentes
21
+ // Handle asset loading with different namespaces
22
22
  build.onResolve({ filter: include }, (args) => {
23
23
  // console.log("[assets-plugin] onResolve", args);
24
24
  const resolvedAlias =
@@ -28,7 +28,7 @@ export default function assetsPlugin({ include = regex } = {}) {
28
28
  parentURL: pathToFileURL(args.importer).href,
29
29
  });
30
30
 
31
- // CRUCIAL: Namespace diferente para entry points
31
+ // CRUCIAL: Different namespace for entry points
32
32
  if (args.kind === "entry-point") {
33
33
  return {
34
34
  path: resolvedAlias,
@@ -42,13 +42,13 @@ export default function assetsPlugin({ include = regex } = {}) {
42
42
  };
43
43
  });
44
44
 
45
- // Loader para assets normales
45
+ // Loader for normal assets
46
46
  build.onLoad({ filter: /.*/, namespace: "dinou-asset" }, async (args) => {
47
47
  const contents = await fs.readFile(args.path);
48
48
  return { contents, loader: "file" };
49
49
  });
50
50
 
51
- // Loader para assets entry points
51
+ // Loader for asset entry points
52
52
  build.onLoad(
53
53
  { filter: /.*/, namespace: "dinou-asset-entry" },
54
54
  async (args) => {
@@ -64,7 +64,7 @@ export default function assetsPlugin({ include = regex } = {}) {
64
64
  const normalizeRel = (p) => p.replace(/\\/g, "/");
65
65
  const processedSourceFiles = new Set();
66
66
 
67
- // Primera pasada: assets normales (archivos individuales)
67
+ // First pass: normal assets (individual files)
68
68
  for (const [oldRelPath, info] of Object.entries(
69
69
  result.metafile.outputs
70
70
  )) {
@@ -88,11 +88,11 @@ export default function assetsPlugin({ include = regex } = {}) {
88
88
  processedSourceFiles.add(sourceFile);
89
89
  }
90
90
 
91
- // Segunda pasada: buscar assets que están dentro de chunks
91
+ // Second pass: find assets that are inside chunks
92
92
  for (const [outputPath, info] of Object.entries(
93
93
  result.metafile.outputs
94
94
  )) {
95
- // Solo buscar en chunks JavaScript
95
+ // Only search in JavaScript chunks
96
96
  if (!outputPath.endsWith(".js") || info.entryPoint) continue;
97
97
 
98
98
  for (const inputPath of Object.keys(info.inputs)) {
@@ -111,10 +111,10 @@ export default function assetsPlugin({ include = regex } = {}) {
111
111
  const scoped = createScopedName(base, sourceFile);
112
112
  const newLocal = `assets/${scoped}${ext}`;
113
113
 
114
- // Leer el asset original
114
+ // Read the original asset
115
115
  const assetContent = await fs.readFile(sourceFile);
116
116
 
117
- // Crear un nuevo output file para este asset
117
+ // Create a new output file for this asset
118
118
  const newOutputFile = {
119
119
  path: path.join(outdir, newLocal),
120
120
  contents: assetContent,
@@ -130,7 +130,7 @@ export default function assetsPlugin({ include = regex } = {}) {
130
130
  // `Extracted asset from chunk: ${sourceFile} → ${newLocal}`
131
131
  // );
132
132
 
133
- // Buscar el chunk que contiene este asset
133
+ // Find the chunk that contains this asset
134
134
  const chunkFile = result.outputFiles.find(
135
135
  (f) =>
136
136
  normalizeRel(path.relative(process.cwd(), f.path)) ===
@@ -140,12 +140,12 @@ export default function assetsPlugin({ include = regex } = {}) {
140
140
  if (chunkFile) {
141
141
  let chunkContent = new TextDecoder().decode(chunkFile.contents);
142
142
 
143
- // ENFOQUE MÁS PRECISO: Buscar el comentario específico de este asset
143
+ // MORE PRECISE APPROACH: Find the specific comment for this asset
144
144
  const assetComment = `// ${inputPath}`;
145
145
  const commentIndex = chunkContent.indexOf(assetComment);
146
146
 
147
147
  if (commentIndex !== -1) {
148
- // Encontrar la línea siguiente que contiene la asignación de variable
148
+ // Find the next line containing the variable assignment
149
149
  const nextLineStart =
150
150
  chunkContent.indexOf("\n", commentIndex) + 1;
151
151
  const nextLineEnd = chunkContent.indexOf("\n", nextLineStart);
@@ -154,7 +154,7 @@ export default function assetsPlugin({ include = regex } = {}) {
154
154
  nextLineEnd
155
155
  );
156
156
 
157
- // Extraer el nombre de la variable (ej: "dinou_default")
157
+ // Extract the variable name (e.g., "dinou_default")
158
158
  const varMatch = assignmentLine.match(
159
159
  /var (\w+)_default = "([^"]+)"/
160
160
  );
@@ -163,7 +163,7 @@ export default function assetsPlugin({ include = regex } = {}) {
163
163
  const varName = varMatch[1];
164
164
  const oldPath = varMatch[2];
165
165
 
166
- // Reemplazar SOLO esta asignación específica
166
+ // Replace ONLY this specific assignment
167
167
  const newAssignmentLine = `var ${varName}_default = "/${newLocal}";`;
168
168
  chunkContent =
169
169
  chunkContent.substring(0, nextLineStart) +
@@ -175,7 +175,7 @@ export default function assetsPlugin({ include = regex } = {}) {
175
175
  // );
176
176
  }
177
177
  } else {
178
- // Fallback: buscar por el nombre de archivo en la ruta
178
+ // Fallback: search by filename in the path
179
179
  const assetName = path.basename(sourceFile);
180
180
  const escapedAssetName = escapeRegExp(assetName);
181
181
  const pattern = new RegExp(
@@ -202,7 +202,7 @@ export default function assetsPlugin({ include = regex } = {}) {
202
202
  }
203
203
  }
204
204
 
205
- // Actualizar referencias en archivos JS/CSS (código existente)
205
+ // Update references in JS/CSS files (existing code)
206
206
  for (const file of result.outputFiles) {
207
207
  const relPath = normalizeRel(path.relative(process.cwd(), file.path));
208
208
  if (!relPath.endsWith(".js") && !relPath.endsWith(".css")) continue;
@@ -226,7 +226,7 @@ export default function assetsPlugin({ include = regex } = {}) {
226
226
  file.contents = new TextEncoder().encode(content);
227
227
  }
228
228
 
229
- // Actualizar paths (código existente)
229
+ // Update paths (existing code)
230
230
  for (const file of result.outputFiles) {
231
231
  const relPath = normalizeRel(path.relative(process.cwd(), file.path));
232
232
  const oldLocal = normalizeRel(path.relative(outdir, relPath));
@@ -7,10 +7,10 @@ export default function babelReactCompilerPlugin() {
7
7
  name: "babel-react-compiler-bridge",
8
8
  setup(build) {
9
9
  const entryPoints = build.initialOptions.entryPoints;
10
- // Interceptamos archivos JS/TS/JSX/TSX
11
- // OJO: Filtramos node_modules para no ralentizar procesando librerías externas
10
+ // Intercept JS/TS/JSX/TSX files
11
+ // NOTE: Filter node_modules to avoid slowing down by processing external libraries
12
12
  build.onLoad({ filter: /\.[jt]sx?$/ }, async (args) => {
13
- // Doble chequeo de seguridad para evitar node_modules
13
+ // Double check security to avoid node_modules
14
14
  if (args.path.includes("node_modules")) return;
15
15
  const abs = path.resolve(args.path);
16
16
 
@@ -25,30 +25,30 @@ export default function babelReactCompilerPlugin() {
25
25
  const source = await fs.readFile(args.path, "utf8");
26
26
  const filename = args.path;
27
27
 
28
- // Transformamos el código con Babel + React Compiler
28
+ // Transform the code with Babel + React Compiler
29
29
  const result = await babel.transformAsync(source, {
30
30
  filename,
31
31
  presets: [
32
- // Necesitamos decirle a Babel que entienda React y TS antes de compilar
32
+ // We need to tell Babel to understand React and TS before compiling
33
33
  ["@babel/preset-react", { runtime: "automatic" }],
34
34
  "@babel/preset-typescript",
35
35
  ],
36
36
  plugins: [
37
- "babel-plugin-react-compiler", // 👈 LA JOYA DE LA CORONA
37
+ "babel-plugin-react-compiler", // 👈 The jewel in the crown
38
38
  ],
39
- sourceMaps: true, // Vital para que los sourcemaps de esbuild funcionen
40
- configFile: false, // Ignoramos babel.config.js globales para ir al grano
39
+ sourceMaps: true, // Vital for esbuild sourcemaps to work
40
+ configFile: false, // Ignore global babel.config.js to get straight to the point
41
41
  });
42
42
 
43
- // Si por alguna razón Babel no devuelve código, dejamos a esbuild actuar
43
+ // If for some reason Babel does not return code, let esbuild handle it
44
44
  if (!result || !result.code) return;
45
45
 
46
46
  return {
47
47
  contents: result.code,
48
- loader: "js", // Babel devuelve JS estándar
48
+ loader: "js", // Babel returns standard JS
49
49
  };
50
50
  } catch (error) {
51
- // Si falla Babel, mostramos error bonito para no romper el build silenciosamente
51
+ // If Babel fails, show a clean error to not break the build silently
52
52
  return {
53
53
  errors: [
54
54
  {
@@ -8,7 +8,7 @@ export default function serverFunctionsPlugin(manifestData = {}) {
8
8
  name: "server-functions-proxy",
9
9
  setup(build) {
10
10
  const root = process.cwd();
11
- const serverFunctions = new Map(); // Recolectar aquí: Map<relativePath, Set<exports>>
11
+ const serverFunctions = new Map(); // Collect server functions here: Map<relativePath, Set<exports>>
12
12
 
13
13
  // 1. TRANSFORM FILES DURING BUILD
14
14
  build.onLoad({ filter: /\.[jt]sx?$/ }, async (args) => {
@@ -20,11 +20,11 @@ export default function serverFunctionsPlugin(manifestData = {}) {
20
20
  if (exports.length === 0) return null;
21
21
 
22
22
  const relativePath = path.relative(root, args.path);
23
- serverFunctions.set(relativePath, new Set(exports)); // Guardar exports como Set para uniqueness
23
+ serverFunctions.set(relativePath, new Set(exports)); // Save exports as a Set to guarantee uniqueness
24
24
 
25
25
  const fileUrl = `file:///${relativePath}`;
26
26
 
27
- // Proxy code (igual que antes)
27
+ // Generate proxy code that forwards calls to the server instead of executing the actual code
28
28
  let proxyCode = `
29
29
  import { createServerFunctionProxy } from "/__SERVER_FUNCTION_PROXY__";
30
30
  `;
@@ -69,13 +69,13 @@ export default function serverFunctionsPlugin(manifestData = {}) {
69
69
  }
70
70
  }
71
71
 
72
- // Generar manifest: convertir Map a objeto simple
72
+ // Generate the final manifest by converting the Map to a plain object
73
73
  const manifestObj = {};
74
74
  for (const [path, exportsSet] of serverFunctions.entries()) {
75
75
  manifestObj[path] = Array.from(exportsSet);
76
76
  }
77
77
 
78
- // Escribir el manifest en el output dir (ej. mismo lugar que otros assets)
78
+ // Write the server functions manifest JSON file to the output directory
79
79
  const manifestPath = path.join(
80
80
  "server_functions_manifest",
81
81
  "server-functions-manifest.json"
@@ -11,7 +11,7 @@ export default function stableChunkNamesAndMapsPlugin({ dev = true } = {}) {
11
11
 
12
12
  const renames = new Map(); // oldFilename → newFilename (e.g., 'chunk-ABC.js' → 'chunk-stable.js')
13
13
  const normalizeRel = (p) => p.replace(/\\/g, "/");
14
- // Primero, renombrar chunks
14
+ // First, rename chunks
15
15
  for (const [oldRelPath, info] of Object.entries(
16
16
  result.metafile.outputs
17
17
  )) {
@@ -21,7 +21,7 @@ export default function stableChunkNamesAndMapsPlugin({ dev = true } = {}) {
21
21
  (f) => f.startsWith("src/") && /\.(js|jsx|ts|tsx)$/.test(f)
22
22
  );
23
23
  if (!sourceFile) continue;
24
- // Nombre estable basado en el archivo fuente (siempre igual)
24
+ // Stable name based on the source file (always the same)
25
25
  const rel = path.relative("src", sourceFile);
26
26
  const normalizedRel = rel.replace(/\\/g, "/");
27
27
  const dir = path.dirname(normalizedRel);
@@ -33,7 +33,7 @@ export default function stableChunkNamesAndMapsPlugin({ dev = true } = {}) {
33
33
  dir === "." ? base : `${dir.replace(/\//g, "-")}-${base}`;
34
34
  let finalName;
35
35
  if (dev) {
36
- finalName = `${stableName}.js`; // 100% estable en dev
36
+ finalName = `${stableName}.js`; // 100% stable in dev
37
37
  } else {
38
38
  const hash = oldRelPath.match(/-([A-Z0-9]+)\./)?.[1] || "";
39
39
  finalName = `${stableName}-${hash}.js`;
@@ -42,7 +42,7 @@ export default function stableChunkNamesAndMapsPlugin({ dev = true } = {}) {
42
42
  const oldLocal = path.basename(oldRelPath);
43
43
  renames.set(oldLocal, finalRelPath);
44
44
  }
45
- // Segundo, renombrar maps correspondientes a los chunks
45
+ // Second, rename maps corresponding to the chunks
46
46
  for (const [oldRelPath, info] of Object.entries(
47
47
  result.metafile.outputs
48
48
  )) {
@@ -56,7 +56,7 @@ export default function stableChunkNamesAndMapsPlugin({ dev = true } = {}) {
56
56
  renames.set(oldMapLocal, newMapLocal);
57
57
  }
58
58
  }
59
- // Paso 3: Actualizar referencias en importers (imports en .js)
59
+ // Step 3: Update references in importers (imports in .js)
60
60
  const outputs = result.metafile.outputs;
61
61
  const escapeRegExp = (string) =>
62
62
  string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -74,22 +74,22 @@ export default function stableChunkNamesAndMapsPlugin({ dev = true } = {}) {
74
74
  const oldImportedLocal = path.basename(importedRelPath);
75
75
  const newImportedLocal = renames.get(oldImportedLocal);
76
76
  if (!newImportedLocal) continue;
77
- // Reemplazar para double quotes con ./
77
+ // Replace for double quotes with ./
78
78
  const oldDouble = `"./${escapeRegExp(oldImportedLocal)}"`;
79
79
  const newDouble = `"./${newImportedLocal}"`;
80
80
  content = content.replace(new RegExp(oldDouble, "g"), newDouble);
81
- // Reemplazar para double quotes sin ./
81
+ // Replace for double quotes without ./
82
82
  const oldDoubleNoDot = `"${escapeRegExp(oldImportedLocal)}"`;
83
83
  const newDoubleNoDot = `"${newImportedLocal}"`;
84
84
  content = content.replace(
85
85
  new RegExp(oldDoubleNoDot, "g"),
86
86
  newDoubleNoDot
87
87
  );
88
- // Reemplazar para single quotes con ./
88
+ // Replace for single quotes with ./
89
89
  const oldSingle = `'./${escapeRegExp(oldImportedLocal)}'`;
90
90
  const newSingle = `'./${newImportedLocal}'`;
91
91
  content = content.replace(new RegExp(oldSingle, "g"), newSingle);
92
- // Reemplazar para single quotes sin ./
92
+ // Replace for single quotes without ./
93
93
  const oldSingleNoDot = `'${escapeRegExp(oldImportedLocal)}'`;
94
94
  const newSingleNoDot = `'${newImportedLocal}'`;
95
95
  content = content.replace(
@@ -99,7 +99,7 @@ export default function stableChunkNamesAndMapsPlugin({ dev = true } = {}) {
99
99
  }
100
100
  importerFile.contents = new TextEncoder().encode(content);
101
101
  }
102
- // Nuevo: Actualizar sourceMappingURL en los .js que se renombran
102
+ // New: Update sourceMappingURL in the .js files being renamed
103
103
  for (const file of result.outputFiles) {
104
104
  if (!file.path.endsWith(".js")) continue;
105
105
  const oldRelPath = normalizeRel(
@@ -123,7 +123,7 @@ export default function stableChunkNamesAndMapsPlugin({ dev = true } = {}) {
123
123
  );
124
124
  file.contents = new TextEncoder().encode(content);
125
125
  }
126
- // Actualizar paths en outputFiles para chunks y maps
126
+ // Update paths in outputFiles for chunks and maps
127
127
  for (const file of result.outputFiles) {
128
128
  const relPath = normalizeRel(path.relative(process.cwd(), file.path));
129
129
  const oldLocal = path.basename(relPath);
@@ -132,7 +132,7 @@ export default function stableChunkNamesAndMapsPlugin({ dev = true } = {}) {
132
132
  file.path = path.join(path.dirname(file.path), newLocal);
133
133
  }
134
134
  }
135
- // Actualizar metafile para consistencia
135
+ // Update metafile for consistency
136
136
  const newOutputs = {};
137
137
  for (const oldRelPath in outputs) {
138
138
  const oldLocal = path.basename(oldRelPath);
@@ -7,7 +7,7 @@ const createPostCSSExtractPlugin = (options = {}) => {
7
7
 
8
8
  let extractedCSS = "";
9
9
 
10
- // El plugin de PostCSS propiamente dicho
10
+ // Define the PostCSS plugin to intercept and extract CSS rules
11
11
  const postcssPlugin = {
12
12
  postcssPlugin: "postcss-extract",
13
13
 
@@ -18,13 +18,13 @@ const createPostCSSExtractPlugin = (options = {}) => {
18
18
  extractedCSS += root.toString();
19
19
  extractedCSS += "\n";
20
20
 
21
- // Limpia el CSS original
21
+ // Remove all CSS rules from the original file to prevent duplicate injection
22
22
  root.removeAll();
23
23
  }
24
24
  },
25
25
  };
26
26
 
27
- // Función para finalizar
27
+ // Write the collected CSS contents to the final output file on disk
28
28
  const finalize = () => {
29
29
  if (!extractedCSS) return;
30
30
  const outputDir = path.dirname(outputFile);