dinou 1.10.1 → 2.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +7 -7
  3. package/cli.js +5 -7
  4. package/dinou/client-error.jsx +1 -1
  5. package/dinou/client.jsx +1 -1
  6. package/dinou/render-html.js +8 -1
  7. package/dinou/server.js +126 -1
  8. package/eject.js +16 -6
  9. package/package.json +18 -14
  10. package/packages/vendor/react-server-dom-esm/LICENSE +21 -0
  11. package/packages/vendor/react-server-dom-esm/README.md +5 -0
  12. package/packages/vendor/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +4477 -0
  13. package/packages/vendor/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js +1783 -0
  14. package/packages/vendor/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +4544 -0
  15. package/packages/vendor/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js +2016 -0
  16. package/packages/vendor/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js +5672 -0
  17. package/packages/vendor/react-server-dom-esm/cjs/react-server-dom-esm-server.node.production.js +2907 -0
  18. package/packages/vendor/react-server-dom-esm/client.browser.js +7 -0
  19. package/packages/vendor/react-server-dom-esm/client.js +3 -0
  20. package/packages/vendor/react-server-dom-esm/client.node.js +7 -0
  21. package/packages/vendor/react-server-dom-esm/esm/package.json +3 -0
  22. package/packages/vendor/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +5586 -0
  23. package/packages/vendor/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js +2620 -0
  24. package/packages/vendor/react-server-dom-esm/esm/react-server-dom-esm-node-loader.production.js +515 -0
  25. package/packages/vendor/react-server-dom-esm/index.js +12 -0
  26. package/packages/vendor/react-server-dom-esm/package.json +63 -0
  27. package/packages/vendor/react-server-dom-esm/server.js +6 -0
  28. package/packages/vendor/react-server-dom-esm/server.node.js +17 -0
  29. package/packages/vendor/react-server-dom-esm/static.js +6 -0
  30. package/packages/vendor/react-server-dom-esm/static.node.js +12 -0
  31. package/react-refresh/esm-hmr/client.js +161 -0
  32. package/react-refresh/esm-hmr/server.js +130 -0
  33. package/react-refresh/is-react-refresh-boundary.js +25 -0
  34. package/react-refresh/react-refresh-entry.js +3 -0
  35. package/react-refresh/react-refresh-runtime.js +28 -0
  36. package/react-refresh/react-refresh-wrap-modules.js +48 -0
  37. package/react-refresh/rollup-plugin-esm-hmr.js +117 -0
  38. package/rollup-plugins/dinou-asset-plugin.js +32 -0
  39. package/rollup-plugins/rollup-plugin-react-client-manifest.js +159 -0
  40. package/rollup.config.js +121 -0
  41. package/webpack.config.js +0 -182
package/CHANGELOG.md CHANGED
@@ -5,6 +5,12 @@ 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
+ ## [2.0.0]
9
+
10
+ ### Changed
11
+
12
+ - Migrated build system from Webpack to Rollup for both development and production.
13
+
8
14
  ## [1.10.1]
9
15
 
10
16
  ### Fixed
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # **dinou**: **A Minimal React 19 Framework**
2
2
 
3
- [**dinou**](https://github.com/roggc/dinou) is a **minimal React 19 framework**. dinou means 19 in Catalan. You can create a dinou [app](https://github.com/roggc/dinou-app) by running the command **`npx create-dinou@latest my-app`**.
3
+ [**dinou**](https://dinou.dev) is a **minimal React 19 framework**. dinou means 19 in Catalan. You can create a dinou [app](https://github.com/roggc/dinou-app) by running the command **`npx create-dinou@latest my-app`**.
4
4
 
5
5
  Or you can create one by yourself with the following steps:
6
6
 
@@ -974,7 +974,7 @@ MY_VAR=my_value
974
974
 
975
975
  ## Styles (Tailwind.css, .module.css, and .css)
976
976
 
977
- dinou is ready to use Tailwind.css, `.module.css`, and `.css` styles. All styles will be generated in a file in webpack folder named `styles.css`. So you must include this in your `page.tsx` or `layout.tsx` file, in the `head` tag:
977
+ dinou is ready to use Tailwind.css, `.module.css`, and `.css` styles. All styles will be generated in a file in `public` folder named `styles.css`. So you must include this in your `page.tsx` or `layout.tsx` file, in the `head` tag:
978
978
 
979
979
  ```typescript
980
980
  <link href="/styles.css" rel="stylesheet"></link>
@@ -1060,7 +1060,7 @@ dinou is ready to use Tailwind.css, `.module.css`, and `.css` styles. All styles
1060
1060
 
1061
1061
  - The above will produce the text `hi world!` in red, underlined, and with a purple background color.
1062
1062
 
1063
- - **Only styles imported under `"use client"` directive will be detected by Webpack and generated in a `styles.css` in webpack folder**. This means that if you want to use server components instead of client components, then you must create an additional file (e.g. `styles.ts`) where you use the `"use client"` directive and import all the `.css` files used in server components.
1063
+ - **Only styles imported under `"use client"` directive will be detected by dinou and generated in a `styles.css` in `public` folder**. This means that if you want to use server components instead of client components, then you must create an additional file (e.g. `styles.ts`) where you use the `"use client"` directive and import all the `.css` files used in server components.
1064
1064
 
1065
1065
  - Example with server components:
1066
1066
 
@@ -1159,7 +1159,7 @@ export default function Component() {
1159
1159
  }
1160
1160
  ```
1161
1161
 
1162
- **Only assets imported under `"use client"` directive will be detected by Webpack and generated in webpack folder**. If you use **server components**, then you must create an additional file (e.g. `assets.ts`) with the `"use client"` directive and import there the assets too:
1162
+ **Only assets imported under `"use client"` directive will be detected by dinou and generated in `public` folder**. If you use **server components**, then you must create an additional file (e.g. `assets.ts`) with the `"use client"` directive and import there the assets too:
1163
1163
 
1164
1164
  ```typescript
1165
1165
  // src/assets.ts
@@ -1199,7 +1199,7 @@ declare module "*.png" {
1199
1199
  // and continue with the rest of supported file extensions
1200
1200
  ```
1201
1201
 
1202
- If you miss a certain file extension you can eject and customize dinou to meet your requirements. Just eject and add the extension in these three places: `webpack.config.js`, `dinou/server.js`, and `dinou/render-html.js`. Just look for the place were all the extensions are mentioned and add yours in these three files.
1202
+ If you miss a certain file extension you can eject and customize dinou to meet your requirements. Just eject and add the extension in these three places: `rollup.config.js`, `dinou/server.js`, and `dinou/render-html.js`. Just look for the place were all the extensions are mentioned and add yours in these three files.
1203
1203
 
1204
1204
  ## Import alias (e.g. `"@/..."`)
1205
1205
 
@@ -1235,9 +1235,9 @@ dinou is ready to support import alias, as `import some from "@/..."`. If you wa
1235
1235
 
1236
1236
  ## How to run a dinou app
1237
1237
 
1238
- Run `npm run dev` (or `npx dinou dev`) to start the dinou app in development mode. Wait for the logs of Webpack and `Listening on port <port>` to load the page on your browser. In development, webpack will emit his files in `____public____` folder.
1238
+ Run `npm run dev` (or `npx dinou dev`) to start the dinou app in development mode. Wait for the logs of the bundler (`waiting for changes...`) and the server (`Listening on port <port>`) to load the page on your browser. In development, the bundler will emit its files in `public` folder.
1239
1239
 
1240
- Run `npm run build` (or `npx dinou build`) to build the app and `npm start` (or `npx dinou start`) to run it. In production, webpack will emit his files in `dist3` folder.
1240
+ Run `npm run build` (or `npx dinou build`) to build the app and `npm start` (or `npx dinou start`) to run it. In production, the bundler will emit its files in `dist3` folder.
1241
1241
 
1242
1242
  ## Eject dinou
1243
1243
 
package/cli.js CHANGED
@@ -25,10 +25,10 @@ program
25
25
  dinouPath,
26
26
  "server.js"
27
27
  )}`;
28
- const startDevServer = `webpack serve --config ${path.join(
28
+ const startDevServer = `cross-env NODE_ENV=development rollup -c ${path.join(
29
29
  __dirname,
30
- "webpack.config.js"
31
- )}`;
30
+ "rollup.config.js"
31
+ )} -w`;
32
32
  runCommand(`npx concurrently "${startExpress}" "${startDevServer}"`);
33
33
  });
34
34
 
@@ -37,10 +37,8 @@ program
37
37
  .description("Builds the app for production")
38
38
  .action(() => {
39
39
  console.log("Building the app...");
40
- const configPath = path.join(__dirname, "webpack.config.js");
41
- runCommand(
42
- `cross-env NODE_ENV=production npx webpack --config ${configPath}`
43
- );
40
+ const configPath = path.join(__dirname, "rollup.config.js");
41
+ runCommand(`cross-env NODE_ENV=production npx rollup -c ${configPath}`);
44
42
  });
45
43
 
46
44
  program
@@ -1,5 +1,5 @@
1
1
  import { use } from "react";
2
- import { createFromFetch } from "react-server-dom-webpack/client";
2
+ import { createFromFetch } from "@matthamlin/react-server-dom-esm/client";
3
3
  import { hydrateRoot } from "react-dom/client";
4
4
 
5
5
  const cache = new Map();
package/dinou/client.jsx CHANGED
@@ -1,5 +1,5 @@
1
1
  import { use } from "react";
2
- import { createFromFetch } from "react-server-dom-webpack/client";
2
+ import { createFromFetch } from "@matthamlin/react-server-dom-esm/client";
3
3
  import { hydrateRoot } from "react-dom/client";
4
4
 
5
5
  const cache = new Map();
@@ -195,7 +195,14 @@ async function renderToStream(reqPath, query) {
195
195
  onShellReady() {
196
196
  stream.pipe(process.stdout);
197
197
  },
198
- bootstrapScripts: ["/main.js"],
198
+ bootstrapModules: isDevelopment
199
+ ? ["/main.js", "/runtime.js"]
200
+ : ["/main.js"],
201
+ ...(isDevelopment
202
+ ? {
203
+ bootstrapScriptContent: `window.HMR_WEBSOCKET_URL="ws://localhost:3001";`,
204
+ }
205
+ : {}),
199
206
  });
200
207
  } catch (error) {
201
208
  process.stdout.write(formatErrorHtml(error));
package/dinou/server.js CHANGED
@@ -57,7 +57,132 @@ const generateStatic = require("./generate-static.js");
57
57
  const renderAppToHtml = require("./render-app-to-html.js");
58
58
  const revalidating = require("./revalidating.js");
59
59
  const isDevelopment = process.env.NODE_ENV !== "production";
60
- const webpackFolder = isDevelopment ? "____public____" : "dist3";
60
+ const webpackFolder = isDevelopment ? "public" : "dist3";
61
+ const chokidar = require("chokidar");
62
+ const { fileURLToPath } = require("url");
63
+ if (isDevelopment) {
64
+ const manifestPath = path.resolve(
65
+ process.cwd(),
66
+ `${webpackFolder}/react-client-manifest.json`
67
+ );
68
+ let currentManifest = {};
69
+
70
+ const watcher = chokidar.watch(manifestPath, { persistent: true });
71
+ let isInitial = true;
72
+
73
+ watcher.on("add", () => {
74
+ if (Object.keys(currentManifest).length === 0 && isInitial) {
75
+ // console.log("Initial manifest loaded.");
76
+ currentManifest = JSON.parse(readFileSync(manifestPath, "utf8"));
77
+ isInitial = false;
78
+ return;
79
+ }
80
+ });
81
+
82
+ function getParents(resolvedPath) {
83
+ const parents = [];
84
+ Object.values(require.cache).forEach((mod) => {
85
+ if (
86
+ mod.children &&
87
+ mod.children.some((child) => child.id === resolvedPath)
88
+ ) {
89
+ parents.push(mod.id);
90
+ }
91
+ });
92
+ return parents;
93
+ }
94
+
95
+ function clearRequireCache(modulePath, visited = new Set()) {
96
+ try {
97
+ const resolved = require.resolve(modulePath);
98
+ if (visited.has(resolved)) return;
99
+ visited.add(resolved);
100
+
101
+ if (require.cache[resolved]) {
102
+ delete require.cache[resolved];
103
+ // console.log(`[Server HMR] Cleared cache for ${resolved}`);
104
+
105
+ const parents = getParents(resolved);
106
+ for (const parent of parents) {
107
+ // Optional: Skip if parent not in src/ (safety)
108
+ if (parent.startsWith(path.resolve(process.cwd(), "src"))) {
109
+ clearRequireCache(parent, visited);
110
+ }
111
+ }
112
+ }
113
+ } catch (err) {
114
+ console.warn(
115
+ `[Server HMR] Could not resolve or clear ${modulePath}: ${err.message}`
116
+ );
117
+ }
118
+ }
119
+
120
+ // function clearAllUserCache() {
121
+ // const srcDir = path.resolve(process.cwd(), "src");
122
+ // Object.keys(require.cache).forEach((file) => {
123
+ // if (file.startsWith(srcDir)) {
124
+ // delete require.cache[file];
125
+ // }
126
+ // });
127
+ // console.log(
128
+ // "[Server HMR] Cleared all src/ require caches due to directive change."
129
+ // );
130
+ // }
131
+
132
+ watcher.on("change", () => {
133
+ try {
134
+ const newManifest = JSON.parse(readFileSync(manifestPath, "utf8"));
135
+
136
+ // Handle removed entries: client -> server switch
137
+ for (const key in currentManifest) {
138
+ if (!(key in newManifest)) {
139
+ const absPath = fileURLToPath(key);
140
+ clearRequireCache(absPath);
141
+ // console.log(`Cleared cache for ${absPath} (client -> server)`);
142
+ }
143
+ }
144
+
145
+ // Handle added entries: server -> client switch
146
+ for (const key in newManifest) {
147
+ if (!(key in currentManifest)) {
148
+ const absPath = fileURLToPath(key);
149
+ clearRequireCache(absPath);
150
+ // console.log(`Cleared cache for ${absPath} (server -> client)`);
151
+ }
152
+ }
153
+ // if (
154
+ // Object.keys(currentManifest).length !== Object.keys(newManifest).length
155
+ // ) {
156
+ // // Only clear if there was a change (add/remove)
157
+ // clearAllUserCache();
158
+ // }
159
+ currentManifest = newManifest;
160
+ } catch (err) {
161
+ console.error("Error handling manifest change:", err);
162
+ }
163
+ });
164
+
165
+ const srcWatcher = chokidar.watch(path.resolve(process.cwd(), "src"), {
166
+ persistent: true,
167
+ ignored: /node_modules/,
168
+ });
169
+
170
+ srcWatcher.on("change", (changedPath) => {
171
+ const posixPath = changedPath.split(path.sep).join(path.posix.sep);
172
+
173
+ const isClientComponent = Object.keys(currentManifest).some((key) =>
174
+ key.includes(posixPath)
175
+ );
176
+
177
+ if (!isClientComponent) {
178
+ clearRequireCache(changedPath);
179
+ // console.log(
180
+ // `[Server HMR] Cleared cache for ${changedPath} in srcWatcher`
181
+ // );
182
+ }
183
+ });
184
+ }
185
+
61
186
  const app = express();
62
187
 
63
188
  app.use(express.json());
package/eject.js CHANGED
@@ -2,6 +2,8 @@ const fs = require("fs");
2
2
  const path = require("path");
3
3
 
4
4
  const dinouPath = path.resolve(__dirname, "dinou");
5
+ const reactRefreshPath = path.resolve(__dirname, "react-refresh");
6
+ const rollupPluginsPath = path.resolve(__dirname, "rollup-plugins");
5
7
  const modulePath = path.resolve(__dirname);
6
8
  const projectRoot = process.cwd();
7
9
 
@@ -9,10 +11,18 @@ fs.cpSync(dinouPath, path.join(projectRoot, "dinou"), {
9
11
  recursive: true,
10
12
  });
11
13
 
12
- if (fs.existsSync(path.join(modulePath, "webpack.config.js"))) {
14
+ fs.cpSync(reactRefreshPath, path.join(projectRoot, "react-refresh"), {
15
+ recursive: true,
16
+ });
17
+
18
+ fs.cpSync(rollupPluginsPath, path.join(projectRoot, "rollup-plugins"), {
19
+ recursive: true,
20
+ });
21
+
22
+ if (fs.existsSync(path.join(modulePath, "rollup.config.js"))) {
13
23
  fs.copyFileSync(
14
- path.join(modulePath, "webpack.config.js"),
15
- path.join(projectRoot, "webpack.config.js")
24
+ path.join(modulePath, "rollup.config.js"),
25
+ path.join(projectRoot, "rollup.config.js")
16
26
  );
17
27
  }
18
28
 
@@ -25,10 +35,10 @@ if (fs.existsSync(path.join(modulePath, "postcss.config.js"))) {
25
35
 
26
36
  const pkg = require(path.join(projectRoot, "package.json"));
27
37
  pkg.scripts["start:express"] = "node --conditions react-server dinou/server.js";
28
- pkg.scripts["start:dev-server"] = "webpack serve --config webpack.config.js";
38
+ pkg.scripts["start:dev-server"] = "cross-env NODE_ENV=development rollup -c -w";
29
39
  pkg.scripts.dev =
30
40
  'concurrently "npm run start:express" "npm run start:dev-server"';
31
- pkg.scripts.build = "cross-env NODE_ENV=production webpack";
41
+ pkg.scripts.build = "cross-env NODE_ENV=production rollup -c";
32
42
  pkg.scripts.start =
33
43
  "cross-env NODE_ENV=production node --conditions react-server dinou/server.js";
34
44
  delete pkg.scripts.eject;
@@ -38,5 +48,5 @@ fs.writeFileSync(
38
48
  );
39
49
 
40
50
  console.log(
41
- "Eject completed. Now you can customize the files in /dinou and webpack.config.js."
51
+ "Eject completed. Now you can customize the files in /dinou and rollup.config.js."
42
52
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dinou",
3
- "version": "1.10.1",
3
+ "version": "2.0.1",
4
4
  "description": "Minimal React 19 Framework",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -21,39 +21,43 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@babel/core": "^7.27.4",
24
+ "@babel/parser": "^7.28.3",
24
25
  "@babel/plugin-syntax-import-meta": "^7.10.4",
25
- "@babel/plugin-transform-modules-commonjs": "^7.27.1",
26
26
  "@babel/preset-react": "^7.27.1",
27
27
  "@babel/preset-typescript": "^7.27.1",
28
28
  "@babel/register": "^7.27.1",
29
- "@pmmmwh/react-refresh-webpack-plugin": "^0.6.1",
29
+ "@babel/traverse": "^7.28.3",
30
+ "@matthamlin/react-server-dom-esm": "file:packages/vendor/react-server-dom-esm",
31
+ "@rollup/plugin-babel": "^6.0.4",
32
+ "@rollup/plugin-commonjs": "^28.0.6",
33
+ "@rollup/plugin-json": "^6.1.0",
34
+ "@rollup/plugin-node-resolve": "^16.0.1",
35
+ "@rollup/plugin-replace": "^6.0.2",
30
36
  "@tailwindcss/postcss": "^4.1.10",
31
37
  "autoprefixer": "^10.4.21",
32
- "babel-loader": "^10.0.0",
38
+ "chokidar": "^4.0.3",
33
39
  "commander": "^14.0.0",
34
40
  "concurrently": "^9.2.0",
35
- "copy-webpack-plugin": "^13.0.0",
36
41
  "cross-env": "^7.0.3",
37
- "css-loader": "^7.1.2",
38
42
  "css-modules-require-hook": "^4.2.3",
39
43
  "dotenv": "^16.5.0",
40
44
  "express": "^5.1.0",
41
45
  "generic-names": "^4.0.0",
42
46
  "loader-utils": "^3.3.1",
43
- "mini-css-extract-plugin": "^2.9.2",
44
47
  "postcss": "^8.5.5",
45
- "postcss-loader": "^8.1.1",
46
48
  "react-refresh": "^0.17.0",
47
49
  "react-server-dom-webpack": "^19.1.0",
50
+ "rollup": "^4.46.2",
51
+ "rollup-plugin-copy": "^3.5.0",
52
+ "rollup-plugin-delete": "^3.0.1",
53
+ "rollup-plugin-postcss": "^4.0.2",
54
+ "rollup-plugin-tsconfig-paths": "^1.5.2",
48
55
  "tailwindcss": "^4.1.10",
49
56
  "tsconfig-paths": "^4.2.0",
50
- "tsconfig-paths-webpack-plugin": "^4.2.0",
51
- "webpack": "^5.99.8",
52
- "webpack-cli": "^6.0.1",
53
- "webpack-dev-server": "^5.2.2"
57
+ "ws": "^8.18.3"
54
58
  },
55
59
  "peerDependencies": {
56
- "react": "^19.1.0",
57
- "react-dom": "^19.1.0"
60
+ "react": ">=19.1.0",
61
+ "react-dom": ">=19.1.0"
58
62
  }
59
63
  }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Meta Platforms, Inc. and affiliates.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ # react-server-dom-esm
2
+
3
+ Experimental React Flight bindings for DOM using ESM.
4
+
5
+ **Use it at your own risk.**