dinou 3.0.0 → 3.0.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.
- package/CHANGELOG.md +14 -0
- package/dinou/core/generate-static-rsc.js +9 -1
- package/dinou/core/generate-static-rscs.js +9 -1
- package/dinou/core/server.js +154 -71
- package/dinou/esbuild/build.mjs +1 -0
- package/dinou/esbuild/dev.mjs +83 -40
- package/dinou/esbuild/helpers-esbuild/get-config-esbuild-prod.mjs +25 -16
- package/dinou/esbuild/helpers-esbuild/get-config-esbuild.mjs +23 -14
- package/dinou/esbuild/helpers-esbuild/get-esbuild-entries.mjs +16 -3
- package/dinou/esbuild/plugins-esbuild/manifest-generator-plugin.mjs +12 -10
- package/dinou/esbuild/plugins-esbuild/react-client-manifest-plugin.mjs +12 -12
- package/dinou/rollup/rollup-plugins/rollup-plugin-react-client-manifest.js +1 -1
- package/dinou/rollup/rollup.config.js +6 -3
- package/dinou/webpack/helpers/get-webpack-entries.js +249 -0
- package/dinou/webpack/webpack.config.js +192 -181
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [3.0.2]
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Fix esbuild development change between server and client components.
|
|
13
|
+
- Fix rollup development change between server and client components.
|
|
14
|
+
- Fix CSS entries for webpack.
|
|
15
|
+
|
|
16
|
+
## [3.0.1]
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- esbuild doesn't give error when 'favicons' folder doesn't exist in root directory.
|
|
21
|
+
|
|
8
22
|
## [3.0.0]
|
|
9
23
|
|
|
10
24
|
### Added
|
|
@@ -5,6 +5,7 @@ const getSSGJSXOrJSX = require("./get-ssg-jsx-or-jsx.js");
|
|
|
5
5
|
const { renderToPipeableStream } = require("react-server-dom-webpack/server");
|
|
6
6
|
|
|
7
7
|
const OUT_DIR = path.resolve("dist2");
|
|
8
|
+
const isWebpack = process.env.DINOU_BUILD_TOOL === "webpack";
|
|
8
9
|
|
|
9
10
|
async function generateStaticRSC(reqPath) {
|
|
10
11
|
const finalReqPath = reqPath.endsWith("/") ? reqPath : reqPath + "/";
|
|
@@ -16,7 +17,14 @@ async function generateStaticRSC(reqPath) {
|
|
|
16
17
|
// console.log("✅ JSX retrieved for:", finalReqPath);
|
|
17
18
|
|
|
18
19
|
const manifest = JSON.parse(
|
|
19
|
-
fs.readFileSync(
|
|
20
|
+
fs.readFileSync(
|
|
21
|
+
path.resolve(
|
|
22
|
+
isWebpack
|
|
23
|
+
? "dist3/react-client-manifest.json"
|
|
24
|
+
: "react_client_manifest/react-client-manifest.json"
|
|
25
|
+
),
|
|
26
|
+
"utf8"
|
|
27
|
+
)
|
|
20
28
|
);
|
|
21
29
|
|
|
22
30
|
fs.mkdirSync(path.dirname(payloadPath), { recursive: true });
|
|
@@ -5,10 +5,18 @@ const getSSGJSXOrJSX = require("./get-ssg-jsx-or-jsx.js");
|
|
|
5
5
|
const { renderToPipeableStream } = require("react-server-dom-webpack/server");
|
|
6
6
|
|
|
7
7
|
const OUT_DIR = path.resolve("dist2");
|
|
8
|
+
const isWebpack = process.env.DINOU_BUILD_TOOL === "webpack";
|
|
8
9
|
|
|
9
10
|
async function generateStaticRSCs(routes) {
|
|
10
11
|
const manifest = JSON.parse(
|
|
11
|
-
fs.readFileSync(
|
|
12
|
+
fs.readFileSync(
|
|
13
|
+
path.resolve(
|
|
14
|
+
isWebpack
|
|
15
|
+
? "dist3/react-client-manifest.json"
|
|
16
|
+
: "react_client_manifest/react-client-manifest.json"
|
|
17
|
+
),
|
|
18
|
+
"utf8"
|
|
19
|
+
)
|
|
12
20
|
);
|
|
13
21
|
|
|
14
22
|
for (const route of routes) {
|
package/dinou/core/server.js
CHANGED
|
@@ -40,68 +40,120 @@ const isDevelopment = process.env.NODE_ENV !== "production";
|
|
|
40
40
|
const outputFolder = isDevelopment ? "public" : "dist3";
|
|
41
41
|
const chokidar = require("chokidar");
|
|
42
42
|
const { fileURLToPath } = require("url");
|
|
43
|
+
const isWebpack = process.env.DINOU_BUILD_TOOL === "webpack";
|
|
43
44
|
if (isDevelopment) {
|
|
44
45
|
const manifestPath = path.resolve(
|
|
45
46
|
process.cwd(),
|
|
46
|
-
|
|
47
|
+
isWebpack
|
|
48
|
+
? `${outputFolder}/react-client-manifest.json`
|
|
49
|
+
: `react_client_manifest/react-client-manifest.json`
|
|
50
|
+
);
|
|
51
|
+
const manifestFolderPath = path.resolve(
|
|
52
|
+
process.cwd(),
|
|
53
|
+
isWebpack ? outputFolder : "react_client_manifest"
|
|
47
54
|
);
|
|
48
|
-
let currentManifest = {};
|
|
49
|
-
|
|
50
|
-
const watcher = chokidar.watch(manifestPath, { persistent: true });
|
|
51
|
-
let isInitial = true;
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
let manifestWatcher = null;
|
|
57
|
+
|
|
58
|
+
function startManifestWatcher() {
|
|
59
|
+
let currentManifest = {};
|
|
60
|
+
let isInitial = true;
|
|
61
|
+
// Si ya existe un watcher viejo, ciérralo primero
|
|
62
|
+
if (manifestWatcher) {
|
|
63
|
+
try {
|
|
64
|
+
manifestWatcher.close();
|
|
65
|
+
} catch (e) {
|
|
66
|
+
console.warn("Failed closing old watcher:", e);
|
|
67
|
+
}
|
|
59
68
|
}
|
|
60
|
-
});
|
|
61
69
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
mod.children.some((child) => child.id === resolvedPath)
|
|
68
|
-
) {
|
|
69
|
-
parents.push(mod.id);
|
|
70
|
-
}
|
|
70
|
+
// console.log("[Watcher] Starting watcher");
|
|
71
|
+
|
|
72
|
+
manifestWatcher = chokidar.watch(manifestFolderPath, {
|
|
73
|
+
persistent: true,
|
|
74
|
+
ignored: /node_modules/,
|
|
71
75
|
});
|
|
72
|
-
return parents;
|
|
73
|
-
}
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (parent.startsWith(path.resolve(process.cwd(), "src"))) {
|
|
89
|
-
clearRequireCache(parent, visited);
|
|
77
|
+
async function loadManifestWithRetry({
|
|
78
|
+
manifestPath,
|
|
79
|
+
maxRetries = 10,
|
|
80
|
+
delayMs = 100,
|
|
81
|
+
} = {}) {
|
|
82
|
+
let attempts = 0;
|
|
83
|
+
while (attempts < maxRetries) {
|
|
84
|
+
try {
|
|
85
|
+
// console.log(`Attempting to load manifest (try ${attempts + 1})...`);
|
|
86
|
+
return JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
87
|
+
} catch (err) {
|
|
88
|
+
if (err.code !== "ENOENT") {
|
|
89
|
+
throw err; // Rethrow if it's not a file not found error
|
|
90
90
|
}
|
|
91
|
+
attempts++;
|
|
92
|
+
if (attempts >= maxRetries) {
|
|
93
|
+
throw err; // Rethrow after max retries
|
|
94
|
+
}
|
|
95
|
+
// Wait for the specified delay before retrying
|
|
96
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
91
97
|
}
|
|
92
98
|
}
|
|
93
|
-
} catch (err) {
|
|
94
|
-
console.warn(
|
|
95
|
-
`[Server HMR] Could not resolve or clear ${modulePath}: ${err.message}`
|
|
96
|
-
);
|
|
97
99
|
}
|
|
98
|
-
}
|
|
99
100
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
function getParents(resolvedPath) {
|
|
102
|
+
const parents = [];
|
|
103
|
+
Object.values(require.cache).forEach((mod) => {
|
|
104
|
+
if (
|
|
105
|
+
mod.children &&
|
|
106
|
+
mod.children.some((child) => child.id === resolvedPath)
|
|
107
|
+
) {
|
|
108
|
+
parents.push(mod.id);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
return parents;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function clearRequireCache(modulePath, visited = new Set()) {
|
|
115
|
+
try {
|
|
116
|
+
const resolved = require.resolve(modulePath);
|
|
117
|
+
if (visited.has(resolved)) return;
|
|
118
|
+
visited.add(resolved);
|
|
119
|
+
|
|
120
|
+
if (require.cache[resolved]) {
|
|
121
|
+
delete require.cache[resolved];
|
|
122
|
+
// console.log(`[Server HMR] Cleared cache for ${resolved}`);
|
|
123
|
+
|
|
124
|
+
const parents = getParents(resolved);
|
|
125
|
+
for (const parent of parents) {
|
|
126
|
+
// Optional: Skip if parent not in src/ (safety)
|
|
127
|
+
if (parent.startsWith(path.resolve(process.cwd(), "src"))) {
|
|
128
|
+
clearRequireCache(parent, visited);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
} catch (err) {
|
|
133
|
+
console.warn(
|
|
134
|
+
`[Server HMR] Could not resolve or clear ${modulePath}: ${err.message}`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let manifestTimeout;
|
|
140
|
+
|
|
141
|
+
function readJSONWithRetry(pathToRead, retries = 4, delay = 10) {
|
|
142
|
+
for (let i = 0; i < retries; i++) {
|
|
143
|
+
try {
|
|
144
|
+
const text = readFileSync(pathToRead, "utf8");
|
|
145
|
+
if (!text.trim()) throw new Error("Empty JSON");
|
|
146
|
+
return JSON.parse(text);
|
|
147
|
+
} catch (err) {
|
|
148
|
+
if (i === retries - 1) throw err;
|
|
149
|
+
// tiny sleep
|
|
150
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, delay);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
103
154
|
|
|
104
|
-
|
|
155
|
+
function handleManifestUpdate(newManifest) {
|
|
156
|
+
// console.log("handle manifest update", newManifest, currentManifest);
|
|
105
157
|
for (const key in currentManifest) {
|
|
106
158
|
if (!(key in newManifest)) {
|
|
107
159
|
const absPath = fileURLToPath(key);
|
|
@@ -120,30 +172,50 @@ if (isDevelopment) {
|
|
|
120
172
|
}
|
|
121
173
|
|
|
122
174
|
currentManifest = newManifest;
|
|
123
|
-
} catch (err) {
|
|
124
|
-
console.error("Error handling manifest change:", err);
|
|
125
175
|
}
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
const srcWatcher = chokidar.watch(path.resolve(process.cwd(), "src"), {
|
|
129
|
-
persistent: true,
|
|
130
|
-
ignored: /node_modules/,
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
srcWatcher.on("change", (changedPath) => {
|
|
134
|
-
const posixPath = changedPath.split(path.sep).join(path.posix.sep);
|
|
135
176
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
177
|
+
async function onManifestChange(chokidarPath, stats, delayMs = 100) {
|
|
178
|
+
if (isWebpack && chokidarPath !== manifestPath) return;
|
|
179
|
+
if (Object.keys(currentManifest).length === 0 && isInitial) {
|
|
180
|
+
try {
|
|
181
|
+
currentManifest = await loadManifestWithRetry({
|
|
182
|
+
manifestPath,
|
|
183
|
+
delayMs,
|
|
184
|
+
});
|
|
185
|
+
// console.log("Loaded initial manifest for HMR.", currentManifest);
|
|
186
|
+
isInitial = false;
|
|
187
|
+
} catch (err) {
|
|
188
|
+
console.error("Failed to load initial manifest after retries:", err);
|
|
189
|
+
}
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
try {
|
|
193
|
+
// console.log("change event");
|
|
194
|
+
clearTimeout(manifestTimeout);
|
|
195
|
+
|
|
196
|
+
manifestTimeout = setTimeout(() => {
|
|
197
|
+
try {
|
|
198
|
+
const newManifest = readJSONWithRetry(manifestPath);
|
|
199
|
+
handleManifestUpdate(newManifest);
|
|
200
|
+
} catch (err) {
|
|
201
|
+
console.error("Manifest not ready:", err.message);
|
|
202
|
+
}
|
|
203
|
+
}, 50);
|
|
204
|
+
} catch (err) {
|
|
205
|
+
console.error("Error handling manifest change:", err);
|
|
206
|
+
}
|
|
145
207
|
}
|
|
146
|
-
|
|
208
|
+
|
|
209
|
+
manifestWatcher.on("add", onManifestChange);
|
|
210
|
+
manifestWatcher.on("unlinkDir", startManifestWatcher);
|
|
211
|
+
manifestWatcher.on("unlink", () => {
|
|
212
|
+
isInitial = true;
|
|
213
|
+
currentManifest = {};
|
|
214
|
+
});
|
|
215
|
+
// manifestWatcher.on("all", (event) => console.log("event", event));
|
|
216
|
+
manifestWatcher.on("change", onManifestChange);
|
|
217
|
+
}
|
|
218
|
+
startManifestWatcher();
|
|
147
219
|
}
|
|
148
220
|
const cookieParser = require("cookie-parser");
|
|
149
221
|
const appUseCookieParser = cookieParser();
|
|
@@ -189,7 +261,11 @@ app.get(/^\/____rsc_payload____\/.*\/?$/, async (req, res) => {
|
|
|
189
261
|
);
|
|
190
262
|
const manifest = JSON.parse(
|
|
191
263
|
readFileSync(
|
|
192
|
-
path.resolve(
|
|
264
|
+
path.resolve(
|
|
265
|
+
isWebpack
|
|
266
|
+
? `${outputFolder}/react-client-manifest.json`
|
|
267
|
+
: `react_client_manifest/react-client-manifest.json`
|
|
268
|
+
),
|
|
193
269
|
"utf8"
|
|
194
270
|
)
|
|
195
271
|
);
|
|
@@ -209,7 +285,12 @@ app.post(/^\/____rsc_payload_error____\/.*\/?$/, async (req, res) => {
|
|
|
209
285
|
).replace("/____rsc_payload_error____", "");
|
|
210
286
|
const jsx = await getErrorJSX(reqPath, { ...req.query }, req.body.error);
|
|
211
287
|
const manifest = readFileSync(
|
|
212
|
-
path.resolve(
|
|
288
|
+
path.resolve(
|
|
289
|
+
process.cwd(),
|
|
290
|
+
isWebpack
|
|
291
|
+
? `${outputFolder}/react-client-manifest.json`
|
|
292
|
+
: `react_client_manifest/react-client-manifest.json`
|
|
293
|
+
),
|
|
213
294
|
"utf8"
|
|
214
295
|
);
|
|
215
296
|
const moduleMap = JSON.parse(manifest);
|
|
@@ -282,7 +363,9 @@ app.post("/____server_function____", async (req, res) => {
|
|
|
282
363
|
const manifest = readFileSync(
|
|
283
364
|
path.resolve(
|
|
284
365
|
process.cwd(),
|
|
285
|
-
|
|
366
|
+
isWebpack
|
|
367
|
+
? `${outputFolder}/react-client-manifest.json`
|
|
368
|
+
: `react_client_manifest/react-client-manifest.json`
|
|
286
369
|
),
|
|
287
370
|
"utf8"
|
|
288
371
|
);
|
package/dinou/esbuild/build.mjs
CHANGED
|
@@ -10,6 +10,7 @@ const __dirname = path.dirname(__filename);
|
|
|
10
10
|
|
|
11
11
|
const outdir = "dist3";
|
|
12
12
|
await fs.rm(outdir, { recursive: true, force: true });
|
|
13
|
+
await fs.rm("react_client_manifest", { recursive: true, force: true });
|
|
13
14
|
|
|
14
15
|
const frameworkEntryPoints = {
|
|
15
16
|
main: path.resolve(__dirname, "../core/client.jsx"),
|
package/dinou/esbuild/dev.mjs
CHANGED
|
@@ -6,17 +6,19 @@ import chokidar from "chokidar";
|
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { regex as assetRegex } from "../core/asset-extensions.js";
|
|
8
8
|
import normalizePath from "./helpers-esbuild/normalize-path.mjs";
|
|
9
|
-
import { fileURLToPath } from "url";
|
|
9
|
+
import { fileURLToPath, pathToFileURL } from "url";
|
|
10
10
|
|
|
11
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
12
12
|
const __dirname = path.dirname(__filename);
|
|
13
13
|
|
|
14
14
|
const outdir = "public";
|
|
15
15
|
await fs.rm(outdir, { recursive: true, force: true });
|
|
16
|
+
await fs.rm("react_client_manifest", { recursive: true, force: true });
|
|
16
17
|
|
|
17
18
|
let currentCtx = null; // Track the active esbuild context
|
|
18
19
|
let debounceTimer = null; // For debouncing recreations
|
|
19
20
|
let clientComponentsPaths = [];
|
|
21
|
+
let currentServerFiles = new Set();
|
|
20
22
|
|
|
21
23
|
const frameworkEntryPoints = {
|
|
22
24
|
main: path.resolve(__dirname, "../core/client.jsx"),
|
|
@@ -42,44 +44,57 @@ const watcher = chokidar.watch("src", {
|
|
|
42
44
|
|
|
43
45
|
const codeCssRegex = /.(js|jsx|ts|tsx|css|scss|less)$/i;
|
|
44
46
|
|
|
47
|
+
let manifest = {};
|
|
48
|
+
let entryPoints = {};
|
|
49
|
+
|
|
50
|
+
async function updateEntriesAndComponents() {
|
|
51
|
+
manifest = {};
|
|
52
|
+
const [
|
|
53
|
+
esbuildEntries,
|
|
54
|
+
detectedCSSEntries,
|
|
55
|
+
detectedAssetEntries,
|
|
56
|
+
serverFiles,
|
|
57
|
+
] = await getEsbuildEntries({ manifest });
|
|
58
|
+
|
|
59
|
+
currentServerFiles = new Set(
|
|
60
|
+
serverFiles.map((f) => normalizePath(path.resolve(f)))
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const componentEntryPoints = [...esbuildEntries].reduce(
|
|
64
|
+
(acc, dCE) => ({ ...acc, [dCE.outfileName]: dCE.absPath }),
|
|
65
|
+
{}
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
clientComponentsPaths = Object.values(componentEntryPoints);
|
|
69
|
+
|
|
70
|
+
const cssEntryPoints = [...detectedCSSEntries].reduce(
|
|
71
|
+
(acc, dCSSE) => ({ ...acc, [dCSSE.outfileName]: dCSSE.absPath }),
|
|
72
|
+
{}
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const assetEntryPoints = [...detectedAssetEntries].reduce(
|
|
76
|
+
(acc, dAE) => ({ ...acc, [dAE.outfileName]: dAE.absPath }),
|
|
77
|
+
{}
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
entryPoints = {
|
|
81
|
+
...frameworkEntryPoints,
|
|
82
|
+
...componentEntryPoints,
|
|
83
|
+
...cssEntryPoints,
|
|
84
|
+
...assetEntryPoints,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
45
88
|
// Function to (re)create esbuild context with current entries
|
|
46
89
|
async function createEsbuildContext() {
|
|
47
90
|
try {
|
|
48
91
|
if (currentCtx) {
|
|
49
92
|
await currentCtx.dispose(); // Clean up old context
|
|
50
|
-
console.log("Disposed old esbuild context");
|
|
93
|
+
// console.log("Disposed old esbuild context");
|
|
51
94
|
}
|
|
52
95
|
|
|
53
96
|
await fs.rm(outdir, { recursive: true, force: true });
|
|
54
|
-
|
|
55
|
-
const manifest = {};
|
|
56
|
-
const [esbuildEntries, detectedCSSEntries, detectedAssetEntries] =
|
|
57
|
-
await getEsbuildEntries({ manifest });
|
|
58
|
-
|
|
59
|
-
const componentEntryPoints = [...esbuildEntries].reduce(
|
|
60
|
-
(acc, dCE) => ({ ...acc, [dCE.outfileName]: dCE.absPath }),
|
|
61
|
-
{}
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
clientComponentsPaths = Object.values(componentEntryPoints);
|
|
65
|
-
|
|
66
|
-
const cssEntryPoints = [...detectedCSSEntries].reduce(
|
|
67
|
-
(acc, dCSSE) => ({ ...acc, [dCSSE.outfileName]: dCSSE.absPath }),
|
|
68
|
-
{}
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
const assetEntryPoints = [...detectedAssetEntries].reduce(
|
|
72
|
-
(acc, dAE) => ({ ...acc, [dAE.outfileName]: dAE.absPath }),
|
|
73
|
-
{}
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
const entryPoints = {
|
|
77
|
-
...frameworkEntryPoints,
|
|
78
|
-
...componentEntryPoints,
|
|
79
|
-
...cssEntryPoints,
|
|
80
|
-
...assetEntryPoints,
|
|
81
|
-
};
|
|
82
|
-
|
|
97
|
+
// console.log("manifest before creating context:", manifest);
|
|
83
98
|
currentCtx = await esbuild.context(
|
|
84
99
|
getConfigEsbuild({
|
|
85
100
|
entryPoints,
|
|
@@ -98,6 +113,7 @@ async function createEsbuildContext() {
|
|
|
98
113
|
|
|
99
114
|
// Initial setup on ready
|
|
100
115
|
watcher.on("ready", async () => {
|
|
116
|
+
await updateEntriesAndComponents();
|
|
101
117
|
await createEsbuildContext();
|
|
102
118
|
});
|
|
103
119
|
|
|
@@ -116,11 +132,12 @@ const debounceRecreateAndReload = () => {
|
|
|
116
132
|
}, 300);
|
|
117
133
|
};
|
|
118
134
|
|
|
119
|
-
watcher.on("add", (file) => {
|
|
135
|
+
watcher.on("add", async (file) => {
|
|
120
136
|
const ext = path.extname(file);
|
|
121
137
|
if (codeCssRegex.test(ext) || assetRegex.test(ext)) {
|
|
122
138
|
// console.log(`New relevant file detected: ${file}. Recreating context...`);
|
|
123
|
-
|
|
139
|
+
await updateEntriesAndComponents();
|
|
140
|
+
debounceRecreateAndReload();
|
|
124
141
|
}
|
|
125
142
|
});
|
|
126
143
|
|
|
@@ -128,33 +145,59 @@ watcher.on("unlink", async (file) => {
|
|
|
128
145
|
const ext = path.extname(file);
|
|
129
146
|
if (codeCssRegex.test(ext) || assetRegex.test(ext)) {
|
|
130
147
|
// console.log(`File deleted: ${file}. Recreating context...`);
|
|
148
|
+
await updateEntriesAndComponents();
|
|
131
149
|
if (currentCtx) {
|
|
132
150
|
await currentCtx.dispose();
|
|
133
151
|
currentCtx = null;
|
|
134
152
|
}
|
|
135
|
-
debounceRecreate(
|
|
153
|
+
debounceRecreate();
|
|
136
154
|
}
|
|
137
155
|
});
|
|
138
156
|
|
|
139
|
-
watcher.on("addDir", (
|
|
157
|
+
watcher.on("addDir", async () => {
|
|
140
158
|
// console.log(`New directory: ${dir}. Recreating context...`);
|
|
141
|
-
|
|
159
|
+
await updateEntriesAndComponents();
|
|
160
|
+
debounceRecreateAndReload();
|
|
142
161
|
});
|
|
143
162
|
|
|
144
|
-
watcher.on("unlinkDir", async (
|
|
163
|
+
watcher.on("unlinkDir", async () => {
|
|
145
164
|
// console.log(`Directory deleted: ${dir}. Recreating context...`);
|
|
165
|
+
await updateEntriesAndComponents();
|
|
146
166
|
if (currentCtx) {
|
|
147
167
|
await currentCtx.dispose();
|
|
148
168
|
currentCtx = null;
|
|
149
169
|
}
|
|
150
|
-
debounceRecreate(
|
|
170
|
+
debounceRecreate();
|
|
151
171
|
});
|
|
152
172
|
|
|
153
|
-
|
|
173
|
+
function existsInManifest(resolvedFile, manifest) {
|
|
174
|
+
const manifestKey = pathToFileURL(resolvedFile).href;
|
|
175
|
+
// console.log("Checking manifest for key:", manifestKey);
|
|
176
|
+
for (const key of Object.keys(manifest)) {
|
|
177
|
+
if (key === manifestKey) {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
watcher.on("change", async (file) => {
|
|
154
185
|
const resolvedFile = normalizePath(path.resolve(file));
|
|
186
|
+
const oldManifest = { ...manifest };
|
|
187
|
+
await updateEntriesAndComponents();
|
|
155
188
|
// Check if changed file is a client component
|
|
156
189
|
const isClientModule = clientComponentsPaths.includes(resolvedFile);
|
|
157
|
-
|
|
190
|
+
const isServerModule = currentServerFiles.has(resolvedFile);
|
|
191
|
+
// console.log(
|
|
192
|
+
// `File changed: ${resolvedFile} | Client Module: ${isClientModule} | Server Module: ${isServerModule}`
|
|
193
|
+
// );
|
|
194
|
+
// console.log("currentServerFiles:", currentServerFiles);
|
|
195
|
+
|
|
196
|
+
if (
|
|
197
|
+
isClientModule &&
|
|
198
|
+
!isServerModule &&
|
|
199
|
+
existsInManifest(resolvedFile, oldManifest)
|
|
200
|
+
) {
|
|
158
201
|
changedIds.add(resolvedFile);
|
|
159
202
|
return;
|
|
160
203
|
}
|
|
@@ -6,6 +6,7 @@ import assetsPlugin from "../plugins-esbuild/assets-plugin.mjs";
|
|
|
6
6
|
import copyStaticFiles from "esbuild-copy-static-files";
|
|
7
7
|
import manifestGeneratorPlugin from "../plugins-esbuild/manifest-generator-plugin.mjs";
|
|
8
8
|
import writePlugin from "../plugins-esbuild/write-plugin.mjs";
|
|
9
|
+
import { existsSync } from "node:fs";
|
|
9
10
|
|
|
10
11
|
const manifestData = {};
|
|
11
12
|
|
|
@@ -14,6 +15,29 @@ export default function getConfigEsbuildProd({
|
|
|
14
15
|
outdir = "dist3",
|
|
15
16
|
manifest = {},
|
|
16
17
|
}) {
|
|
18
|
+
let plugins = [
|
|
19
|
+
TsconfigPathsPlugin({}),
|
|
20
|
+
cssProcessorPlugin({ outdir }),
|
|
21
|
+
reactClientManifestPlugin({
|
|
22
|
+
manifest,
|
|
23
|
+
manifestPath: `react_client_manifest/react-client-manifest.json`,
|
|
24
|
+
}),
|
|
25
|
+
assetsPlugin(),
|
|
26
|
+
manifestGeneratorPlugin(manifestData),
|
|
27
|
+
serverFunctionsPlugin(manifestData),
|
|
28
|
+
writePlugin(),
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
if (existsSync("favicons")) {
|
|
32
|
+
plugins = [
|
|
33
|
+
copyStaticFiles({
|
|
34
|
+
src: "favicons",
|
|
35
|
+
dest: outdir,
|
|
36
|
+
}),
|
|
37
|
+
...plugins,
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
|
|
17
41
|
return {
|
|
18
42
|
entryPoints,
|
|
19
43
|
outdir,
|
|
@@ -36,21 +60,6 @@ export default function getConfigEsbuildProd({
|
|
|
36
60
|
"/__hmr_client__.js",
|
|
37
61
|
"/react-refresh-entry.js",
|
|
38
62
|
],
|
|
39
|
-
plugins
|
|
40
|
-
copyStaticFiles({
|
|
41
|
-
src: "favicons",
|
|
42
|
-
dest: outdir,
|
|
43
|
-
}),
|
|
44
|
-
TsconfigPathsPlugin({}),
|
|
45
|
-
cssProcessorPlugin({ outdir }),
|
|
46
|
-
reactClientManifestPlugin({
|
|
47
|
-
manifest,
|
|
48
|
-
manifestPath: `${outdir}/react-client-manifest.json`,
|
|
49
|
-
}),
|
|
50
|
-
assetsPlugin(),
|
|
51
|
-
manifestGeneratorPlugin(manifestData),
|
|
52
|
-
serverFunctionsPlugin(manifestData),
|
|
53
|
-
writePlugin(),
|
|
54
|
-
],
|
|
63
|
+
plugins,
|
|
55
64
|
};
|
|
56
65
|
}
|
|
@@ -7,6 +7,7 @@ import stableChunkNamesAndMapsPlugin from "../plugins-esbuild/stable-chunk-names
|
|
|
7
7
|
import assetsPlugin from "../plugins-esbuild/assets-plugin.mjs";
|
|
8
8
|
import skipMissingEntryPointsPlugin from "../plugins-esbuild/skip-missing-entry-points-plugin.mjs";
|
|
9
9
|
import copyStaticFiles from "esbuild-copy-static-files";
|
|
10
|
+
import { existsSync } from "node:fs";
|
|
10
11
|
|
|
11
12
|
export default function getConfigEsbuild({
|
|
12
13
|
entryPoints,
|
|
@@ -15,6 +16,27 @@ export default function getConfigEsbuild({
|
|
|
15
16
|
changedIds,
|
|
16
17
|
hmrEngine,
|
|
17
18
|
}) {
|
|
19
|
+
let plugins = [
|
|
20
|
+
skipMissingEntryPointsPlugin(),
|
|
21
|
+
TsconfigPathsPlugin({}),
|
|
22
|
+
cssProcessorPlugin(),
|
|
23
|
+
reactClientManifestPlugin({ manifest }),
|
|
24
|
+
assetsPlugin(),
|
|
25
|
+
stableChunkNamesAndMapsPlugin(),
|
|
26
|
+
serverFunctionsPlugin(),
|
|
27
|
+
esmHmrPlugin({ entryName: "main", changedIds, hmrEngine }),
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
if (existsSync("favicons")) {
|
|
31
|
+
plugins = [
|
|
32
|
+
copyStaticFiles({
|
|
33
|
+
src: "favicons",
|
|
34
|
+
dest: outdir,
|
|
35
|
+
}),
|
|
36
|
+
...plugins,
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
|
|
18
40
|
return {
|
|
19
41
|
entryPoints,
|
|
20
42
|
outdir,
|
|
@@ -37,19 +59,6 @@ export default function getConfigEsbuild({
|
|
|
37
59
|
"/__hmr_client__.js",
|
|
38
60
|
"/react-refresh-entry.js",
|
|
39
61
|
],
|
|
40
|
-
plugins
|
|
41
|
-
copyStaticFiles({
|
|
42
|
-
src: "favicons",
|
|
43
|
-
dest: outdir,
|
|
44
|
-
}),
|
|
45
|
-
skipMissingEntryPointsPlugin(),
|
|
46
|
-
TsconfigPathsPlugin({}),
|
|
47
|
-
cssProcessorPlugin(),
|
|
48
|
-
reactClientManifestPlugin({ manifest }),
|
|
49
|
-
assetsPlugin(),
|
|
50
|
-
stableChunkNamesAndMapsPlugin(),
|
|
51
|
-
serverFunctionsPlugin(),
|
|
52
|
-
esmHmrPlugin({ entryName: "main", changedIds, hmrEngine }),
|
|
53
|
-
],
|
|
62
|
+
plugins,
|
|
54
63
|
};
|
|
55
64
|
}
|