From 4b4b95c7cd02d0aa591c82cc4813b0ba4d73dd8f Mon Sep 17 00:00:00 2001 From: Gordon Farquharson Date: Tue, 23 Sep 2025 18:14:22 +0100 Subject: [PATCH 1/2] feat: :truck: Migration Guides V2 Document and inform how to upgrade Static Servers BREAKING CHANGE: Static Asset Servers - new interface for multiple manifests per application --- DEVELOPMENT.md | 4 - docs/astro.config.mjs | 9 +++ .../docs/guides/creating-a-static-manifest.md | 76 +++++++++++++++++++ docs/src/content/docs/migrating/v1-v2.md | 72 ++++++++++++++++++ package.json | 1 + src/utils/config-helpers.ts | 7 +- 6 files changed, 162 insertions(+), 7 deletions(-) create mode 100644 docs/src/content/docs/guides/creating-a-static-manifest.md create mode 100644 docs/src/content/docs/migrating/v1-v2.md diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 690c26c..797eb59 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -54,7 +54,3 @@ npm run build:dev We use a docker image in our CI/CD pipeline for building. This can be used locally, see [Compiler README.md](./compiler/README.md) - -## Testing - -Coming soon... 🚀 diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index d85450f..490122b 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -33,6 +33,10 @@ export default defineConfig({ label: 'Serving a static site', link: `${import.meta.env.BASE_URL}guides/serving-a-static-site/`, }, + { + label: 'Creating static assets', + link: `${import.meta.env.BASE_URL}guides/creating-a-static-manifest/`, + }, ], collapsed: true, }, @@ -45,6 +49,11 @@ export default defineConfig({ collapsed: true, autogenerate: { directory: 'reference' }, }, + { + label: 'Migrating', + collapsed: true, + autogenerate: { directory: 'migrating' }, + }, ], }), ], diff --git a/docs/src/content/docs/guides/creating-a-static-manifest.md b/docs/src/content/docs/guides/creating-a-static-manifest.md new file mode 100644 index 0000000..5d82b1a --- /dev/null +++ b/docs/src/content/docs/guides/creating-a-static-manifest.md @@ -0,0 +1,76 @@ +--- +title: Creating a Static Asset Manifest +description: How to generate a static-asset-manifest for creating Static Servers. +--- + +Apart from using `npx fastedge-init` to create Static Sites you can also access the built-in tools +directly. + +`npx fastedge-init` is using this concept under the hood. + +## Static files + +Because the `wasm` runtime has no concept of a file system we are unable to serve static files in +the normal manner. + +To solve for this we are able to read files at `compile` time and store them within the wasm binary +itself as a UintArrayBuffer. + +For this purpose the FastEdge-sdk-js provides a `npx fastedge-assets` command. + +### fastedge-assets + +This command takes an input folder and an output filename. + +e.g. + +```sh +npx fastedge-assets ./public ./src/public-static-assets.ts +``` + +It then creates a "Static Assets Manifest" file which is a mapping of all files to include within +the binary at compile time. (i.e. all files within the `/public` directory) + +Simplified example: + +```js +const staticAssetManifest = { + '/gcore.png': { + assetKey: '/gcore.png', + contentType: 'image/png', + fileInfo: { size: 40261, assetPath: './images/gcore.png' }, + type: 'wasm-inline', + }, + '/home.png': { + assetKey: '/home.png', + contentType: 'image/png', + fileInfo: { size: 1502064, assetPath: './images/home.png' }, + type: 'wasm-inline', + }, +}; + +export { staticAssetManifest }; +``` + +This `manifest` can then be consumed by creating a Static Server using: + +```js +import { createStaticServer } from '@gcoredev/fastedge-sdk-js'; + +createStaticServer(staticAssetManifest, serverConfig); +``` + +Because +wizer +runs all top-level code before taking a snapshot, you need to ensure that `createStaticServer()` is +called within the main file at the top level. It cannot be nested in functions or async code that +may not run during compilation. + +This ensures that `staticAssetManifest` is iterated over and all files read into wasm memory. After +which `wizer` snapshots the current state, and creates the final wasm binary with all the file +contents included within the memory at startup. This process ensures there is **NO** start-up delay +and all files are available at runtime. + +There is a more complete example in our +FastEdge-examples +repo. diff --git a/docs/src/content/docs/migrating/v1-v2.md b/docs/src/content/docs/migrating/v1-v2.md new file mode 100644 index 0000000..e9e0e1c --- /dev/null +++ b/docs/src/content/docs/migrating/v1-v2.md @@ -0,0 +1,72 @@ +--- +title: Version 1.x.x > 2.x.x +description: Breaking changes in FastEdge-sdk-js@2.0.0 +--- + +### Static Asset Servers + +The way Static Asset Manifests are consumed has changed. + +The new version allows for multiple manifests within the same application as well as the ability to +read file content as a string. + +The easiest way for most people to make this migration is to purely re-run: + +```sh +npx fastedge-init +``` + +Unless you have custom written code using these functions, the default `static-index.js` should be +updated automatically for you. + +Version 1: + +```ts +import { getStaticServer, createStaticAssetsCache } from '@gcoredev/fastedge-sdk-js'; +import { staticAssetManifest } from './build/static-server-manifest.js'; +import { serverConfig } from './build-config.js'; + +const staticAssets = createStaticAssetsCache(staticAssetManifest); + +const staticServer = getStaticServer(serverConfig, staticAssets); + +async function handleRequest(event) { + const response = await staticServer.serveRequest(event.request); + if (response != null) { + return response; + } + + return new Response('Not found', { status: 404 }); +} + +addEventListener('fetch', (event) => event.respondWith(handleRequest(event))); +``` + +Version 2: + +```ts +import { createStaticServer } from '@gcoredev/fastedge-sdk-js'; +import { staticAssetManifest } from './build/static-asset-manifest.js'; +import { serverConfig } from './build-config.js'; + +const staticServer = createStaticServer(staticAssetManifest, serverConfig); + +async function handleRequest(event) { + const response = await staticServer.serveRequest(event.request); + if (response != null) { + return response; + } + + return new Response('Not found', { status: 404 }); +} + +addEventListener('fetch', (event) => event.respondWith(handleRequest(event))); +``` + +:::note[INFO] + +For more examples about the new version see our +FastEdge-examples +repo. + +::: diff --git a/package.json b/package.json index a544b48..212985b 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ }, "files": [ "types", + "bin/fastedge-assets.js", "bin/fastedge-build.js", "bin/fastedge-init.js", "lib/*.wasm", diff --git a/src/utils/config-helpers.ts b/src/utils/config-helpers.ts index 2d54064..68a8e13 100644 --- a/src/utils/config-helpers.ts +++ b/src/utils/config-helpers.ts @@ -3,14 +3,14 @@ * @param str - The string to process. * @returns The string without the './' prefix. */ -const removeDotSlashPrefix = (str: string): string => str.replace(/^\.\//u, ''); +const removeDotSlashPrefix = (str: string = ''): string => str.replace(/^\.\//u, ''); /** * Removes trailing slashes from a given string. * @param str - The string to process. * @returns The string without trailing slashes. */ -const removeTrailingSlash = (str: string): string => str.replace(/\/+$/u, ''); +const removeTrailingSlash = (str: string = ''): string => str.replace(/\/+$/u, ''); /** * Takes a path string and ensures it has no trailing slash and has a single preceding slash. @@ -152,7 +152,8 @@ function normalizeConfig>( const normalizeFn = normalizeFns[normalizeFnKey]; if (normalizeFn) { // eslint-disable-next-line @typescript-eslint/no-explicit-any - result[key] = normalizeFn(config[key] as any) as T[keyof T]; + const input = (config[key] ?? undefined) as any; + result[key] = normalizeFn(input) as T[keyof T]; } }); From f0bdf47166c12cf0f62def20a2c3e6a7f9339729 Mon Sep 17 00:00:00 2001 From: Gordon Farquharson Date: Tue, 23 Sep 2025 19:21:35 +0100 Subject: [PATCH 2/2] feat: :bug: Ensure FastEdge-assets is included as a binary fastedge-assets is now a node script fastedge-assets new interface --- esbuild/cli-binaries.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esbuild/cli-binaries.js b/esbuild/cli-binaries.js index 13b2f6c..92f9eb8 100644 --- a/esbuild/cli-binaries.js +++ b/esbuild/cli-binaries.js @@ -3,7 +3,7 @@ import { fileURLToPath } from "node:url"; import path from "node:path"; import { readFileSync, writeFileSync } from "node:fs"; -const entryPoints = [ +const entryPoints = [ { src: "./src/cli/fastedge-assets/asset-cli.ts", dest: "./bin/fastedge-assets.js" }, { src: "./src/cli/fastedge-build/build.ts", dest: "./bin/fastedge-build.js" }, { src: "./src/cli/fastedge-init/init.ts", dest: "./bin/fastedge-init.js" }, @@ -50,5 +50,6 @@ const prependNodeShebangToFile = (relativeFilePath) => { } }; +prependNodeShebangToFile("./bin/fastedge-assets.js"); prependNodeShebangToFile("./bin/fastedge-build.js"); prependNodeShebangToFile("./bin/fastedge-init.js");