@jasonshimmy/vite-plugin-cer-app 0.28.2 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/cli/adapters/cloudflare.d.ts +2 -2
- package/dist/cli/adapters/cloudflare.d.ts.map +1 -1
- package/dist/cli/adapters/cloudflare.js +83 -159
- package/dist/cli/adapters/cloudflare.js.map +1 -1
- package/dist/cli/adapters/deployment-mode.d.ts +10 -0
- package/dist/cli/adapters/deployment-mode.d.ts.map +1 -0
- package/dist/cli/adapters/deployment-mode.js +59 -0
- package/dist/cli/adapters/deployment-mode.js.map +1 -0
- package/dist/cli/adapters/netlify.d.ts +5 -4
- package/dist/cli/adapters/netlify.d.ts.map +1 -1
- package/dist/cli/adapters/netlify.js +26 -150
- package/dist/cli/adapters/netlify.js.map +1 -1
- package/dist/cli/adapters/vercel.d.ts +2 -3
- package/dist/cli/adapters/vercel.d.ts.map +1 -1
- package/dist/cli/adapters/vercel.js +36 -111
- package/dist/cli/adapters/vercel.js.map +1 -1
- package/dist/cli/adapters/web-bridge.d.ts +3 -0
- package/dist/cli/adapters/web-bridge.d.ts.map +1 -0
- package/dist/cli/adapters/web-bridge.js +110 -0
- package/dist/cli/adapters/web-bridge.js.map +1 -0
- package/dist/cli/checks/lighthouse.d.ts +7 -1
- package/dist/cli/checks/lighthouse.d.ts.map +1 -1
- package/dist/cli/checks/lighthouse.js +49 -44
- package/dist/cli/checks/lighthouse.js.map +1 -1
- package/dist/cli/checks/links.js.map +1 -1
- package/dist/cli/checks/performance.d.ts +3 -0
- package/dist/cli/checks/performance.d.ts.map +1 -1
- package/dist/cli/checks/performance.js +56 -15
- package/dist/cli/checks/performance.js.map +1 -1
- package/dist/cli/checks/quality.d.ts +35 -0
- package/dist/cli/checks/quality.d.ts.map +1 -0
- package/dist/cli/checks/quality.js +72 -0
- package/dist/cli/checks/quality.js.map +1 -0
- package/dist/cli/checks/seo.d.ts +9 -0
- package/dist/cli/checks/seo.d.ts.map +1 -0
- package/dist/cli/checks/seo.js +40 -0
- package/dist/cli/checks/seo.js.map +1 -0
- package/dist/cli/commands/adapt.js.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +2 -51
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +12 -0
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/dev.d.ts +4 -0
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +1 -72
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/generate.d.ts +1 -4
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +4 -73
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/preview-paths.d.ts +3 -0
- package/dist/cli/commands/preview-paths.d.ts.map +1 -0
- package/dist/cli/commands/preview-paths.js +8 -0
- package/dist/cli/commands/preview-paths.js.map +1 -0
- package/dist/cli/commands/preview.d.ts +11 -0
- package/dist/cli/commands/preview.d.ts.map +1 -1
- package/dist/cli/commands/preview.js +124 -458
- package/dist/cli/commands/preview.js.map +1 -1
- package/dist/cli/config.d.ts +3 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +68 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/create/index.js.map +1 -1
- package/dist/cli/create/templates/spa/package.json.tpl +1 -1
- package/dist/cli/create/templates/ssg/package.json.tpl +1 -1
- package/dist/cli/create/templates/ssr/package.json.tpl +1 -1
- package/dist/plugin/build-ssg.d.ts.map +1 -1
- package/dist/plugin/build-ssg.js +81 -15
- package/dist/plugin/build-ssg.js.map +1 -1
- package/dist/plugin/build-ssr.d.ts.map +1 -1
- package/dist/plugin/build-ssr.js +3 -1
- package/dist/plugin/build-ssr.js.map +1 -1
- package/dist/plugin/content/scanner.d.ts.map +1 -1
- package/dist/plugin/content/scanner.js +2 -7
- package/dist/plugin/content/scanner.js.map +1 -1
- package/dist/plugin/dev-server.d.ts +8 -0
- package/dist/plugin/dev-server.d.ts.map +1 -1
- package/dist/plugin/dev-server.js.map +1 -1
- package/dist/plugin/dts-generator.d.ts.map +1 -1
- package/dist/plugin/dts-generator.js +4 -1
- package/dist/plugin/dts-generator.js.map +1 -1
- package/dist/plugin/file-scanner.d.ts +4 -0
- package/dist/plugin/file-scanner.d.ts.map +1 -0
- package/dist/plugin/file-scanner.js +59 -0
- package/dist/plugin/file-scanner.js.map +1 -0
- package/dist/plugin/html-post-process.d.ts +1 -1
- package/dist/plugin/html-post-process.d.ts.map +1 -1
- package/dist/plugin/html-post-process.js +7 -5
- package/dist/plugin/html-post-process.js.map +1 -1
- package/dist/plugin/index.d.ts +1 -4
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +26 -8
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/path-utils.js.map +1 -1
- package/dist/plugin/scanner.d.ts +2 -2
- package/dist/plugin/scanner.d.ts.map +1 -1
- package/dist/plugin/scanner.js +4 -10
- package/dist/plugin/scanner.js.map +1 -1
- package/dist/plugin/server-content.d.ts +3 -0
- package/dist/plugin/server-content.d.ts.map +1 -0
- package/dist/plugin/server-content.js +25 -0
- package/dist/plugin/server-content.js.map +1 -0
- package/dist/plugin/transforms/auto-import.d.ts.map +1 -1
- package/dist/plugin/transforms/auto-import.js +6 -5
- package/dist/plugin/transforms/auto-import.js.map +1 -1
- package/dist/plugin/transforms/head-inject.d.ts.map +1 -1
- package/dist/plugin/virtual/composables.js +1 -1
- package/dist/plugin/virtual/composables.js.map +1 -1
- package/dist/plugin/virtual/content-components.d.ts +3 -1
- package/dist/plugin/virtual/content-components.d.ts.map +1 -1
- package/dist/plugin/virtual/content-components.js +105 -22
- package/dist/plugin/virtual/content-components.js.map +1 -1
- package/dist/plugin/virtual/layouts.js +1 -1
- package/dist/plugin/virtual/layouts.js.map +1 -1
- package/dist/plugin/virtual/middleware.js +1 -1
- package/dist/plugin/virtual/middleware.js.map +1 -1
- package/dist/plugin/virtual/plugins.js +1 -1
- package/dist/plugin/virtual/plugins.js.map +1 -1
- package/dist/plugin/virtual/routes.js +1 -1
- package/dist/plugin/virtual/routes.js.map +1 -1
- package/dist/plugin/virtual/server-api.js +1 -1
- package/dist/plugin/virtual/server-api.js.map +1 -1
- package/dist/plugin/virtual/server-middleware.js +1 -1
- package/dist/plugin/virtual/server-middleware.js.map +1 -1
- package/dist/runtime/app-template.d.ts.map +1 -1
- package/dist/runtime/app-template.js +18 -8
- package/dist/runtime/app-template.js.map +1 -1
- package/dist/runtime/composables/index.d.ts +2 -0
- package/dist/runtime/composables/index.d.ts.map +1 -1
- package/dist/runtime/composables/index.js +1 -0
- package/dist/runtime/composables/index.js.map +1 -1
- package/dist/runtime/composables/render-content.d.ts +10 -0
- package/dist/runtime/composables/render-content.d.ts.map +1 -0
- package/dist/runtime/composables/render-content.js +21 -0
- package/dist/runtime/composables/render-content.js.map +1 -0
- package/dist/runtime/composables/use-active-headings.js.map +1 -1
- package/dist/runtime/composables/use-auth.d.ts.map +1 -1
- package/dist/runtime/composables/use-auth.js +14 -6
- package/dist/runtime/composables/use-auth.js.map +1 -1
- package/dist/runtime/composables/use-content-page.d.ts +2 -0
- package/dist/runtime/composables/use-content-page.d.ts.map +1 -1
- package/dist/runtime/composables/use-content-page.js +1 -1
- package/dist/runtime/composables/use-content-page.js.map +1 -1
- package/dist/runtime/composables/use-content.d.ts.map +1 -1
- package/dist/runtime/composables/use-content.js.map +1 -1
- package/dist/runtime/composables/use-cookie.js.map +1 -1
- package/dist/runtime/composables/use-runtime-config.js.map +1 -1
- package/dist/runtime/composables/use-session.js.map +1 -1
- package/dist/runtime/content/client.d.ts +2 -3
- package/dist/runtime/content/client.d.ts.map +1 -1
- package/dist/runtime/content/client.js +4 -5
- package/dist/runtime/content/client.js.map +1 -1
- package/dist/runtime/entry-server-template.d.ts.map +1 -1
- package/dist/runtime/entry-server-template.js +45 -15
- package/dist/runtime/entry-server-template.js.map +1 -1
- package/dist/runtime/isr-handler.d.ts +4 -15
- package/dist/runtime/isr-handler.d.ts.map +1 -1
- package/dist/runtime/isr-handler.js +64 -45
- package/dist/runtime/isr-handler.js.map +1 -1
- package/dist/runtime/request-dispatcher.d.ts +31 -0
- package/dist/runtime/request-dispatcher.d.ts.map +1 -0
- package/dist/runtime/request-dispatcher.js +152 -0
- package/dist/runtime/request-dispatcher.js.map +1 -0
- package/dist/runtime/route-matching.d.ts +20 -0
- package/dist/runtime/route-matching.d.ts.map +1 -0
- package/dist/runtime/route-matching.js +45 -0
- package/dist/runtime/route-matching.js.map +1 -0
- package/dist/types/api.d.ts +3 -0
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/config.d.ts +27 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js.map +1 -1
- package/dist/types/content.d.ts +2 -0
- package/dist/types/content.d.ts.map +1 -1
- package/dist/types/page.d.ts +11 -7
- package/dist/types/page.d.ts.map +1 -1
- package/package.json +30 -16
- package/dist/cli/commands/preview-isr.d.ts +0 -66
- package/dist/cli/commands/preview-isr.d.ts.map +0 -1
- package/dist/cli/commands/preview-isr.js +0 -132
- package/dist/cli/commands/preview-isr.js.map +0 -1
package/README.md
CHANGED
|
@@ -273,3 +273,5 @@ For a read-only CI/release check, use `npm run check:runtime`. It exits non-zero
|
|
|
273
273
|
## License
|
|
274
274
|
|
|
275
275
|
MIT
|
|
276
|
+
|
|
277
|
+
See [production content, islands and quality checks](docs/production-content.md) for complete Markdown SSR, selective content imports, Vite preview, static CSS and release gates.
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* generated `_worker.js` (Cloudflare Pages Advanced Mode convention).
|
|
10
10
|
* The worker sets globalThis.__CER_CLIENT_TEMPLATE__ before dynamically
|
|
11
11
|
* importing the server bundle, bypassing the node:fs call in server.js.
|
|
12
|
-
* -
|
|
13
|
-
*
|
|
12
|
+
* - Bundles the server graph into _worker.js and removes server intermediates.
|
|
13
|
+
* - Copies public files to dist/; the worker forwards asset requests to ASSETS.
|
|
14
14
|
* - Writes `wrangler.toml` with nodejs_compat for AsyncLocalStorage + streams.
|
|
15
15
|
*
|
|
16
16
|
* SPA/SSG mode:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../../src/cli/adapters/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;
|
|
1
|
+
{"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../../src/cli/adapters/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAwGH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBtE"}
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* generated `_worker.js` (Cloudflare Pages Advanced Mode convention).
|
|
10
10
|
* The worker sets globalThis.__CER_CLIENT_TEMPLATE__ before dynamically
|
|
11
11
|
* importing the server bundle, bypassing the node:fs call in server.js.
|
|
12
|
-
* -
|
|
13
|
-
*
|
|
12
|
+
* - Bundles the server graph into _worker.js and removes server intermediates.
|
|
13
|
+
* - Copies public files to dist/; the worker forwards asset requests to ASSETS.
|
|
14
14
|
* - Writes `wrangler.toml` with nodejs_compat for AsyncLocalStorage + streams.
|
|
15
15
|
*
|
|
16
16
|
* SPA/SSG mode:
|
|
@@ -24,7 +24,11 @@
|
|
|
24
24
|
* https://developers.cloudflare.com/workers/runtime-apis/nodejs/
|
|
25
25
|
*/
|
|
26
26
|
import { join } from 'pathe';
|
|
27
|
-
import {
|
|
27
|
+
import { requiresServer, prerenderedPaths, prerenderedFallback } from './deployment-mode.js';
|
|
28
|
+
import { WEB_BRIDGE } from './web-bridge.js';
|
|
29
|
+
import { build } from 'vite';
|
|
30
|
+
import { gzipSync } from 'node:zlib';
|
|
31
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync, copyFileSync, cpSync, readdirSync, statSync, rmSync, } from 'node:fs';
|
|
28
32
|
// ─── Worker bridge template ───────────────────────────────────────────────────
|
|
29
33
|
/**
|
|
30
34
|
* Generates the _worker.js content with the client HTML inlined.
|
|
@@ -41,7 +45,7 @@ import { existsSync, mkdirSync, writeFileSync, readFileSync, copyFileSync, cpSyn
|
|
|
41
45
|
* buffered until the full page is rendered.
|
|
42
46
|
* - Exports `{ fetch }` — the Cloudflare Pages _worker.js module format.
|
|
43
47
|
*/
|
|
44
|
-
function generateWorkerBridge(clientHtml) {
|
|
48
|
+
function generateWorkerBridge(clientHtml, paths, fallback) {
|
|
45
49
|
// Escape the HTML for embedding in a JS template literal.
|
|
46
50
|
const escaped = clientHtml.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
|
|
47
51
|
return `\
|
|
@@ -49,146 +53,58 @@ function generateWorkerBridge(clientHtml) {
|
|
|
49
53
|
// Cloudflare Pages _worker.js — Advanced Mode SSR bridge.
|
|
50
54
|
// Requires compatibility_flags = ["nodejs_compat"] in wrangler.toml.
|
|
51
55
|
import { Readable } from 'node:stream'
|
|
56
|
+
import { EventEmitter } from 'node:events'
|
|
52
57
|
|
|
53
58
|
// Inline the client HTML template so the server bundle does not need node:fs.
|
|
54
59
|
// Must be set before the dynamic import below resolves.
|
|
55
60
|
globalThis.__CER_CLIENT_TEMPLATE__ = \`${escaped}\`
|
|
56
61
|
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (!search) return {}
|
|
73
|
-
const qs = search.startsWith('?') ? search.slice(1) : search
|
|
74
|
-
const result = {}
|
|
75
|
-
for (const part of qs.split('&')) {
|
|
76
|
-
if (!part) continue
|
|
77
|
-
const eqIdx = part.indexOf('=')
|
|
78
|
-
if (eqIdx === -1) result[decodeURIComponent(part)] = ''
|
|
79
|
-
else result[decodeURIComponent(part.slice(0, eqIdx))] = decodeURIComponent(part.slice(eqIdx + 1))
|
|
80
|
-
}
|
|
81
|
-
return result
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async function toNodeRequest(webReq) {
|
|
85
|
-
const url = new URL(webReq.url)
|
|
86
|
-
const hasBody = webReq.body !== null
|
|
87
|
-
&& webReq.method !== 'GET'
|
|
88
|
-
&& webReq.method !== 'HEAD'
|
|
89
|
-
const body = hasBody ? Buffer.from(await webReq.arrayBuffer()) : null
|
|
90
|
-
const req = Object.assign(
|
|
91
|
-
body ? Readable.from([body]) : Readable.from([]),
|
|
92
|
-
{
|
|
93
|
-
url: url.pathname + url.search,
|
|
94
|
-
method: webReq.method,
|
|
95
|
-
headers: Object.fromEntries(webReq.headers.entries()),
|
|
96
|
-
},
|
|
97
|
-
)
|
|
98
|
-
req.query = parseQuery(url.search)
|
|
99
|
-
if (body !== null) {
|
|
100
|
-
const ct = webReq.headers.get('content-type') ?? ''
|
|
101
|
-
if (ct.includes('application/json')) {
|
|
102
|
-
try { req.body = JSON.parse(body.toString('utf-8')) } catch { req.body = undefined }
|
|
103
|
-
} else {
|
|
104
|
-
req.body = body
|
|
62
|
+
const app = await import('./server/server.js')
|
|
63
|
+
${WEB_BRIDGE}
|
|
64
|
+
const paths = ${JSON.stringify(paths)}
|
|
65
|
+
const dispatchers = new WeakMap()
|
|
66
|
+
async function readDocument(path, req, assets) {
|
|
67
|
+
let url = new URL(path, 'https://' + req.headers.host)
|
|
68
|
+
for (let redirects = 0; redirects < 5; redirects++) {
|
|
69
|
+
const response = await assets.fetch(new Request(url))
|
|
70
|
+
const location = response.headers.get('location')
|
|
71
|
+
if (response.status >= 300 && response.status < 400 && location) {
|
|
72
|
+
await response.body?.cancel()
|
|
73
|
+
const next = new URL(location, url)
|
|
74
|
+
if (next.origin !== url.origin) return null
|
|
75
|
+
url = next
|
|
76
|
+
continue
|
|
105
77
|
}
|
|
78
|
+
if (response.status !== 200) { await response.body?.cancel(); return null }
|
|
79
|
+
return response.text()
|
|
106
80
|
}
|
|
107
|
-
return
|
|
81
|
+
return null
|
|
108
82
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const promise = new Promise((res) => { _resolve = res })
|
|
118
|
-
const res = {
|
|
119
|
-
statusCode: 200,
|
|
120
|
-
setHeader(name, value) { headers[name.toLowerCase()] = String(value) },
|
|
121
|
-
getHeader(name) { return headers[name.toLowerCase()] },
|
|
122
|
-
removeHeader(name) { delete headers[name.toLowerCase()] },
|
|
123
|
-
write(chunk) {
|
|
124
|
-
if (_ended) return
|
|
125
|
-
void writer.write(typeof chunk === 'string' ? encoder.encode(chunk) : chunk).catch(() => {})
|
|
126
|
-
},
|
|
127
|
-
end(chunk) {
|
|
128
|
-
if (_ended) return
|
|
129
|
-
_ended = true
|
|
130
|
-
if (chunk) void writer.write(typeof chunk === 'string' ? encoder.encode(chunk) : chunk).catch(() => {})
|
|
131
|
-
void writer.close().catch(() => {})
|
|
132
|
-
_resolve(new Response(readable, { status: res.statusCode, headers }))
|
|
133
|
-
},
|
|
134
|
-
json(data) {
|
|
135
|
-
this.setHeader('Content-Type', 'application/json; charset=utf-8')
|
|
136
|
-
this.end(JSON.stringify(data))
|
|
137
|
-
},
|
|
138
|
-
status(code) { this.statusCode = code; return this },
|
|
139
|
-
get writableEnded() { return _ended },
|
|
140
|
-
}
|
|
141
|
-
return { res, promise }
|
|
83
|
+
function dispatcher(assets) {
|
|
84
|
+
if (!assets || !app.createDispatchRequest) return app.dispatchRequest
|
|
85
|
+
if (!dispatchers.has(assets)) dispatchers.set(assets, app.createDispatchRequest({ prerendered: {
|
|
86
|
+
paths, fallback: ${JSON.stringify(fallback)},
|
|
87
|
+
read: (path, req) => readDocument(path === '/' ? '/index.html' : path.split('/').map(encodeURIComponent).join('/') + '/index.html', req, assets),
|
|
88
|
+
notFound: (req) => readDocument('/404.html', req, assets),
|
|
89
|
+
} }))
|
|
90
|
+
return dispatchers.get(assets)
|
|
142
91
|
}
|
|
143
92
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
// Run server middleware chain (auth, logging, CORS, etc.).
|
|
153
|
-
if (!(await runServerMiddleware(nodeReq, res))) return promise
|
|
154
|
-
|
|
155
|
-
// Route /api/* requests to the API handlers exported by the server bundle.
|
|
156
|
-
if (urlPath.startsWith('/api/')) {
|
|
157
|
-
for (const route of (apiRoutes ?? [])) {
|
|
158
|
-
const params = matchApiPattern(route.path, urlPath)
|
|
159
|
-
if (params !== null) {
|
|
160
|
-
nodeReq.params = params
|
|
161
|
-
const fn = route.handlers[method.toLowerCase()]
|
|
162
|
-
?? route.handlers[method.toUpperCase()]
|
|
163
|
-
?? route.handlers['default']
|
|
164
|
-
if (typeof fn === 'function') {
|
|
165
|
-
// Wrap in request context so useCookie / useSession work in API handlers.
|
|
166
|
-
runWithRequestContext(nodeReq, res, () => Promise.resolve(fn(nodeReq, res))).catch(() => {
|
|
167
|
-
if (!res.writableEnded) {
|
|
168
|
-
res.statusCode = 500
|
|
169
|
-
res.end(JSON.stringify({ error: 'Internal Server Error' }))
|
|
170
|
-
}
|
|
171
|
-
})
|
|
172
|
-
return promise
|
|
173
|
-
}
|
|
174
|
-
}
|
|
93
|
+
export default {
|
|
94
|
+
async fetch(request, env, _ctx) {
|
|
95
|
+
let path
|
|
96
|
+
try { path = decodeURIComponent(new URL(request.url).pathname) }
|
|
97
|
+
catch { return new Response('Bad Request', { status: 400 }) }
|
|
98
|
+
if (['server', 'client', '.vite'].includes(path.split('/')[1]) || ['/ssg-manifest.json', '/cer-client-manifest.json', '/cer-startup-manifest.json'].includes(path)) {
|
|
99
|
+
return new Response('Not Found', { status: 404 })
|
|
175
100
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (!res.writableEnded) {
|
|
182
|
-
res.statusCode = 500
|
|
183
|
-
res.end('Internal Server Error')
|
|
101
|
+
// Advanced-mode workers own all requests, including static assets.
|
|
102
|
+
if (env?.ASSETS && (request.method === 'GET' || request.method === 'HEAD') && !path.startsWith('/api/')) {
|
|
103
|
+
const asset = await env.ASSETS.fetch(request)
|
|
104
|
+
if (asset.status < 400 && !asset.headers.get('content-type')?.includes('text/html')) return asset
|
|
105
|
+
await asset.body?.cancel()
|
|
184
106
|
}
|
|
185
|
-
|
|
186
|
-
return promise
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
export default {
|
|
190
|
-
async fetch(request, _env, _ctx) {
|
|
191
|
-
return handleRequest(request)
|
|
107
|
+
return handleRequest(request, dispatcher(env?.ASSETS))
|
|
192
108
|
},
|
|
193
109
|
}
|
|
194
110
|
`;
|
|
@@ -199,11 +115,9 @@ export async function runCloudflareAdapter(root) {
|
|
|
199
115
|
if (!existsSync(distDir)) {
|
|
200
116
|
throw new Error(`[cer-app] No dist/ directory found at ${distDir}. Run 'cer-app build' first.`);
|
|
201
117
|
}
|
|
202
|
-
const
|
|
203
|
-
const ssgManifest = join(distDir, 'ssg-manifest.json');
|
|
204
|
-
const isSSR = existsSync(serverBundle) && !existsSync(ssgManifest);
|
|
118
|
+
const isSSR = requiresServer(distDir);
|
|
205
119
|
if (isSSR) {
|
|
206
|
-
_buildSSR(root, distDir);
|
|
120
|
+
await _buildSSR(root, distDir);
|
|
207
121
|
}
|
|
208
122
|
else {
|
|
209
123
|
_buildStatic(root, distDir);
|
|
@@ -219,34 +133,39 @@ export async function runCloudflareAdapter(root) {
|
|
|
219
133
|
}
|
|
220
134
|
}
|
|
221
135
|
// ─── SSR output ───────────────────────────────────────────────────────────────
|
|
222
|
-
function _buildSSR(root, distDir) {
|
|
136
|
+
async function _buildSSR(root, distDir) {
|
|
223
137
|
const clientHtmlPath = join(distDir, 'client/index.html');
|
|
224
138
|
const clientHtml = existsSync(clientHtmlPath)
|
|
225
139
|
? readFileSync(clientHtmlPath, 'utf-8')
|
|
226
140
|
: '';
|
|
227
141
|
// Write the worker bridge with inlined client HTML.
|
|
228
142
|
const workerPath = join(distDir, '_worker.js');
|
|
229
|
-
writeFileSync(workerPath, generateWorkerBridge(clientHtml));
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
143
|
+
writeFileSync(workerPath, generateWorkerBridge(clientHtml, prerenderedPaths(distDir), prerenderedFallback(distDir)));
|
|
144
|
+
// Bundle everything into the platform-reserved worker file. Leaving server/
|
|
145
|
+
// in the public asset tree could expose source when the platform fails open.
|
|
146
|
+
const result = await build({
|
|
147
|
+
root, configFile: false, logLevel: 'error', ssr: { noExternal: true },
|
|
148
|
+
build: { ssr: workerPath, write: false, target: 'es2022', minify: false,
|
|
149
|
+
rollupOptions: { output: { inlineDynamicImports: true, entryFileNames: '_worker.js' } },
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
const output = (Array.isArray(result) ? result[0] : result);
|
|
153
|
+
const worker = output.output.find((item) => item.type === 'chunk')?.code;
|
|
154
|
+
if (!worker)
|
|
155
|
+
throw new Error('[cer-app] Cloudflare bundling produced no worker');
|
|
156
|
+
writeFileSync(workerPath, worker);
|
|
157
|
+
const compressed = gzipSync(worker).byteLength;
|
|
158
|
+
console.log(`[cer-app] Cloudflare worker: ${Buffer.byteLength(worker)} bytes raw / ${compressed} bytes gzip`);
|
|
159
|
+
// This is a framework advisory, not a claim about mutable platform plan limits.
|
|
160
|
+
if (compressed > 1024 * 1024)
|
|
161
|
+
console.warn('[cer-app] Cloudflare worker exceeds the 1 MiB gzip advisory budget; verify current platform size, startup and CPU limits before deployment.');
|
|
245
162
|
// Copy assets from dist/client/ into dist/ (at the same URL paths).
|
|
246
|
-
//
|
|
247
|
-
// requests that don't match a static file fall through to _worker.js.
|
|
163
|
+
// Advanced-mode owns all requests and forwards public assets through ASSETS.
|
|
248
164
|
// We deliberately skip index.html so HTML requests hit the SSR worker.
|
|
249
165
|
_copyClientAssets(join(distDir, 'client'), distDir);
|
|
166
|
+
for (const name of ['server', 'client', '.vite', 'ssg-manifest.json', 'cer-client-manifest.json', 'cer-startup-manifest.json'])
|
|
167
|
+
rmSync(join(distDir, name), { recursive: true, force: true });
|
|
168
|
+
writeFileSync(join(distDir, '_routes.json'), JSON.stringify({ version: 1, include: ['/*'], exclude: [] }, null, 2));
|
|
250
169
|
// wrangler.toml: nodejs_compat for AsyncLocalStorage + node:stream support.
|
|
251
170
|
_writeWranglerToml(root, true);
|
|
252
171
|
}
|
|
@@ -258,6 +177,10 @@ function _buildStatic(root, distDir) {
|
|
|
258
177
|
// Move assets alongside the HTML so Cloudflare Pages serves them correctly.
|
|
259
178
|
_copyClientAssets(clientDir, distDir);
|
|
260
179
|
}
|
|
180
|
+
// Static deployment has no worker to protect build-only files.
|
|
181
|
+
for (const name of ['server', 'client', '.vite', 'ssg-manifest.json', 'cer-client-manifest.json', 'cer-startup-manifest.json']) {
|
|
182
|
+
rmSync(join(distDir, name), { recursive: true, force: true });
|
|
183
|
+
}
|
|
261
184
|
// SPA: everything is already in dist/ — nothing to reorganise.
|
|
262
185
|
_writeWranglerToml(root, false);
|
|
263
186
|
}
|
|
@@ -266,14 +189,15 @@ function _writeWranglerToml(root, ssrMode) {
|
|
|
266
189
|
const lines = [
|
|
267
190
|
'# Auto-generated by @jasonshimmy/vite-plugin-cer-app — do not edit.',
|
|
268
191
|
'name = "cer-app"',
|
|
269
|
-
|
|
192
|
+
// node:fs imports and a full process implementation are used by CER's
|
|
193
|
+
// server graph even though document/content reads use embedded snapshots.
|
|
194
|
+
'compatibility_date = "2025-09-15"',
|
|
270
195
|
];
|
|
271
196
|
if (ssrMode) {
|
|
272
197
|
lines.push('compatibility_flags = ["nodejs_compat"]');
|
|
273
198
|
}
|
|
274
199
|
lines.push('');
|
|
275
|
-
lines.push('
|
|
276
|
-
lines.push('dir = "dist"');
|
|
200
|
+
lines.push('pages_build_output_dir = "dist"');
|
|
277
201
|
lines.push('');
|
|
278
202
|
writeFileSync(join(root, 'wrangler.toml'), lines.join('\n'));
|
|
279
203
|
}
|
|
@@ -287,7 +211,7 @@ function _copyClientAssets(clientDir, destDir) {
|
|
|
287
211
|
return;
|
|
288
212
|
mkdirSync(destDir, { recursive: true });
|
|
289
213
|
for (const entry of readdirSync(clientDir)) {
|
|
290
|
-
if (entry === 'index.html')
|
|
214
|
+
if (entry === 'index.html' || entry === '.vite')
|
|
291
215
|
continue;
|
|
292
216
|
const src = join(clientDir, entry);
|
|
293
217
|
const dest = join(destDir, entry);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../../src/cli/adapters/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAC5B,OAAO,EACL,UAAU,EACV,SAAS,EACT,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,MAAM,EACN,WAAW,EACX,QAAQ,
|
|
1
|
+
{"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../../src/cli/adapters/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAC5B,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC5F,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,EACL,UAAU,EACV,SAAS,EACT,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,MAAM,EACN,WAAW,EACX,QAAQ,EACR,MAAM,GACP,MAAM,SAAS,CAAA;AAEhB,iFAAiF;AAEjF;;;;;;;;;;;;;;GAcG;AACH,SAAS,oBAAoB,CAAC,UAAkB,EAAE,KAAe,EAAE,QAAkB;IACnF,0DAA0D;IAC1D,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAE/F,OAAO;;;;;;;;;yCASgC,OAAO;;;EAG9C,UAAU;gBACI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;uBAsBd,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;CAwB9C,CAAA;AACD,CAAC;AAED,iFAAiF;AAEjF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAY;IACrD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAClC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,yCAAyC,OAAO,8BAA8B,CAC/E,CAAA;IACH,CAAC;IAED,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,CAAA;IAErC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAChC,CAAC;SAAM,CAAC;QACN,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC7B,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAA;IACrD,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;QACzC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;QAC/B,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAA;IAC1D,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAA;IAC1D,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,OAAe;IACpD,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAA;IACzD,MAAM,UAAU,GAAG,UAAU,CAAC,cAAc,CAAC;QAC3C,CAAC,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC;QACvC,CAAC,CAAC,EAAE,CAAA;IAEN,oDAAoD;IACpD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;IAC9C,aAAa,CAAC,UAAU,EAAE,oBAAoB,CAAC,UAAU,EAAE,gBAAgB,CAAC,OAAO,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAEpH,4EAA4E;IAC5E,6EAA6E;IAC7E,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC;QACzB,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;QACrE,KAAK,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK;YACrE,aAAa,EAAE,EAAE,MAAM,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,EAAE;SACxF;KACF,CAAC,CAAA;IACF,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAuD,CAAA;IACjH,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,IAAI,CAAA;IACxE,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAA;IAChF,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;IACjC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,UAAU,CAAA;IAC9C,OAAO,CAAC,GAAG,CAAC,gCAAgC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,gBAAgB,UAAU,aAAa,CAAC,CAAA;IAC7G,gFAAgF;IAChF,IAAI,UAAU,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,CAAC,IAAI,CAAC,6IAA6I,CAAC,CAAA;IAEzL,oEAAoE;IACpE,6EAA6E;IAC7E,uEAAuE;IACvE,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAA;IACnD,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,2BAA2B,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7L,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IAEnH,4EAA4E;IAC5E,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;AAChC,CAAC;AAED,iFAAiF;AAEjF,SAAS,YAAY,CAAC,IAAY,EAAE,OAAe;IACjD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IAEzC,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,iEAAiE;QACjE,4EAA4E;QAC5E,iBAAiB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IACvC,CAAC;IACD,+DAA+D;IAC/D,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,2BAA2B,CAAC,EAAE,CAAC;QAC/H,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAC/D,CAAC;IACD,+DAA+D;IAE/D,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;AACjC,CAAC;AAED,iFAAiF;AAEjF,SAAS,kBAAkB,CAAC,IAAY,EAAE,OAAgB;IACxD,MAAM,KAAK,GAAG;QACZ,qEAAqE;QACrE,kBAAkB;QAClB,sEAAsE;QACtE,0EAA0E;QAC1E,mCAAmC;KACpC,CAAA;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAA;IACvD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAA;IAC7C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;AAC9D,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,SAAiB,EAAE,OAAe;IAC3D,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAM;IAClC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACvC,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3C,IAAI,KAAK,KAAK,YAAY,IAAI,KAAK,KAAK,OAAO;YAAE,SAAQ;QACzD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACjC,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YAChC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACxC,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QACzB,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function prerenderedPaths(distDir: string): string[];
|
|
2
|
+
export declare function prerenderedFallback(distDir: string): boolean | undefined;
|
|
3
|
+
export declare function copyPrerenderedDocuments(distDir: string, target: string): void;
|
|
4
|
+
/** Keep build-generated public metadata available in hybrid deployments. */
|
|
5
|
+
export declare function copyGeneratedPublicFiles(distDir: string, target: string): void;
|
|
6
|
+
export declare function nodeDispatcherSource(distDir: string, documentRoot: string): string;
|
|
7
|
+
/** A retained server is optional for pure SSG, but required for hybrid/fallback. */
|
|
8
|
+
export declare function requiresServer(distDir: string): boolean;
|
|
9
|
+
export declare function isPublicBuildFile(distDir: string, path: string): boolean;
|
|
10
|
+
//# sourceMappingURL=deployment-mode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment-mode.d.ts","sourceRoot":"","sources":["../../../src/cli/adapters/deployment-mode.ts"],"names":[],"mappings":"AAIA,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAK1D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAGxE;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAQ9E;AAED,4EAA4E;AAC5E,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAM9E;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAOlF;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CASvD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAIxE"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { existsSync, readFileSync, mkdirSync, copyFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'pathe';
|
|
3
|
+
import { normalizeDocumentPath } from '../../runtime/request-dispatcher.js';
|
|
4
|
+
export function prerenderedPaths(distDir) {
|
|
5
|
+
const file = join(distDir, 'ssg-manifest.json');
|
|
6
|
+
if (!existsSync(file))
|
|
7
|
+
return [];
|
|
8
|
+
const manifest = JSON.parse(readFileSync(file, 'utf8'));
|
|
9
|
+
return (manifest.paths ?? []).map(normalizeDocumentPath);
|
|
10
|
+
}
|
|
11
|
+
export function prerenderedFallback(distDir) {
|
|
12
|
+
const file = join(distDir, 'ssg-manifest.json');
|
|
13
|
+
return existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')).fallback === true : undefined;
|
|
14
|
+
}
|
|
15
|
+
export function copyPrerenderedDocuments(distDir, target) {
|
|
16
|
+
mkdirSync(target, { recursive: true });
|
|
17
|
+
for (const path of prerenderedPaths(distDir)) {
|
|
18
|
+
const file = path === '/' ? 'index.html' : path.slice(1) + '/index.html';
|
|
19
|
+
mkdirSync(join(target, file, '..'), { recursive: true });
|
|
20
|
+
copyFileSync(join(distDir, file), join(target, file));
|
|
21
|
+
}
|
|
22
|
+
if (existsSync(join(distDir, '404.html')))
|
|
23
|
+
copyFileSync(join(distDir, '404.html'), join(target, '404.html'));
|
|
24
|
+
}
|
|
25
|
+
/** Keep build-generated public metadata available in hybrid deployments. */
|
|
26
|
+
export function copyGeneratedPublicFiles(distDir, target) {
|
|
27
|
+
for (const file of ['sitemap.xml', 'robots.txt', 'form-dummy/index.html']) {
|
|
28
|
+
if (!existsSync(join(distDir, file)))
|
|
29
|
+
continue;
|
|
30
|
+
mkdirSync(join(target, file, '..'), { recursive: true });
|
|
31
|
+
copyFileSync(join(distDir, file), join(target, file));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function nodeDispatcherSource(distDir, documentRoot) {
|
|
35
|
+
return `const dispatchRequest = app.createDispatchRequest ? app.createDispatchRequest({ prerendered: {
|
|
36
|
+
paths: ${JSON.stringify(prerenderedPaths(distDir))},
|
|
37
|
+
fallback: ${JSON.stringify(prerenderedFallback(distDir))},
|
|
38
|
+
notFound: () => { try { return readFileSync(new URL(${JSON.stringify(documentRoot + '404.html')}, import.meta.url), 'utf8') } catch { return null } },
|
|
39
|
+
read: (path) => readFileSync(new URL(${JSON.stringify(documentRoot)} + (path === '/' ? 'index.html' : path.slice(1).split('/').map(encodeURIComponent).join('/') + '/index.html'), import.meta.url), 'utf8'),
|
|
40
|
+
} }) : app.dispatchRequest\n`;
|
|
41
|
+
}
|
|
42
|
+
/** A retained server is optional for pure SSG, but required for hybrid/fallback. */
|
|
43
|
+
export function requiresServer(distDir) {
|
|
44
|
+
const manifestPath = join(distDir, 'ssg-manifest.json');
|
|
45
|
+
const manifest = existsSync(manifestPath)
|
|
46
|
+
? JSON.parse(readFileSync(manifestPath, 'utf-8'))
|
|
47
|
+
: null;
|
|
48
|
+
const required = !manifest || !!(manifest.hybrid || manifest.fallback);
|
|
49
|
+
const serverExists = existsSync(join(distDir, 'server/server.js'));
|
|
50
|
+
if (manifest && required && !serverExists)
|
|
51
|
+
throw new Error('[cer-app] Hybrid/fallback build is missing its server bundle. Rebuild before adapting.');
|
|
52
|
+
return required && serverExists;
|
|
53
|
+
}
|
|
54
|
+
export function isPublicBuildFile(distDir, path) {
|
|
55
|
+
const relative = path.slice(distDir.length + 1);
|
|
56
|
+
return !['server', 'client', '.vite'].some((name) => relative === name || relative.startsWith(`${name}/`)) &&
|
|
57
|
+
!/^(?:ssg-manifest|cer-client-manifest|cer-startup-manifest)\.json$/.test(relative);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=deployment-mode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment-mode.js","sourceRoot":"","sources":["../../../src/cli/adapters/deployment-mode.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,15 +7,16 @@
|
|
|
7
7
|
* SSR mode:
|
|
8
8
|
* - Writes a `netlify/functions/ssr.mjs` bridge that converts Netlify
|
|
9
9
|
* Functions v2 Web API (Request/Response) to the Node.js-style handler
|
|
10
|
-
* used by the cer-app server bundle.
|
|
11
|
-
* - Creates `.netlify/publish/` with
|
|
10
|
+
* used by the cer-app server bundle. Delegates routing to dispatchRequest.
|
|
11
|
+
* - Creates `.netlify/publish/` with public assets and generated metadata
|
|
12
|
+
* (including form registration HTML, but excluding routed documents),
|
|
12
13
|
* so Netlify's CDN serves static files and everything else falls through
|
|
13
14
|
* to the SSR function.
|
|
14
15
|
* - Writes `netlify.toml` with the publish directory and catch-all redirect.
|
|
15
16
|
*
|
|
16
17
|
* SPA/SSG mode:
|
|
17
|
-
* - Writes `netlify.toml`
|
|
18
|
-
*
|
|
18
|
+
* - Writes `netlify.toml` with a filtered SSG publish directory and 404
|
|
19
|
+
* fallback, or a SPA publish directory and app-shell fallback.
|
|
19
20
|
*
|
|
20
21
|
* Responses are streamed via the Web Streams TransformStream API — chunks written
|
|
21
22
|
* by the SSR handler are forwarded to the client as they arrive rather than being
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"netlify.d.ts","sourceRoot":"","sources":["../../../src/cli/adapters/netlify.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"netlify.d.ts","sourceRoot":"","sources":["../../../src/cli/adapters/netlify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AA+CH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBnE"}
|