@astrojs/cloudflare 7.2.0 → 7.3.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 +129 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +113 -47
- package/dist/wasm-module-loader.d.ts +14 -0
- package/dist/wasm-module-loader.js +88 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -75,6 +75,92 @@ export default defineConfig({
|
|
|
75
75
|
|
|
76
76
|
Note that this adapter does not support using [Cloudflare Pages Middleware](https://developers.cloudflare.com/pages/platform/functions/middleware/). Astro will bundle the [Astro middleware](https://docs.astro.build/en/guides/middleware/) into each page.
|
|
77
77
|
|
|
78
|
+
### routes.strategy
|
|
79
|
+
|
|
80
|
+
`routes.strategy: "auto" | "include" | "exclude"`
|
|
81
|
+
|
|
82
|
+
default `"auto"`
|
|
83
|
+
|
|
84
|
+
Determines how `routes.json` will be generated if no [custom `_routes.json`](#custom-_routesjson) is provided.
|
|
85
|
+
|
|
86
|
+
There are three options available:
|
|
87
|
+
|
|
88
|
+
- **`"auto"` (default):** Will automatically select the strategy that generates the fewest entries. This should almost always be sufficient, so choose this option unless you have a specific reason not to.
|
|
89
|
+
|
|
90
|
+
- **`include`:** Pages and endpoints that are not pre-rendered are listed as `include` entries, telling Cloudflare to invoke these routes as functions. `exclude` entries are only used to resolve conflicts. Usually the best strategy when your website has mostly static pages and only a few dynamic pages or endpoints.
|
|
91
|
+
|
|
92
|
+
Example: For `src/pages/index.astro` (static), `src/pages/company.astro` (static), `src/pages/users/faq.astro` (static) and `/src/pages/users/[id].astro` (SSR) this will produce the following `_routes.json`:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"version": 1,
|
|
97
|
+
"include": [
|
|
98
|
+
"/_image", // Astro's image endpoint
|
|
99
|
+
"/users/*" // Dynamic route
|
|
100
|
+
],
|
|
101
|
+
"exclude": [
|
|
102
|
+
// Static routes that needs to be exempted from the dynamic wildcard route above
|
|
103
|
+
"/users/faq/",
|
|
104
|
+
"/users/faq/index.html"
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
- **`exclude`:** Pre-rendered pages are listed as `exclude` entries (telling Cloudflare to handle these routes as static assets). Usually the best strategy when your website has mostly dynamic pages or endpoints and only a few static pages.
|
|
110
|
+
|
|
111
|
+
Example: For the same pages as in the previous example this will produce the following `_routes.json`:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"version": 1,
|
|
116
|
+
"include": [
|
|
117
|
+
"/*" // Handle everything as function except the routes below
|
|
118
|
+
],
|
|
119
|
+
"exclude": [
|
|
120
|
+
// All static assets
|
|
121
|
+
"/",
|
|
122
|
+
"/company/",
|
|
123
|
+
"/index.html",
|
|
124
|
+
"/users/faq/",
|
|
125
|
+
"/favicon.png",
|
|
126
|
+
"/company/index.html",
|
|
127
|
+
"/users/faq/index.html"
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### routes.include
|
|
133
|
+
|
|
134
|
+
`routes.include: string[]`
|
|
135
|
+
|
|
136
|
+
default `[]`
|
|
137
|
+
|
|
138
|
+
If you want to use the automatic `_routes.json` generation, but want to include additional routes (e.g. when having custom functions in the `functions` folder), you can use the `routes.include` option to add additional routes to the `include` array.
|
|
139
|
+
|
|
140
|
+
### routes.exclude
|
|
141
|
+
|
|
142
|
+
`routes.exclude: string[]`
|
|
143
|
+
|
|
144
|
+
default `[]`
|
|
145
|
+
|
|
146
|
+
If you want to use the automatic `_routes.json` generation, but want to exclude additional routes, you can use the `routes.exclude` option to add additional routes to the `exclude` array.
|
|
147
|
+
|
|
148
|
+
The following example automatically generates `_routes.json` while including and excluding additional routes. Note that that is only necessary if you have custom functions in the `functions` folder that are not handled by Astro.
|
|
149
|
+
|
|
150
|
+
```diff
|
|
151
|
+
// astro.config.mjs
|
|
152
|
+
export default defineConfig({
|
|
153
|
+
adapter: cloudflare({
|
|
154
|
+
mode: 'directory',
|
|
155
|
+
+ routes: {
|
|
156
|
+
+ strategy: 'include',
|
|
157
|
+
+ include: ['/users/*'], // handled by custom function: functions/users/[id].js
|
|
158
|
+
+ exclude: ['/users/faq'], // handled by static page: pages/users/faq.astro
|
|
159
|
+
+ },
|
|
160
|
+
}),
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
78
164
|
## Enabling Preview
|
|
79
165
|
|
|
80
166
|
In order for preview to work you must install `wrangler`
|
|
@@ -191,6 +277,49 @@ export default defineConfig({
|
|
|
191
277
|
});
|
|
192
278
|
```
|
|
193
279
|
|
|
280
|
+
## Wasm module imports
|
|
281
|
+
|
|
282
|
+
`wasmModuleImports: boolean`
|
|
283
|
+
|
|
284
|
+
default: `false`
|
|
285
|
+
|
|
286
|
+
Whether or not to import `.wasm` files [directly as ES modules](https://github.com/WebAssembly/esm-integration/tree/main/proposals/esm-integration).
|
|
287
|
+
|
|
288
|
+
Add `wasmModuleImports: true` to `astro.config.mjs` to enable in both the Cloudflare build and the Astro dev server.
|
|
289
|
+
|
|
290
|
+
```diff
|
|
291
|
+
// astro.config.mjs
|
|
292
|
+
import {defineConfig} from "astro/config";
|
|
293
|
+
import cloudflare from '@astrojs/cloudflare';
|
|
294
|
+
|
|
295
|
+
export default defineConfig({
|
|
296
|
+
adapter: cloudflare({
|
|
297
|
+
+ wasmModuleImports: true
|
|
298
|
+
}),
|
|
299
|
+
output: 'server'
|
|
300
|
+
})
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Once enabled, you can import a web assembly module in Astro with a `.wasm?module` import.
|
|
304
|
+
|
|
305
|
+
The following is an example of importing a Wasm module that then responds to requests by adding the request's number parameters together.
|
|
306
|
+
|
|
307
|
+
```javascript
|
|
308
|
+
// pages/add/[a]/[b].js
|
|
309
|
+
import mod from '../util/add.wasm?module';
|
|
310
|
+
|
|
311
|
+
// instantiate ahead of time to share module
|
|
312
|
+
const addModule: any = new WebAssembly.Instance(mod);
|
|
313
|
+
|
|
314
|
+
export async function GET(context) {
|
|
315
|
+
const a = Number.parseInt(context.params.a);
|
|
316
|
+
const b = Number.parseInt(context.params.b);
|
|
317
|
+
return new Response(`${addModule.exports.add(a, b)}`);
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
While this example is trivial, Wasm can be used to accelerate computationally intensive operations which do not involve significant I/O such as embedding an image processing library.
|
|
322
|
+
|
|
194
323
|
## Headers, Redirects and function invocation routes
|
|
195
324
|
|
|
196
325
|
Cloudflare has support for adding custom [headers](https://developers.cloudflare.com/pages/platform/headers/), configuring static [redirects](https://developers.cloudflare.com/pages/platform/redirects/) and defining which routes should [invoke functions](https://developers.cloudflare.com/pages/platform/functions/routing/#function-invocation-routes). Cloudflare looks for `_headers`, `_redirects`, and `_routes.json` files in your build output directory to configure these features. This means they should be placed in your Astro project’s `public/` directory.
|
package/dist/index.d.ts
CHANGED
|
@@ -4,12 +4,26 @@ export type { DirectoryRuntime } from './server.directory.js';
|
|
|
4
4
|
type Options = {
|
|
5
5
|
mode?: 'directory' | 'advanced';
|
|
6
6
|
functionPerRoute?: boolean;
|
|
7
|
+
/** Configure automatic `routes.json` generation */
|
|
8
|
+
routes?: {
|
|
9
|
+
/** Strategy for generating `include` and `exclude` patterns
|
|
10
|
+
* - `auto`: Will use the strategy that generates the least amount of entries.
|
|
11
|
+
* - `include`: For each page or endpoint in your application that is not prerendered, an entry in the `include` array will be generated. For each page that is prerendered and whoose path is matched by an `include` entry, an entry in the `exclude` array will be generated.
|
|
12
|
+
* - `exclude`: One `"/*"` entry in the `include` array will be generated. For each page that is prerendered, an entry in the `exclude` array will be generated.
|
|
13
|
+
* */
|
|
14
|
+
strategy?: 'auto' | 'include' | 'exclude';
|
|
15
|
+
/** Additional `include` patterns */
|
|
16
|
+
include?: string[];
|
|
17
|
+
/** Additional `exclude` patterns */
|
|
18
|
+
exclude?: string[];
|
|
19
|
+
};
|
|
7
20
|
/**
|
|
8
21
|
* 'off': current behaviour (wrangler is needed)
|
|
9
22
|
* 'local': use a static req.cf object, and env vars defined in wrangler.toml & .dev.vars (astro dev is enough)
|
|
10
23
|
* 'remote': use a dynamic real-live req.cf object, and env vars defined in wrangler.toml & .dev.vars (astro dev is enough)
|
|
11
24
|
*/
|
|
12
25
|
runtime?: 'off' | 'local' | 'remote';
|
|
26
|
+
wasmModuleImports?: boolean;
|
|
13
27
|
};
|
|
14
28
|
export declare function getAdapter({ isModeDirectory, functionPerRoute, }: {
|
|
15
29
|
isModeDirectory: boolean;
|
package/dist/index.js
CHANGED
|
@@ -6,10 +6,11 @@ import { AstroError } from "astro/errors";
|
|
|
6
6
|
import esbuild from "esbuild";
|
|
7
7
|
import * as fs from "node:fs";
|
|
8
8
|
import * as os from "node:os";
|
|
9
|
-
import { sep } from "node:path";
|
|
9
|
+
import { basename, dirname, relative, sep } from "node:path";
|
|
10
10
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
11
11
|
import glob from "tiny-glob";
|
|
12
12
|
import { getEnvVars } from "./parser.js";
|
|
13
|
+
import { wasmModuleLoader } from "./wasm-module-loader.js";
|
|
13
14
|
class StorageFactory {
|
|
14
15
|
storages = /* @__PURE__ */ new Map();
|
|
15
16
|
storage(namespace) {
|
|
@@ -146,6 +147,15 @@ function createIntegration(args) {
|
|
|
146
147
|
server: new URL(`.${SERVER_BUILD_FOLDER}`, config.outDir),
|
|
147
148
|
serverEntry: "_worker.mjs",
|
|
148
149
|
redirects: false
|
|
150
|
+
},
|
|
151
|
+
vite: {
|
|
152
|
+
// load .wasm files as WebAssembly modules
|
|
153
|
+
plugins: [
|
|
154
|
+
wasmModuleLoader({
|
|
155
|
+
disabled: !args?.wasmModuleImports,
|
|
156
|
+
assetsDirectory: config.build.assets
|
|
157
|
+
})
|
|
158
|
+
]
|
|
149
159
|
}
|
|
150
160
|
});
|
|
151
161
|
},
|
|
@@ -229,6 +239,7 @@ function createIntegration(args) {
|
|
|
229
239
|
},
|
|
230
240
|
"astro:build:done": async ({ pages, routes, dir }) => {
|
|
231
241
|
const functionsUrl = new URL("functions/", _config.root);
|
|
242
|
+
const assetsUrl = new URL(_buildConfig.assets, _buildConfig.client);
|
|
232
243
|
if (isModeDirectory) {
|
|
233
244
|
await fs.promises.mkdir(functionsUrl, { recursive: true });
|
|
234
245
|
}
|
|
@@ -237,35 +248,56 @@ function createIntegration(args) {
|
|
|
237
248
|
const entryPaths = entryPointsURL.map((entry) => fileURLToPath(entry));
|
|
238
249
|
const outputUrl = new URL("$astro", _buildConfig.server);
|
|
239
250
|
const outputDir = fileURLToPath(outputUrl);
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
251
|
+
const entryPathsGroupedByDepth = !args.wasmModuleImports ? [entryPaths] : entryPaths.reduce((sum, thisPath) => {
|
|
252
|
+
const depthFromRoot = thisPath.split(sep).length;
|
|
253
|
+
sum.set(depthFromRoot, (sum.get(depthFromRoot) || []).concat(thisPath));
|
|
254
|
+
return sum;
|
|
255
|
+
}, /* @__PURE__ */ new Map()).values();
|
|
256
|
+
for (const pathsGroup of entryPathsGroupedByDepth) {
|
|
257
|
+
const pagesDirname = relative(fileURLToPath(_buildConfig.server), pathsGroup[0]).split(
|
|
258
|
+
sep
|
|
259
|
+
)[0];
|
|
260
|
+
const absolutePagesDirname = fileURLToPath(new URL(pagesDirname, _buildConfig.server));
|
|
261
|
+
const urlWithinFunctions = new URL(
|
|
262
|
+
relative(absolutePagesDirname, pathsGroup[0]),
|
|
263
|
+
functionsUrl
|
|
264
|
+
);
|
|
265
|
+
const relativePathToAssets = relative(
|
|
266
|
+
dirname(fileURLToPath(urlWithinFunctions)),
|
|
267
|
+
fileURLToPath(assetsUrl)
|
|
268
|
+
);
|
|
269
|
+
await esbuild.build({
|
|
270
|
+
target: "es2020",
|
|
271
|
+
platform: "browser",
|
|
272
|
+
conditions: ["workerd", "worker", "browser"],
|
|
273
|
+
external: [
|
|
274
|
+
"node:assert",
|
|
275
|
+
"node:async_hooks",
|
|
276
|
+
"node:buffer",
|
|
277
|
+
"node:diagnostics_channel",
|
|
278
|
+
"node:events",
|
|
279
|
+
"node:path",
|
|
280
|
+
"node:process",
|
|
281
|
+
"node:stream",
|
|
282
|
+
"node:string_decoder",
|
|
283
|
+
"node:util"
|
|
284
|
+
],
|
|
285
|
+
entryPoints: pathsGroup,
|
|
286
|
+
outbase: absolutePagesDirname,
|
|
287
|
+
outdir: outputDir,
|
|
288
|
+
allowOverwrite: true,
|
|
289
|
+
format: "esm",
|
|
290
|
+
bundle: true,
|
|
291
|
+
minify: _config.vite?.build?.minify !== false,
|
|
292
|
+
banner: {
|
|
293
|
+
js: SHIM
|
|
294
|
+
},
|
|
295
|
+
logOverride: {
|
|
296
|
+
"ignored-bare-import": "silent"
|
|
297
|
+
},
|
|
298
|
+
plugins: !args?.wasmModuleImports ? [] : [rewriteWasmImportPath({ relativePathToAssets })]
|
|
299
|
+
});
|
|
300
|
+
}
|
|
269
301
|
const outputFiles = await glob(`**/*`, {
|
|
270
302
|
cwd: outputDir,
|
|
271
303
|
filesOnly: true
|
|
@@ -322,7 +354,12 @@ function createIntegration(args) {
|
|
|
322
354
|
},
|
|
323
355
|
logOverride: {
|
|
324
356
|
"ignored-bare-import": "silent"
|
|
325
|
-
}
|
|
357
|
+
},
|
|
358
|
+
plugins: !args?.wasmModuleImports ? [] : [
|
|
359
|
+
rewriteWasmImportPath({
|
|
360
|
+
relativePathToAssets: isModeDirectory ? relative(fileURLToPath(functionsUrl), fileURLToPath(assetsUrl)) : relative(fileURLToPath(_buildConfig.client), fileURLToPath(assetsUrl))
|
|
361
|
+
})
|
|
362
|
+
]
|
|
326
363
|
});
|
|
327
364
|
await fs.promises.rename(buildPath, finalBuildUrl);
|
|
328
365
|
if (isModeDirectory) {
|
|
@@ -344,6 +381,9 @@ function createIntegration(args) {
|
|
|
344
381
|
}
|
|
345
382
|
}
|
|
346
383
|
}
|
|
384
|
+
if (!isModeDirectory) {
|
|
385
|
+
cloudflareSpecialFiles.push("_worker.js");
|
|
386
|
+
}
|
|
347
387
|
const routesExists = await fs.promises.stat(new URL("./_routes.json", _config.outDir)).then((stat) => stat.isFile()).catch(() => false);
|
|
348
388
|
if (!routesExists) {
|
|
349
389
|
const functionEndpoints = routes.filter((route) => potentialFunctionRouteTypes.includes(route.type) && !route.prerender).map((route) => {
|
|
@@ -399,29 +439,34 @@ function createIntegration(args) {
|
|
|
399
439
|
);
|
|
400
440
|
}
|
|
401
441
|
staticPathList.push(...routes.filter((r) => r.type === "redirect").map((r) => r.route));
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
442
|
+
const strategy = args?.routes?.strategy ?? "auto";
|
|
443
|
+
const includeStrategy = strategy === "exclude" ? void 0 : {
|
|
444
|
+
include: deduplicatePatterns(
|
|
445
|
+
functionEndpoints.map((endpoint) => endpoint.includePattern).concat(args?.routes?.include ?? [])
|
|
446
|
+
),
|
|
447
|
+
exclude: deduplicatePatterns(
|
|
448
|
+
staticPathList.filter(
|
|
449
|
+
(file) => functionEndpoints.some((endpoint) => endpoint.regexp.test(file))
|
|
450
|
+
).concat(args?.routes?.exclude ?? [])
|
|
408
451
|
)
|
|
409
|
-
|
|
410
|
-
if (include.length === 0) {
|
|
411
|
-
include = ["/"];
|
|
412
|
-
exclude = ["/"];
|
|
413
|
-
}
|
|
414
|
-
if (include.length + exclude.length > staticPathList.length) {
|
|
415
|
-
include = ["/*"];
|
|
416
|
-
exclude = deduplicatePatterns(staticPathList);
|
|
452
|
+
};
|
|
453
|
+
if (includeStrategy?.include.length === 0) {
|
|
454
|
+
includeStrategy.include = ["/"];
|
|
455
|
+
includeStrategy.exclude = ["/"];
|
|
417
456
|
}
|
|
457
|
+
const excludeStrategy = strategy === "include" ? void 0 : {
|
|
458
|
+
include: ["/*"],
|
|
459
|
+
exclude: deduplicatePatterns(staticPathList.concat(args?.routes?.exclude ?? []))
|
|
460
|
+
};
|
|
461
|
+
const includeStrategyLength = includeStrategy ? includeStrategy.include.length + includeStrategy.exclude.length : Infinity;
|
|
462
|
+
const excludeStrategyLength = excludeStrategy ? excludeStrategy.include.length + excludeStrategy.exclude.length : Infinity;
|
|
463
|
+
const winningStrategy = includeStrategyLength <= excludeStrategyLength ? includeStrategy : excludeStrategy;
|
|
418
464
|
await fs.promises.writeFile(
|
|
419
465
|
new URL("./_routes.json", _config.outDir),
|
|
420
466
|
JSON.stringify(
|
|
421
467
|
{
|
|
422
468
|
version: 1,
|
|
423
|
-
|
|
424
|
-
exclude
|
|
469
|
+
...winningStrategy
|
|
425
470
|
},
|
|
426
471
|
null,
|
|
427
472
|
2
|
|
@@ -447,6 +492,27 @@ function deduplicatePatterns(patterns) {
|
|
|
447
492
|
return true;
|
|
448
493
|
});
|
|
449
494
|
}
|
|
495
|
+
function rewriteWasmImportPath({
|
|
496
|
+
relativePathToAssets
|
|
497
|
+
}) {
|
|
498
|
+
return {
|
|
499
|
+
name: "wasm-loader",
|
|
500
|
+
setup(build) {
|
|
501
|
+
build.onResolve({ filter: /.*\.wasm.mjs$/ }, (args) => {
|
|
502
|
+
const updatedPath = [
|
|
503
|
+
relativePathToAssets.replaceAll("\\", "/"),
|
|
504
|
+
basename(args.path).replace(/\.mjs$/, "")
|
|
505
|
+
].join("/");
|
|
506
|
+
return {
|
|
507
|
+
path: updatedPath,
|
|
508
|
+
// change the reference to the changed module
|
|
509
|
+
external: true
|
|
510
|
+
// mark it as external in the bundle
|
|
511
|
+
};
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
}
|
|
450
516
|
export {
|
|
451
517
|
createIntegration as default,
|
|
452
518
|
getAdapter
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* Loads '*.wasm?module' imports as WebAssembly modules, which is the only way to load WASM in cloudflare workers.
|
|
4
|
+
* Current proposal for WASM modules: https://github.com/WebAssembly/esm-integration/tree/main/proposals/esm-integration
|
|
5
|
+
* Cloudflare worker WASM from javascript support: https://developers.cloudflare.com/workers/runtime-apis/webassembly/javascript/
|
|
6
|
+
* @param disabled - if true throws a helpful error message if wasm is encountered and wasm imports are not enabled,
|
|
7
|
+
* otherwise it will error obscurely in the esbuild and vite builds
|
|
8
|
+
* @param assetsDirectory - the folder name for the assets directory in the build directory. Usually '_astro'
|
|
9
|
+
* @returns Vite plugin to load WASM tagged with '?module' as a WASM modules
|
|
10
|
+
*/
|
|
11
|
+
export declare function wasmModuleLoader({ disabled, assetsDirectory, }: {
|
|
12
|
+
disabled: boolean;
|
|
13
|
+
assetsDirectory: string;
|
|
14
|
+
}): Plugin;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import {} from "vite";
|
|
4
|
+
function wasmModuleLoader({
|
|
5
|
+
disabled,
|
|
6
|
+
assetsDirectory
|
|
7
|
+
}) {
|
|
8
|
+
const postfix = ".wasm?module";
|
|
9
|
+
let isDev = false;
|
|
10
|
+
return {
|
|
11
|
+
name: "vite:wasm-module-loader",
|
|
12
|
+
enforce: "pre",
|
|
13
|
+
configResolved(config) {
|
|
14
|
+
isDev = config.command === "serve";
|
|
15
|
+
},
|
|
16
|
+
config(_, __) {
|
|
17
|
+
return {
|
|
18
|
+
assetsInclude: ["**/*.wasm?module"],
|
|
19
|
+
build: { rollupOptions: { external: /^__WASM_ASSET__.+\.wasm\.mjs$/i } }
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
load(id, _) {
|
|
23
|
+
if (!id.endsWith(postfix)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (disabled) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`WASM module's cannot be loaded unless you add \`wasmModuleImports: true\` to your astro config.`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
const filePath = id.slice(0, -1 * "?module".length);
|
|
32
|
+
const data = fs.readFileSync(filePath);
|
|
33
|
+
const base64 = data.toString("base64");
|
|
34
|
+
const base64Module = `
|
|
35
|
+
const wasmModule = new WebAssembly.Module(Uint8Array.from(atob("${base64}"), c => c.charCodeAt(0)));
|
|
36
|
+
export default wasmModule
|
|
37
|
+
`;
|
|
38
|
+
if (isDev) {
|
|
39
|
+
return base64Module;
|
|
40
|
+
} else {
|
|
41
|
+
let hash = hashString(base64);
|
|
42
|
+
const assetName = path.basename(filePath).split(".")[0] + "." + hash + ".wasm";
|
|
43
|
+
this.emitFile({
|
|
44
|
+
type: "asset",
|
|
45
|
+
// put it explicitly in the _astro assets directory with `fileName` rather than `name` so that
|
|
46
|
+
// vite doesn't give it a random id in its name. We need to be able to easily rewrite from
|
|
47
|
+
// the .mjs loader and the actual wasm asset later in the ESbuild for the worker
|
|
48
|
+
fileName: path.join(assetsDirectory, assetName),
|
|
49
|
+
source: fs.readFileSync(filePath)
|
|
50
|
+
});
|
|
51
|
+
const chunkId = this.emitFile({
|
|
52
|
+
type: "prebuilt-chunk",
|
|
53
|
+
fileName: assetName + ".mjs",
|
|
54
|
+
code: base64Module
|
|
55
|
+
});
|
|
56
|
+
return `
|
|
57
|
+
import wasmModule from "__WASM_ASSET__${chunkId}.wasm.mjs";
|
|
58
|
+
export default wasmModule;
|
|
59
|
+
`;
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
// output original wasm file relative to the chunk
|
|
63
|
+
renderChunk(code, chunk, _) {
|
|
64
|
+
if (isDev)
|
|
65
|
+
return;
|
|
66
|
+
if (!/__WASM_ASSET__/g.test(code))
|
|
67
|
+
return;
|
|
68
|
+
const final = code.replaceAll(/__WASM_ASSET__([a-z\d]+).wasm.mjs/g, (s, assetId) => {
|
|
69
|
+
const fileName = this.getFileName(assetId);
|
|
70
|
+
const relativePath = path.relative(path.dirname(chunk.fileName), fileName).replaceAll("\\", "/");
|
|
71
|
+
return `./${relativePath}`;
|
|
72
|
+
});
|
|
73
|
+
return { code: final };
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function hashString(str) {
|
|
78
|
+
let hash = 0;
|
|
79
|
+
for (let i = 0; i < str.length; i++) {
|
|
80
|
+
const char = str.charCodeAt(i);
|
|
81
|
+
hash = (hash << 5) - hash + char;
|
|
82
|
+
hash &= hash;
|
|
83
|
+
}
|
|
84
|
+
return new Uint32Array([hash])[0].toString(36);
|
|
85
|
+
}
|
|
86
|
+
export {
|
|
87
|
+
wasmModuleLoader
|
|
88
|
+
};
|
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": "7.
|
|
4
|
+
"version": "7.3.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"author": "withastro",
|
|
@@ -41,19 +41,19 @@
|
|
|
41
41
|
"esbuild": "^0.19.2",
|
|
42
42
|
"find-up": "^6.3.0",
|
|
43
43
|
"tiny-glob": "^0.2.9",
|
|
44
|
+
"vite": "^4.4.9",
|
|
44
45
|
"@astrojs/underscore-redirects": "0.3.0"
|
|
45
46
|
},
|
|
46
47
|
"peerDependencies": {
|
|
47
|
-
"astro": "^3.1.
|
|
48
|
+
"astro": "^3.1.3"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"@types/iarna__toml": "^2.0.2",
|
|
51
52
|
"chai": "^4.3.7",
|
|
52
53
|
"cheerio": "1.0.0-rc.12",
|
|
53
|
-
"kill-port": "^2.0.1",
|
|
54
54
|
"mocha": "^10.2.0",
|
|
55
55
|
"wrangler": "^3.5.1",
|
|
56
|
-
"astro": "3.1.
|
|
56
|
+
"astro": "3.1.3",
|
|
57
57
|
"astro-scripts": "0.0.14"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|