waku 0.18.0 → 0.18.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 (57) hide show
  1. package/README.md +33 -2
  2. package/dist/cjs/cli.js +24 -13
  3. package/dist/cjs/dev.js +2 -2
  4. package/dist/cjs/lib/{builder.js → builder/build.js} +26 -103
  5. package/dist/cjs/lib/builder/output-cloudflare.js +47 -0
  6. package/dist/cjs/lib/builder/output-deno.js +38 -0
  7. package/dist/cjs/lib/builder/output-vercel.js +89 -0
  8. package/dist/cjs/lib/plugins/vite-plugin-rsc-delegate.js +12 -6
  9. package/dist/cjs/lib/plugins/vite-plugin-rsc-hmr.js +41 -17
  10. package/dist/cjs/lib/rsc/handler-dev.js +4 -1
  11. package/dist/cjs/lib/rsc/html-renderer.js +24 -23
  12. package/dist/cjs/lib/rsc/utils.js +4 -2
  13. package/dist/cjs/lib/rsc/worker-api.js +24 -4
  14. package/dist/cjs/lib/rsc/worker-impl.js +14 -9
  15. package/dist/cjs/lib/utils/merge-vite-config.js +25 -0
  16. package/dist/cjs/router/common.js +3 -1
  17. package/dist/cli.js +24 -13
  18. package/dist/dev.d.ts +1 -1
  19. package/dist/dev.js +1 -1
  20. package/dist/lib/builder/build.d.ts +8 -0
  21. package/dist/lib/{builder.js → builder/build.js} +31 -108
  22. package/dist/lib/builder/output-cloudflare.d.ts +2 -0
  23. package/dist/lib/builder/output-cloudflare.js +33 -0
  24. package/dist/lib/builder/output-deno.d.ts +2 -0
  25. package/dist/lib/builder/output-deno.js +24 -0
  26. package/dist/lib/builder/output-vercel.d.ts +2 -0
  27. package/dist/lib/builder/output-vercel.js +75 -0
  28. package/dist/lib/plugins/vite-plugin-rsc-delegate.d.ts +2 -2
  29. package/dist/lib/plugins/vite-plugin-rsc-delegate.js +12 -6
  30. package/dist/lib/plugins/vite-plugin-rsc-hmr.d.ts +2 -1
  31. package/dist/lib/plugins/vite-plugin-rsc-hmr.js +38 -12
  32. package/dist/lib/rsc/handler-dev.js +7 -4
  33. package/dist/lib/rsc/html-renderer.js +24 -23
  34. package/dist/lib/rsc/utils.js +4 -2
  35. package/dist/lib/rsc/worker-api.d.ts +5 -0
  36. package/dist/lib/rsc/worker-api.js +21 -4
  37. package/dist/lib/rsc/worker-impl.js +15 -10
  38. package/dist/lib/utils/merge-vite-config.d.ts +2 -0
  39. package/dist/lib/utils/merge-vite-config.js +16 -0
  40. package/dist/router/common.js +3 -1
  41. package/package.json +8 -8
  42. package/src/cli.ts +32 -10
  43. package/src/dev.ts +1 -1
  44. package/src/lib/{builder.ts → builder/build.ts} +47 -141
  45. package/src/lib/builder/output-cloudflare.ts +54 -0
  46. package/src/lib/builder/output-deno.ts +42 -0
  47. package/src/lib/builder/output-vercel.ts +99 -0
  48. package/src/lib/plugins/vite-plugin-rsc-delegate.ts +18 -9
  49. package/src/lib/plugins/vite-plugin-rsc-hmr.ts +39 -8
  50. package/src/lib/rsc/handler-dev.ts +11 -4
  51. package/src/lib/rsc/html-renderer.ts +31 -28
  52. package/src/lib/rsc/utils.ts +5 -3
  53. package/src/lib/rsc/worker-api.ts +28 -6
  54. package/src/lib/rsc/worker-impl.ts +16 -11
  55. package/src/lib/utils/merge-vite-config.ts +29 -0
  56. package/src/router/common.ts +3 -1
  57. package/dist/lib/builder.d.ts +0 -5
package/README.md CHANGED
@@ -8,9 +8,12 @@
8
8
 
9
9
  <!-- [![size](https://img.shields.io/bundlephobia/minzip/waku)](https://bundlephobia.com/result?p=waku) -->
10
10
 
11
+ Waku means "frame" in Japanese. Waku-Waku means being excited.
12
+ https://github.com/dai-shi/waku/discussions/260
13
+
11
14
  ## Project status
12
15
 
13
- We are working toward v1-alpha: https://github.com/dai-shi/waku/issues/24
16
+ Roadmap: See https://github.com/dai-shi/waku/issues/24 (working towards v1-alpha)
14
17
 
15
18
  Feel free to try it _seriously_ with non-production projects and give us feedback.
16
19
 
@@ -73,7 +76,7 @@ pnpm create waku
73
76
  These commands will create an example app that you can use as a
74
77
  starting point for your project.
75
78
 
76
- Minimum requirement: Node.js 18
79
+ Minimum requirement: Node.js 18.3.0
77
80
 
78
81
  ## Practices
79
82
 
@@ -290,6 +293,34 @@ Alternatively, you could create a project with something like
290
293
  `npm create waku@latest` and copy files from the example
291
294
  folder in the repository.
292
295
 
296
+ ## Deploy
297
+
298
+ ### Vercel
299
+
300
+ ```sh
301
+ vercel
302
+ ```
303
+
304
+ Then change the setting as follows (needs redeploy for the first time):
305
+
306
+ ![vercel](https://github.com/dai-shi/waku/assets/490574/6bd317a8-2772-42f4-92d4-b508af7d7460)
307
+
308
+ ### Cloudflare (experimental)
309
+
310
+ ```sh
311
+ npm run build -- --with-cloudflare
312
+ rm -r node_modules
313
+ npm install --omit=dev --omit=peer
314
+ npx wrangler dev # or deploy
315
+ ```
316
+
317
+ ### Deno Deploy (experimental)
318
+
319
+ ```sh
320
+ npm run build -- --with-deno
321
+ DENO_DEPLOY_TOKEN=... deployctl deploy --project=... --prod serve.ts --exclude node_modules
322
+ ```
323
+
293
324
  ## Tweets
294
325
 
295
326
  <https://github.com/dai-shi/waku/discussions/150>
package/dist/cjs/cli.js CHANGED
@@ -13,7 +13,7 @@ const _servestatic = require("@hono/node-server/serve-static");
13
13
  const _config = require("./lib/config.js");
14
14
  const _honodev = require("./lib/middleware/hono-dev.js");
15
15
  const _honoprd = require("./lib/middleware/hono-prd.js");
16
- const _builder = require("./lib/builder.js");
16
+ const _build = require("./lib/builder/build.js");
17
17
  function _interop_require_default(obj) {
18
18
  return obj && obj.__esModule ? obj : {
19
19
  default: obj
@@ -68,6 +68,15 @@ const { values, positionals } = (0, _nodeutil.parseArgs)({
68
68
  'with-ssr': {
69
69
  type: 'boolean'
70
70
  },
71
+ 'with-vercel': {
72
+ type: 'boolean'
73
+ },
74
+ 'with-cloudflare': {
75
+ type: 'boolean'
76
+ },
77
+ 'with-deno': {
78
+ type: 'boolean'
79
+ },
71
80
  version: {
72
81
  type: 'boolean',
73
82
  short: 'v'
@@ -85,20 +94,24 @@ if (values.version) {
85
94
  } else if (values.help) {
86
95
  displayUsage();
87
96
  } else {
97
+ const withSsr = !!values['with-ssr'];
88
98
  switch(cmd){
89
99
  case 'dev':
90
100
  runDev({
91
- ssr: !!values['with-ssr']
101
+ ssr: withSsr
92
102
  });
93
103
  break;
94
104
  case 'build':
95
105
  runBuild({
96
- ssr: !!values['with-ssr']
106
+ ssr: withSsr,
107
+ vercel: values['with-vercel'],
108
+ cloudflare: !!values['with-cloudflare'],
109
+ deno: !!values['with-deno']
97
110
  });
98
111
  break;
99
112
  case 'start':
100
113
  runStart({
101
- ssr: !!values['with-ssr']
114
+ ssr: withSsr
102
115
  });
103
116
  break;
104
117
  default:
@@ -111,16 +124,12 @@ if (values.version) {
111
124
  }
112
125
  async function runDev(options) {
113
126
  const app = new _hono.Hono();
114
- app.use('*', (0, _honodev.honoMiddleware)({
115
- ssr: options.ssr
116
- }));
127
+ app.use('*', (0, _honodev.honoMiddleware)(options));
117
128
  const port = parseInt(process.env.PORT || '3000', 10);
118
129
  startServer(app, port);
119
130
  }
120
131
  async function runBuild(options) {
121
- await (0, _builder.build)({
122
- ssr: options.ssr
123
- });
132
+ await (0, _build.build)(options);
124
133
  }
125
134
  async function runStart(options) {
126
135
  const { distDir, publicDir, entriesJs } = await (0, _config.resolveConfig)({});
@@ -128,7 +137,7 @@ async function runStart(options) {
128
137
  const app = new _hono.Hono();
129
138
  app.use('*', (0, _honoprd.honoMiddleware)({
130
139
  entries,
131
- ssr: options.ssr
140
+ ...options
132
141
  }));
133
142
  app.use('*', (0, _servestatic.serveStatic)({
134
143
  root: _nodepath.default.join(distDir, publicDir)
@@ -148,7 +157,7 @@ async function startServer(app, port) {
148
157
  console.log(`warn: Port ${port} is in use, trying ${port + 1} instead.`);
149
158
  startServer(app, port + 1);
150
159
  } else {
151
- console.error('Failed to start server');
160
+ console.error(`Failed to start server: ${err.message}`);
152
161
  }
153
162
  });
154
163
  }
@@ -162,8 +171,10 @@ Commands:
162
171
  start Start the production server
163
172
 
164
173
  Options:
165
- -c, --config <path> Path to the configuration file
166
174
  --with-ssr Use opt-in SSR
175
+ --with-vercel Output for Vercel on build
176
+ --with-cloudflare Output for Cloudflare on build
177
+ --with-deno Output for Deno on build
167
178
  -v, --version Display the version number
168
179
  -h, --help Display this help message
169
180
  `);
package/dist/cjs/dev.js CHANGED
@@ -10,7 +10,7 @@ function _export(target, all) {
10
10
  }
11
11
  _export(exports, {
12
12
  build: function() {
13
- return _builder.build;
13
+ return _build.build;
14
14
  },
15
15
  connectMiddleware: function() {
16
16
  return _connectdev.connectMiddleware;
@@ -25,4 +25,4 @@ _export(exports, {
25
25
  const _honodev = require("./lib/middleware/hono-dev.js");
26
26
  const _connectdev = require("./lib/middleware/connect-dev.js");
27
27
  const _handlerdev = require("./lib/rsc/handler-dev.js");
28
- const _builder = require("./lib/builder.js");
28
+ const _build = require("./lib/builder/build.js");
@@ -13,18 +13,21 @@ const _nodestream = require("node:stream");
13
13
  const _promises = require("node:stream/promises");
14
14
  const _vite = require("vite");
15
15
  const _pluginreact = /*#__PURE__*/ _interop_require_default(require("@vitejs/plugin-react"));
16
- const _config = require("./config.js");
17
- const _path = require("./utils/path.js");
18
- const _nodefs = require("./utils/node-fs.js");
19
- const _stream = require("./utils/stream.js");
20
- const _utils = require("./rsc/utils.js");
21
- const _rscrenderer = require("./rsc/rsc-renderer.js");
22
- const _htmlrenderer = require("./rsc/html-renderer.js");
23
- const _vitepluginrscindex = require("./plugins/vite-plugin-rsc-index.js");
24
- const _vitepluginrscanalyze = require("./plugins/vite-plugin-rsc-analyze.js");
25
- const _vitepluginnonjsresolve = require("./plugins/vite-plugin-nonjs-resolve.js");
26
- const _vitepluginrsctransform = require("./plugins/vite-plugin-rsc-transform.js");
27
- const _patchreactrefresh = require("./plugins/patch-react-refresh.js");
16
+ const _config = require("../config.js");
17
+ const _path = require("../utils/path.js");
18
+ const _nodefs = require("../utils/node-fs.js");
19
+ const _stream = require("../utils/stream.js");
20
+ const _utils = require("../rsc/utils.js");
21
+ const _rscrenderer = require("../rsc/rsc-renderer.js");
22
+ const _htmlrenderer = require("../rsc/html-renderer.js");
23
+ const _vitepluginrscindex = require("../plugins/vite-plugin-rsc-index.js");
24
+ const _vitepluginrscanalyze = require("../plugins/vite-plugin-rsc-analyze.js");
25
+ const _vitepluginnonjsresolve = require("../plugins/vite-plugin-nonjs-resolve.js");
26
+ const _vitepluginrsctransform = require("../plugins/vite-plugin-rsc-transform.js");
27
+ const _patchreactrefresh = require("../plugins/patch-react-refresh.js");
28
+ const _outputvercel = require("./output-vercel.js");
29
+ const _outputcloudflare = require("./output-cloudflare.js");
30
+ const _outputdeno = require("./output-deno.js");
28
31
  function _interop_require_default(obj) {
29
32
  return obj && obj.__esModule ? obj : {
30
33
  default: obj
@@ -368,7 +371,7 @@ export function loadHtml(pathStr) {
368
371
  const code = (0, _utils.generatePrefetchCode)(basePrefix, inputsForPrefetch, moduleIdsForPrefetch) + (customCode || '');
369
372
  if (code) {
370
373
  // HACK is this too naive to inject script code?
371
- htmlStr = htmlStr.replace(/<\/head>/, `<script>${code}</script></head>`);
374
+ htmlStr = htmlStr.replace(/<\/head>/, `<script type="module" async>${code}</script></head>`);
372
375
  }
373
376
  const htmlResult = ssr && await (0, _htmlrenderer.renderHtml)({
374
377
  config,
@@ -402,93 +405,6 @@ export function loadHtml(pathStr) {
402
405
  htmlFiles
403
406
  };
404
407
  };
405
- const emitVercelOutput = async (rootDir, config, clientBuildOutput, rscFiles, htmlFiles, ssr)=>{
406
- // FIXME somehow utils/(path,node-fs).ts doesn't work
407
- const [path, { existsSync, mkdirSync, readdirSync, symlinkSync, writeFileSync }] = await Promise.all([
408
- Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("node:path"))),
409
- Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("node:fs")))
410
- ]);
411
- const clientFiles = clientBuildOutput.output.map(({ fileName })=>path.join(rootDir, config.distDir, config.publicDir, fileName));
412
- const srcDir = path.join(rootDir, config.distDir, config.publicDir);
413
- const dstDir = path.join(rootDir, config.distDir, '.vercel', 'output');
414
- for (const file of [
415
- ...clientFiles,
416
- ...rscFiles,
417
- ...htmlFiles
418
- ]){
419
- const dstFile = path.join(dstDir, 'static', path.relative(srcDir, file));
420
- if (!existsSync(dstFile)) {
421
- mkdirSync(path.dirname(dstFile), {
422
- recursive: true
423
- });
424
- symlinkSync(path.relative(path.dirname(dstFile), file), dstFile);
425
- }
426
- }
427
- // for serverless function
428
- const serverlessDir = path.join(dstDir, 'functions', config.rscPath + '.func');
429
- mkdirSync(path.join(serverlessDir, config.distDir), {
430
- recursive: true
431
- });
432
- mkdirSync(path.join(serverlessDir, 'node_modules'));
433
- symlinkSync(path.relative(path.join(serverlessDir, 'node_modules'), path.join(rootDir, 'node_modules', 'waku')), path.join(serverlessDir, 'node_modules', 'waku'));
434
- for (const file of readdirSync(path.join(rootDir, config.distDir))){
435
- if ([
436
- '.vercel'
437
- ].includes(file)) {
438
- continue;
439
- }
440
- symlinkSync(path.relative(path.join(serverlessDir, config.distDir), path.join(rootDir, config.distDir, file)), path.join(serverlessDir, config.distDir, file));
441
- }
442
- const vcConfigJson = {
443
- runtime: 'nodejs18.x',
444
- handler: 'serve.js',
445
- launcherType: 'Nodejs'
446
- };
447
- writeFileSync(path.join(serverlessDir, '.vc-config.json'), JSON.stringify(vcConfigJson, null, 2));
448
- writeFileSync(path.join(serverlessDir, 'package.json'), JSON.stringify({
449
- type: 'module'
450
- }, null, 2));
451
- writeFileSync(path.join(serverlessDir, 'serve.js'), `
452
- import path from 'node:path';
453
- import { connectMiddleware } from 'waku';
454
- const entries = import(path.resolve('${config.distDir}', '${config.entriesJs}'));
455
- export default async function handler(req, res) {
456
- connectMiddleware({ entries, ssr: true })(req, res, () => {
457
- throw new Error('not handled');
458
- });
459
- }
460
- `);
461
- const overrides = Object.fromEntries(rscFiles.filter((file)=>!path.extname(file)).map((file)=>[
462
- path.relative(srcDir, file),
463
- {
464
- contentType: 'text/plain'
465
- }
466
- ]));
467
- const basePrefix = config.basePath + config.rscPath + '/';
468
- const routes = [
469
- {
470
- src: basePrefix + '(.*)',
471
- dest: basePrefix
472
- },
473
- ...ssr ? htmlFiles.map((htmlFile)=>{
474
- const file = config.basePath + path.relative(srcDir, htmlFile);
475
- const src = file.endsWith('/' + config.indexHtml) ? file.slice(0, -('/' + config.indexHtml).length) || '/' : file;
476
- return {
477
- src,
478
- dest: basePrefix
479
- };
480
- }) : []
481
- ];
482
- const configJson = {
483
- version: 3,
484
- overrides,
485
- routes
486
- };
487
- mkdirSync(dstDir, {
488
- recursive: true
489
- });
490
- writeFileSync(path.join(dstDir, 'config.json'), JSON.stringify(configJson, null, 2));
491
- };
492
408
  const resolveFileName = (fname)=>{
493
409
  for (const ext of [
494
410
  '.js',
@@ -510,9 +426,16 @@ async function build(options) {
510
426
  const distEntriesFile = resolveFileName((0, _path.joinPath)(rootDir, config.distDir, config.entriesJs));
511
427
  const { commonEntryFiles, clientEntryFiles, serverEntryFiles } = await analyzeEntries(entriesFile);
512
428
  const serverBuildOutput = await buildServerBundle(rootDir, config, entriesFile, distEntriesFile, commonEntryFiles, clientEntryFiles, serverEntryFiles);
513
- const clientBuildOutput = await buildClientBundle(rootDir, config, commonEntryFiles, clientEntryFiles, serverBuildOutput);
429
+ await buildClientBundle(rootDir, config, commonEntryFiles, clientEntryFiles, serverBuildOutput);
514
430
  const { buildConfig, getClientModules, rscFiles } = await emitRscFiles(rootDir, config, distEntriesFile);
515
431
  const { htmlFiles } = await emitHtmlFiles(rootDir, config, distEntriesFile, buildConfig, getClientModules, !!options?.ssr);
516
- // https://vercel.com/docs/build-output-api/v3
517
- await emitVercelOutput(rootDir, config, clientBuildOutput, rscFiles, htmlFiles, !!options?.ssr);
432
+ if (options?.vercel ?? process.env.VERCEL) {
433
+ await (0, _outputvercel.emitVercelOutput)(rootDir, config, rscFiles, htmlFiles, !!options?.ssr);
434
+ }
435
+ if (options?.cloudflare) {
436
+ await (0, _outputcloudflare.emitCloudflareOutput)(rootDir, config, !!options?.ssr);
437
+ }
438
+ if (options?.deno) {
439
+ await (0, _outputdeno.emitDenoOutput)(rootDir, config, !!options?.ssr);
440
+ }
518
441
  }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "emitCloudflareOutput", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return emitCloudflareOutput;
9
+ }
10
+ });
11
+ const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
12
+ const _nodefs = require("node:fs");
13
+ function _interop_require_default(obj) {
14
+ return obj && obj.__esModule ? obj : {
15
+ default: obj
16
+ };
17
+ }
18
+ const emitCloudflareOutput = async (rootDir, config, ssr)=>{
19
+ const outputDir = _nodepath.default.resolve('.');
20
+ const relativeRootDir = _nodepath.default.relative(outputDir, rootDir);
21
+ const entriesFile = _nodepath.default.join(relativeRootDir, config.distDir, config.entriesJs);
22
+ const publicDir = _nodepath.default.join(relativeRootDir, config.distDir, config.publicDir);
23
+ if (!(0, _nodefs.existsSync)(_nodepath.default.join(outputDir, 'serve.js'))) {
24
+ (0, _nodefs.writeFileSync)(_nodepath.default.join(outputDir, 'serve.js'), `
25
+ import { honoMiddleware } from 'waku';
26
+ import { Hono } from 'hono';
27
+ import { serveStatic } from 'hono/cloudflare-workers';
28
+
29
+ const entries = import('./${entriesFile}');
30
+
31
+ const app = new Hono();
32
+ app.use('*', honoMiddleware({ entries, ssr: ${ssr} }));
33
+ app.use('*', serveStatic({ root: './' }));
34
+ export default app;
35
+ `);
36
+ }
37
+ if (!(0, _nodefs.existsSync)(_nodepath.default.join(outputDir, 'wrangler.toml'))) {
38
+ (0, _nodefs.writeFileSync)(_nodepath.default.join(outputDir, 'wrangler.toml'), `
39
+ name = "waku-project"
40
+ main = "serve.js"
41
+ compatibility_date = "2023-12-06"
42
+
43
+ [site]
44
+ bucket = "./${publicDir}"
45
+ `);
46
+ }
47
+ };
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "emitDenoOutput", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return emitDenoOutput;
9
+ }
10
+ });
11
+ const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
12
+ const _nodefs = require("node:fs");
13
+ function _interop_require_default(obj) {
14
+ return obj && obj.__esModule ? obj : {
15
+ default: obj
16
+ };
17
+ }
18
+ const emitDenoOutput = async (rootDir, config, ssr)=>{
19
+ const outputDir = _nodepath.default.resolve('.');
20
+ const relativeRootDir = _nodepath.default.relative(outputDir, rootDir);
21
+ const entriesFile = _nodepath.default.join(relativeRootDir, config.distDir, config.entriesJs);
22
+ const publicDir = _nodepath.default.join(relativeRootDir, config.distDir, config.publicDir);
23
+ if (!(0, _nodefs.existsSync)(_nodepath.default.join(outputDir, 'serve.ts'))) {
24
+ (0, _nodefs.writeFileSync)(_nodepath.default.join(outputDir, 'serve.ts'), `
25
+ import { Hono } from "https://deno.land/x/hono/mod.ts";
26
+ import { serveStatic } from "https://deno.land/x/hono/middleware.ts";
27
+ import { honoMiddleware } from "npm:waku@0.18.1";
28
+
29
+ const entries = import('./${entriesFile}');
30
+
31
+ const app = new Hono();
32
+ app.use('*', honoMiddleware({ entries, ssr: ${ssr} }));
33
+ app.use("*", serveStatic({ root: "${publicDir}" }));
34
+
35
+ Deno.serve(app.fetch);
36
+ `);
37
+ }
38
+ };
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "emitVercelOutput", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return emitVercelOutput;
9
+ }
10
+ });
11
+ const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
12
+ const _nodefs = require("node:fs");
13
+ function _interop_require_default(obj) {
14
+ return obj && obj.__esModule ? obj : {
15
+ default: obj
16
+ };
17
+ }
18
+ const emitVercelOutput = async (rootDir, config, rscFiles, htmlFiles, ssr)=>{
19
+ const publicDir = _nodepath.default.join(rootDir, config.distDir, config.publicDir);
20
+ const outputDir = _nodepath.default.resolve('.vercel', 'output');
21
+ (0, _nodefs.cpSync)(_nodepath.default.join(rootDir, config.distDir, config.publicDir), _nodepath.default.join(outputDir, 'static'), {
22
+ recursive: true
23
+ });
24
+ // for serverless function
25
+ const serverlessDir = _nodepath.default.join(outputDir, 'functions', config.rscPath + '.func');
26
+ (0, _nodefs.mkdirSync)(_nodepath.default.join(serverlessDir, config.distDir), {
27
+ recursive: true
28
+ });
29
+ (0, _nodefs.mkdirSync)(_nodepath.default.join(serverlessDir, 'node_modules'), {
30
+ recursive: true
31
+ });
32
+ (0, _nodefs.cpSync)(_nodepath.default.join(rootDir, 'node_modules', 'waku'), _nodepath.default.join(serverlessDir, 'node_modules', 'waku'), {
33
+ dereference: true,
34
+ recursive: true
35
+ });
36
+ (0, _nodefs.cpSync)(_nodepath.default.join(rootDir, config.distDir), _nodepath.default.join(serverlessDir, config.distDir), {
37
+ recursive: true
38
+ });
39
+ const vcConfigJson = {
40
+ runtime: 'nodejs18.x',
41
+ handler: 'serve.js',
42
+ launcherType: 'Nodejs'
43
+ };
44
+ (0, _nodefs.writeFileSync)(_nodepath.default.join(serverlessDir, '.vc-config.json'), JSON.stringify(vcConfigJson, null, 2));
45
+ (0, _nodefs.writeFileSync)(_nodepath.default.join(serverlessDir, 'package.json'), JSON.stringify({
46
+ type: 'module'
47
+ }, null, 2));
48
+ (0, _nodefs.writeFileSync)(_nodepath.default.join(serverlessDir, 'serve.js'), `
49
+ import path from 'node:path';
50
+ import { connectMiddleware } from 'waku';
51
+ const entries = import(path.resolve('${config.distDir}', '${config.entriesJs}'));
52
+ export default async function handler(req, res) {
53
+ connectMiddleware({ entries, ssr: ${ssr} })(req, res, () => {
54
+ res.statusCode = 404;
55
+ res.end();
56
+ });
57
+ }
58
+ `);
59
+ const overrides = Object.fromEntries(rscFiles.filter((file)=>!_nodepath.default.extname(file)).map((file)=>[
60
+ _nodepath.default.relative(publicDir, file),
61
+ {
62
+ contentType: 'text/plain'
63
+ }
64
+ ]));
65
+ const basePrefix = config.basePath + config.rscPath + '/';
66
+ const routes = [
67
+ {
68
+ src: basePrefix + '(.*)',
69
+ dest: basePrefix
70
+ },
71
+ ...ssr ? htmlFiles.map((htmlFile)=>{
72
+ const file = config.basePath + _nodepath.default.relative(publicDir, htmlFile);
73
+ const src = file.endsWith('/' + config.indexHtml) ? file.slice(0, -('/' + config.indexHtml).length) || '/' : file;
74
+ return {
75
+ src,
76
+ dest: basePrefix
77
+ };
78
+ }) : []
79
+ ];
80
+ const configJson = {
81
+ version: 3,
82
+ overrides,
83
+ routes
84
+ };
85
+ (0, _nodefs.mkdirSync)(outputDir, {
86
+ recursive: true
87
+ });
88
+ (0, _nodefs.writeFileSync)(_nodepath.default.join(outputDir, 'config.json'), JSON.stringify(configJson, null, 2));
89
+ };
@@ -10,7 +10,6 @@ Object.defineProperty(exports, "rscDelegatePlugin", {
10
10
  });
11
11
  const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
12
12
  const _core = /*#__PURE__*/ _interop_require_wildcard(require("@swc/core"));
13
- const _path = require("../utils/path.js");
14
13
  function _interop_require_default(obj) {
15
14
  return obj && obj.__esModule ? obj : {
16
15
  default: obj
@@ -62,13 +61,17 @@ const CSS_LANGS_RE = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?
62
61
  function rscDelegatePlugin(importCallback) {
63
62
  let mode = 'development';
64
63
  let base = '/';
64
+ let server;
65
65
  return {
66
66
  name: 'rsc-delegate-plugin',
67
67
  configResolved (config) {
68
68
  mode = config.mode;
69
69
  base = config.base;
70
70
  },
71
- transform (code, id) {
71
+ configureServer (serverInstance) {
72
+ server = serverInstance;
73
+ },
74
+ async transform (code, id) {
72
75
  const ext = _nodepath.default.extname(id);
73
76
  if (mode === 'development' && [
74
77
  '.ts',
@@ -87,10 +90,13 @@ function rscDelegatePlugin(importCallback) {
87
90
  const source = base + '@id/__x00__' + item.source.value;
88
91
  importCallback(source);
89
92
  } else if (CSS_LANGS_RE.test(item.source.value)) {
90
- const filePath = _nodepath.default.join(_nodepath.default.dirname(id), item.source.value);
91
- // HACK this relies on Vite's internal implementation detail.
92
- const source = base + '@fs' + (0, _path.encodeFilePathToAbsolute)(filePath);
93
- importCallback(source);
93
+ const resolvedSource = await server.pluginContainer.resolveId(item.source.value, id, {
94
+ ssr: true
95
+ });
96
+ if (resolvedSource?.id) {
97
+ const transformedResult = await server.transformRequest(resolvedSource.id);
98
+ transformedResult && importCallback(transformedResult);
99
+ }
94
100
  }
95
101
  }
96
102
  }
@@ -12,36 +12,37 @@ _export(exports, {
12
12
  hotImport: function() {
13
13
  return hotImport;
14
14
  },
15
+ moduleImport: function() {
16
+ return moduleImport;
17
+ },
15
18
  rscHmrPlugin: function() {
16
19
  return rscHmrPlugin;
17
20
  }
18
21
  });
19
- const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
20
- function _interop_require_default(obj) {
21
- return obj && obj.__esModule ? obj : {
22
- default: obj
23
- };
24
- }
25
22
  const customCode = `
23
+ import { createHotContext as __vite__createHotContext } from "/@vite/client";
24
+ import.meta.hot = __vite__createHotContext(import.meta.url);
25
+
26
26
  if (import.meta.hot && !globalThis.__WAKU_HMR_CONFIGURED__) {
27
27
  globalThis.__WAKU_HMR_CONFIGURED__ = true;
28
+
28
29
  import.meta.hot.on('hot-import', (data) => import(/* @vite-ignore */ data));
30
+
31
+ import.meta.hot.on('module', (data) => {
32
+ const code = data.code;
33
+ const script = document.createElement('script');
34
+ script.type = 'module';
35
+ script.text = code;
36
+ document.head.appendChild(script);
37
+ });
29
38
  }
30
39
  `;
31
40
  function rscHmrPlugin() {
32
41
  return {
33
42
  name: 'rsc-hmr-plugin',
34
- async transform (code, id) {
35
- const ext = _nodepath.default.extname(id);
36
- if ([
37
- '.ts',
38
- '.tsx',
39
- '.js',
40
- '.jsx'
41
- ].includes(ext)) {
42
- return code + customCode;
43
- }
44
- return code;
43
+ enforce: 'post',
44
+ transformIndexHtml (html) {
45
+ return html.replace('</body>', `<script type="module" async>${customCode}</script></body>`);
45
46
  }
46
47
  };
47
48
  }
@@ -68,3 +69,26 @@ function hotImport(vite, source) {
68
69
  data: source
69
70
  });
70
71
  }
72
+ const modulePendingMap = new WeakMap();
73
+ function moduleImport(viteServer, result) {
74
+ let sourceSet = modulePendingMap.get(viteServer);
75
+ if (!sourceSet) {
76
+ sourceSet = new Set();
77
+ modulePendingMap.set(viteServer, sourceSet);
78
+ viteServer.ws.on('connection', ()=>{
79
+ for (const result of sourceSet){
80
+ viteServer.ws.send({
81
+ type: 'custom',
82
+ event: 'module',
83
+ data: result
84
+ });
85
+ }
86
+ });
87
+ }
88
+ sourceSet.add(result);
89
+ viteServer.ws.send({
90
+ type: 'custom',
91
+ event: 'module',
92
+ data: result
93
+ });
94
+ }
@@ -22,6 +22,7 @@ const _vitepluginnonjsresolve = require("../plugins/vite-plugin-nonjs-resolve.js
22
22
  const _patchreactrefresh = require("../plugins/patch-react-refresh.js");
23
23
  const _vitepluginrscindex = require("../plugins/vite-plugin-rsc-index.js");
24
24
  const _vitepluginrschmr = require("../plugins/vite-plugin-rsc-hmr.js");
25
+ const _mergeviteconfig = require("../utils/merge-vite-config.js");
25
26
  function _interop_require_default(obj) {
26
27
  return obj && obj.__esModule ? obj : {
27
28
  default: obj
@@ -34,7 +35,7 @@ function createHandler(options) {
34
35
  }
35
36
  const configPromise = (0, _config.resolveConfig)(options.config || {});
36
37
  const vitePromise = configPromise.then(async (config)=>{
37
- const viteServer = await (0, _vite.createServer)({
38
+ const mergedViteConfig = await (0, _mergeviteconfig.mergeUserViteConfig)({
38
39
  base: config.basePath,
39
40
  optimizeDeps: {
40
41
  include: [
@@ -59,10 +60,12 @@ function createHandler(options) {
59
60
  middlewareMode: true
60
61
  }
61
62
  });
63
+ const viteServer = await (0, _vite.createServer)(mergedViteConfig);
62
64
  (0, _workerapi.registerReloadCallback)((type)=>viteServer.ws.send({
63
65
  type
64
66
  }));
65
67
  (0, _workerapi.registerImportCallback)((source)=>(0, _vitepluginrschmr.hotImport)(viteServer, source));
68
+ (0, _workerapi.registerModuleCallback)((result)=>(0, _vitepluginrschmr.moduleImport)(viteServer, result));
66
69
  return viteServer;
67
70
  });
68
71
  const entries = Promise.all([