@astrojs/cloudflare 10.4.1 → 11.0.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/dist/entrypoints/server.js +6 -7
- package/dist/index.d.ts +1 -3
- package/dist/index.js +38 -104
- package/dist/utils/cloudflare-module-loader.js +11 -6
- package/package.json +3 -3
- package/dist/utils/index.d.ts +0 -8
- package/dist/utils/index.js +0 -55
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { App } from 'astro/app';
|
|
2
|
+
import { setGetEnv } from 'astro/env/setup';
|
|
2
3
|
import { createGetEnv } from '../utils/env.js';
|
|
3
4
|
export function createExports(manifest) {
|
|
4
5
|
const app = new App(manifest);
|
|
@@ -29,16 +30,14 @@ export function createExports(manifest) {
|
|
|
29
30
|
caches: caches,
|
|
30
31
|
ctx: {
|
|
31
32
|
waitUntil: (promise) => context.waitUntil(promise),
|
|
32
|
-
|
|
33
|
+
// Currently not available: https://developers.cloudflare.com/pages/platform/known-issues/#pages-functions
|
|
34
|
+
passThroughOnException: () => {
|
|
35
|
+
throw new Error('`passThroughOnException` is currently not available in Cloudflare Pages. See https://developers.cloudflare.com/pages/platform/known-issues/#pages-functions.');
|
|
36
|
+
},
|
|
33
37
|
},
|
|
34
38
|
},
|
|
35
39
|
};
|
|
36
|
-
|
|
37
|
-
// the users's astro version or if astro:env is not enabled in the project
|
|
38
|
-
const setupModule = 'astro/env/setup';
|
|
39
|
-
await import(/* @vite-ignore */ setupModule)
|
|
40
|
-
.then((mod) => mod.setGetEnv(createGetEnv(env)))
|
|
41
|
-
.catch(() => { });
|
|
40
|
+
setGetEnv(createGetEnv(env));
|
|
42
41
|
const response = await app.render(request, { routeData, locals });
|
|
43
42
|
if (app.setCookieHeaders) {
|
|
44
43
|
for (const setCookieHeader of app.setCookieHeaders(response)) {
|
package/dist/index.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export type Options = {
|
|
|
31
31
|
* Proxy configuration for the platform.
|
|
32
32
|
*/
|
|
33
33
|
platformProxy?: {
|
|
34
|
-
/** Toggle the proxy. Default `undefined`, which equals to `
|
|
34
|
+
/** Toggle the proxy. Default `undefined`, which equals to `true`. */
|
|
35
35
|
enabled?: boolean;
|
|
36
36
|
/** Path to the configuration file. Default `wrangler.toml`. */
|
|
37
37
|
configPath?: string;
|
|
@@ -50,7 +50,5 @@ export type Options = {
|
|
|
50
50
|
* for reference on how these file types are exported
|
|
51
51
|
*/
|
|
52
52
|
cloudflareModules?: boolean;
|
|
53
|
-
/** @deprecated - use `cloudflareModules`, which defaults to true. You can set `cloudflareModuleLoading: false` to disable */
|
|
54
|
-
wasmModuleImports?: boolean;
|
|
55
53
|
};
|
|
56
54
|
export default function createIntegration(args?: Options): AstroIntegration;
|
package/dist/index.js
CHANGED
|
@@ -1,95 +1,66 @@
|
|
|
1
1
|
import { createReadStream } from 'node:fs';
|
|
2
|
-
import { appendFile, rename, stat
|
|
2
|
+
import { appendFile, rename, stat } from 'node:fs/promises';
|
|
3
3
|
import { createInterface } from 'node:readline/promises';
|
|
4
4
|
import { appendForwardSlash, prependForwardSlash, removeLeadingForwardSlash, } from '@astrojs/internal-helpers/path';
|
|
5
5
|
import { createRedirectsFromAstroRoutes } from '@astrojs/underscore-redirects';
|
|
6
6
|
import { AstroError } from 'astro/errors';
|
|
7
|
-
import { walk } from 'estree-walker';
|
|
8
|
-
import MagicString from 'magic-string';
|
|
9
7
|
import { getPlatformProxy } from 'wrangler';
|
|
10
8
|
import { cloudflareModuleLoader, } from './utils/cloudflare-module-loader.js';
|
|
11
9
|
import { createGetEnv } from './utils/env.js';
|
|
12
10
|
import { createRoutesFile, getParts } from './utils/generate-routes-json.js';
|
|
13
11
|
import { setImageConfig } from './utils/image-config.js';
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
function wrapWithSlashes(path) {
|
|
13
|
+
return prependForwardSlash(appendForwardSlash(path));
|
|
14
|
+
}
|
|
15
|
+
function setProcessEnv(config, env) {
|
|
16
|
+
const getEnv = createGetEnv(env);
|
|
17
|
+
if (config.experimental.env?.schema) {
|
|
18
|
+
for (const key of Object.keys(config.experimental.env.schema)) {
|
|
19
|
+
const value = getEnv(key);
|
|
20
|
+
if (value !== undefined) {
|
|
21
|
+
process.env[key] = value;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function createPlatformProxy(platformProxy) {
|
|
27
|
+
return getPlatformProxy({
|
|
28
|
+
configPath: platformProxy?.configPath ?? 'wrangler.toml',
|
|
29
|
+
experimentalJsonConfig: platformProxy?.experimentalJsonConfig ?? false,
|
|
30
|
+
persist: platformProxy?.persist ?? true,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
16
33
|
export default function createIntegration(args) {
|
|
17
34
|
let _config;
|
|
18
|
-
const cloudflareModulePlugin = cloudflareModuleLoader(args?.cloudflareModules ??
|
|
19
|
-
// Initialize the unused chunk analyzer as a shared state between hooks.
|
|
20
|
-
// The analyzer is used on earlier hooks to collect information about used hooks on a Vite plugin
|
|
21
|
-
// and then later after the full build to clean up unused chunks, so it has to be shared between them.
|
|
22
|
-
const chunkAnalyzer = new NonServerChunkDetector();
|
|
35
|
+
const cloudflareModulePlugin = cloudflareModuleLoader(args?.cloudflareModules ?? true);
|
|
23
36
|
return {
|
|
24
37
|
name: '@astrojs/cloudflare',
|
|
25
38
|
hooks: {
|
|
26
|
-
'astro:config:setup': ({ command, config, updateConfig, logger }) => {
|
|
39
|
+
'astro:config:setup': ({ command, config, updateConfig, logger, addWatchFile }) => {
|
|
27
40
|
updateConfig({
|
|
28
41
|
build: {
|
|
29
|
-
client: new URL(`.${
|
|
42
|
+
client: new URL(`.${wrapWithSlashes(config.base)}`, config.outDir),
|
|
30
43
|
server: new URL('./_worker.js/', config.outDir),
|
|
31
44
|
serverEntry: 'index.js',
|
|
32
45
|
redirects: false,
|
|
33
46
|
},
|
|
34
47
|
vite: {
|
|
35
|
-
// load .wasm files as WebAssembly modules
|
|
36
48
|
plugins: [
|
|
49
|
+
// https://developers.cloudflare.com/pages/functions/module-support/
|
|
50
|
+
// Allows imports of '.wasm', '.bin', and '.txt' file types
|
|
37
51
|
cloudflareModulePlugin,
|
|
38
|
-
chunkAnalyzer.getPlugin(),
|
|
39
|
-
{
|
|
40
|
-
name: 'dynamic-imports-analyzer',
|
|
41
|
-
enforce: 'post',
|
|
42
|
-
generateBundle(_, bundle) {
|
|
43
|
-
let astrojsSSRVirtualEntryAST;
|
|
44
|
-
const prerenderImports = [];
|
|
45
|
-
let entryChunk;
|
|
46
|
-
// Find all pages (ignore the ssr entrypoint) which are prerendered based on the dynamic imports of the prerender chunk
|
|
47
|
-
for (const chunk of Object.values(bundle)) {
|
|
48
|
-
if (chunk.type !== 'chunk')
|
|
49
|
-
continue;
|
|
50
|
-
if (chunk.name === '_@astrojs-ssr-virtual-entry') {
|
|
51
|
-
astrojsSSRVirtualEntryAST = this.parse(chunk.code);
|
|
52
|
-
entryChunk = chunk;
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
const isPrerendered = chunk.dynamicImports.some((entry) => entry.includes('prerender'));
|
|
56
|
-
if (isPrerendered) {
|
|
57
|
-
prerenderImports.push(chunk.fileName);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (!astrojsSSRVirtualEntryAST)
|
|
61
|
-
return;
|
|
62
|
-
if (!entryChunk)
|
|
63
|
-
return;
|
|
64
|
-
const s = new MagicString(entryChunk.code);
|
|
65
|
-
const constsToRemove = [];
|
|
66
|
-
walk(astrojsSSRVirtualEntryAST, {
|
|
67
|
-
leave(node) {
|
|
68
|
-
// We are only looking for VariableDeclarations, since both (dynamic imports and pageMap) are declared as constants in the code
|
|
69
|
-
if (node.type !== 'VariableDeclaration')
|
|
70
|
-
return;
|
|
71
|
-
if (!node.declarations[0] ||
|
|
72
|
-
node.declarations[0].type !== 'VariableDeclarator')
|
|
73
|
-
return;
|
|
74
|
-
// This function will remove the dynamic imports from the entrypoint
|
|
75
|
-
mutateDynamicPageImportsInPlace(node, prerenderImports, constsToRemove, s);
|
|
76
|
-
// This function will remove the pageMap entries which are invalid now
|
|
77
|
-
mutatePageMapInPlace(node, constsToRemove, s);
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
entryChunk.code = s.toString();
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
52
|
],
|
|
84
53
|
},
|
|
85
|
-
image: setImageConfig(args?.imageService ?? '
|
|
54
|
+
image: setImageConfig(args?.imageService ?? 'compile', config.image, command, logger),
|
|
86
55
|
});
|
|
56
|
+
addWatchFile(new URL('./wrangler.toml', config.root));
|
|
57
|
+
addWatchFile(new URL('./wrangler.json', config.root));
|
|
87
58
|
},
|
|
88
59
|
'astro:config:done': ({ setAdapter, config }) => {
|
|
89
|
-
_config = config;
|
|
90
60
|
if (config.output === 'static') {
|
|
91
61
|
throw new AstroError('[@astrojs/cloudflare] `output: "server"` or `output: "hybrid"` is required to use this adapter. Otherwise, this adapter is not necessary to deploy a static site to Cloudflare.');
|
|
92
62
|
}
|
|
63
|
+
_config = config;
|
|
93
64
|
setAdapter({
|
|
94
65
|
name: '@astrojs/cloudflare',
|
|
95
66
|
serverEntrypoint: '@astrojs/cloudflare/entrypoints/server.js',
|
|
@@ -113,21 +84,9 @@ export default function createIntegration(args) {
|
|
|
113
84
|
});
|
|
114
85
|
},
|
|
115
86
|
'astro:server:setup': async ({ server }) => {
|
|
116
|
-
if (args?.platformProxy?.enabled === true) {
|
|
117
|
-
const platformProxy = await
|
|
118
|
-
|
|
119
|
-
experimentalJsonConfig: args.platformProxy.experimentalJsonConfig ?? false,
|
|
120
|
-
persist: args.platformProxy.persist ?? true,
|
|
121
|
-
});
|
|
122
|
-
const getEnv = createGetEnv(platformProxy.env);
|
|
123
|
-
if (_config.experimental.env?.schema) {
|
|
124
|
-
for (const key of Object.keys(_config.experimental.env.schema)) {
|
|
125
|
-
const value = getEnv(key);
|
|
126
|
-
if (value !== undefined) {
|
|
127
|
-
process.env[key] = value;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
87
|
+
if ((args?.platformProxy?.enabled ?? true) === true) {
|
|
88
|
+
const platformProxy = await createPlatformProxy(args?.platformProxy);
|
|
89
|
+
setProcessEnv(_config, platformProxy.env);
|
|
131
90
|
const clientLocalsSymbol = Symbol.for('astro.locals');
|
|
132
91
|
server.middlewares.use(async function middleware(req, res, next) {
|
|
133
92
|
Reflect.set(req, clientLocalsSymbol, {
|
|
@@ -137,7 +96,10 @@ export default function createIntegration(args) {
|
|
|
137
96
|
caches: platformProxy.caches,
|
|
138
97
|
ctx: {
|
|
139
98
|
waitUntil: (promise) => platformProxy.ctx.waitUntil(promise),
|
|
140
|
-
|
|
99
|
+
// Currently not available: https://developers.cloudflare.com/pages/platform/known-issues/#pages-functions
|
|
100
|
+
passThroughOnException: () => {
|
|
101
|
+
throw new AstroError('`passThroughOnException` is currently not available in Cloudflare Pages. See https://developers.cloudflare.com/pages/platform/known-issues/#pages-functions.');
|
|
102
|
+
},
|
|
141
103
|
},
|
|
142
104
|
},
|
|
143
105
|
});
|
|
@@ -186,20 +148,6 @@ export default function createIntegration(args) {
|
|
|
186
148
|
// @ts-expect-error
|
|
187
149
|
vite.build.rollupOptions.output.banner ||=
|
|
188
150
|
'globalThis.process ??= {}; globalThis.process.env ??= {};';
|
|
189
|
-
// @ts-expect-error
|
|
190
|
-
vite.build.rollupOptions.output.manualChunks = (id) => {
|
|
191
|
-
if (id.includes('node_modules')) {
|
|
192
|
-
if (id.indexOf('node_modules') !== -1) {
|
|
193
|
-
const basic = id.toString().split('node_modules/')[1];
|
|
194
|
-
const sub1 = basic.split('/')[0];
|
|
195
|
-
if (sub1 !== '.pnpm') {
|
|
196
|
-
return sub1.toString();
|
|
197
|
-
}
|
|
198
|
-
const name2 = basic.split('/')[1];
|
|
199
|
-
return name2.split('@')[name2[0] === '@' ? 1 : 0].toString();
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
151
|
vite.build.rollupOptions.external = _config.vite.build?.rollupOptions?.external ?? [];
|
|
204
152
|
// Cloudflare env is only available per request. This isn't feasible for code that access env vars
|
|
205
153
|
// in a global way, so we shim their access as `process.env.*`. This is not the recommended way for users to access environment variables. But we'll add this for compatibility for chosen variables. Mainly to support `@astrojs/db`
|
|
@@ -219,8 +167,6 @@ export default function createIntegration(args) {
|
|
|
219
167
|
vite.build ||= {};
|
|
220
168
|
vite.build.rollupOptions ||= {};
|
|
221
169
|
vite.build.rollupOptions.output ||= {};
|
|
222
|
-
// @ts-expect-error
|
|
223
|
-
vite.build.rollupOptions.output.manualChunks = undefined;
|
|
224
170
|
}
|
|
225
171
|
},
|
|
226
172
|
'astro:build:done': async ({ pages, routes, dir, logger }) => {
|
|
@@ -300,18 +246,6 @@ export default function createIntegration(args) {
|
|
|
300
246
|
logger.error('Failed to write _redirects file');
|
|
301
247
|
}
|
|
302
248
|
}
|
|
303
|
-
// Get chunks from the bundle that are not needed on the server and delete them
|
|
304
|
-
// Those modules are build only for prerendering routes.
|
|
305
|
-
const chunksToDelete = chunkAnalyzer.getNonServerChunks();
|
|
306
|
-
for (const chunk of chunksToDelete) {
|
|
307
|
-
try {
|
|
308
|
-
// Chunks are located on `./_worker.js` directory inside of the output directory
|
|
309
|
-
await unlink(new URL(`./_worker.js/${chunk}`, _config.outDir));
|
|
310
|
-
}
|
|
311
|
-
catch (error) {
|
|
312
|
-
logger.warn(`Issue while trying to delete unused file from server bundle: ${new URL(`./_worker.js/${chunk}`, _config.outDir).toString()}`);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
249
|
},
|
|
316
250
|
},
|
|
317
251
|
};
|
|
@@ -51,7 +51,7 @@ export function cloudflareModuleLoader(enabled) {
|
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
53
|
if (!enabled) {
|
|
54
|
-
throw new Error(`Cloudflare module loading is experimental. The ${maybeExtension} module cannot be loaded unless you add \`
|
|
54
|
+
throw new Error(`Cloudflare module loading is experimental. The ${maybeExtension} module cannot be loaded unless you add \`cloudflareModules: true\` to your astro config.`);
|
|
55
55
|
}
|
|
56
56
|
const moduleLoader = renderers[moduleType];
|
|
57
57
|
const filePath = id.replace(/\?\w+$/, '');
|
|
@@ -126,7 +126,10 @@ export function cloudflareModuleLoader(enabled) {
|
|
|
126
126
|
for (const chunk of Object.values(bundle)) {
|
|
127
127
|
const repls = chunk.name && replacementsByChunkName.get(chunk.name);
|
|
128
128
|
for (const replacement of repls || []) {
|
|
129
|
-
replacement.fileName
|
|
129
|
+
if (!replacement.fileName) {
|
|
130
|
+
replacement.fileName = [];
|
|
131
|
+
}
|
|
132
|
+
replacement.fileName.push(chunk.fileName);
|
|
130
133
|
}
|
|
131
134
|
}
|
|
132
135
|
},
|
|
@@ -140,11 +143,13 @@ export function cloudflareModuleLoader(enabled) {
|
|
|
140
143
|
if (!replacement.fileName) {
|
|
141
144
|
continue;
|
|
142
145
|
}
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
for (const fileName of replacement.fileName) {
|
|
147
|
+
const repls = replacementsByFileName.get(fileName) || [];
|
|
148
|
+
if (!repls.length) {
|
|
149
|
+
replacementsByFileName.set(fileName, repls);
|
|
150
|
+
}
|
|
151
|
+
repls.push(replacement);
|
|
146
152
|
}
|
|
147
|
-
repls.push(replacement);
|
|
148
153
|
}
|
|
149
154
|
for (const [fileName, repls] of replacementsByFileName.entries()) {
|
|
150
155
|
const filepath = path.join(baseDir, '_worker.js', fileName);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrojs/cloudflare",
|
|
3
3
|
"description": "Deploy your site to Cloudflare Workers/Pages",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "11.0.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"author": "withastro",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"wrangler": "^3.39.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"astro": "^4.
|
|
42
|
+
"astro": "^4.10.3"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"astro": "^4.10.
|
|
45
|
+
"astro": "^4.10.3",
|
|
46
46
|
"cheerio": "1.0.0-rc.12",
|
|
47
47
|
"execa": "^8.0.1",
|
|
48
48
|
"fast-glob": "^3.3.2",
|
package/dist/utils/index.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { Node } from 'estree-walker';
|
|
2
|
-
import type MagicString from 'magic-string';
|
|
3
|
-
export declare function mutatePageMapInPlace(node: Extract<Node, {
|
|
4
|
-
type: 'VariableDeclaration';
|
|
5
|
-
}>, constsToRemove: string[], s: MagicString): void;
|
|
6
|
-
export declare function mutateDynamicPageImportsInPlace(node: Extract<Node, {
|
|
7
|
-
type: 'VariableDeclaration';
|
|
8
|
-
}>, prerenderImports: string[], constsToRemove: string[], s: MagicString): void;
|
package/dist/utils/index.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
export function mutatePageMapInPlace(node, constsToRemove, s) {
|
|
2
|
-
const declarator = node.declarations[0];
|
|
3
|
-
if (declarator.id.type !== 'Identifier')
|
|
4
|
-
return;
|
|
5
|
-
if (declarator.id.name !== 'pageMap')
|
|
6
|
-
return;
|
|
7
|
-
if (!declarator.init || declarator.init.type !== 'NewExpression')
|
|
8
|
-
return;
|
|
9
|
-
if (!declarator.init.arguments[0] || declarator.init.arguments[0].type !== 'ArrayExpression')
|
|
10
|
-
return;
|
|
11
|
-
for (const arrayExpression of declarator.init.arguments[0].elements) {
|
|
12
|
-
if (!arrayExpression || arrayExpression.type !== 'ArrayExpression')
|
|
13
|
-
continue;
|
|
14
|
-
if (!arrayExpression.elements[1] || arrayExpression.elements[1].type !== 'Identifier')
|
|
15
|
-
continue;
|
|
16
|
-
if (constsToRemove.includes(arrayExpression.elements[1].name)) {
|
|
17
|
-
// @ts-expect-error - @types/estree seem to be wrong
|
|
18
|
-
if (arrayExpression.start && arrayExpression.end) {
|
|
19
|
-
// @ts-expect-error - @types/estree seem to be wrong
|
|
20
|
-
s.remove(arrayExpression.start, arrayExpression.end);
|
|
21
|
-
// We need to check if there are any leftover commas, which are not part of the `ArrayExpression` node
|
|
22
|
-
// @ts-expect-error - @types/estree seem to be wrong
|
|
23
|
-
const endChar = s.slice(arrayExpression.end, arrayExpression.end + 1);
|
|
24
|
-
if (endChar.includes(',')) {
|
|
25
|
-
// @ts-expect-error - @types/estree seem to be wrong
|
|
26
|
-
s.remove(arrayExpression.end, arrayExpression.end + 1);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
export function mutateDynamicPageImportsInPlace(node, prerenderImports, constsToRemove, s) {
|
|
33
|
-
const declarator = node.declarations[0];
|
|
34
|
-
if (declarator.id.type !== 'Identifier')
|
|
35
|
-
return;
|
|
36
|
-
if (!declarator.id.name.startsWith('_page'))
|
|
37
|
-
return;
|
|
38
|
-
if (!declarator.init || declarator.init.type !== 'ArrowFunctionExpression')
|
|
39
|
-
return;
|
|
40
|
-
if (!declarator.init.body || declarator.init.body.type !== 'ImportExpression')
|
|
41
|
-
return;
|
|
42
|
-
if (!declarator.init.body.source || declarator.init.body.source.type !== 'Literal')
|
|
43
|
-
return;
|
|
44
|
-
const sourceValue = declarator.init.body.source.value;
|
|
45
|
-
if (typeof sourceValue !== 'string')
|
|
46
|
-
return;
|
|
47
|
-
if (prerenderImports.some((importItem) => sourceValue.includes(importItem))) {
|
|
48
|
-
// @ts-expect-error - @types/estree seem to be wrong
|
|
49
|
-
if (node.start && node.end) {
|
|
50
|
-
constsToRemove.push(declarator.id.name);
|
|
51
|
-
// @ts-expect-error - @types/estree seem to be wrong
|
|
52
|
-
s.remove(node.start, node.end);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|