dinou 2.4.1 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/cli.js +110 -6
- package/dinou/core/asset-extensions.js +3 -1
- package/dinou/core/client-error-webpack.jsx +36 -0
- package/dinou/core/client-webpack.jsx +23 -0
- package/dinou/core/get-asset-from-manifest.js +7 -0
- package/dinou/core/render-html.js +5 -1
- package/dinou/core/server-function-proxy-webpack.js +23 -0
- package/dinou/core/server.js +7 -10
- package/dinou/esbuild/build.mjs +65 -0
- package/dinou/esbuild/dev.mjs +163 -0
- package/dinou/esbuild/helpers-esbuild/get-config-esbuild-prod.mjs +65 -0
- package/dinou/esbuild/helpers-esbuild/get-config-esbuild.mjs +64 -0
- package/dinou/esbuild/helpers-esbuild/get-esbuild-entries.mjs +366 -0
- package/dinou/esbuild/helpers-esbuild/normalize-path.mjs +5 -0
- package/dinou/esbuild/helpers-esbuild/write.mjs +59 -0
- package/dinou/esbuild/plugins-esbuild/assets-plugin.mjs +241 -0
- package/dinou/esbuild/plugins-esbuild/css-processor-plugin.mjs +82 -0
- package/dinou/esbuild/plugins-esbuild/manifest-generator-plugin.mjs +55 -0
- package/dinou/esbuild/plugins-esbuild/react-client-manifest-plugin.mjs +59 -0
- package/dinou/esbuild/plugins-esbuild/server-functions-plugin.mjs +110 -0
- package/dinou/esbuild/plugins-esbuild/skip-missing-entry-points-plugin.mjs +34 -0
- package/dinou/esbuild/plugins-esbuild/stable-chunk-names-and-maps-plugin.mjs +155 -0
- package/dinou/esbuild/plugins-esbuild/write-metafile-plugin.mjs +16 -0
- package/dinou/esbuild/plugins-esbuild/write-plugin.mjs +10 -0
- package/dinou/esbuild/plugins-postcss/postcss-extract-plugin.js +47 -0
- package/dinou/esbuild/react-refresh/babel-config.js +13 -0
- package/dinou/esbuild/react-refresh/esm-hmr/client.mjs +159 -0
- package/dinou/esbuild/react-refresh/esm-hmr/server.js +134 -0
- package/dinou/esbuild/react-refresh/esm-hmr-plugin.mjs +224 -0
- package/dinou/esbuild/react-refresh/react-refresh-runtime.mjs +31 -0
- package/dinou/rollup/react-refresh/is-react-refresh-boundary.js +25 -0
- package/dinou/rollup/react-refresh/react-refresh-entry.js +3 -0
- package/dinou/{rollup-plugins → rollup/rollup-plugins}/dinou-asset-plugin.js +2 -2
- package/dinou/{rollup-plugins → rollup/rollup-plugins}/rollup-plugin-react-client-manifest.js +3 -3
- package/dinou/{rollup.config.js → rollup/rollup.config.js} +8 -8
- package/dinou/webpack/loaders/server-functions-loader.js +69 -0
- package/dinou/webpack/plugins/manifest-generator-plugin.js +45 -0
- package/dinou/webpack/plugins/server-functions-plugin.js +44 -0
- package/dinou/webpack/postcss.config.js +6 -0
- package/dinou/webpack/webpack.config.js +228 -0
- package/eject.js +27 -8
- package/package.json +21 -3
- /package/dinou/{react-refresh/is-react-refresh-boundary.js → esbuild/react-refresh/is-react-refresh-boundary.mjs} +0 -0
- /package/dinou/{react-refresh → esbuild/react-refresh}/react-refresh-entry.js +0 -0
- /package/dinou/{postcss.config.js → rollup/postcss.config.js} +0 -0
- /package/dinou/{react-refresh → rollup/react-refresh}/esm-hmr/client.js +0 -0
- /package/dinou/{react-refresh → rollup/react-refresh}/esm-hmr/server.js +0 -0
- /package/dinou/{react-refresh → rollup/react-refresh}/react-refresh-runtime.js +0 -0
- /package/dinou/{react-refresh → rollup/react-refresh}/react-refresh-wrap-modules.js +0 -0
- /package/dinou/{react-refresh → rollup/react-refresh}/rollup-plugin-esm-hmr.js +0 -0
- /package/dinou/{rollup-plugins → rollup/rollup-plugins}/manifest-generator-plugin.js +0 -0
- /package/dinou/{rollup-plugins → rollup/rollup-plugins}/rollup-plugin-server-functions.js +0 -0
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.1]
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- esbuild doesn't give error when 'favicons' folder doesn't exist in root directory.
|
|
13
|
+
|
|
14
|
+
## [3.0.0]
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- esbuild integration (the one used by default).
|
|
19
|
+
- rollup integration (optionally used).
|
|
20
|
+
- webpack integration (optionally used).
|
|
21
|
+
|
|
8
22
|
## [2.4.1]
|
|
9
23
|
|
|
10
24
|
### Fixed
|
package/cli.js
CHANGED
|
@@ -26,24 +26,90 @@ program
|
|
|
26
26
|
const startExpress = `node --conditions react-server --import ${
|
|
27
27
|
pathToFileURL(path.join(corePath, "register-loader.mjs")).href
|
|
28
28
|
} ${path.join(corePath, "server.js")}`;
|
|
29
|
-
const startDevServer = `
|
|
29
|
+
const startDevServer = `node ${path.join(dinouPath, "esbuild/dev.mjs")}`;
|
|
30
|
+
runCommand(`npx concurrently "${startExpress}" "${startDevServer}"`);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
program
|
|
34
|
+
.command("build")
|
|
35
|
+
.description("Builds the app for production")
|
|
36
|
+
.action(() => {
|
|
37
|
+
console.log("Building the app...");
|
|
38
|
+
const esbuildPath = path.join(dinouPath, "esbuild/build.mjs");
|
|
39
|
+
runCommand(`cross-env NODE_ENV=production node ${esbuildPath}`);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
program
|
|
43
|
+
.command("start")
|
|
44
|
+
.description("Start the app in production mode")
|
|
45
|
+
.action(() => {
|
|
46
|
+
console.log("Starting the app...");
|
|
47
|
+
runCommand(
|
|
48
|
+
`cross-env NODE_ENV=production node --conditions react-server --import ${
|
|
49
|
+
pathToFileURL(path.join(corePath, "register-loader.mjs")).href
|
|
50
|
+
} ${path.join(corePath, "server.js")}`
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
program
|
|
55
|
+
.command("dev:esbuild")
|
|
56
|
+
.description("Starts")
|
|
57
|
+
.action(() => {
|
|
58
|
+
console.log("Starting...");
|
|
59
|
+
const startExpress = `node --conditions react-server --import ${
|
|
60
|
+
pathToFileURL(path.join(corePath, "register-loader.mjs")).href
|
|
61
|
+
} ${path.join(corePath, "server.js")}`;
|
|
62
|
+
const startDevServer = `node ${path.join(dinouPath, "esbuild/dev.mjs")}`;
|
|
63
|
+
runCommand(`npx concurrently "${startExpress}" "${startDevServer}"`);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
program
|
|
67
|
+
.command("build:esbuild")
|
|
68
|
+
.description("Builds the app for production")
|
|
69
|
+
.action(() => {
|
|
70
|
+
console.log("Building the app...");
|
|
71
|
+
const esbuildPath = path.join(dinouPath, "esbuild/build.mjs");
|
|
72
|
+
runCommand(`cross-env NODE_ENV=production node ${esbuildPath}`);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
program
|
|
76
|
+
.command("start:esbuild")
|
|
77
|
+
.description("Start the app in production mode")
|
|
78
|
+
.action(() => {
|
|
79
|
+
console.log("Starting the app...");
|
|
80
|
+
runCommand(
|
|
81
|
+
`cross-env NODE_ENV=production node --conditions react-server --import ${
|
|
82
|
+
pathToFileURL(path.join(corePath, "register-loader.mjs")).href
|
|
83
|
+
} ${path.join(corePath, "server.js")}`
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
program
|
|
88
|
+
.command("dev:rollup")
|
|
89
|
+
.description("Starts")
|
|
90
|
+
.action(() => {
|
|
91
|
+
console.log("Starting...");
|
|
92
|
+
const startExpress = `node --conditions react-server --import ${
|
|
93
|
+
pathToFileURL(path.join(corePath, "register-loader.mjs")).href
|
|
94
|
+
} ${path.join(corePath, "server.js")}`;
|
|
95
|
+
const startDevServer = `rollup -c ${path.join(
|
|
30
96
|
dinouPath,
|
|
31
|
-
"rollup.config.js"
|
|
97
|
+
"rollup/rollup.config.js"
|
|
32
98
|
)} -w`;
|
|
33
99
|
runCommand(`npx concurrently "${startExpress}" "${startDevServer}"`);
|
|
34
100
|
});
|
|
35
101
|
|
|
36
102
|
program
|
|
37
|
-
.command("build")
|
|
103
|
+
.command("build:rollup")
|
|
38
104
|
.description("Builds the app for production")
|
|
39
105
|
.action(() => {
|
|
40
106
|
console.log("Building the app...");
|
|
41
|
-
const configPath = path.join(dinouPath, "rollup.config.js");
|
|
107
|
+
const configPath = path.join(dinouPath, "rollup/rollup.config.js");
|
|
42
108
|
runCommand(`cross-env NODE_ENV=production npx rollup -c ${configPath}`);
|
|
43
109
|
});
|
|
44
110
|
|
|
45
111
|
program
|
|
46
|
-
.command("start")
|
|
112
|
+
.command("start:rollup")
|
|
47
113
|
.description("Start the app in production mode")
|
|
48
114
|
.action(() => {
|
|
49
115
|
console.log("Starting the app...");
|
|
@@ -54,9 +120,47 @@ program
|
|
|
54
120
|
);
|
|
55
121
|
});
|
|
56
122
|
|
|
123
|
+
program
|
|
124
|
+
.command("dev:webpack")
|
|
125
|
+
.description("Starts")
|
|
126
|
+
.action(() => {
|
|
127
|
+
console.log("Starting...");
|
|
128
|
+
const startExpress = `cross-env DINOU_BUILD_TOOL=webpack node --conditions react-server --import ${
|
|
129
|
+
pathToFileURL(path.join(corePath, "register-loader.mjs")).href
|
|
130
|
+
} ${path.join(corePath, "server.js")}`;
|
|
131
|
+
const startDevServer = `webpack serve --config ${path.join(
|
|
132
|
+
dinouPath,
|
|
133
|
+
"webpack/webpack.config.js"
|
|
134
|
+
)}`;
|
|
135
|
+
runCommand(`npx concurrently "${startExpress}" "${startDevServer}"`);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
program
|
|
139
|
+
.command("build:webpack")
|
|
140
|
+
.description("Builds the app for production")
|
|
141
|
+
.action(() => {
|
|
142
|
+
console.log("Building the app...");
|
|
143
|
+
const configPath = path.join(dinouPath, "webpack/webpack.config.js");
|
|
144
|
+
runCommand(
|
|
145
|
+
`cross-env NODE_ENV=production npx webpack --config ${configPath}`
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
program
|
|
150
|
+
.command("start:webpack")
|
|
151
|
+
.description("Start the app in production mode")
|
|
152
|
+
.action(() => {
|
|
153
|
+
console.log("Starting the app...");
|
|
154
|
+
runCommand(
|
|
155
|
+
`cross-env NODE_ENV=production DINOU_BUILD_TOOL=webpack node --conditions react-server --import ${
|
|
156
|
+
pathToFileURL(path.join(corePath, "register-loader.mjs")).href
|
|
157
|
+
} ${path.join(corePath, "server.js")}`
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
|
|
57
161
|
program
|
|
58
162
|
.command("eject")
|
|
59
|
-
.description("Copy the framework
|
|
163
|
+
.description("Copy the framework to the root of the project")
|
|
60
164
|
.action(() => {
|
|
61
165
|
console.log("Executing eject...");
|
|
62
166
|
require("./eject");
|
|
@@ -22,10 +22,12 @@ const extensions = [
|
|
|
22
22
|
"mjpg",
|
|
23
23
|
];
|
|
24
24
|
|
|
25
|
+
const globPattern = `**/*.{${extensions.join(",")}}`;
|
|
26
|
+
|
|
25
27
|
// 🔹 regex útil para plugins tipo Rollup/PostCSS
|
|
26
28
|
const regex = new RegExp(`\\.(${extensions.join("|")})$`, "i");
|
|
27
29
|
|
|
28
30
|
// 🔹 versión con punto para comparaciones directas
|
|
29
31
|
const extensionsWithDot = extensions.map((ext) => `.${ext}`);
|
|
30
32
|
|
|
31
|
-
module.exports = { extensions, extensionsWithDot, regex };
|
|
33
|
+
module.exports = { extensions, extensionsWithDot, regex, globPattern };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { use } from "react";
|
|
2
|
+
import { createFromFetch } from "react-server-dom-webpack/client";
|
|
3
|
+
import { hydrateRoot } from "react-dom/client";
|
|
4
|
+
|
|
5
|
+
const cache = new Map();
|
|
6
|
+
const route = window.location.href.replace(window.location.origin, "");
|
|
7
|
+
|
|
8
|
+
function Root() {
|
|
9
|
+
let content = cache.get(route);
|
|
10
|
+
if (!content) {
|
|
11
|
+
content = createFromFetch(
|
|
12
|
+
fetch("/____rsc_payload_error____" + route, {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
},
|
|
17
|
+
body: JSON.stringify({
|
|
18
|
+
error: {
|
|
19
|
+
message: window.__DINOU_ERROR_MESSAGE__ || "Unknown error",
|
|
20
|
+
stack: window.__DINOU_ERROR_STACK__ || "No stack trace available",
|
|
21
|
+
},
|
|
22
|
+
}),
|
|
23
|
+
})
|
|
24
|
+
);
|
|
25
|
+
cache.set(route, content);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return use(content);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
hydrateRoot(document, <Root />);
|
|
32
|
+
|
|
33
|
+
// HMR
|
|
34
|
+
if (import.meta.hot) {
|
|
35
|
+
import.meta.hot.accept();
|
|
36
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { use } from "react";
|
|
2
|
+
import { createFromFetch } from "react-server-dom-webpack/client";
|
|
3
|
+
import { hydrateRoot } from "react-dom/client";
|
|
4
|
+
|
|
5
|
+
const cache = new Map();
|
|
6
|
+
const route = window.location.href.replace(window.location.origin, "");
|
|
7
|
+
|
|
8
|
+
function Root() {
|
|
9
|
+
let content = cache.get(route);
|
|
10
|
+
if (!content) {
|
|
11
|
+
content = createFromFetch(fetch("/____rsc_payload____" + route));
|
|
12
|
+
cache.set(route, content);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return use(content);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
hydrateRoot(document, <Root />);
|
|
19
|
+
|
|
20
|
+
// HMR
|
|
21
|
+
if (import.meta.hot) {
|
|
22
|
+
import.meta.hot.accept();
|
|
23
|
+
}
|
|
@@ -3,6 +3,7 @@ const path = require("path");
|
|
|
3
3
|
|
|
4
4
|
let manifest = {};
|
|
5
5
|
let read = false;
|
|
6
|
+
const isWebpack = process.env.DINOU_BUILD_TOOL === "webpack";
|
|
6
7
|
|
|
7
8
|
function getAssetFromManifest(name) {
|
|
8
9
|
if (process.env.NODE_ENV === "production" && !read) {
|
|
@@ -11,6 +12,12 @@ function getAssetFromManifest(name) {
|
|
|
11
12
|
manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
12
13
|
read = true;
|
|
13
14
|
}
|
|
15
|
+
} else if (isWebpack && !read) {
|
|
16
|
+
const manifestPath = path.resolve(process.cwd(), "public/manifest.json");
|
|
17
|
+
if (fs.existsSync(manifestPath)) {
|
|
18
|
+
manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
19
|
+
read = true;
|
|
20
|
+
}
|
|
14
21
|
}
|
|
15
22
|
return "/" + (manifest[name] || name);
|
|
16
23
|
}
|
|
@@ -30,6 +30,7 @@ const getSSGJSX = require("./get-ssg-jsx.js");
|
|
|
30
30
|
const { getErrorJSX } = require("./get-error-jsx");
|
|
31
31
|
const { renderJSXToClientJSX } = require("./render-jsx-to-client-jsx");
|
|
32
32
|
const isDevelopment = process.env.NODE_ENV !== "production";
|
|
33
|
+
const isWebpack = process.env.DINOU_BUILD_TOOL === "webpack";
|
|
33
34
|
|
|
34
35
|
function formatErrorHtml(error) {
|
|
35
36
|
const message = error.message || "Unknown error";
|
|
@@ -175,7 +176,10 @@ async function renderToStream(reqPath, query, cookies = {}) {
|
|
|
175
176
|
stream.pipe(process.stdout);
|
|
176
177
|
},
|
|
177
178
|
bootstrapModules: isDevelopment
|
|
178
|
-
? [
|
|
179
|
+
? [
|
|
180
|
+
getAssetFromManifest("main.js"),
|
|
181
|
+
isWebpack ? undefined : getAssetFromManifest("runtime.js"),
|
|
182
|
+
].filter(Boolean)
|
|
179
183
|
: [getAssetFromManifest("main.js")],
|
|
180
184
|
...(isDevelopment
|
|
181
185
|
? {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// public/server-function-proxy.js
|
|
2
|
+
import { createFromFetch } from "react-server-dom-webpack/client";
|
|
3
|
+
|
|
4
|
+
export function createServerFunctionProxy(id) {
|
|
5
|
+
return new Proxy(() => {}, {
|
|
6
|
+
apply: async (_target, _thisArg, args) => {
|
|
7
|
+
const res = await fetch("/____server_function____", {
|
|
8
|
+
method: "POST",
|
|
9
|
+
headers: { "Content-Type": "application/json" },
|
|
10
|
+
body: JSON.stringify({ id, args }),
|
|
11
|
+
});
|
|
12
|
+
if (!res.ok) throw new Error("Server function failed");
|
|
13
|
+
|
|
14
|
+
const contentType = res.headers.get("content-type") || "";
|
|
15
|
+
|
|
16
|
+
if (contentType.includes("text/x-component")) {
|
|
17
|
+
return createFromFetch(Promise.resolve(res));
|
|
18
|
+
} else {
|
|
19
|
+
return res.json();
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
package/dinou/core/server.js
CHANGED
|
@@ -37,13 +37,13 @@ const generateStatic = require("./generate-static.js");
|
|
|
37
37
|
const renderAppToHtml = require("./render-app-to-html.js");
|
|
38
38
|
const revalidating = require("./revalidating.js");
|
|
39
39
|
const isDevelopment = process.env.NODE_ENV !== "production";
|
|
40
|
-
const
|
|
40
|
+
const outputFolder = isDevelopment ? "public" : "dist3";
|
|
41
41
|
const chokidar = require("chokidar");
|
|
42
42
|
const { fileURLToPath } = require("url");
|
|
43
43
|
if (isDevelopment) {
|
|
44
44
|
const manifestPath = path.resolve(
|
|
45
45
|
process.cwd(),
|
|
46
|
-
`${
|
|
46
|
+
`${outputFolder}/react-client-manifest.json`
|
|
47
47
|
);
|
|
48
48
|
let currentManifest = {};
|
|
49
49
|
|
|
@@ -151,7 +151,7 @@ const app = express();
|
|
|
151
151
|
app.use(appUseCookieParser);
|
|
152
152
|
app.use(express.json());
|
|
153
153
|
|
|
154
|
-
app.use(express.static(path.resolve(process.cwd(),
|
|
154
|
+
app.use(express.static(path.resolve(process.cwd(), outputFolder)));
|
|
155
155
|
|
|
156
156
|
app.get("/.well-known/appspecific/com.chrome.devtools.json", (req, res) => {
|
|
157
157
|
res.setHeader("Content-Type", "application/json");
|
|
@@ -159,7 +159,7 @@ app.get("/.well-known/appspecific/com.chrome.devtools.json", (req, res) => {
|
|
|
159
159
|
name: "Dinou DevTools",
|
|
160
160
|
description: "Dinou DevTools for Chrome",
|
|
161
161
|
version: "1.0.0",
|
|
162
|
-
devtools_page: `/${
|
|
162
|
+
devtools_page: `/${outputFolder}/devtools.html`,
|
|
163
163
|
});
|
|
164
164
|
});
|
|
165
165
|
|
|
@@ -189,7 +189,7 @@ app.get(/^\/____rsc_payload____\/.*\/?$/, async (req, res) => {
|
|
|
189
189
|
);
|
|
190
190
|
const manifest = JSON.parse(
|
|
191
191
|
readFileSync(
|
|
192
|
-
path.resolve(`${
|
|
192
|
+
path.resolve(`${outputFolder}/react-client-manifest.json`),
|
|
193
193
|
"utf8"
|
|
194
194
|
)
|
|
195
195
|
);
|
|
@@ -209,10 +209,7 @@ app.post(/^\/____rsc_payload_error____\/.*\/?$/, async (req, res) => {
|
|
|
209
209
|
).replace("/____rsc_payload_error____", "");
|
|
210
210
|
const jsx = await getErrorJSX(reqPath, { ...req.query }, req.body.error);
|
|
211
211
|
const manifest = readFileSync(
|
|
212
|
-
path.resolve(
|
|
213
|
-
process.cwd(),
|
|
214
|
-
`${webpackFolder}/react-client-manifest.json`
|
|
215
|
-
),
|
|
212
|
+
path.resolve(process.cwd(), `${outputFolder}/react-client-manifest.json`),
|
|
216
213
|
"utf8"
|
|
217
214
|
);
|
|
218
215
|
const moduleMap = JSON.parse(manifest);
|
|
@@ -285,7 +282,7 @@ app.post("/____server_function____", async (req, res) => {
|
|
|
285
282
|
const manifest = readFileSync(
|
|
286
283
|
path.resolve(
|
|
287
284
|
process.cwd(),
|
|
288
|
-
`${
|
|
285
|
+
`${outputFolder}/react-client-manifest.json`
|
|
289
286
|
),
|
|
290
287
|
"utf8"
|
|
291
288
|
);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import esbuild from "esbuild";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import getConfigEsbuildProd from "./helpers-esbuild/get-config-esbuild-prod.mjs";
|
|
4
|
+
import getEsbuildEntries from "./helpers-esbuild/get-esbuild-entries.mjs";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
|
|
11
|
+
const outdir = "dist3";
|
|
12
|
+
await fs.rm(outdir, { recursive: true, force: true });
|
|
13
|
+
|
|
14
|
+
const frameworkEntryPoints = {
|
|
15
|
+
main: path.resolve(__dirname, "../core/client.jsx"),
|
|
16
|
+
error: path.resolve(__dirname, "../core/client-error.jsx"),
|
|
17
|
+
serverFunctionProxy: path.resolve(
|
|
18
|
+
__dirname,
|
|
19
|
+
"../core/server-function-proxy.js"
|
|
20
|
+
),
|
|
21
|
+
runtime: path.resolve(__dirname, "react-refresh/react-refresh-runtime.mjs"),
|
|
22
|
+
"react-refresh-entry": path.resolve(
|
|
23
|
+
__dirname,
|
|
24
|
+
"react-refresh/react-refresh-entry.js"
|
|
25
|
+
),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const manifest = {};
|
|
30
|
+
|
|
31
|
+
const [esbuildEntries, detectedCSSEntries, detectedAssetEntries] =
|
|
32
|
+
await getEsbuildEntries({ manifest });
|
|
33
|
+
|
|
34
|
+
const componentEntryPoints = [...esbuildEntries].reduce(
|
|
35
|
+
(acc, dCE) => ({ ...acc, [dCE.outfileName]: dCE.absPath }),
|
|
36
|
+
{}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const cssEntryPoints = [...detectedCSSEntries].reduce(
|
|
40
|
+
(acc, dCSSE) => ({ ...acc, [dCSSE.outfileName]: dCSSE.absPath }),
|
|
41
|
+
{}
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const assetEntryPoints = [...detectedAssetEntries].reduce(
|
|
45
|
+
(acc, dAE) => ({ ...acc, [dAE.outfileName]: dAE.absPath }),
|
|
46
|
+
{}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const entryPoints = {
|
|
50
|
+
...frameworkEntryPoints,
|
|
51
|
+
...componentEntryPoints,
|
|
52
|
+
...cssEntryPoints,
|
|
53
|
+
...assetEntryPoints,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
await esbuild.build(
|
|
57
|
+
getConfigEsbuildProd({
|
|
58
|
+
entryPoints,
|
|
59
|
+
manifest,
|
|
60
|
+
outdir,
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
} catch (err) {
|
|
64
|
+
console.error("Error in build:", err);
|
|
65
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import esbuild from "esbuild";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import getConfigEsbuild from "./helpers-esbuild/get-config-esbuild.mjs";
|
|
4
|
+
import getEsbuildEntries from "./helpers-esbuild/get-esbuild-entries.mjs";
|
|
5
|
+
import chokidar from "chokidar";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { regex as assetRegex } from "../core/asset-extensions.js";
|
|
8
|
+
import normalizePath from "./helpers-esbuild/normalize-path.mjs";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
|
|
14
|
+
const outdir = "public";
|
|
15
|
+
await fs.rm(outdir, { recursive: true, force: true });
|
|
16
|
+
|
|
17
|
+
let currentCtx = null; // Track the active esbuild context
|
|
18
|
+
let debounceTimer = null; // For debouncing recreations
|
|
19
|
+
let clientComponentsPaths = [];
|
|
20
|
+
|
|
21
|
+
const frameworkEntryPoints = {
|
|
22
|
+
main: path.resolve(__dirname, "../core/client.jsx"),
|
|
23
|
+
error: path.resolve(__dirname, "../core/client-error.jsx"),
|
|
24
|
+
serverFunctionProxy: path.resolve(
|
|
25
|
+
__dirname,
|
|
26
|
+
"../core/server-function-proxy.js"
|
|
27
|
+
),
|
|
28
|
+
runtime: path.resolve(__dirname, "react-refresh/react-refresh-runtime.mjs"),
|
|
29
|
+
"react-refresh-entry": path.resolve(
|
|
30
|
+
__dirname,
|
|
31
|
+
"react-refresh/react-refresh-entry.js"
|
|
32
|
+
),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const changedIds = new Set();
|
|
36
|
+
const hmrEngine = { value: null };
|
|
37
|
+
|
|
38
|
+
const watcher = chokidar.watch("src", {
|
|
39
|
+
ignoreInitial: true,
|
|
40
|
+
ignored: /node_modules|dist/,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const codeCssRegex = /.(js|jsx|ts|tsx|css|scss|less)$/i;
|
|
44
|
+
|
|
45
|
+
// Function to (re)create esbuild context with current entries
|
|
46
|
+
async function createEsbuildContext() {
|
|
47
|
+
try {
|
|
48
|
+
if (currentCtx) {
|
|
49
|
+
await currentCtx.dispose(); // Clean up old context
|
|
50
|
+
console.log("Disposed old esbuild context");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
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
|
+
|
|
83
|
+
currentCtx = await esbuild.context(
|
|
84
|
+
getConfigEsbuild({
|
|
85
|
+
entryPoints,
|
|
86
|
+
manifest,
|
|
87
|
+
changedIds,
|
|
88
|
+
hmrEngine,
|
|
89
|
+
})
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
await currentCtx.watch();
|
|
93
|
+
// console.log("✓ Watching (changes will trigger rebuild)");
|
|
94
|
+
} catch (err) {
|
|
95
|
+
console.error("Error recreating context:", err);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Initial setup on ready
|
|
100
|
+
watcher.on("ready", async () => {
|
|
101
|
+
await createEsbuildContext();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const debounceRecreate = () => {
|
|
105
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
106
|
+
debounceTimer = setTimeout(async () => {
|
|
107
|
+
await createEsbuildContext();
|
|
108
|
+
}, 300); // 300ms debounce — adjust as needed
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const debounceRecreateAndReload = () => {
|
|
112
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
113
|
+
debounceTimer = setTimeout(async () => {
|
|
114
|
+
await createEsbuildContext();
|
|
115
|
+
hmrEngine.value.broadcastMessage({ type: "reload" });
|
|
116
|
+
}, 300);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
watcher.on("add", (file) => {
|
|
120
|
+
const ext = path.extname(file);
|
|
121
|
+
if (codeCssRegex.test(ext) || assetRegex.test(ext)) {
|
|
122
|
+
// console.log(`New relevant file detected: ${file}. Recreating context...`);
|
|
123
|
+
debounceRecreateAndReload(file);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
watcher.on("unlink", async (file) => {
|
|
128
|
+
const ext = path.extname(file);
|
|
129
|
+
if (codeCssRegex.test(ext) || assetRegex.test(ext)) {
|
|
130
|
+
// console.log(`File deleted: ${file}. Recreating context...`);
|
|
131
|
+
if (currentCtx) {
|
|
132
|
+
await currentCtx.dispose();
|
|
133
|
+
currentCtx = null;
|
|
134
|
+
}
|
|
135
|
+
debounceRecreate(file);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
watcher.on("addDir", (dir) => {
|
|
140
|
+
// console.log(`New directory: ${dir}. Recreating context...`);
|
|
141
|
+
debounceRecreateAndReload(dir);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
watcher.on("unlinkDir", async (dir) => {
|
|
145
|
+
// console.log(`Directory deleted: ${dir}. Recreating context...`);
|
|
146
|
+
if (currentCtx) {
|
|
147
|
+
await currentCtx.dispose();
|
|
148
|
+
currentCtx = null;
|
|
149
|
+
}
|
|
150
|
+
debounceRecreate(dir);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
watcher.on("change", (file) => {
|
|
154
|
+
const resolvedFile = normalizePath(path.resolve(file));
|
|
155
|
+
// Check if changed file is a client component
|
|
156
|
+
const isClientModule = clientComponentsPaths.includes(resolvedFile);
|
|
157
|
+
if (isClientModule) {
|
|
158
|
+
changedIds.add(resolvedFile);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// Server module, css module, or other file changed
|
|
162
|
+
debounceRecreateAndReload();
|
|
163
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { TsconfigPathsPlugin } from "@esbuild-plugins/tsconfig-paths";
|
|
2
|
+
import reactClientManifestPlugin from "../plugins-esbuild/react-client-manifest-plugin.mjs";
|
|
3
|
+
import serverFunctionsPlugin from "../plugins-esbuild/server-functions-plugin.mjs";
|
|
4
|
+
import cssProcessorPlugin from "../plugins-esbuild/css-processor-plugin.mjs";
|
|
5
|
+
import assetsPlugin from "../plugins-esbuild/assets-plugin.mjs";
|
|
6
|
+
import copyStaticFiles from "esbuild-copy-static-files";
|
|
7
|
+
import manifestGeneratorPlugin from "../plugins-esbuild/manifest-generator-plugin.mjs";
|
|
8
|
+
import writePlugin from "../plugins-esbuild/write-plugin.mjs";
|
|
9
|
+
import { existsSync } from "node:fs";
|
|
10
|
+
|
|
11
|
+
const manifestData = {};
|
|
12
|
+
|
|
13
|
+
export default function getConfigEsbuildProd({
|
|
14
|
+
entryPoints,
|
|
15
|
+
outdir = "dist3",
|
|
16
|
+
manifest = {},
|
|
17
|
+
}) {
|
|
18
|
+
let plugins = [
|
|
19
|
+
TsconfigPathsPlugin({}),
|
|
20
|
+
cssProcessorPlugin({ outdir }),
|
|
21
|
+
reactClientManifestPlugin({
|
|
22
|
+
manifest,
|
|
23
|
+
manifestPath: `${outdir}/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
|
+
|
|
41
|
+
return {
|
|
42
|
+
entryPoints,
|
|
43
|
+
outdir,
|
|
44
|
+
format: "esm",
|
|
45
|
+
bundle: true,
|
|
46
|
+
splitting: true,
|
|
47
|
+
sourcemap: false,
|
|
48
|
+
chunkNames: "[name]-[hash]",
|
|
49
|
+
entryNames: "[name]-[hash]",
|
|
50
|
+
jsx: "automatic",
|
|
51
|
+
target: "es2022",
|
|
52
|
+
write: false,
|
|
53
|
+
conditions: ["style"],
|
|
54
|
+
metafile: true,
|
|
55
|
+
logLevel: "warning",
|
|
56
|
+
minify: true,
|
|
57
|
+
external: [
|
|
58
|
+
"/__SERVER_FUNCTION_PROXY__",
|
|
59
|
+
"/serverFunctionProxy.js",
|
|
60
|
+
"/__hmr_client__.js",
|
|
61
|
+
"/react-refresh-entry.js",
|
|
62
|
+
],
|
|
63
|
+
plugins,
|
|
64
|
+
};
|
|
65
|
+
}
|