dinou 6.1.1 → 7.0.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.
Files changed (135) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +9461 -1080
  3. package/cli.js +392 -169
  4. package/dinou/adapters/bun.js +62 -0
  5. package/dinou/adapters/cloudflare.js +65 -0
  6. package/dinou/adapters/deno.js +48 -0
  7. package/dinou/adapters/netlify.js +85 -0
  8. package/dinou/adapters/node.mjs +31 -0
  9. package/dinou/bun/build.mjs +1077 -0
  10. package/dinou/cloudflare/build.mjs +1121 -0
  11. package/dinou/cloudflare/shims/child_process.js +14 -0
  12. package/dinou/cloudflare/shims/empty.js +2 -0
  13. package/dinou/cloudflare/shims/fs.js +99 -0
  14. package/dinou/cloudflare/shims/os.js +29 -0
  15. package/dinou/config.js +1 -0
  16. package/dinou/config.mjs +2 -0
  17. package/dinou/constants.js +29 -4
  18. package/dinou/core/babel-esm-loader.js +66 -37
  19. package/dinou/core/bailout-proxy.js +61 -0
  20. package/dinou/core/build-static-pages.js +309 -157
  21. package/dinou/core/cache-revalidate.js +471 -144
  22. package/dinou/core/cache-slot.js +387 -0
  23. package/dinou/core/client-redirect.jsx +12 -7
  24. package/dinou/core/client-webpack.jsx +457 -82
  25. package/dinou/core/client.jsx +452 -82
  26. package/dinou/core/config.js +11 -0
  27. package/dinou/core/dinou-paths.js +52 -0
  28. package/dinou/core/edge-ssr.js +122 -0
  29. package/dinou/core/export-static.mjs +64 -0
  30. package/dinou/core/generate-route-types.js +252 -0
  31. package/dinou/core/generate-static-page.js +55 -94
  32. package/dinou/core/generate-static-rsc.js +47 -15
  33. package/dinou/core/generate-static.js +212 -10
  34. package/dinou/core/generating-isg.js +5 -0
  35. package/dinou/core/get-asset-from-manifest.js +9 -3
  36. package/dinou/core/get-error-jsx.js +221 -41
  37. package/dinou/core/get-file-path-and-dynamic-params.js +9 -13
  38. package/dinou/core/get-jsx.js +172 -95
  39. package/dinou/core/handler.js +2296 -0
  40. package/dinou/core/http-adapter.js +115 -0
  41. package/dinou/core/import-module.js +83 -53
  42. package/dinou/core/layout-functions.js +181 -0
  43. package/dinou/core/link.jsx +18 -6
  44. package/dinou/core/load-dinou-config.js +60 -0
  45. package/dinou/core/manifest-provider.js +261 -0
  46. package/dinou/core/navigation-utils.js +4 -0
  47. package/dinou/core/navigation.js +50 -39
  48. package/dinou/core/parse-exports.js +207 -2
  49. package/dinou/core/ppr-context.js +105 -0
  50. package/dinou/core/ppr-runtime.js +263 -0
  51. package/dinou/core/redirect.jsx +20 -19
  52. package/dinou/core/render-jsx-to-client-jsx.js +133 -15
  53. package/dinou/core/request-context.js +47 -13
  54. package/dinou/core/resolve-module-ppr.js +32 -0
  55. package/dinou/core/revalidating.js +28 -9
  56. package/dinou/core/route-generator.js +107 -0
  57. package/dinou/core/rsc-renderer.js +90 -0
  58. package/dinou/core/run-ssg.js +19 -0
  59. package/dinou/core/scan-dependency-components.js +218 -0
  60. package/dinou/core/server-function-proxy-webpack.js +3 -0
  61. package/dinou/core/server-function-proxy.js +3 -0
  62. package/dinou/core/slot.js +302 -0
  63. package/dinou/core/status-manifest.js +41 -1
  64. package/dinou/core/storage-adapter.js +522 -0
  65. package/dinou/core/url-resolver.js +16 -16
  66. package/dinou/core/vfs.js +139 -68
  67. package/dinou/deno/build.mjs +1112 -0
  68. package/dinou/deno/seed-kv.js +115 -0
  69. package/dinou/esbuild/build.mjs +51 -1
  70. package/dinou/esbuild/dev.mjs +290 -224
  71. package/dinou/esbuild/helpers-esbuild/get-config-esbuild-prod.mjs +3 -2
  72. package/dinou/esbuild/helpers-esbuild/get-config-esbuild.mjs +104 -16
  73. package/dinou/esbuild/helpers-esbuild/get-esbuild-entries.mjs +31 -19
  74. package/dinou/esbuild/helpers-esbuild/strip-namespace.mjs +9 -0
  75. package/dinou/esbuild/helpers-esbuild/swc-disk-cache.mjs +225 -0
  76. package/dinou/esbuild/helpers-esbuild/update-manifest-for-module.mjs +7 -0
  77. package/dinou/esbuild/helpers-esbuild/write.mjs +111 -2
  78. package/dinou/esbuild/plugins-esbuild/assets-plugin.mjs +236 -161
  79. package/dinou/esbuild/plugins-esbuild/css-processor-plugin.mjs +101 -5
  80. package/dinou/esbuild/plugins-esbuild/react-client-manifest-plugin.mjs +63 -24
  81. package/dinou/esbuild/plugins-esbuild/server-functions-plugin.mjs +177 -56
  82. package/dinou/esbuild/plugins-esbuild/skip-missing-entry-points-plugin.mjs +3 -0
  83. package/dinou/esbuild/plugins-esbuild/stable-chunk-names-and-maps-plugin.mjs +182 -137
  84. package/dinou/esbuild/plugins-postcss/postcss-extract-plugin.js +38 -11
  85. package/dinou/esbuild/react-refresh/esm-hmr/client.mjs +55 -8
  86. package/dinou/esbuild/react-refresh/esm-hmr/server.js +1 -1
  87. package/dinou/esbuild/react-refresh/esm-hmr-plugin.mjs +238 -101
  88. package/dinou/esbuild/react-refresh/is-react-refresh-boundary.mjs +18 -4
  89. package/dinou/index.d.ts +315 -11
  90. package/dinou/index.js +12 -6
  91. package/dinou/index.mjs +9 -0
  92. package/dinou/node/build.mjs +195 -0
  93. package/dinou/node/bundle-dual-engine.mjs +1012 -0
  94. package/dinou/node/dev.mjs +2589 -0
  95. package/dinou/node/port-selector.mjs +164 -0
  96. package/dinou/node/terminal-status.mjs +345 -0
  97. package/dinou/package.json +16 -14
  98. package/dinou/rollup/react-refresh/esm-hmr/client.js +66 -10
  99. package/dinou/rollup/react-refresh/esm-hmr/server.js +1 -1
  100. package/dinou/rollup/react-refresh/is-react-refresh-boundary.js +24 -5
  101. package/dinou/rollup/react-refresh/react-refresh-runtime.js +13 -6
  102. package/dinou/rollup/react-refresh/react-refresh-wrap-modules.js +56 -11
  103. package/dinou/rollup/react-refresh/rollup-plugin-esm-hmr.js +176 -48
  104. package/dinou/rollup/rollup-plugins/dinou-asset-plugin.js +9 -5
  105. package/dinou/rollup/rollup-plugins/rollup-plugin-memory.js +66 -0
  106. package/dinou/rollup/rollup-plugins/rollup-plugin-react-client-manifest.js +468 -123
  107. package/dinou/rollup/rollup-plugins/rollup-plugin-server-functions.js +44 -12
  108. package/dinou/rollup/rollup-plugins/rollup-plugin-swc.js +100 -0
  109. package/dinou/rollup/rollup.config.js +155 -43
  110. package/dinou/server.d.ts +114 -12
  111. package/dinou/server.js +35 -10
  112. package/dinou/server.mjs +30 -9
  113. package/dinou/webpack/helpers/get-webpack-entries.js +14 -19
  114. package/dinou/webpack/loaders/server-functions-loader.js +22 -1
  115. package/dinou/webpack/loaders/swc-loader.js +76 -0
  116. package/dinou/webpack/plugins/manifest-generator-plugin.js +1 -0
  117. package/dinou/webpack/plugins/server-functions-plugin.js +75 -19
  118. package/dinou/webpack/plugins/webpack-memory-plugin.js +66 -0
  119. package/dinou/webpack/webpack.config.js +227 -29
  120. package/eject.js +173 -94
  121. package/package.json +110 -108
  122. package/dinou/core/asset-require-hook.js +0 -58
  123. package/dinou/core/client-error-webpack.jsx +0 -432
  124. package/dinou/core/client-error.jsx +0 -432
  125. package/dinou/core/concurrency-manager.js +0 -48
  126. package/dinou/core/context-proxy.js +0 -68
  127. package/dinou/core/generate-static-pages.js +0 -130
  128. package/dinou/core/generate-static-rscs.js +0 -151
  129. package/dinou/core/get-ssg-metadata.js +0 -31
  130. package/dinou/core/register-loader.mjs +0 -11
  131. package/dinou/core/register-paths.js +0 -27
  132. package/dinou/core/render-app-to-html.js +0 -430
  133. package/dinou/core/render-html.js +0 -407
  134. package/dinou/core/server.js +0 -1542
  135. package/dinou/esbuild/plugins-esbuild/write-metafile-plugin.mjs +0 -16
@@ -43,7 +43,8 @@ async function getCSSEntries({
43
43
  const csss = new Set();
44
44
 
45
45
  const importNodes = [];
46
- traverse.default(ast, {
46
+ const traverseFn = typeof traverse === "function" ? traverse : (traverse.default || traverse);
47
+ traverseFn(ast, {
47
48
  ImportDeclaration(nodePath) {
48
49
  importNodes.push(nodePath);
49
50
  },
@@ -144,10 +145,20 @@ async function getCSSEntries({
144
145
  absolute: true,
145
146
  });
146
147
 
148
+ const serverFiles = new Set();
149
+
147
150
  // Gather client modules and update manifest entries
151
+ let fileScanCount = 0;
148
152
  for (const absPath of files) {
153
+ if (++fileScanCount % 5 === 0) {
154
+ await new Promise((resolve) => setImmediate(resolve));
155
+ }
149
156
  const code = readFileSync(absPath, "utf8");
150
- const isClientModule = useClientRegex.test(code.trim());
157
+ const trimmed = code.trim();
158
+ if (useServerRegex.test(trimmed)) {
159
+ serverFiles.add(path.resolve(absPath).replace(/\\/g, "/").toLowerCase());
160
+ }
161
+ const isClientModule = useClientRegex.test(trimmed);
151
162
  const normalizedPath = normalizePath(absPath);
152
163
 
153
164
  if (isClientModule) {
@@ -157,22 +168,6 @@ async function getCSSEntries({
157
168
  absPath: normalizedPath,
158
169
  name,
159
170
  });
160
- const { imports } = await getImportsAndAssetsAndCsss(
161
- code,
162
- absPath,
163
- new Set(),
164
- true,
165
- );
166
- const clientComponentRegex = /\.(js|jsx|ts|tsx)$/i;
167
- imports.forEach((imp) => {
168
- if (clientComponentRegex.test(imp) && !imp.includes("node_modules")) {
169
- const name = path.basename(imp, path.extname(imp));
170
- detectedClientEntries.add({
171
- absPath: normalizePath(imp),
172
- name,
173
- });
174
- }
175
- });
176
171
  } else if (isPageOrLayout(absPath)) {
177
172
  try {
178
173
  const { csss } = await getImportsAndAssetsAndCsss(code, absPath);
@@ -205,7 +200,7 @@ async function getCSSEntries({
205
200
  dCSSE.outfileName = outfileName;
206
201
  }
207
202
 
208
- return [detectedCSSEntries, detectedClientEntries];
203
+ return [detectedCSSEntries, detectedClientEntries, serverFiles];
209
204
  }
210
205
 
211
206
  module.exports = getCSSEntries;
@@ -5,13 +5,34 @@ const parseExports = require("../../core/parse-exports.js");
5
5
  const { useServerRegex } = require("../../constants.js");
6
6
 
7
7
  module.exports = function (source) {
8
+ const options = this.getOptions ? this.getOptions() : {};
9
+ const norm = path.resolve(this.resourcePath).replace(/\\/g, "/").toLowerCase();
10
+
11
+ if (options.serverFiles) {
12
+ if (!options.serverFiles.has(norm)) {
13
+ if (!source.includes("use server")) {
14
+ return source;
15
+ }
16
+ if (useServerRegex.test(source)) {
17
+ options.serverFiles.add(norm);
18
+ } else {
19
+ return source;
20
+ }
21
+ }
22
+ }
23
+
8
24
  let hasUseServer = false;
9
25
 
10
26
  if (useServerRegex.test(source)) {
11
27
  hasUseServer = true;
12
28
  }
13
29
 
14
- if (!hasUseServer) return source;
30
+ if (!hasUseServer) {
31
+ if (options.serverFiles) {
32
+ options.serverFiles.delete(norm);
33
+ }
34
+ return source;
35
+ }
15
36
 
16
37
  const exports = parseExports(source);
17
38
  if (exports.length === 0) return source;
@@ -0,0 +1,76 @@
1
+ // dinou/webpack/loaders/swc-loader.js
2
+ // Ultra-fast SWC transpilation loader for Webpack.
3
+ // Replaces heavy Babel pipeline in development and eliminates multi-second rebuild latencies.
4
+
5
+ const path = require("path");
6
+
7
+ let swc = null;
8
+ try {
9
+ swc = require("@swc/core");
10
+ } catch (e) {
11
+ // Handled on first invocation
12
+ }
13
+
14
+ module.exports = function (source, inputSourceMap) {
15
+ if (this.cacheable) this.cacheable(true);
16
+
17
+ if (!swc) {
18
+ try {
19
+ swc = require("@swc/core");
20
+ } catch (e) {
21
+ throw new Error(
22
+ "[@swc/core] not found. Please ensure @swc/core is installed to use swc-loader."
23
+ );
24
+ }
25
+ }
26
+
27
+ const callback = this.async();
28
+ const options = this.getOptions ? this.getOptions() : {};
29
+ const isDev =
30
+ options.isDevelopment !== undefined
31
+ ? options.isDevelopment
32
+ : process.env.NODE_ENV !== "production";
33
+
34
+ const resourcePath = this.resourcePath;
35
+ const isTs = /\.tsx?$/i.test(resourcePath);
36
+ const isJsx = /\.[jt]sx$/i.test(resourcePath);
37
+
38
+ swc
39
+ .transform(source, {
40
+ filename: resourcePath,
41
+ sourceMaps: this.sourceMap ? true : false,
42
+ inputSourceMap:
43
+ typeof inputSourceMap === "string"
44
+ ? inputSourceMap
45
+ : inputSourceMap
46
+ ? JSON.stringify(inputSourceMap)
47
+ : undefined,
48
+ jsc: {
49
+ parser: isTs
50
+ ? { syntax: "typescript", tsx: isJsx, dynamicImport: true }
51
+ : { syntax: "ecmascript", jsx: true, dynamicImport: true },
52
+ target: "es2022",
53
+ transform: {
54
+ react: {
55
+ runtime: "automatic",
56
+ development: isDev,
57
+ refresh: false,
58
+ },
59
+ },
60
+ },
61
+ })
62
+ .then((output) => {
63
+ let map = undefined;
64
+ if (output.map) {
65
+ try {
66
+ map = JSON.parse(output.map);
67
+ } catch (e) {
68
+ map = output.map;
69
+ }
70
+ }
71
+ callback(null, output.code, map);
72
+ })
73
+ .catch((err) => {
74
+ callback(err);
75
+ });
76
+ };
@@ -17,6 +17,7 @@ class ManifestGeneratorPlugin {
17
17
  stage: Compilation.PROCESS_ASSETS_STAGE_ANALYSE,
18
18
  },
19
19
  (assets) => {
20
+ this.manifestData = {};
20
21
  // Traverse chunks to generate manifest
21
22
  for (const chunk of compilation.chunks) {
22
23
  if (!chunk.name) continue; // only chunks with a name
@@ -1,3 +1,4 @@
1
+ const path = require("path");
1
2
  const manifestGeneratorPlugin = require("./manifest-generator-plugin");
2
3
 
3
4
  class WebpackServerFunctionsPluginSimple {
@@ -19,25 +20,9 @@ class WebpackServerFunctionsPluginSimple {
19
20
  stage: Compilation.PROCESS_ASSETS_STAGE_REPORT,
20
21
  },
21
22
  (assets) => {
22
- // 1. Replace placeholder
23
- const manifest = manifestGeneratorPlugin.manifestData;
24
- const hashedPath = manifest["serverFunctionProxy.js"] || "serverFunctionProxy.js";
25
-
26
- for (const [filename, asset] of Object.entries(assets)) {
27
- if (filename.endsWith(".js")) {
28
- let code = asset.source();
29
- if (code.includes("__SERVER_FUNCTION_PROXY__")) {
30
- code = code.replace(/__SERVER_FUNCTION_PROXY__/g, hashedPath);
31
- compilation.updateAsset(
32
- filename,
33
- new sources.RawSource(code)
34
- );
35
- }
36
- }
37
- }
38
-
39
- // 2. Collect all server function files
23
+ // 1. Collect all server function files generated by loader
40
24
  const serverFunctionsManifest = {};
25
+ const serverFunctionPaths = new Set();
41
26
 
42
27
  for (const [filename, asset] of Object.entries(assets)) {
43
28
  if (
@@ -48,6 +33,9 @@ class WebpackServerFunctionsPluginSimple {
48
33
  const content = asset.source();
49
34
  const entry = JSON.parse(content);
50
35
  serverFunctionsManifest[entry.path] = entry.exports;
36
+ serverFunctionPaths.add(
37
+ path.resolve(process.cwd(), entry.path).replace(/\\/g, "/").toLowerCase()
38
+ );
51
39
 
52
40
  // Delete this temporary file
53
41
  delete assets[filename];
@@ -57,7 +45,7 @@ class WebpackServerFunctionsPluginSimple {
57
45
  }
58
46
  }
59
47
 
60
- // 3. Generate final manifest
48
+ // 2. Generate final manifest
61
49
  const manifestContent = JSON.stringify(
62
50
  serverFunctionsManifest,
63
51
  null,
@@ -67,6 +55,74 @@ class WebpackServerFunctionsPluginSimple {
67
55
  "server-functions-manifest.json",
68
56
  new sources.RawSource(manifestContent)
69
57
  );
58
+
59
+ // 3. If no server functions exist in this compilation, do not touch any assets
60
+ if (serverFunctionPaths.size === 0) {
61
+ return;
62
+ }
63
+
64
+ // 4. Identify ONLY chunks that actually bundle a server function module
65
+ const targetAssetFiles = new Set();
66
+
67
+ for (const chunk of compilation.chunks) {
68
+ let chunkModules = [];
69
+ try {
70
+ chunkModules = compilation.chunkGraph
71
+ ? compilation.chunkGraph.getChunkModules(chunk)
72
+ : (chunk.getModules ? chunk.getModules() : []);
73
+ } catch (e) {
74
+ chunkModules = [];
75
+ }
76
+
77
+ let containsServerFunction = false;
78
+ for (const mod of chunkModules) {
79
+ if (mod.resource) {
80
+ const norm = path.resolve(mod.resource).replace(/\\/g, "/").toLowerCase();
81
+ if (serverFunctionPaths.has(norm)) {
82
+ containsServerFunction = true;
83
+ break;
84
+ }
85
+ }
86
+ if (mod.modules) {
87
+ for (const sub of mod.modules) {
88
+ if (sub.resource) {
89
+ const normSub = path.resolve(sub.resource).replace(/\\/g, "/").toLowerCase();
90
+ if (serverFunctionPaths.has(normSub)) {
91
+ containsServerFunction = true;
92
+ break;
93
+ }
94
+ }
95
+ }
96
+ }
97
+ if (containsServerFunction) break;
98
+ }
99
+
100
+ if (containsServerFunction) {
101
+ for (const file of chunk.files) {
102
+ targetAssetFiles.add(file);
103
+ }
104
+ }
105
+ }
106
+
107
+ // 5. Replace placeholder ONLY in chunks that actually contain server functions
108
+ const manifest = manifestGeneratorPlugin.manifestData;
109
+ const hashedPath = manifest["serverFunctionProxy.js"] || "serverFunctionProxy.js";
110
+
111
+ for (const filename of targetAssetFiles) {
112
+ if (filename.endsWith(".js") && assets[filename]) {
113
+ let code = assets[filename].source();
114
+ if (typeof code !== "string") {
115
+ code = code.toString("utf8");
116
+ }
117
+ if (code.includes("__SERVER_FUNCTION_PROXY__")) {
118
+ code = code.replace(/__SERVER_FUNCTION_PROXY__/g, hashedPath);
119
+ compilation.updateAsset(
120
+ filename,
121
+ new sources.RawSource(code)
122
+ );
123
+ }
124
+ }
125
+ }
70
126
  }
71
127
  );
72
128
  }
@@ -0,0 +1,66 @@
1
+ // dinou/webpack/plugins/webpack-memory-plugin.js
2
+ // Captures Webpack client assets, chunks, manifests, and sourcemaps in memory (globalThis.__DINOU_MEM_FILES__)
3
+ // and sets global raw manifests in dev mode to prevent massive disk writes.
4
+
5
+ const path = require("path");
6
+
7
+ class WebpackMemoryPlugin {
8
+ constructor(options = {}) {
9
+ this.options = options;
10
+ }
11
+
12
+ apply(compiler) {
13
+ const isDev =
14
+ process.env.NODE_ENV !== "production" ||
15
+ process.env.DINOU_DEV === "true";
16
+
17
+ // Only acts in development mode. In production, Webpack writes to .dinou/dist3 normally.
18
+ if (!isDev) {
19
+ return;
20
+ }
21
+
22
+ const pluginName = "WebpackMemoryPlugin";
23
+
24
+ compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
25
+ compilation.hooks.afterProcessAssets.tap(pluginName, (assets) => {
26
+ if (typeof globalThis !== "undefined") {
27
+ if (!globalThis.__DINOU_MEM_FILES__) {
28
+ globalThis.__DINOU_MEM_FILES__ = new Map();
29
+ }
30
+ }
31
+
32
+ for (const [filename, asset] of Object.entries(assets)) {
33
+ if (!asset) continue;
34
+
35
+ const normKey = filename.replace(/\\/g, "/");
36
+ const cleanKey = normKey.replace(/^\/+/, "");
37
+ const raw = typeof asset.source === "function" ? asset.source() : asset;
38
+ const buf = Buffer.isBuffer(raw) ? raw : Buffer.from(raw || "");
39
+
40
+ if (typeof globalThis !== "undefined" && globalThis.__DINOU_MEM_FILES__) {
41
+ globalThis.__DINOU_MEM_FILES__.set(cleanKey, buf);
42
+ globalThis.__DINOU_MEM_FILES__.set("/" + cleanKey, buf);
43
+ const base = path.basename(cleanKey);
44
+ globalThis.__DINOU_MEM_FILES__.set(base, buf);
45
+ }
46
+
47
+ if (cleanKey === "react-client-manifest.json") {
48
+ try {
49
+ globalThis.__DINOU_RAW_CLIENT_MANIFEST__ = JSON.parse(buf.toString("utf8"));
50
+ } catch (e) {}
51
+ } else if (cleanKey === "server-functions-manifest.json") {
52
+ try {
53
+ globalThis.__DINOU_RAW_SERVER_FUNCTIONS_MANIFEST__ = JSON.parse(buf.toString("utf8"));
54
+ } catch (e) {}
55
+ } else if (cleanKey === "manifest.json") {
56
+ try {
57
+ globalThis.__DINOU_RAW_ASSET_MANIFEST__ = JSON.parse(buf.toString("utf8"));
58
+ } catch (e) {}
59
+ }
60
+ }
61
+ });
62
+ });
63
+ }
64
+ }
65
+
66
+ module.exports = WebpackMemoryPlugin;