From c3f976fa3ecc2b6c97b666bc5054635abea648e2 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 16:22:30 -0300 Subject: [PATCH 01/33] Removed ignores --- .gitignore | 1 - .prettierignore | 1 - examples/blog-multiple-authors/.gitignore | 1 - examples/blog/.gitignore | 1 - examples/component/.gitignore | 1 - examples/docs/.gitignore | 1 - examples/env-vars/.gitignore | 1 - examples/framework-alpine/.gitignore | 1 - examples/framework-lit/.gitignore | 1 - examples/framework-multiple/.gitignore | 1 - examples/framework-preact/.gitignore | 1 - examples/framework-react/.gitignore | 1 - examples/framework-solid/.gitignore | 1 - examples/framework-svelte/.gitignore | 1 - examples/framework-vue/.gitignore | 1 - examples/integrations-playground/.gitignore | 1 - examples/minimal/.gitignore | 1 - examples/non-html-pages/.gitignore | 1 - examples/portfolio/.gitignore | 1 - examples/starter/.gitignore | 1 - examples/subpath/.gitignore | 1 - examples/with-markdown-plugins/.gitignore | 1 - examples/with-markdown-shiki/.gitignore | 1 - examples/with-markdown/.gitignore | 1 - examples/with-nanostores/.gitignore | 1 - examples/with-tailwindcss/.gitignore | 1 - examples/with-vite-plugin-pwa/.gitignore | 1 - 27 files changed, 27 deletions(-) diff --git a/.gitignore b/.gitignore index 30c24d1e9698..fa9abb6d0e3c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ node_modules/ dist/ -.output/ *.tsbuildinfo .DS_Store .vercel diff --git a/.prettierignore b/.prettierignore index 7c89fbaf5aef..7b6398b3e22d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,7 +4,6 @@ # Deep Directories **/dist -**/.output **/smoke **/node_modules **/fixtures diff --git a/examples/blog-multiple-authors/.gitignore b/examples/blog-multiple-authors/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/blog-multiple-authors/.gitignore +++ b/examples/blog-multiple-authors/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/blog/.gitignore b/examples/blog/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/blog/.gitignore +++ b/examples/blog/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/component/.gitignore b/examples/component/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/component/.gitignore +++ b/examples/component/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/docs/.gitignore b/examples/docs/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/docs/.gitignore +++ b/examples/docs/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/env-vars/.gitignore b/examples/env-vars/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/env-vars/.gitignore +++ b/examples/env-vars/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/framework-alpine/.gitignore b/examples/framework-alpine/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/framework-alpine/.gitignore +++ b/examples/framework-alpine/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/framework-lit/.gitignore b/examples/framework-lit/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/framework-lit/.gitignore +++ b/examples/framework-lit/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/framework-multiple/.gitignore b/examples/framework-multiple/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/framework-multiple/.gitignore +++ b/examples/framework-multiple/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/framework-preact/.gitignore b/examples/framework-preact/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/framework-preact/.gitignore +++ b/examples/framework-preact/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/framework-react/.gitignore b/examples/framework-react/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/framework-react/.gitignore +++ b/examples/framework-react/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/framework-solid/.gitignore b/examples/framework-solid/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/framework-solid/.gitignore +++ b/examples/framework-solid/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/framework-svelte/.gitignore b/examples/framework-svelte/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/framework-svelte/.gitignore +++ b/examples/framework-svelte/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/framework-vue/.gitignore b/examples/framework-vue/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/framework-vue/.gitignore +++ b/examples/framework-vue/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/integrations-playground/.gitignore b/examples/integrations-playground/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/integrations-playground/.gitignore +++ b/examples/integrations-playground/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/minimal/.gitignore b/examples/minimal/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/minimal/.gitignore +++ b/examples/minimal/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/non-html-pages/.gitignore b/examples/non-html-pages/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/non-html-pages/.gitignore +++ b/examples/non-html-pages/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/portfolio/.gitignore b/examples/portfolio/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/portfolio/.gitignore +++ b/examples/portfolio/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/starter/.gitignore b/examples/starter/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/starter/.gitignore +++ b/examples/starter/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/subpath/.gitignore b/examples/subpath/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/subpath/.gitignore +++ b/examples/subpath/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/with-markdown-plugins/.gitignore b/examples/with-markdown-plugins/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/with-markdown-plugins/.gitignore +++ b/examples/with-markdown-plugins/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/with-markdown-shiki/.gitignore b/examples/with-markdown-shiki/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/with-markdown-shiki/.gitignore +++ b/examples/with-markdown-shiki/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/with-markdown/.gitignore b/examples/with-markdown/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/with-markdown/.gitignore +++ b/examples/with-markdown/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/with-nanostores/.gitignore b/examples/with-nanostores/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/with-nanostores/.gitignore +++ b/examples/with-nanostores/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/with-tailwindcss/.gitignore b/examples/with-tailwindcss/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/with-tailwindcss/.gitignore +++ b/examples/with-tailwindcss/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ diff --git a/examples/with-vite-plugin-pwa/.gitignore b/examples/with-vite-plugin-pwa/.gitignore index 7329a851d0ac..02f6e50b494c 100644 --- a/examples/with-vite-plugin-pwa/.gitignore +++ b/examples/with-vite-plugin-pwa/.gitignore @@ -1,6 +1,5 @@ # build output dist/ -.output/ # dependencies node_modules/ From a55569d9de69631693342fa342870296df80625a Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 17:26:38 -0300 Subject: [PATCH 02/33] Migration to v3 --- packages/integrations/vercel/package.json | 5 +- .../vercel/src/edge/entrypopint.ts | 21 ++ packages/integrations/vercel/src/edge/shim.ts | 4 + packages/integrations/vercel/src/index.ts | 209 ++++++++++-------- .../entrypoint.ts} | 0 .../src/{ => serverless}/request-transform.ts | 0 pnpm-lock.yaml | 22 +- 7 files changed, 160 insertions(+), 101 deletions(-) create mode 100644 packages/integrations/vercel/src/edge/entrypopint.ts create mode 100644 packages/integrations/vercel/src/edge/shim.ts rename packages/integrations/vercel/src/{server-entrypoint.ts => serverless/entrypoint.ts} (100%) rename packages/integrations/vercel/src/{ => serverless}/request-transform.ts (100%) diff --git a/packages/integrations/vercel/package.json b/packages/integrations/vercel/package.json index 440d298dce6f..82429da4188a 100644 --- a/packages/integrations/vercel/package.json +++ b/packages/integrations/vercel/package.json @@ -15,7 +15,8 @@ "homepage": "https://astro.build", "exports": { ".": "./dist/index.js", - "./server-entrypoint": "./dist/server-entrypoint.js", + "./edge": "./dist/edge/entrypoint.js", + "./serverless": "./dist/serverless/entrypoint.js", "./package.json": "./package.json" }, "scripts": { @@ -25,7 +26,7 @@ }, "dependencies": { "@astrojs/webapi": "^0.11.1", - "esbuild": "^0.14.38" + "@vercel/routing-utils": "^1.13.1" }, "devDependencies": { "astro": "workspace:*", diff --git a/packages/integrations/vercel/src/edge/entrypopint.ts b/packages/integrations/vercel/src/edge/entrypopint.ts new file mode 100644 index 000000000000..016ddac90aa4 --- /dev/null +++ b/packages/integrations/vercel/src/edge/entrypopint.ts @@ -0,0 +1,21 @@ +import './shim.js'; + +import type { SSRManifest } from 'astro'; +import { App } from 'astro/app'; + +export function createExports(manifest: SSRManifest) { + const app = new App(manifest); + + const handler = async (request: Request): Promise => { + if (app.match(request)) { + return app.render(request); + } + + return new Response(null, { + status: 404, + statusText: 'Not found', + }); + }; + + return { default: handler }; +} diff --git a/packages/integrations/vercel/src/edge/shim.ts b/packages/integrations/vercel/src/edge/shim.ts new file mode 100644 index 000000000000..1a4a6ee9be4c --- /dev/null +++ b/packages/integrations/vercel/src/edge/shim.ts @@ -0,0 +1,4 @@ +(globalThis as any).process = { + argv: [], + env: {}, +}; diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts index 35d20d42f661..d9d9ec9cced5 100644 --- a/packages/integrations/vercel/src/index.ts +++ b/packages/integrations/vercel/src/index.ts @@ -1,139 +1,166 @@ -import type { AstroAdapter, AstroConfig, AstroIntegration, RouteData } from 'astro'; +import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; import type { PathLike } from 'fs'; import fs from 'fs/promises'; -import { fileURLToPath } from 'url'; -import esbuild from 'esbuild'; +import { getTransformedRoutes, Redirect, Rewrite } from '@vercel/routing-utils'; const writeJson = (path: PathLike, data: any) => fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); -const ENTRYFILE = '__astro_entry'; - -export function getAdapter(): AstroAdapter { +export function getAdapter({ edge }: { edge: boolean }): AstroAdapter { return { name: '@astrojs/vercel', - serverEntrypoint: '@astrojs/vercel/server-entrypoint', + serverEntrypoint: `@astrojs/vercel/${edge ? 'edge' : 'serverless'}`, exports: ['default'], }; } -export default function vercel(): AstroIntegration { +export interface Options { + edge?: boolean; +} + +export default function vercel({ edge = false }: Options = {}): AstroIntegration { let _config: AstroConfig; - let _serverEntry: URL; + let _serverOut: URL; + let _serverEntry: string; return { name: '@astrojs/vercel', hooks: { 'astro:config:setup': ({ config }) => { - config.outDir = new URL('./.output/', config.root); - config.build.format = 'directory'; + config.outDir = new URL('./.vercel/output/', config.root); }, 'astro:config:done': ({ setAdapter, config }) => { - setAdapter(getAdapter()); + if (edge) { + throw new Error('The `edge` option is not yet supported.'); + } + + setAdapter(getAdapter({ edge })); _config = config; - _serverEntry = new URL(`./server/pages/${ENTRYFILE}.js`, config.outDir); }, 'astro:build:setup': ({ vite, target }) => { if (target === 'server') { - vite.build!.rollupOptions = { - input: [], - output: { - format: 'cjs', - file: fileURLToPath(_serverEntry), - dir: undefined, - entryFileNames: undefined, - chunkFileNames: undefined, - assetFileNames: undefined, - inlineDynamicImports: true, + vite.build = { + ...(vite.build || {}), + rollupOptions: { + ...(vite.build?.rollupOptions || {}), + output: { + ...(vite.build?.rollupOptions || {}), + format: 'cjs', + }, }, }; } }, 'astro:build:start': async ({ buildConfig }) => { - buildConfig.serverEntry = `${ENTRYFILE}.js`; + buildConfig.serverEntry = _serverEntry = 'entry.js'; buildConfig.client = new URL('./static/', _config.outDir); - buildConfig.server = new URL('./server/pages/', _config.outDir); + buildConfig.server = _serverOut = new URL('./functions/render.func/', _config.outDir); - if (String(process.env.ENABLE_FILE_SYSTEM_API) !== '1') { + if (String(process.env.ENABLE_VC_BUILD) !== '1') { console.warn( - `The enviroment variable "ENABLE_FILE_SYSTEM_API" was not found. Make sure you have it set to "1" in your Vercel project.\nLearn how to set enviroment variables here: https://vercel.com/docs/concepts/projects/environment-variables` + `The enviroment variable "ENABLE_VC_BUILD" was not found. Make sure you have it set to "1" in your Vercel project.\nLearn how to set enviroment variables here: https://vercel.com/docs/concepts/projects/environment-variables` ); } }, 'astro:build:done': async ({ routes }) => { - // Bundle dependecies - await esbuild.build({ - entryPoints: [fileURLToPath(_serverEntry)], - outfile: fileURLToPath(_serverEntry), - bundle: true, - format: 'cjs', - platform: 'node', - target: 'node14', - allowOverwrite: true, - minifyWhitespace: true, - }); + if (edge) { + // Edge function config + // https://vercel.com/docs/build-output-api/v3#vercel-primitives/edge-functions/configuration + await writeJson(new URL(`./.vc-config.json`, _serverOut), { + runtime: 'edge', + entrypoint: _serverEntry, + }); + } else { + // Serverless function config + // https://vercel.com/docs/build-output-api/v3#vercel-primitives/serverless-functions/configuration + await writeJson(new URL(`./.vc-config.json`, _serverOut), { + runtime: 'nodejs14.x', + handler: _serverEntry, + launcherType: 'Nodejs', + }); + } - let staticRoutes: RouteData[] = []; - let dynamicRoutes: RouteData[] = []; + let rewrites: Rewrite[] = []; + let redirects: Redirect[] = []; for (const route of routes) { - if (route.params.length === 0) staticRoutes.push(route); - else dynamicRoutes.push(route); + const path = + _config.base + + route.segments + .map((segments) => + segments + .map((part) => + part.spread + ? `:${part.content}*` + : part.dynamic + ? `:${part.content}` + : part.content + ) + .join('') + ) + .join('/'); + + rewrites.push({ + source: path, + destination: '/render', + }); + + if (_config.trailingSlash === 'always') { + redirects.push({ + source: path, + destination: path + '/', + }); + } else if (_config.trailingSlash === 'never') { + redirects.push({ + source: path + '/', + destination: path, + }); + } } - // Routes Manifest - // https://vercel.com/docs/file-system-api#configuration/routes - await writeJson(new URL(`./routes-manifest.json`, _config.outDir), { + // Output configuration + // https://vercel.com/docs/build-output-api/v3#build-output-configuration + await writeJson(new URL(`./config.json`, _config.outDir), { version: 3, - basePath: '/', - pages404: false, - redirects: - // Extracted from Next.js v12.1.5 - _config.trailingSlash === 'always' - ? [ - { - source: '/:file((?!\\.well-known(?:/.*)?)(?:[^/]+/)*[^/]+\\.\\w+)/', - destination: '/:file', - internal: true, - statusCode: 308, - regex: '^(?:/((?!\\.well-known(?:/.*)?)(?:[^/]+/)*[^/]+\\.\\w+))/$', - }, - { - source: '/:notfile((?!\\.well-known(?:/.*)?)(?:[^/]+/)*[^/\\.]+)', - destination: '/:notfile/', - internal: true, - statusCode: 308, - regex: '^(?:/((?!\\.well-known(?:/.*)?)(?:[^/]+/)*[^/\\.]+))$', - }, - ] - : _config.trailingSlash === 'never' - ? [ - { - source: '/:path+/', - destination: '/:path+', - internal: true, - statusCode: 308, - regex: '^(?:/((?:[^/]+?)(?:/(?:[^/]+?))*))/$', - }, - ] - : undefined, - rewrites: staticRoutes.map((route) => { - let source = route.pathname as string; + routes: getTransformedRoutes({ + nowConfig: { + rewrites: [], + redirects: + _config.trailingSlash !== 'ignore' + ? routes + .filter((route) => route.type === 'page' && !route.pathname?.endsWith('/')) + .map((route) => { + const path = + '/' + + route.segments + .map((segments) => + segments + .map((part) => + part.spread + ? `:${part.content}*` + : part.dynamic + ? `:${part.content}` + : part.content + ) + .join('') + ) + .join('/'); - if (_config.trailingSlash === 'always' && !source.endsWith('/')) { - source += '/'; - } + let source, destination; - return { - source, - regex: route.pattern.toString(), - destination: `/${ENTRYFILE}`, - }; + if (_config.trailingSlash === 'always') { + source = path; + destination = path + '/'; + } else { + source = path + '/'; + destination = path; + } + + return { source, destination, statusCode: 308 }; + }) + : [], + }, }), - dynamicRoutes: dynamicRoutes.map((route) => ({ - page: `/${ENTRYFILE}`, - regex: route.pattern.toString(), - })), }); }, }, diff --git a/packages/integrations/vercel/src/server-entrypoint.ts b/packages/integrations/vercel/src/serverless/entrypoint.ts similarity index 100% rename from packages/integrations/vercel/src/server-entrypoint.ts rename to packages/integrations/vercel/src/serverless/entrypoint.ts diff --git a/packages/integrations/vercel/src/request-transform.ts b/packages/integrations/vercel/src/serverless/request-transform.ts similarity index 100% rename from packages/integrations/vercel/src/request-transform.ts rename to packages/integrations/vercel/src/serverless/request-transform.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7920fc6ed2f5..080b2400c11b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1443,12 +1443,12 @@ importers: packages/integrations/vercel: specifiers: '@astrojs/webapi': ^0.11.1 + '@vercel/routing-utils': ^1.13.1 astro: workspace:* astro-scripts: workspace:* - esbuild: ^0.14.38 dependencies: '@astrojs/webapi': link:../../webapi - esbuild: 0.14.38 + '@vercel/routing-utils': 1.13.1 devDependencies: astro: link:../../astro astro-scripts: link:../../../scripts @@ -4318,6 +4318,14 @@ packages: '@unocss/scope': 0.15.6 dev: true + /@vercel/routing-utils/1.13.1: + resolution: {integrity: sha512-LNKkr9AuX4dX79eJIhPJw5EcStYHxHFp/htFRHtuMVSHmxpDQQ2Wv4LqgQY+dMzvpQ207h9JKIRlI1XQqiswpw==} + dependencies: + path-to-regexp: 6.1.0 + optionalDependencies: + ajv: 6.12.6 + dev: false + /@vitejs/plugin-vue/2.3.1_vue@3.2.33: resolution: {integrity: sha512-YNzBt8+jt6bSwpt7LP890U1UcTOIZZxfpE5WOJ638PNxSEKOqAi0+FSKS0nVeukfdZ0Ai/H7AFd6k3hayfGZqQ==} engines: {node: '>=12.0.0'} @@ -4504,7 +4512,6 @@ packages: fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - dev: true /ajv/8.11.0: resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} @@ -6088,7 +6095,6 @@ packages: /fast-deep-equal/3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true /fast-diff/1.2.0: resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} @@ -6106,7 +6112,6 @@ packages: /fast-json-stable-stringify/2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true /fast-levenshtein/2.0.6: resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} @@ -7123,7 +7128,6 @@ packages: /json-schema-traverse/0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true /json-schema-traverse/1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} @@ -8403,6 +8407,10 @@ packages: /path-parse/1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + /path-to-regexp/6.1.0: + resolution: {integrity: sha512-h9DqehX3zZZDCEm+xbfU0ZmwCGFCAAraPJWMXJ4+v32NjZJilVg3k1TcKsRgIb8IQ/izZSaydDc1OhJCZvs2Dw==} + dev: false + /path-to-regexp/6.2.0: resolution: {integrity: sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==} dev: false @@ -8645,7 +8653,6 @@ packages: /punycode/2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} - dev: true /queue-microtask/1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -10292,7 +10299,6 @@ packages: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.1.1 - dev: true /urlpattern-polyfill/1.0.0-rc5: resolution: {integrity: sha512-OxVmQLKMQbDZX1m8Ljuf26rzMUJ7lm3cnBAicqrB0qmo1qb/koH7EXayeHiZdiyc6Z0OnaHETW2JCoVHgTnGGA==} From 8a9d292737ecc3bb938be22c0d3ef69113adb84b Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 18:14:59 -0300 Subject: [PATCH 03/33] More changes --- packages/integrations/vercel/package.json | 3 +- packages/integrations/vercel/src/index.ts | 103 +++++++++++++--------- pnpm-lock.yaml | 2 + 3 files changed, 66 insertions(+), 42 deletions(-) diff --git a/packages/integrations/vercel/package.json b/packages/integrations/vercel/package.json index 82429da4188a..ae92a9df71aa 100644 --- a/packages/integrations/vercel/package.json +++ b/packages/integrations/vercel/package.json @@ -26,7 +26,8 @@ }, "dependencies": { "@astrojs/webapi": "^0.11.1", - "@vercel/routing-utils": "^1.13.1" + "@vercel/routing-utils": "^1.13.1", + "esbuild": "^0.14.38" }, "devDependencies": { "astro": "workspace:*", diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts index d9d9ec9cced5..b441467a639a 100644 --- a/packages/integrations/vercel/src/index.ts +++ b/packages/integrations/vercel/src/index.ts @@ -1,6 +1,9 @@ import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; import type { PathLike } from 'fs'; + import fs from 'fs/promises'; +import { fileURLToPath } from 'url'; +import esbuild from 'esbuild'; import { getTransformedRoutes, Redirect, Rewrite } from '@vercel/routing-utils'; const writeJson = (path: PathLike, data: any) => @@ -38,13 +41,13 @@ export default function vercel({ edge = false }: Options = {}): AstroIntegration _config = config; }, 'astro:build:setup': ({ vite, target }) => { - if (target === 'server') { + if (!edge && target === 'server') { vite.build = { ...(vite.build || {}), rollupOptions: { ...(vite.build?.rollupOptions || {}), output: { - ...(vite.build?.rollupOptions || {}), + ...(vite.build?.rollupOptions?.output || {}), format: 'cjs', }, }, @@ -63,6 +66,18 @@ export default function vercel({ edge = false }: Options = {}): AstroIntegration } }, 'astro:build:done': async ({ routes }) => { + const entryPath = fileURLToPath(new URL(_serverEntry, _serverOut)); + + // Bundle dependencies + await esbuild.build({ + entryPoints: [entryPath], + outfile: entryPath, + bundle: true, + target: 'node14', + allowOverwrite: true, + ...(edge ? { format: 'esm', platform: 'browser' } : { format: 'cjs', platform: 'node' }), + }); + if (edge) { // Edge function config // https://vercel.com/docs/build-output-api/v3#vercel-primitives/edge-functions/configuration @@ -118,49 +133,55 @@ export default function vercel({ edge = false }: Options = {}): AstroIntegration } } + const transformedRoutes = getTransformedRoutes({ + nowConfig: { + rewrites: [], + redirects: + _config.trailingSlash !== 'ignore' + ? routes + .filter((route) => route.type === 'page' && !route.pathname?.endsWith('/')) + .map((route) => { + const path = + '/' + + route.segments + .map((segments) => + segments + .map((part) => + part.spread + ? `:${part.content}*` + : part.dynamic + ? `:${part.content}` + : part.content + ) + .join('') + ) + .join('/'); + + let source, destination; + + if (_config.trailingSlash === 'always') { + source = path; + destination = path + '/'; + } else { + source = path + '/'; + destination = path; + } + + return { source, destination, statusCode: 308 }; + }) + : [], + }, + }); + + if (transformedRoutes.error) { + throw new Error(JSON.stringify(transformedRoutes.error, null, 2)); + } + // Output configuration // https://vercel.com/docs/build-output-api/v3#build-output-configuration await writeJson(new URL(`./config.json`, _config.outDir), { version: 3, - routes: getTransformedRoutes({ - nowConfig: { - rewrites: [], - redirects: - _config.trailingSlash !== 'ignore' - ? routes - .filter((route) => route.type === 'page' && !route.pathname?.endsWith('/')) - .map((route) => { - const path = - '/' + - route.segments - .map((segments) => - segments - .map((part) => - part.spread - ? `:${part.content}*` - : part.dynamic - ? `:${part.content}` - : part.content - ) - .join('') - ) - .join('/'); - - let source, destination; - - if (_config.trailingSlash === 'always') { - source = path; - destination = path + '/'; - } else { - source = path + '/'; - destination = path; - } - - return { source, destination, statusCode: 308 }; - }) - : [], - }, - }), + routes: transformedRoutes.routes, }); }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2a59f5457f05..87acc9171b37 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1440,9 +1440,11 @@ importers: '@vercel/routing-utils': ^1.13.1 astro: workspace:* astro-scripts: workspace:* + esbuild: ^0.14.38 dependencies: '@astrojs/webapi': link:../../webapi '@vercel/routing-utils': 1.13.1 + esbuild: 0.14.38 devDependencies: astro: link:../../astro astro-scripts: link:../../../scripts From 34cd040343a49e33b07a96b62b380a8b49c7308d Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 18:24:53 -0300 Subject: [PATCH 04/33] Remove legacy redirects --- packages/integrations/vercel/src/index.ts | 38 +---------------------- 1 file changed, 1 insertion(+), 37 deletions(-) diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts index b441467a639a..ae2e41c23e1a 100644 --- a/packages/integrations/vercel/src/index.ts +++ b/packages/integrations/vercel/src/index.ts @@ -134,43 +134,7 @@ export default function vercel({ edge = false }: Options = {}): AstroIntegration } const transformedRoutes = getTransformedRoutes({ - nowConfig: { - rewrites: [], - redirects: - _config.trailingSlash !== 'ignore' - ? routes - .filter((route) => route.type === 'page' && !route.pathname?.endsWith('/')) - .map((route) => { - const path = - '/' + - route.segments - .map((segments) => - segments - .map((part) => - part.spread - ? `:${part.content}*` - : part.dynamic - ? `:${part.content}` - : part.content - ) - .join('') - ) - .join('/'); - - let source, destination; - - if (_config.trailingSlash === 'always') { - source = path; - destination = path + '/'; - } else { - source = path + '/'; - destination = path; - } - - return { source, destination, statusCode: 308 }; - }) - : [], - }, + nowConfig: { rewrites, redirects }, }); if (transformedRoutes.error) { From 0219fcd53b19f9dc45bde11b7f568d1eca89b08c Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 18:25:12 -0300 Subject: [PATCH 05/33] Fail when there is no ENABLE_VC_BUILD --- packages/integrations/vercel/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts index ae2e41c23e1a..d7c0c349d221 100644 --- a/packages/integrations/vercel/src/index.ts +++ b/packages/integrations/vercel/src/index.ts @@ -60,7 +60,7 @@ export default function vercel({ edge = false }: Options = {}): AstroIntegration buildConfig.server = _serverOut = new URL('./functions/render.func/', _config.outDir); if (String(process.env.ENABLE_VC_BUILD) !== '1') { - console.warn( + throw new Error( `The enviroment variable "ENABLE_VC_BUILD" was not found. Make sure you have it set to "1" in your Vercel project.\nLearn how to set enviroment variables here: https://vercel.com/docs/concepts/projects/environment-variables` ); } From 9de24d268c01870527b1d0142999e92d0497e93d Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 18:44:46 -0300 Subject: [PATCH 06/33] Fix edge --- .../vercel/src/edge/{entrypopint.ts => entrypoint.ts} | 0 packages/integrations/vercel/src/index.ts | 4 ---- 2 files changed, 4 deletions(-) rename packages/integrations/vercel/src/edge/{entrypopint.ts => entrypoint.ts} (100%) diff --git a/packages/integrations/vercel/src/edge/entrypopint.ts b/packages/integrations/vercel/src/edge/entrypoint.ts similarity index 100% rename from packages/integrations/vercel/src/edge/entrypopint.ts rename to packages/integrations/vercel/src/edge/entrypoint.ts diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts index d7c0c349d221..93259a06bb55 100644 --- a/packages/integrations/vercel/src/index.ts +++ b/packages/integrations/vercel/src/index.ts @@ -33,10 +33,6 @@ export default function vercel({ edge = false }: Options = {}): AstroIntegration config.outDir = new URL('./.vercel/output/', config.root); }, 'astro:config:done': ({ setAdapter, config }) => { - if (edge) { - throw new Error('The `edge` option is not yet supported.'); - } - setAdapter(getAdapter({ edge })); _config = config; }, From e11b6f1160b68ad68befebd97e205e1d4ca80d60 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 18:49:53 -0300 Subject: [PATCH 07/33] Updated readme --- packages/integrations/vercel/README.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/integrations/vercel/README.md b/packages/integrations/vercel/README.md index 0536fa49fdb2..e9f9097b690d 100644 --- a/packages/integrations/vercel/README.md +++ b/packages/integrations/vercel/README.md @@ -13,24 +13,27 @@ export default defineConfig({ }); ``` -When you build your project, Astro will know to use the `.output` folder format that Vercel expects. +When you build your project, Astro will know to use the `.vercel/output` folder format that Vercel expects. -``` -astro build -``` +## Deploying -That's it! You can deploy by CLI (`vercel deploy`) or by connecting your new repo in the [Vercel Dashboard](https://vercel.com/). +You can deploy by CLI (`vercel deploy`) or by connecting your new repo in the [Vercel Dashboard](https://vercel.com/). Alternatively, you can create a production build locally: + +```sh +ENABLE_VC_BUILD=1 astro build +vercel deploy --prebuilt +``` ## Requirements -**Vercel's [File System API](https://vercel.com/docs/file-system-api/v2) must be enabled.** You must enable it yourself by setting the environment variable: `ENABLE_FILE_SYSTEM_API=1`. +**Vercel's [Build Output API](https://vercel.com/docs/build-output-api/v3) must be enabled.** You must enable it yourself by setting the environment variable: `ENABLE_VC_BUILD=1`. ```js // vercel.json { "build": { "env": { - "ENABLE_FILE_SYSTEM_API": "1" + "ENABLE_VC_BUILD": "1" } } } From f6ddaed39181017d33874ceae3e5a405bc1a87a5 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 18:52:41 -0300 Subject: [PATCH 08/33] Changeset --- .changeset/tiny-apes-shave.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/tiny-apes-shave.md diff --git a/.changeset/tiny-apes-shave.md b/.changeset/tiny-apes-shave.md new file mode 100644 index 000000000000..cd703136223f --- /dev/null +++ b/.changeset/tiny-apes-shave.md @@ -0,0 +1,8 @@ +--- +'@astrojs/vercel': minor +--- + +Updated to Build Output API (v3): + +- Make sure to rename the `ENABLE_FILE_SYSTEM_API` enviroment variable to `ENABLE_VC_BUILD`. +- The output folder changed from `.output` to `.vercel/output` From a7a966e2cfe3081973251a2470c6e74b9b519998 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 20:13:28 -0300 Subject: [PATCH 09/33] Added static mode --- packages/integrations/vercel/src/index.ts | 149 ++++++++++++++-------- 1 file changed, 93 insertions(+), 56 deletions(-) diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts index 93259a06bb55..8f9d19dc748b 100644 --- a/packages/integrations/vercel/src/index.ts +++ b/packages/integrations/vercel/src/index.ts @@ -9,35 +9,56 @@ import { getTransformedRoutes, Redirect, Rewrite } from '@vercel/routing-utils'; const writeJson = (path: PathLike, data: any) => fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); -export function getAdapter({ edge }: { edge: boolean }): AstroAdapter { - return { +export interface Options { + /** + * - `static`: generates a static website following Vercel's output formats, redirects, etc. + * - `serverless`: SSR inside a [Node.js 14 function](https://vercel.com/docs/concepts/functions/serverless-functions). + * - `edge`: SSR inside a [Edge function](https://vercel.com/docs/concepts/functions/edge-functions). + * + * @type {'static' | 'serverless' | 'edge'} + * @default {'serverless'} + */ + mode?: 'static' | 'serverless' | 'edge'; +} + +function getAdapter({ mode }: { mode: NonNullable }): AstroAdapter { + let adapter: AstroAdapter = { name: '@astrojs/vercel', - serverEntrypoint: `@astrojs/vercel/${edge ? 'edge' : 'serverless'}`, - exports: ['default'], }; -} -export interface Options { - edge?: boolean; + if (mode !== 'static') { + adapter.serverEntrypoint = `@astrojs/vercel/${mode}`; + adapter.exports = ['default']; + } + + return adapter; } -export default function vercel({ edge = false }: Options = {}): AstroIntegration { +export default function vercel({ mode = 'serverless' }: Options = {}): AstroIntegration { let _config: AstroConfig; - let _serverOut: URL; + let _vercelOut: URL; + let _functionsFolder: URL; let _serverEntry: string; return { name: '@astrojs/vercel', hooks: { 'astro:config:setup': ({ config }) => { - config.outDir = new URL('./.vercel/output/', config.root); + _vercelOut = new URL('./.vercel/output/', config.root); + + if (mode === 'static') { + config.outDir = new URL('./static/', _vercelOut); + config.build.format = 'directory'; + } else { + config.outDir = _vercelOut; + } }, 'astro:config:done': ({ setAdapter, config }) => { - setAdapter(getAdapter({ edge })); + setAdapter(getAdapter({ mode })); _config = config; }, 'astro:build:setup': ({ vite, target }) => { - if (!edge && target === 'server') { + if (mode === 'serverless' && target === 'server') { vite.build = { ...(vite.build || {}), rollupOptions: { @@ -51,44 +72,55 @@ export default function vercel({ edge = false }: Options = {}): AstroIntegration } }, 'astro:build:start': async ({ buildConfig }) => { - buildConfig.serverEntry = _serverEntry = 'entry.js'; - buildConfig.client = new URL('./static/', _config.outDir); - buildConfig.server = _serverOut = new URL('./functions/render.func/', _config.outDir); - if (String(process.env.ENABLE_VC_BUILD) !== '1') { throw new Error( `The enviroment variable "ENABLE_VC_BUILD" was not found. Make sure you have it set to "1" in your Vercel project.\nLearn how to set enviroment variables here: https://vercel.com/docs/concepts/projects/environment-variables` ); } - }, - 'astro:build:done': async ({ routes }) => { - const entryPath = fileURLToPath(new URL(_serverEntry, _serverOut)); - - // Bundle dependencies - await esbuild.build({ - entryPoints: [entryPath], - outfile: entryPath, - bundle: true, - target: 'node14', - allowOverwrite: true, - ...(edge ? { format: 'esm', platform: 'browser' } : { format: 'cjs', platform: 'node' }), - }); - if (edge) { - // Edge function config - // https://vercel.com/docs/build-output-api/v3#vercel-primitives/edge-functions/configuration - await writeJson(new URL(`./.vc-config.json`, _serverOut), { - runtime: 'edge', - entrypoint: _serverEntry, - }); + if (mode === 'static') { + buildConfig.serverEntry = _serverEntry = 'entry.mjs'; + buildConfig.staticMode = true; } else { - // Serverless function config - // https://vercel.com/docs/build-output-api/v3#vercel-primitives/serverless-functions/configuration - await writeJson(new URL(`./.vc-config.json`, _serverOut), { - runtime: 'nodejs14.x', - handler: _serverEntry, - launcherType: 'Nodejs', + buildConfig.serverEntry = _serverEntry = 'entry.js'; + buildConfig.client = new URL('./static/', _vercelOut); + buildConfig.server = _functionsFolder = new URL('./functions/render.func/', _vercelOut); + } + }, + 'astro:build:done': async ({ routes }) => { + // Build function + if (mode !== 'static') { + const entryPath = fileURLToPath(new URL(_serverEntry, _functionsFolder)); + const edge = mode === 'edge'; + + // Bundle dependencies + await esbuild.build({ + entryPoints: [entryPath], + outfile: entryPath, + bundle: true, + target: 'node14', + allowOverwrite: true, + ...(edge + ? { format: 'esm', platform: 'browser' } + : { format: 'cjs', platform: 'node' }), }); + + if (edge) { + // Edge function config + // https://vercel.com/docs/build-output-api/v3#vercel-primitives/edge-functions/configuration + await writeJson(new URL(`./.vc-config.json`, _functionsFolder), { + runtime: 'edge', + entrypoint: _serverEntry, + }); + } else { + // Serverless function config + // https://vercel.com/docs/build-output-api/v3#vercel-primitives/serverless-functions/configuration + await writeJson(new URL(`./.vc-config.json`, _functionsFolder), { + runtime: 'nodejs14.x', + handler: _serverEntry, + launcherType: 'Nodejs', + }); + } } let rewrites: Rewrite[] = []; @@ -111,22 +143,27 @@ export default function vercel({ edge = false }: Options = {}): AstroIntegration ) .join('/'); - rewrites.push({ - source: path, - destination: '/render', - }); - - if (_config.trailingSlash === 'always') { - redirects.push({ + if (mode !== 'static') { + rewrites.push({ source: path, - destination: path + '/', - }); - } else if (_config.trailingSlash === 'never') { - redirects.push({ - source: path + '/', - destination: path, + destination: '/render', }); } + + // trailingSlash for pages + if (route.type === 'page' && route.segments.length > 0) { + if (_config.trailingSlash === 'always') { + redirects.push({ + source: path, + destination: path + '/', + }); + } else if (_config.trailingSlash === 'never') { + redirects.push({ + source: path + '/', + destination: path, + }); + } + } } const transformedRoutes = getTransformedRoutes({ @@ -139,7 +176,7 @@ export default function vercel({ edge = false }: Options = {}): AstroIntegration // Output configuration // https://vercel.com/docs/build-output-api/v3#build-output-configuration - await writeJson(new URL(`./config.json`, _config.outDir), { + await writeJson(new URL(`./config.json`, _vercelOut), { version: 3, routes: transformedRoutes.routes, }); From c201c6007a7fc849968529544db5c8f76f46488a Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 20:16:49 -0300 Subject: [PATCH 10/33] Updated documentation --- .changeset/tiny-apes-shave.md | 3 ++- packages/integrations/vercel/README.md | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/.changeset/tiny-apes-shave.md b/.changeset/tiny-apes-shave.md index cd703136223f..139979e322af 100644 --- a/.changeset/tiny-apes-shave.md +++ b/.changeset/tiny-apes-shave.md @@ -5,4 +5,5 @@ Updated to Build Output API (v3): - Make sure to rename the `ENABLE_FILE_SYSTEM_API` enviroment variable to `ENABLE_VC_BUILD`. -- The output folder changed from `.output` to `.vercel/output` +- The output folder changed from `.output` to `.vercel/output`. +- New `static` mode! diff --git a/packages/integrations/vercel/README.md b/packages/integrations/vercel/README.md index e9f9097b690d..345d27622cff 100644 --- a/packages/integrations/vercel/README.md +++ b/packages/integrations/vercel/README.md @@ -41,6 +41,25 @@ vercel deploy --prebuilt [Learn more about setting enviroment variables in Vercel](https://vercel.com/docs/concepts/projects/environment-variables). +## Options + +```js +import { defineConfig } from 'astro/config'; +import vercel from '@astrojs/vercel'; + +export default defineConfig({ + adapter: vercel({ + /** + * - `static`: generates a static website following Vercel's output formats, redirects, etc. + * - `serverless` (default): SSR inside a [Node.js 14 function](https://vercel.com/docs/concepts/functions/serverless-functions). + * - `edge`: SSR inside a [Edge function](https://vercel.com/docs/concepts/functions/edge-functions). + * + */ + mode: 'serverless' + }) +}); +``` + ## Limitations From 5f5a0d79a590a5209b2bce8f85b8c23e5a343b4c Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 22:13:50 -0300 Subject: [PATCH 11/33] Updated shim --- packages/integrations/vercel/src/edge/entrypoint.ts | 2 -- packages/integrations/vercel/src/edge/shim.ts | 4 +++- packages/integrations/vercel/src/index.ts | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/integrations/vercel/src/edge/entrypoint.ts b/packages/integrations/vercel/src/edge/entrypoint.ts index 016ddac90aa4..45ab97cd4885 100644 --- a/packages/integrations/vercel/src/edge/entrypoint.ts +++ b/packages/integrations/vercel/src/edge/entrypoint.ts @@ -1,5 +1,3 @@ -import './shim.js'; - import type { SSRManifest } from 'astro'; import { App } from 'astro/app'; diff --git a/packages/integrations/vercel/src/edge/shim.ts b/packages/integrations/vercel/src/edge/shim.ts index 1a4a6ee9be4c..16af239f19c2 100644 --- a/packages/integrations/vercel/src/edge/shim.ts +++ b/packages/integrations/vercel/src/edge/shim.ts @@ -1,4 +1,6 @@ -(globalThis as any).process = { +export let process = { argv: [], env: {}, }; + +export let global = { crypto: globalThis.crypto }; diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts index 8f9d19dc748b..d0d82aaff51a 100644 --- a/packages/integrations/vercel/src/index.ts +++ b/packages/integrations/vercel/src/index.ts @@ -101,7 +101,11 @@ export default function vercel({ mode = 'serverless' }: Options = {}): AstroInte target: 'node14', allowOverwrite: true, ...(edge - ? { format: 'esm', platform: 'browser' } + ? { + format: 'esm', + platform: 'browser', + inject: [fileURLToPath(new URL('./edge/shim.js', import.meta.url))], + } : { format: 'cjs', platform: 'node' }), }); From 83c29a32dc7ffa796fcb9cfe7d4876cde65e4c9a Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 22:59:00 -0300 Subject: [PATCH 12/33] Made edge work! --- packages/integrations/vercel/package.json | 1 - packages/integrations/vercel/src/index.ts | 90 ++++++++++------------- packages/integrations/vercel/src/utils.ts | 34 +++++++++ pnpm-lock.yaml | 20 ++--- 4 files changed, 78 insertions(+), 67 deletions(-) create mode 100644 packages/integrations/vercel/src/utils.ts diff --git a/packages/integrations/vercel/package.json b/packages/integrations/vercel/package.json index 217478436c14..cc33b1021503 100644 --- a/packages/integrations/vercel/package.json +++ b/packages/integrations/vercel/package.json @@ -26,7 +26,6 @@ }, "dependencies": { "@astrojs/webapi": "^0.11.1", - "@vercel/routing-utils": "^1.13.1", "esbuild": "^0.14.38" }, "devDependencies": { diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts index d0d82aaff51a..ff161a92d208 100644 --- a/packages/integrations/vercel/src/index.ts +++ b/packages/integrations/vercel/src/index.ts @@ -1,13 +1,9 @@ import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; -import type { PathLike } from 'fs'; -import fs from 'fs/promises'; import { fileURLToPath } from 'url'; import esbuild from 'esbuild'; -import { getTransformedRoutes, Redirect, Rewrite } from '@vercel/routing-utils'; -const writeJson = (path: PathLike, data: any) => - fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); +import { getPattern, writeJson } from './utils.js'; export interface Options { /** @@ -21,6 +17,16 @@ export interface Options { mode?: 'static' | 'serverless' | 'edge'; } +// https://vercel.com/docs/project-configuration#legacy/routes +interface VercelRoute { + src: string; + methods?: string[]; + dest?: string; + headers?: Record; + status?: number; + continue?: boolean; +} + function getAdapter({ mode }: { mode: NonNullable }): AstroAdapter { let adapter: AstroAdapter = { name: '@astrojs/vercel', @@ -127,62 +133,42 @@ export default function vercel({ mode = 'serverless' }: Options = {}): AstroInte } } - let rewrites: Rewrite[] = []; - let redirects: Redirect[] = []; - - for (const route of routes) { - const path = - _config.base + - route.segments - .map((segments) => - segments - .map((part) => - part.spread - ? `:${part.content}*` - : part.dynamic - ? `:${part.content}` - : part.content - ) - .join('') - ) - .join('/'); - - if (mode !== 'static') { - rewrites.push({ - source: path, - destination: '/render', + let redirects: VercelRoute[] = []; + + if (_config.trailingSlash === 'always') { + for (const route of routes) { + if (route.type !== 'page' || route.segments.length === 0) continue; + + const path = _config.base + getPattern(route); + redirects.push({ + src: path, + headers: { Location: path + '/' }, + status: 308, }); } - - // trailingSlash for pages - if (route.type === 'page' && route.segments.length > 0) { - if (_config.trailingSlash === 'always') { - redirects.push({ - source: path, - destination: path + '/', - }); - } else if (_config.trailingSlash === 'never') { - redirects.push({ - source: path + '/', - destination: path, - }); - } + } else if (_config.trailingSlash === 'never') { + for (const route of routes) { + if (route.type !== 'page' || route.segments.length === 0) continue; + + const path = _config.base + getPattern(route); + redirects.push({ + src: path + '/', + headers: { Location: path }, + status: 308, + }); } } - const transformedRoutes = getTransformedRoutes({ - nowConfig: { rewrites, redirects }, - }); - - if (transformedRoutes.error) { - throw new Error(JSON.stringify(transformedRoutes.error, null, 2)); - } - // Output configuration // https://vercel.com/docs/build-output-api/v3#build-output-configuration await writeJson(new URL(`./config.json`, _vercelOut), { version: 3, - routes: transformedRoutes.routes, + routes: [ + ...redirects, + { handle: 'filesystem' }, + ...(mode === 'edge' ? [{ src: '/.*', middlewarePath: 'render' }] : []), + ...(mode === 'serverless' ? [{ src: '/.*', dest: 'render' }] : []), + ], }); }, }, diff --git a/packages/integrations/vercel/src/utils.ts b/packages/integrations/vercel/src/utils.ts new file mode 100644 index 000000000000..c3615621f854 --- /dev/null +++ b/packages/integrations/vercel/src/utils.ts @@ -0,0 +1,34 @@ +import type { RouteData } from 'astro'; +import type { PathLike } from 'fs'; + +import fs from 'fs/promises'; + +export async function writeJson(path: PathLike, data: any) { + await fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); +} + +// Copied from /home/juanm04/dev/misc/astro/packages/astro/src/core/routing/manifest/create.ts +// 2022-04-26 +export function getPattern({ segments }: RouteData) { + return segments + .map((segment) => { + return segment[0].spread + ? '(?:\\/(.*?))?' + : '\\/' + + segment + .map((part) => { + if (part) + return part.dynamic + ? '([^/]+?)' + : part.content + .normalize() + .replace(/\?/g, '%3F') + .replace(/#/g, '%23') + .replace(/%5B/g, '[') + .replace(/%5D/g, ']') + .replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + }) + .join(''); + }) + .join(''); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5462c564202c..6552ef97d979 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1437,13 +1437,11 @@ importers: packages/integrations/vercel: specifiers: '@astrojs/webapi': ^0.11.1 - '@vercel/routing-utils': ^1.13.1 astro: workspace:* astro-scripts: workspace:* esbuild: ^0.14.38 dependencies: '@astrojs/webapi': link:../../webapi - '@vercel/routing-utils': 1.13.1 esbuild: 0.14.38 devDependencies: astro: link:../../astro @@ -4314,14 +4312,6 @@ packages: '@unocss/scope': 0.15.6 dev: true - /@vercel/routing-utils/1.13.1: - resolution: {integrity: sha512-LNKkr9AuX4dX79eJIhPJw5EcStYHxHFp/htFRHtuMVSHmxpDQQ2Wv4LqgQY+dMzvpQ207h9JKIRlI1XQqiswpw==} - dependencies: - path-to-regexp: 6.1.0 - optionalDependencies: - ajv: 6.12.6 - dev: false - /@vitejs/plugin-vue/2.3.1_vue@3.2.33: resolution: {integrity: sha512-YNzBt8+jt6bSwpt7LP890U1UcTOIZZxfpE5WOJ638PNxSEKOqAi0+FSKS0nVeukfdZ0Ai/H7AFd6k3hayfGZqQ==} engines: {node: '>=12.0.0'} @@ -4508,6 +4498,7 @@ packages: fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 + dev: true /ajv/8.11.0: resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} @@ -6091,6 +6082,7 @@ packages: /fast-deep-equal/3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true /fast-diff/1.2.0: resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} @@ -6108,6 +6100,7 @@ packages: /fast-json-stable-stringify/2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true /fast-levenshtein/2.0.6: resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} @@ -7124,6 +7117,7 @@ packages: /json-schema-traverse/0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true /json-schema-traverse/1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} @@ -8403,10 +8397,6 @@ packages: /path-parse/1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - /path-to-regexp/6.1.0: - resolution: {integrity: sha512-h9DqehX3zZZDCEm+xbfU0ZmwCGFCAAraPJWMXJ4+v32NjZJilVg3k1TcKsRgIb8IQ/izZSaydDc1OhJCZvs2Dw==} - dev: false - /path-to-regexp/6.2.0: resolution: {integrity: sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==} dev: false @@ -8649,6 +8639,7 @@ packages: /punycode/2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} + dev: true /queue-microtask/1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -10295,6 +10286,7 @@ packages: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.1.1 + dev: true /urlpattern-polyfill/1.0.0-rc5: resolution: {integrity: sha512-OxVmQLKMQbDZX1m8Ljuf26rzMUJ7lm3cnBAicqrB0qmo1qb/koH7EXayeHiZdiyc6Z0OnaHETW2JCoVHgTnGGA==} From b32c21facbeb9f3a22ce1bdb90fc6eeac31e95f5 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 23:08:27 -0300 Subject: [PATCH 13/33] Updated changeset --- .changeset/tiny-apes-shave.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.changeset/tiny-apes-shave.md b/.changeset/tiny-apes-shave.md index 139979e322af..970396888882 100644 --- a/.changeset/tiny-apes-shave.md +++ b/.changeset/tiny-apes-shave.md @@ -2,8 +2,11 @@ '@astrojs/vercel': minor --- -Updated to Build Output API (v3): -- Make sure to rename the `ENABLE_FILE_SYSTEM_API` enviroment variable to `ENABLE_VC_BUILD`. -- The output folder changed from `.output` to `.vercel/output`. -- New `static` mode! +**Vercel Adapter v0.2** + +- Updated to Build Output API (v3) + - Make sure to rename the `ENABLE_FILE_SYSTEM_API` enviroment variable to `ENABLE_VC_BUILD`. + - The output folder changed from `.output` to `.vercel/output`. +- You can now deploy to the `edge`! See the README for more info. +- `trailingSlash` redirects works without a `vercel.json` file: just configure them inside your `astro.config.mjs` From aa983b4c95bf9eab3fff1db1b09d7902cff01dca Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Tue, 26 Apr 2022 23:10:13 -0300 Subject: [PATCH 14/33] Ensure empty dir --- packages/integrations/vercel/src/index.ts | 7 ++++++- packages/integrations/vercel/src/utils.ts | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts index ff161a92d208..2f2b9b04c4b5 100644 --- a/packages/integrations/vercel/src/index.ts +++ b/packages/integrations/vercel/src/index.ts @@ -3,7 +3,7 @@ import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; import { fileURLToPath } from 'url'; import esbuild from 'esbuild'; -import { getPattern, writeJson } from './utils.js'; +import { getPattern, emptyDir, writeJson } from './utils.js'; export interface Options { /** @@ -87,6 +87,11 @@ export default function vercel({ mode = 'serverless' }: Options = {}): AstroInte if (mode === 'static') { buildConfig.serverEntry = _serverEntry = 'entry.mjs'; buildConfig.staticMode = true; + + // Ensure to have `.vercel/output` empty. + // This is because, when building to static, outDir = .vercel/output/static/, + // so .vercel/output itself won't get cleaned. + await emptyDir(_vercelOut); } else { buildConfig.serverEntry = _serverEntry = 'entry.js'; buildConfig.client = new URL('./static/', _vercelOut); diff --git a/packages/integrations/vercel/src/utils.ts b/packages/integrations/vercel/src/utils.ts index c3615621f854..53b6d3407d8c 100644 --- a/packages/integrations/vercel/src/utils.ts +++ b/packages/integrations/vercel/src/utils.ts @@ -7,6 +7,11 @@ export async function writeJson(path: PathLike, data: any) { await fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); } +export async function emptyDir(dir: PathLike): Promise { + await fs.rm(dir, { recursive: true, force: true, maxRetries: 3 }); + await fs.mkdir(dir, { recursive: true }); +} + // Copied from /home/juanm04/dev/misc/astro/packages/astro/src/core/routing/manifest/create.ts // 2022-04-26 export function getPattern({ segments }: RouteData) { From cff5ed007ef6c048b8d278497f24f7bcc8181167 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Wed, 27 Apr 2022 12:39:53 -0300 Subject: [PATCH 15/33] Fixed redirects for dynamic paths --- packages/integrations/vercel/src/index.ts | 12 +++++------- packages/integrations/vercel/src/utils.ts | 22 ++++++++++++++++++++-- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts index 2f2b9b04c4b5..48418712ae01 100644 --- a/packages/integrations/vercel/src/index.ts +++ b/packages/integrations/vercel/src/index.ts @@ -3,7 +3,7 @@ import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; import { fileURLToPath } from 'url'; import esbuild from 'esbuild'; -import { getPattern, emptyDir, writeJson } from './utils.js'; +import { getMatchPattern, getReplacePattern, emptyDir, writeJson } from './utils.js'; export interface Options { /** @@ -144,10 +144,9 @@ export default function vercel({ mode = 'serverless' }: Options = {}): AstroInte for (const route of routes) { if (route.type !== 'page' || route.segments.length === 0) continue; - const path = _config.base + getPattern(route); redirects.push({ - src: path, - headers: { Location: path + '/' }, + src: _config.base + getMatchPattern(route.segments), + headers: { Location: _config.base + getReplacePattern(route.segments) + '/' }, status: 308, }); } @@ -155,10 +154,9 @@ export default function vercel({ mode = 'serverless' }: Options = {}): AstroInte for (const route of routes) { if (route.type !== 'page' || route.segments.length === 0) continue; - const path = _config.base + getPattern(route); redirects.push({ - src: path + '/', - headers: { Location: path }, + src: _config.base + getMatchPattern(route.segments) + '/', + headers: { Location: _config.base + getReplacePattern(route.segments) }, status: 308, }); } diff --git a/packages/integrations/vercel/src/utils.ts b/packages/integrations/vercel/src/utils.ts index 53b6d3407d8c..0159b51a1e9d 100644 --- a/packages/integrations/vercel/src/utils.ts +++ b/packages/integrations/vercel/src/utils.ts @@ -1,4 +1,4 @@ -import type { RouteData } from 'astro'; +import type { RoutePart } from 'astro'; import type { PathLike } from 'fs'; import fs from 'fs/promises'; @@ -14,7 +14,7 @@ export async function emptyDir(dir: PathLike): Promise { // Copied from /home/juanm04/dev/misc/astro/packages/astro/src/core/routing/manifest/create.ts // 2022-04-26 -export function getPattern({ segments }: RouteData) { +export function getMatchPattern(segments: RoutePart[][]) { return segments .map((segment) => { return segment[0].spread @@ -37,3 +37,21 @@ export function getPattern({ segments }: RouteData) { }) .join(''); } + +export function getReplacePattern(segments: RoutePart[][]) { + let n = 0; + let result = ''; + + for (const segment of segments) { + for (const part of segment) { + if (part.dynamic) result += '$' + ++n; + else result += part.content; + } + result += '/'; + } + + // Remove trailing slash + result = result.slice(0, -1); + + return result; +} From efa720ebede832caa7f016ac773f530c8631166b Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Wed, 27 Apr 2022 15:00:31 -0300 Subject: [PATCH 16/33] Removed extra declaration --- packages/integrations/vercel/src/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts index 48418712ae01..6fbe3884a44e 100644 --- a/packages/integrations/vercel/src/index.ts +++ b/packages/integrations/vercel/src/index.ts @@ -85,7 +85,6 @@ export default function vercel({ mode = 'serverless' }: Options = {}): AstroInte } if (mode === 'static') { - buildConfig.serverEntry = _serverEntry = 'entry.mjs'; buildConfig.staticMode = true; // Ensure to have `.vercel/output` empty. From de4568c22648b00ea7c6921e61954296b9b85d33 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Fri, 29 Apr 2022 22:00:09 -0300 Subject: [PATCH 17/33] Splited imports --- packages/integrations/vercel/package.json | 8 +- .../integrations/vercel/src/edge/adapter.ts | 80 ++++++++ packages/integrations/vercel/src/index.ts | 178 ------------------ packages/integrations/vercel/src/lib/fs.ts | 14 ++ .../integrations/vercel/src/lib/redirects.ts | 83 ++++++++ .../vercel/src/serverless/adapter.ts | 94 +++++++++ .../integrations/vercel/src/static/adapter.ts | 50 +++++ packages/integrations/vercel/src/utils.ts | 57 ------ 8 files changed, 326 insertions(+), 238 deletions(-) create mode 100644 packages/integrations/vercel/src/edge/adapter.ts delete mode 100644 packages/integrations/vercel/src/index.ts create mode 100644 packages/integrations/vercel/src/lib/fs.ts create mode 100644 packages/integrations/vercel/src/lib/redirects.ts create mode 100644 packages/integrations/vercel/src/serverless/adapter.ts create mode 100644 packages/integrations/vercel/src/static/adapter.ts delete mode 100644 packages/integrations/vercel/src/utils.ts diff --git a/packages/integrations/vercel/package.json b/packages/integrations/vercel/package.json index cc33b1021503..2813ea1dd903 100644 --- a/packages/integrations/vercel/package.json +++ b/packages/integrations/vercel/package.json @@ -14,9 +14,11 @@ "bugs": "https://github.com/withastro/astro/issues", "homepage": "https://astro.build", "exports": { - ".": "./dist/index.js", - "./edge": "./dist/edge/entrypoint.js", - "./serverless": "./dist/serverless/entrypoint.js", + "./edge": "./dist/edge/adapter.js", + "./edge/entrypoint": "./dist/edge/entrypoint.js", + "./serverless": "./dist/serverless/adapter.js", + "./serverless/entrypoint": "./dist/serverless/entrypoint.js", + "./static": "./dist/serverless/adapter.js", "./package.json": "./package.json" }, "scripts": { diff --git a/packages/integrations/vercel/src/edge/adapter.ts b/packages/integrations/vercel/src/edge/adapter.ts new file mode 100644 index 000000000000..bb82b985a346 --- /dev/null +++ b/packages/integrations/vercel/src/edge/adapter.ts @@ -0,0 +1,80 @@ +import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; + +import { fileURLToPath } from 'url'; +import esbuild from 'esbuild'; + +import { writeJson, getVercelOutput } from '../lib/fs.js'; +import { getRedirects } from '../lib/redirects.js'; + +const PACKAGE_NAME = '@astrojs/vercel/edge'; + +function getAdapter(): AstroAdapter { + return { + name: PACKAGE_NAME, + serverEntrypoint: `${PACKAGE_NAME}/entrypoint`, + exports: ['default'], + }; +} + +export default function vercelEdge(): AstroIntegration { + let _config: AstroConfig; + let functionFolder: URL; + let serverEntry: string; + + return { + name: PACKAGE_NAME, + hooks: { + 'astro:config:setup': ({ config }) => { + config.outDir = getVercelOutput(config.root); + }, + 'astro:config:done': ({ setAdapter, config }) => { + setAdapter(getAdapter()); + _config = config; + }, + 'astro:build:start': async ({ buildConfig }) => { + if (String(process.env.ENABLE_VC_BUILD) !== '1') { + throw new Error( + `The enviroment variable "ENABLE_VC_BUILD" was not found. Make sure you have it set to "1" in your Vercel project.\nLearn how to set enviroment variables here: https://vercel.com/docs/concepts/projects/environment-variables` + ); + } + + buildConfig.serverEntry = serverEntry = 'entry.mjs'; + buildConfig.client = new URL('./static/', _config.outDir); + buildConfig.server = functionFolder = new URL('./functions/render.func', _config.outDir); + }, + 'astro:build:done': async ({ routes }) => { + const entryPath = fileURLToPath(new URL(serverEntry, functionFolder)); + + // Bundle dependencies + await esbuild.build({ + entryPoints: [entryPath], + outfile: entryPath, + inject: [fileURLToPath(new URL('./shim.js', import.meta.url))], + bundle: true, + target: 'node14', + format: 'esm', + platform: 'browser', + allowOverwrite: true, + }); + + // Edge function config + // https://vercel.com/docs/build-output-api/v3#vercel-primitives/edge-functions/configuration + await writeJson(new URL(`./.vc-config.json`, functionFolder), { + runtime: 'edge', + entrypoint: serverEntry, + }); + + // Output configuration + // https://vercel.com/docs/build-output-api/v3#build-output-configuration + await writeJson(new URL(`./config.json`, _config.outDir), { + version: 3, + routes: [ + ...getRedirects(routes, _config), + { handle: 'filesystem' }, + { src: '/.*', middlewarePath: 'render' }, + ], + }); + }, + }, + }; +} diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts deleted file mode 100644 index 6fbe3884a44e..000000000000 --- a/packages/integrations/vercel/src/index.ts +++ /dev/null @@ -1,178 +0,0 @@ -import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; - -import { fileURLToPath } from 'url'; -import esbuild from 'esbuild'; - -import { getMatchPattern, getReplacePattern, emptyDir, writeJson } from './utils.js'; - -export interface Options { - /** - * - `static`: generates a static website following Vercel's output formats, redirects, etc. - * - `serverless`: SSR inside a [Node.js 14 function](https://vercel.com/docs/concepts/functions/serverless-functions). - * - `edge`: SSR inside a [Edge function](https://vercel.com/docs/concepts/functions/edge-functions). - * - * @type {'static' | 'serverless' | 'edge'} - * @default {'serverless'} - */ - mode?: 'static' | 'serverless' | 'edge'; -} - -// https://vercel.com/docs/project-configuration#legacy/routes -interface VercelRoute { - src: string; - methods?: string[]; - dest?: string; - headers?: Record; - status?: number; - continue?: boolean; -} - -function getAdapter({ mode }: { mode: NonNullable }): AstroAdapter { - let adapter: AstroAdapter = { - name: '@astrojs/vercel', - }; - - if (mode !== 'static') { - adapter.serverEntrypoint = `@astrojs/vercel/${mode}`; - adapter.exports = ['default']; - } - - return adapter; -} - -export default function vercel({ mode = 'serverless' }: Options = {}): AstroIntegration { - let _config: AstroConfig; - let _vercelOut: URL; - let _functionsFolder: URL; - let _serverEntry: string; - - return { - name: '@astrojs/vercel', - hooks: { - 'astro:config:setup': ({ config }) => { - _vercelOut = new URL('./.vercel/output/', config.root); - - if (mode === 'static') { - config.outDir = new URL('./static/', _vercelOut); - config.build.format = 'directory'; - } else { - config.outDir = _vercelOut; - } - }, - 'astro:config:done': ({ setAdapter, config }) => { - setAdapter(getAdapter({ mode })); - _config = config; - }, - 'astro:build:setup': ({ vite, target }) => { - if (mode === 'serverless' && target === 'server') { - vite.build = { - ...(vite.build || {}), - rollupOptions: { - ...(vite.build?.rollupOptions || {}), - output: { - ...(vite.build?.rollupOptions?.output || {}), - format: 'cjs', - }, - }, - }; - } - }, - 'astro:build:start': async ({ buildConfig }) => { - if (String(process.env.ENABLE_VC_BUILD) !== '1') { - throw new Error( - `The enviroment variable "ENABLE_VC_BUILD" was not found. Make sure you have it set to "1" in your Vercel project.\nLearn how to set enviroment variables here: https://vercel.com/docs/concepts/projects/environment-variables` - ); - } - - if (mode === 'static') { - buildConfig.staticMode = true; - - // Ensure to have `.vercel/output` empty. - // This is because, when building to static, outDir = .vercel/output/static/, - // so .vercel/output itself won't get cleaned. - await emptyDir(_vercelOut); - } else { - buildConfig.serverEntry = _serverEntry = 'entry.js'; - buildConfig.client = new URL('./static/', _vercelOut); - buildConfig.server = _functionsFolder = new URL('./functions/render.func/', _vercelOut); - } - }, - 'astro:build:done': async ({ routes }) => { - // Build function - if (mode !== 'static') { - const entryPath = fileURLToPath(new URL(_serverEntry, _functionsFolder)); - const edge = mode === 'edge'; - - // Bundle dependencies - await esbuild.build({ - entryPoints: [entryPath], - outfile: entryPath, - bundle: true, - target: 'node14', - allowOverwrite: true, - ...(edge - ? { - format: 'esm', - platform: 'browser', - inject: [fileURLToPath(new URL('./edge/shim.js', import.meta.url))], - } - : { format: 'cjs', platform: 'node' }), - }); - - if (edge) { - // Edge function config - // https://vercel.com/docs/build-output-api/v3#vercel-primitives/edge-functions/configuration - await writeJson(new URL(`./.vc-config.json`, _functionsFolder), { - runtime: 'edge', - entrypoint: _serverEntry, - }); - } else { - // Serverless function config - // https://vercel.com/docs/build-output-api/v3#vercel-primitives/serverless-functions/configuration - await writeJson(new URL(`./.vc-config.json`, _functionsFolder), { - runtime: 'nodejs14.x', - handler: _serverEntry, - launcherType: 'Nodejs', - }); - } - } - - let redirects: VercelRoute[] = []; - - if (_config.trailingSlash === 'always') { - for (const route of routes) { - if (route.type !== 'page' || route.segments.length === 0) continue; - - redirects.push({ - src: _config.base + getMatchPattern(route.segments), - headers: { Location: _config.base + getReplacePattern(route.segments) + '/' }, - status: 308, - }); - } - } else if (_config.trailingSlash === 'never') { - for (const route of routes) { - if (route.type !== 'page' || route.segments.length === 0) continue; - - redirects.push({ - src: _config.base + getMatchPattern(route.segments) + '/', - headers: { Location: _config.base + getReplacePattern(route.segments) }, - status: 308, - }); - } - } - - // Output configuration - // https://vercel.com/docs/build-output-api/v3#build-output-configuration - await writeJson(new URL(`./config.json`, _vercelOut), { - version: 3, - routes: [ - ...redirects, - { handle: 'filesystem' }, - ...(mode === 'edge' ? [{ src: '/.*', middlewarePath: 'render' }] : []), - ...(mode === 'serverless' ? [{ src: '/.*', dest: 'render' }] : []), - ], - }); - }, - }, - }; -} diff --git a/packages/integrations/vercel/src/lib/fs.ts b/packages/integrations/vercel/src/lib/fs.ts new file mode 100644 index 000000000000..da145b1d1355 --- /dev/null +++ b/packages/integrations/vercel/src/lib/fs.ts @@ -0,0 +1,14 @@ +import type { PathLike } from 'fs'; + +import fs from 'fs/promises'; + +export async function writeJson(path: PathLike, data: T) { + await fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); +} + +export async function emptyDir(dir: PathLike): Promise { + await fs.rm(dir, { recursive: true, force: true, maxRetries: 3 }); + await fs.mkdir(dir, { recursive: true }); +} + +export const getVercelOutput = (root: URL) => new URL('./.vercel/output/', root); diff --git a/packages/integrations/vercel/src/lib/redirects.ts b/packages/integrations/vercel/src/lib/redirects.ts new file mode 100644 index 000000000000..b52ce8725c8d --- /dev/null +++ b/packages/integrations/vercel/src/lib/redirects.ts @@ -0,0 +1,83 @@ +import type { AstroConfig, RoutePart, RouteData } from 'astro'; + +// https://vercel.com/docs/project-configuration#legacy/routes +interface VercelRoute { + src: string; + methods?: string[]; + dest?: string; + headers?: Record; + status?: number; + continue?: boolean; +} + +// Copied from /home/juanm04/dev/misc/astro/packages/astro/src/core/routing/manifest/create.ts +// 2022-04-26 +function getMatchPattern(segments: RoutePart[][]) { + return segments + .map((segment) => { + return segment[0].spread + ? '(?:\\/(.*?))?' + : '\\/' + + segment + .map((part) => { + if (part) + return part.dynamic + ? '([^/]+?)' + : part.content + .normalize() + .replace(/\?/g, '%3F') + .replace(/#/g, '%23') + .replace(/%5B/g, '[') + .replace(/%5D/g, ']') + .replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + }) + .join(''); + }) + .join(''); +} + +function getReplacePattern(segments: RoutePart[][]) { + let n = 0; + let result = ''; + + for (const segment of segments) { + for (const part of segment) { + if (part.dynamic) result += '$' + ++n; + else result += part.content; + } + result += '/'; + } + + // Remove trailing slash + result = result.slice(0, -1); + + return result; +} + +export function getRedirects(routes: RouteData[], config: AstroConfig): VercelRoute[] { + let redirects: VercelRoute[] = []; + + if (config.trailingSlash === 'always') { + for (const route of routes) { + if (route.type !== 'page' || route.segments.length === 0) continue; + + redirects.push({ + src: config.base + getMatchPattern(route.segments), + headers: { Location: config.base + getReplacePattern(route.segments) + '/' }, + status: 308, + }); + } + } else if (config.trailingSlash === 'never') { + for (const route of routes) { + if (route.type !== 'page' || route.segments.length === 0) continue; + + redirects.push({ + src: config.base + getMatchPattern(route.segments) + '/', + headers: { Location: config.base + getReplacePattern(route.segments) }, + status: 308, + }); + } + } + + return redirects; +} diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts new file mode 100644 index 000000000000..3ca9a1cdb9c3 --- /dev/null +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -0,0 +1,94 @@ +import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; + +import { fileURLToPath } from 'url'; +import esbuild from 'esbuild'; + +import { writeJson, getVercelOutput } from '../lib/fs.js'; +import { getRedirects } from '../lib/redirects.js'; + +const PACKAGE_NAME = '@astrojs/vercel/serverless'; + +function getAdapter(): AstroAdapter { + return { + name: PACKAGE_NAME, + serverEntrypoint: `${PACKAGE_NAME}/entrypoint`, + exports: ['default'], + }; +} + +export default function vercelEdge(): AstroIntegration { + let _config: AstroConfig; + let functionFolder: URL; + let serverEntry: string; + + return { + name: PACKAGE_NAME, + hooks: { + 'astro:config:setup': ({ config }) => { + config.outDir = getVercelOutput(config.root); + }, + 'astro:config:done': ({ setAdapter, config }) => { + setAdapter(getAdapter()); + _config = config; + }, + 'astro:build:setup': ({ vite, target }) => { + if (target === 'server') { + vite.build = { + ...(vite.build || {}), + rollupOptions: { + ...(vite.build?.rollupOptions || {}), + output: { + ...(vite.build?.rollupOptions?.output || {}), + format: 'cjs', + }, + }, + }; + } + }, + 'astro:build:start': async ({ buildConfig }) => { + if (String(process.env.ENABLE_VC_BUILD) !== '1') { + throw new Error( + `The enviroment variable "ENABLE_VC_BUILD" was not found. Make sure you have it set to "1" in your Vercel project.\nLearn how to set enviroment variables here: https://vercel.com/docs/concepts/projects/environment-variables` + ); + } + + buildConfig.serverEntry = serverEntry = 'entry.js'; + buildConfig.client = new URL('./static/', _config.outDir); + buildConfig.server = functionFolder = new URL('./functions/render.func', _config.outDir); + }, + 'astro:build:done': async ({ routes }) => { + const entryPath = fileURLToPath(new URL(serverEntry, functionFolder)); + + // Bundle dependencies + await esbuild.build({ + entryPoints: [entryPath], + outfile: entryPath, + bundle: true, + target: 'node14', + format: 'cjs', + platform: 'node', + allowOverwrite: true, + }); + + // Edge function config + // https://vercel.com/docs/build-output-api/v3#vercel-primitives/edge-functions/configuration + await writeJson(new URL(`./.vc-config.json`, functionFolder), { + runtime: 'nodejs14.x', + handler: serverEntry, + launcherType: 'Nodejs', + }); + + // Output configuration + // https://vercel.com/docs/build-output-api/v3#build-output-configuration + await writeJson(new URL(`./config.json`, _config.outDir), { + version: 3, + routes: [ + ...getRedirects(routes, _config), + { handle: 'filesystem' }, + { src: '/.*', dest: 'render' }, + ], + }); + }, + }, + }; +} diff --git a/packages/integrations/vercel/src/static/adapter.ts b/packages/integrations/vercel/src/static/adapter.ts new file mode 100644 index 000000000000..876fd620c2d5 --- /dev/null +++ b/packages/integrations/vercel/src/static/adapter.ts @@ -0,0 +1,50 @@ +import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; + +import { getVercelOutput, writeJson, emptyDir } from '../lib/fs.js'; +import { getRedirects } from '../lib/redirects.js'; + +const PACKAGE_NAME = '@astrojs/vercel/static'; + +function getAdapter(): AstroAdapter { + return { name: PACKAGE_NAME }; +} + +export default function vercelStatic(): AstroIntegration { + let _config: AstroConfig; + + return { + name: '@astrojs/vercel', + hooks: { + 'astro:config:setup': ({ config }) => { + config.outDir = new URL('./static/', getVercelOutput(config.root)); + config.build.format = 'directory'; + }, + 'astro:config:done': ({ setAdapter, config }) => { + setAdapter(getAdapter()); + _config = config; + }, + 'astro:build:start': async ({ buildConfig }) => { + if (String(process.env.ENABLE_VC_BUILD) !== '1') { + throw new Error( + `The enviroment variable "ENABLE_VC_BUILD" was not found. Make sure you have it set to "1" in your Vercel project.\nLearn how to set enviroment variables here: https://vercel.com/docs/concepts/projects/environment-variables` + ); + } + + buildConfig.staticMode = true; + + // Ensure to have `.vercel/output` empty. + // This is because, when building to static, outDir = .vercel/output/static/, + // so .vercel/output itself won't get cleaned. + await emptyDir(getVercelOutput(_config.root)); + }, + 'astro:build:done': async ({ routes }) => { + // Output configuration + // https://vercel.com/docs/build-output-api/v3#build-output-configuration + await writeJson(new URL(`./config.json`, _config.outDir), { + version: 3, + routes: [...getRedirects(routes, _config), { handle: 'filesystem' }], + }); + }, + }, + }; +} diff --git a/packages/integrations/vercel/src/utils.ts b/packages/integrations/vercel/src/utils.ts deleted file mode 100644 index 0159b51a1e9d..000000000000 --- a/packages/integrations/vercel/src/utils.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { RoutePart } from 'astro'; -import type { PathLike } from 'fs'; - -import fs from 'fs/promises'; - -export async function writeJson(path: PathLike, data: any) { - await fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); -} - -export async function emptyDir(dir: PathLike): Promise { - await fs.rm(dir, { recursive: true, force: true, maxRetries: 3 }); - await fs.mkdir(dir, { recursive: true }); -} - -// Copied from /home/juanm04/dev/misc/astro/packages/astro/src/core/routing/manifest/create.ts -// 2022-04-26 -export function getMatchPattern(segments: RoutePart[][]) { - return segments - .map((segment) => { - return segment[0].spread - ? '(?:\\/(.*?))?' - : '\\/' + - segment - .map((part) => { - if (part) - return part.dynamic - ? '([^/]+?)' - : part.content - .normalize() - .replace(/\?/g, '%3F') - .replace(/#/g, '%23') - .replace(/%5B/g, '[') - .replace(/%5D/g, ']') - .replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - }) - .join(''); - }) - .join(''); -} - -export function getReplacePattern(segments: RoutePart[][]) { - let n = 0; - let result = ''; - - for (const segment of segments) { - for (const part of segment) { - if (part.dynamic) result += '$' + ++n; - else result += part.content; - } - result += '/'; - } - - // Remove trailing slash - result = result.slice(0, -1); - - return result; -} From 87ac091c56f9209a4e7df3a125312c479eef84e1 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Fri, 29 Apr 2022 22:02:17 -0300 Subject: [PATCH 18/33] Updated readme --- packages/integrations/vercel/README.md | 29 ++++++++++++-------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/packages/integrations/vercel/README.md b/packages/integrations/vercel/README.md index 345d27622cff..45712cb18c98 100644 --- a/packages/integrations/vercel/README.md +++ b/packages/integrations/vercel/README.md @@ -6,7 +6,7 @@ Use this integration in your Astro configuration file: ```js import { defineConfig } from 'astro/config'; -import vercel from '@astrojs/vercel'; +import vercel from '@astrojs/vercel/serverless'; export default defineConfig({ adapter: vercel() @@ -41,23 +41,20 @@ vercel deploy --prebuilt [Learn more about setting enviroment variables in Vercel](https://vercel.com/docs/concepts/projects/environment-variables). -## Options +## Targets -```js -import { defineConfig } from 'astro/config'; -import vercel from '@astrojs/vercel'; +You can deploy to different targes: -export default defineConfig({ - adapter: vercel({ - /** - * - `static`: generates a static website following Vercel's output formats, redirects, etc. - * - `serverless` (default): SSR inside a [Node.js 14 function](https://vercel.com/docs/concepts/functions/serverless-functions). - * - `edge`: SSR inside a [Edge function](https://vercel.com/docs/concepts/functions/edge-functions). - * - */ - mode: 'serverless' - }) -}); +- `static`: generates a static website following Vercel's output formats, redirects, etc. +- `serverless`: SSR inside a [Node.js 14 function](https://vercel.com/docs/concepts/functions/serverless-functions). +- `edge`: SSR inside a [Edge function](https://vercel.com/docs/concepts/functions/edge-functions). + +You can change where to target by changing the import: + +```js +import vercel from '@astrojs/vercel/static'; +import vercel from '@astrojs/vercel/serverless'; +import vercel from '@astrojs/vercel/edge'; ``` From 595391d05e5bc8327b9dd67e79472b033f6e1e1a Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Fri, 29 Apr 2022 22:16:44 -0300 Subject: [PATCH 19/33] Fixed some urls --- packages/integrations/vercel/src/edge/adapter.ts | 4 ++-- packages/integrations/vercel/src/serverless/adapter.ts | 4 ++-- packages/integrations/vercel/src/static/adapter.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/integrations/vercel/src/edge/adapter.ts b/packages/integrations/vercel/src/edge/adapter.ts index bb82b985a346..72c26c05581b 100644 --- a/packages/integrations/vercel/src/edge/adapter.ts +++ b/packages/integrations/vercel/src/edge/adapter.ts @@ -40,10 +40,10 @@ export default function vercelEdge(): AstroIntegration { buildConfig.serverEntry = serverEntry = 'entry.mjs'; buildConfig.client = new URL('./static/', _config.outDir); - buildConfig.server = functionFolder = new URL('./functions/render.func', _config.outDir); + buildConfig.server = functionFolder = new URL('./functions/render.func/', _config.outDir); }, 'astro:build:done': async ({ routes }) => { - const entryPath = fileURLToPath(new URL(serverEntry, functionFolder)); + const entryPath = fileURLToPath(new URL(`./${serverEntry}`, functionFolder)); // Bundle dependencies await esbuild.build({ diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index 3ca9a1cdb9c3..6652539b1fce 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -54,10 +54,10 @@ export default function vercelEdge(): AstroIntegration { buildConfig.serverEntry = serverEntry = 'entry.js'; buildConfig.client = new URL('./static/', _config.outDir); - buildConfig.server = functionFolder = new URL('./functions/render.func', _config.outDir); + buildConfig.server = functionFolder = new URL('./functions/render.func/', _config.outDir); }, 'astro:build:done': async ({ routes }) => { - const entryPath = fileURLToPath(new URL(serverEntry, functionFolder)); + const entryPath = fileURLToPath(new URL(`./${serverEntry}`, functionFolder)); // Bundle dependencies await esbuild.build({ diff --git a/packages/integrations/vercel/src/static/adapter.ts b/packages/integrations/vercel/src/static/adapter.ts index 876fd620c2d5..489ab356b1e0 100644 --- a/packages/integrations/vercel/src/static/adapter.ts +++ b/packages/integrations/vercel/src/static/adapter.ts @@ -40,7 +40,7 @@ export default function vercelStatic(): AstroIntegration { 'astro:build:done': async ({ routes }) => { // Output configuration // https://vercel.com/docs/build-output-api/v3#build-output-configuration - await writeJson(new URL(`./config.json`, _config.outDir), { + await writeJson(new URL(`./config.json`, getVercelOutput(_config.root)), { version: 3, routes: [...getRedirects(routes, _config), { handle: 'filesystem' }], }); From 5fcd8d4e7882f6bc3d886caa9b010f617a8c5763 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Wed, 4 May 2022 14:29:10 -0300 Subject: [PATCH 20/33] Deprecated shim! --- packages/integrations/vercel/src/edge/shim.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/integrations/vercel/src/edge/shim.ts b/packages/integrations/vercel/src/edge/shim.ts index 16af239f19c2..f7ac655bfcef 100644 --- a/packages/integrations/vercel/src/edge/shim.ts +++ b/packages/integrations/vercel/src/edge/shim.ts @@ -2,5 +2,3 @@ export let process = { argv: [], env: {}, }; - -export let global = { crypto: globalThis.crypto }; From a60f182654d5c3852587b253bedbd9332c106b6c Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Thu, 5 May 2022 09:35:49 -0300 Subject: [PATCH 21/33] [test]: Vercel NFT --- packages/integrations/vercel/package.json | 1 + packages/integrations/vercel/src/lib/fs.ts | 34 ++- .../vercel/src/serverless/adapter.ts | 60 ++-- pnpm-lock.yaml | 270 +++++++++++++++--- 4 files changed, 295 insertions(+), 70 deletions(-) diff --git a/packages/integrations/vercel/package.json b/packages/integrations/vercel/package.json index 2813ea1dd903..47746f827cb8 100644 --- a/packages/integrations/vercel/package.json +++ b/packages/integrations/vercel/package.json @@ -28,6 +28,7 @@ }, "dependencies": { "@astrojs/webapi": "^0.11.1", + "@vercel/nft": "^0.18.2", "esbuild": "^0.14.38" }, "devDependencies": { diff --git a/packages/integrations/vercel/src/lib/fs.ts b/packages/integrations/vercel/src/lib/fs.ts index da145b1d1355..b0677e8ce376 100644 --- a/packages/integrations/vercel/src/lib/fs.ts +++ b/packages/integrations/vercel/src/lib/fs.ts @@ -1,6 +1,7 @@ import type { PathLike } from 'fs'; - -import fs from 'fs/promises'; +import * as fs from 'fs/promises'; +import { fileURLToPath } from 'url'; +import { nodeFileTrace } from '@vercel/nft'; export async function writeJson(path: PathLike, data: T) { await fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); @@ -12,3 +13,32 @@ export async function emptyDir(dir: PathLike): Promise { } export const getVercelOutput = (root: URL) => new URL('./.vercel/output/', root); + +export async function copyFunctionNFT(root: URL, functionFolder: URL, serverEntry: string) { + const result = await nodeFileTrace([fileURLToPath(new URL(`./${serverEntry}`, functionFolder))], { + base: fileURLToPath(root), + }); + + for (const file of result.fileList) { + if (file.startsWith('.vercel/')) continue; + const origin = new URL(file, root); + const dest = new URL(file, functionFolder); + + const meta = await fs.stat(origin); + const isSymlink = (await fs.lstat(origin)).isSymbolicLink(); + + // Create directories + if (meta.isDirectory() && !isSymlink) { + await fs.mkdir(new URL('..', dest), { recursive: true }); + } else { + await fs.mkdir(new URL('.', dest), { recursive: true }); + } + + if (isSymlink) { + const link = await fs.readlink(origin); + await fs.symlink(link, dest, meta.isDirectory() ? 'dir' : 'file'); + } else { + await fs.copyFile(origin, dest); + } + } +} diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index 6652539b1fce..8e3efd7c6741 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -1,9 +1,6 @@ import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; -import { fileURLToPath } from 'url'; -import esbuild from 'esbuild'; - -import { writeJson, getVercelOutput } from '../lib/fs.js'; +import { writeJson, copyFunctionNFT, getVercelOutput } from '../lib/fs.js'; import { getRedirects } from '../lib/redirects.js'; const PACKAGE_NAME = '@astrojs/vercel/serverless'; @@ -31,20 +28,20 @@ export default function vercelEdge(): AstroIntegration { setAdapter(getAdapter()); _config = config; }, - 'astro:build:setup': ({ vite, target }) => { - if (target === 'server') { - vite.build = { - ...(vite.build || {}), - rollupOptions: { - ...(vite.build?.rollupOptions || {}), - output: { - ...(vite.build?.rollupOptions?.output || {}), - format: 'cjs', - }, - }, - }; - } - }, + // 'astro:build:setup': ({ vite, target }) => { + // if (target === 'server') { + // vite.build = { + // ...(vite.build || {}), + // rollupOptions: { + // ...(vite.build?.rollupOptions || {}), + // output: { + // ...(vite.build?.rollupOptions?.output || {}), + // format: 'cjs', + // }, + // }, + // }; + // } + // }, 'astro:build:start': async ({ buildConfig }) => { if (String(process.env.ENABLE_VC_BUILD) !== '1') { throw new Error( @@ -57,18 +54,19 @@ export default function vercelEdge(): AstroIntegration { buildConfig.server = functionFolder = new URL('./functions/render.func/', _config.outDir); }, 'astro:build:done': async ({ routes }) => { - const entryPath = fileURLToPath(new URL(`./${serverEntry}`, functionFolder)); - // Bundle dependencies - await esbuild.build({ - entryPoints: [entryPath], - outfile: entryPath, - bundle: true, - target: 'node14', - format: 'cjs', - platform: 'node', - allowOverwrite: true, - }); + // await esbuild.build({ + // entryPoints: [entryPath], + // outfile: entryPath, + // bundle: true, + // target: 'node14.19', + // format: 'esm', + // platform: 'node', + // allowOverwrite: true, + // }); + + // Copy necessary files (e.g. node_modules/) + await copyFunctionNFT(_config.root, functionFolder, serverEntry); // Edge function config // https://vercel.com/docs/build-output-api/v3#vercel-primitives/edge-functions/configuration @@ -78,6 +76,10 @@ export default function vercelEdge(): AstroIntegration { launcherType: 'Nodejs', }); + await writeJson(new URL(`./package.json`, functionFolder), { + type: 'module', + }); + // Output configuration // https://vercel.com/docs/build-output-api/v3#build-output-configuration await writeJson(new URL(`./config.json`, _config.outDir), { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 53d38b33beef..fa4964ed9728 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1468,11 +1468,13 @@ importers: packages/integrations/vercel: specifiers: '@astrojs/webapi': ^0.11.1 + '@vercel/nft': ^0.18.2 astro: workspace:* astro-scripts: workspace:* esbuild: ^0.14.38 dependencies: '@astrojs/webapi': link:../../webapi + '@vercel/nft': 0.18.2 esbuild: 0.14.38 devDependencies: astro: link:../../astro @@ -3522,6 +3524,24 @@ packages: read-yaml-file: 1.1.0 dev: true + /@mapbox/node-pre-gyp/1.0.9: + resolution: {integrity: sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==} + hasBin: true + dependencies: + detect-libc: 2.0.1 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.6.7 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.3.7 + tar: 6.1.11 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + /@nanostores/preact/0.1.3_szcmxo7i5hx4oviopihqnbgbg4: resolution: {integrity: sha512-uiX1ned0LrzASot+sPUjyJzr8Js3pX075omazgsSdLf0zPp4ss8xwTiuNh5FSKigTSQEVqZFiS+W8CnHIrX62A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -4386,6 +4406,26 @@ packages: '@unocss/scope': 0.15.6 dev: true + /@vercel/nft/0.18.2: + resolution: {integrity: sha512-Oxy4y5JDh7CMbaxEGjKKzHcnQ1gRQqtfp+x3xvOmZYixXHwaD2RMJDTzaPz0b2B3pgVbbPOHY87wffJPFDaoFg==} + hasBin: true + dependencies: + '@mapbox/node-pre-gyp': 1.0.9 + acorn: 8.7.0 + bindings: 1.5.0 + estree-walker: 2.0.2 + glob: 7.2.0 + graceful-fs: 4.2.10 + micromatch: 4.0.5 + node-gyp-build: 4.4.0 + node-pre-gyp: 0.13.0 + resolve-from: 5.0.0 + rollup-pluginutils: 2.8.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + /@vitejs/plugin-vue/2.3.1_vue@3.2.33: resolution: {integrity: sha512-YNzBt8+jt6bSwpt7LP890U1UcTOIZZxfpE5WOJ638PNxSEKOqAi0+FSKS0nVeukfdZ0Ai/H7AFd6k3hayfGZqQ==} engines: {node: '>=12.0.0'} @@ -4501,6 +4541,10 @@ packages: resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} dev: true + /abbrev/1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: false + /abort-controller/3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -4541,7 +4585,6 @@ packages: resolution: {integrity: sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==} engines: {node: '>=0.4.0'} hasBin: true - dev: true /adm-zip/0.5.9: resolution: {integrity: sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==} @@ -4555,7 +4598,6 @@ packages: debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true /aggregate-error/3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} @@ -4622,7 +4664,6 @@ packages: /ansi-regex/2.1.1: resolution: {integrity: sha1-w7M6te42DYbg5ijwRorn7yfWVN8=} engines: {node: '>=0.10.0'} - dev: true /ansi-regex/5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -4659,14 +4700,20 @@ packages: /aproba/1.2.0: resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==} - dev: true /are-we-there-yet/1.1.7: resolution: {integrity: sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==} dependencies: delegates: 1.0.0 readable-stream: 2.3.7 - dev: true + + /are-we-there-yet/2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.0 + dev: false /arg/5.0.1: resolution: {integrity: sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==} @@ -4852,6 +4899,12 @@ packages: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} + /bindings/1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + dependencies: + file-uri-to-path: 1.0.0 + dev: false + /bl/4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} dependencies: @@ -5118,7 +5171,6 @@ packages: /chownr/1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - dev: true /chownr/2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} @@ -5177,7 +5229,6 @@ packages: /code-point-at/1.1.0: resolution: {integrity: sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=} engines: {node: '>=0.10.0'} - dev: true /color-convert/1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -5203,6 +5254,11 @@ packages: simple-swizzle: 0.2.2 dev: true + /color-support/1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + dev: false + /color/4.2.3: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} engines: {node: '>=12.5.0'} @@ -5255,7 +5311,6 @@ packages: /console-control-strings/1.1.0: resolution: {integrity: sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=} - dev: true /convert-source-map/1.8.0: resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} @@ -5271,7 +5326,6 @@ packages: /core-util-is/1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true /cross-spawn/5.1.0: resolution: {integrity: sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=} @@ -5374,6 +5428,12 @@ packages: engines: {node: '>=0.11'} dev: true + /debug/3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + dependencies: + ms: 2.1.3 + dev: false + /debug/4.3.3_supports-color@8.1.1: resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} engines: {node: '>=6.0'} @@ -5443,7 +5503,6 @@ packages: /deep-extend/0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} - dev: true /deep-is/0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -5504,7 +5563,6 @@ packages: /delegates/1.0.0: resolution: {integrity: sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=} - dev: true /depd/2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} @@ -5527,12 +5585,10 @@ packages: resolution: {integrity: sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=} engines: {node: '>=0.10'} hasBin: true - dev: true /detect-libc/2.0.1: resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==} engines: {node: '>=8'} - dev: true /detective/5.2.0: resolution: {integrity: sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==} @@ -6089,6 +6145,10 @@ packages: '@types/unist': 2.0.6 dev: false + /estree-walker/0.6.1: + resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} + dev: false + /estree-walker/1.0.1: resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} dev: true @@ -6224,6 +6284,10 @@ packages: flat-cache: 3.0.4 dev: true + /file-uri-to-path/1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + dev: false + /file-uri-to-path/2.0.0: resolution: {integrity: sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==} engines: {node: '>= 6'} @@ -6329,6 +6393,12 @@ packages: universalify: 2.0.0 dev: true + /fs-minipass/1.2.7: + resolution: {integrity: sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==} + dependencies: + minipass: 2.9.0 + dev: false + /fs-minipass/2.1.0: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} @@ -6376,7 +6446,21 @@ packages: string-width: 1.0.2 strip-ansi: 3.0.1 wide-align: 1.1.5 - dev: true + + /gauge/3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + dependencies: + aproba: 1.2.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: false /gensync/1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} @@ -6567,7 +6651,6 @@ packages: /has-unicode/2.0.1: resolution: {integrity: sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=} - dev: true /has/1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} @@ -6773,7 +6856,6 @@ packages: debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true /human-id/1.0.2: resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} @@ -6793,7 +6875,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 - dev: true /idb/6.1.5: resolution: {integrity: sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==} @@ -6802,6 +6883,12 @@ packages: /ieee754/1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + /ignore-walk/3.0.4: + resolution: {integrity: sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==} + dependencies: + minimatch: 3.1.2 + dev: false + /ignore/5.2.0: resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} engines: {node: '>= 4'} @@ -6845,7 +6932,6 @@ packages: /ini/1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true /inline-style-parser/0.1.1: resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} @@ -6970,7 +7056,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: number-is-nan: 1.0.1 - dev: true /is-fullwidth-code-point/3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} @@ -7150,7 +7235,6 @@ packages: /isarray/1.0.0: resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=} - dev: true /isexe/2.0.0: resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} @@ -7450,6 +7534,13 @@ packages: sourcemap-codec: 1.4.8 dev: false + /make-dir/3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.0 + dev: false + /map-obj/1.0.1: resolution: {integrity: sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=} engines: {node: '>=0.10.0'} @@ -7991,6 +8082,13 @@ packages: /minimist/1.2.6: resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + /minipass/2.9.0: + resolution: {integrity: sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==} + dependencies: + safe-buffer: 5.2.1 + yallist: 3.1.1 + dev: false + /minipass/3.1.6: resolution: {integrity: sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==} engines: {node: '>=8'} @@ -7998,6 +8096,12 @@ packages: yallist: 4.0.0 dev: false + /minizlib/1.3.3: + resolution: {integrity: sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==} + dependencies: + minipass: 2.9.0 + dev: false + /minizlib/2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} @@ -8072,7 +8176,6 @@ packages: /ms/2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true /nanoid/3.3.1: resolution: {integrity: sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==} @@ -8098,6 +8201,16 @@ packages: resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} dev: true + /needle/2.9.1: + resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==} + engines: {node: '>= 4.4.x'} + hasBin: true + dependencies: + debug: 3.2.7 + iconv-lite: 0.4.24 + sax: 1.2.4 + dev: false + /netmask/2.0.2: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} @@ -8158,9 +8271,47 @@ packages: fetch-blob: 3.1.5 formdata-polyfill: 4.0.10 + /node-gyp-build/4.4.0: + resolution: {integrity: sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==} + hasBin: true + dev: false + + /node-pre-gyp/0.13.0: + resolution: {integrity: sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ==} + deprecated: 'Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future' + hasBin: true + dependencies: + detect-libc: 1.0.3 + mkdirp: 0.5.6 + needle: 2.9.1 + nopt: 4.0.3 + npm-packlist: 1.4.8 + npmlog: 4.1.2 + rc: 1.2.8 + rimraf: 2.7.1 + semver: 5.7.1 + tar: 4.4.19 + dev: false + /node-releases/2.0.3: resolution: {integrity: sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw==} + /nopt/4.0.3: + resolution: {integrity: sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==} + hasBin: true + dependencies: + abbrev: 1.1.1 + osenv: 0.1.5 + dev: false + + /nopt/5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: false + /normalize-package-data/2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} dependencies: @@ -8181,6 +8332,24 @@ packages: /not/0.1.0: resolution: {integrity: sha1-yWkcF0bFXc++VMvYvU/wQbwrUZ0=} + /npm-bundled/1.1.2: + resolution: {integrity: sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==} + dependencies: + npm-normalize-package-bin: 1.0.1 + dev: false + + /npm-normalize-package-bin/1.0.1: + resolution: {integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==} + dev: false + + /npm-packlist/1.4.8: + resolution: {integrity: sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==} + dependencies: + ignore-walk: 3.0.4 + npm-bundled: 1.1.2 + npm-normalize-package-bin: 1.0.1 + dev: false + /npm-run-path/4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -8201,7 +8370,15 @@ packages: console-control-strings: 1.1.0 gauge: 2.7.4 set-blocking: 2.0.0 - dev: true + + /npmlog/5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + dev: false /nth-check/2.0.1: resolution: {integrity: sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==} @@ -8211,7 +8388,6 @@ packages: /number-is-nan/1.0.1: resolution: {integrity: sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=} engines: {node: '>=0.10.0'} - dev: true /object-assign/4.1.1: resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} @@ -8309,10 +8485,21 @@ packages: wcwidth: 1.0.1 dev: false + /os-homedir/1.0.2: + resolution: {integrity: sha1-/7xJiDNuDoM94MFox+8VISGqf7M=} + engines: {node: '>=0.10.0'} + dev: false + /os-tmpdir/1.0.2: resolution: {integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=} engines: {node: '>=0.10.0'} - dev: true + + /osenv/0.1.5: + resolution: {integrity: sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==} + dependencies: + os-homedir: 1.0.2 + os-tmpdir: 1.0.2 + dev: false /outdent/0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} @@ -8688,7 +8875,6 @@ packages: /process-nextick-args/2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true /prompts/2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} @@ -8773,7 +8959,6 @@ packages: ini: 1.3.8 minimist: 1.2.6 strip-json-comments: 2.0.1 - dev: true /react-dom/17.0.2_react@17.0.2: resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} @@ -8857,7 +9042,6 @@ packages: safe-buffer: 5.1.2 string_decoder: 1.1.1 util-deprecate: 1.0.2 - dev: true /readable-stream/3.6.0: resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} @@ -9062,7 +9246,6 @@ packages: /resolve-from/5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} - dev: true /resolve/1.22.0: resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} @@ -9130,7 +9313,6 @@ packages: hasBin: true dependencies: glob: 7.2.0 - dev: true /rollup-plugin-terser/7.0.2_rollup@2.70.2: resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} @@ -9144,6 +9326,12 @@ packages: terser: 5.12.1 dev: true + /rollup-pluginutils/2.8.2: + resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} + dependencies: + estree-walker: 0.6.1 + dev: false + /rollup/2.70.2: resolution: {integrity: sha512-EitogNZnfku65I1DD5Mxe8JYRUCy0hkK5X84IlDtUs+O6JRMpRciXTzyCUuX11b5L5pvjH+OmFXiQ3XjabcXgg==} engines: {node: '>=10.0.0'} @@ -9177,7 +9365,6 @@ packages: /safer-buffer/2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true /sander/0.5.1: resolution: {integrity: sha1-dB4kXiMfB8r7b98PEzrfohalAq0=} @@ -9224,7 +9411,6 @@ packages: /semver/5.7.1: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} hasBin: true - dev: true /semver/6.3.0: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} @@ -9256,7 +9442,6 @@ packages: /set-blocking/2.0.0: resolution: {integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=} - dev: true /setprototypeof/1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -9534,7 +9719,6 @@ packages: code-point-at: 1.1.0 is-fullwidth-code-point: 1.0.0 strip-ansi: 3.0.1 - dev: true /string-width/4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} @@ -9586,7 +9770,6 @@ packages: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} dependencies: safe-buffer: 5.1.2 - dev: true /string_decoder/1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -9614,7 +9797,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: ansi-regex: 2.1.1 - dev: true /strip-ansi/6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} @@ -9666,7 +9848,6 @@ packages: /strip-json-comments/2.0.1: resolution: {integrity: sha1-PFMZQukIwml8DsNEhYwobHygpgo=} engines: {node: '>=0.10.0'} - dev: true /strip-json-comments/3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} @@ -9837,6 +10018,19 @@ packages: readable-stream: 3.6.0 dev: true + /tar/4.4.19: + resolution: {integrity: sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==} + engines: {node: '>=4.5'} + dependencies: + chownr: 1.1.4 + fs-minipass: 1.2.7 + minipass: 2.9.0 + minizlib: 1.3.3 + mkdirp: 0.5.6 + safe-buffer: 5.2.1 + yallist: 3.1.1 + dev: false + /tar/6.1.11: resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==} engines: {node: '>= 10'} @@ -10654,8 +10848,7 @@ packages: /wide-align/1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} dependencies: - string-width: 1.0.2 - dev: true + string-width: 4.2.3 /widest-line/4.0.1: resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} @@ -10872,7 +11065,6 @@ packages: /yallist/3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true /yallist/4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} From 0830562b2c65a7b75156997fcc3454a7bb577380 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Thu, 5 May 2022 16:47:40 -0300 Subject: [PATCH 22/33] Beautify --- .../vercel/src/serverless/adapter.ts | 39 ++++--------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index 8e3efd7c6741..2125cbf5a15c 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -28,20 +28,6 @@ export default function vercelEdge(): AstroIntegration { setAdapter(getAdapter()); _config = config; }, - // 'astro:build:setup': ({ vite, target }) => { - // if (target === 'server') { - // vite.build = { - // ...(vite.build || {}), - // rollupOptions: { - // ...(vite.build?.rollupOptions || {}), - // output: { - // ...(vite.build?.rollupOptions?.output || {}), - // format: 'cjs', - // }, - // }, - // }; - // } - // }, 'astro:build:start': async ({ buildConfig }) => { if (String(process.env.ENABLE_VC_BUILD) !== '1') { throw new Error( @@ -54,32 +40,23 @@ export default function vercelEdge(): AstroIntegration { buildConfig.server = functionFolder = new URL('./functions/render.func/', _config.outDir); }, 'astro:build:done': async ({ routes }) => { - // Bundle dependencies - // await esbuild.build({ - // entryPoints: [entryPath], - // outfile: entryPath, - // bundle: true, - // target: 'node14.19', - // format: 'esm', - // platform: 'node', - // allowOverwrite: true, - // }); - // Copy necessary files (e.g. node_modules/) await copyFunctionNFT(_config.root, functionFolder, serverEntry); - // Edge function config - // https://vercel.com/docs/build-output-api/v3#vercel-primitives/edge-functions/configuration + // Enable ESM + // https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda/ + await writeJson(new URL(`./package.json`, functionFolder), { + type: 'module', + }); + + // Serverless function config + // https://vercel.com/docs/build-output-api/v3#vercel-primitives/serverless-functions/configuration await writeJson(new URL(`./.vc-config.json`, functionFolder), { runtime: 'nodejs14.x', handler: serverEntry, launcherType: 'Nodejs', }); - await writeJson(new URL(`./package.json`, functionFolder), { - type: 'module', - }); - // Output configuration // https://vercel.com/docs/build-output-api/v3#build-output-configuration await writeJson(new URL(`./config.json`, _config.outDir), { From 85a797feef2dc24091458a4fe92736c09915cb0e Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Thu, 5 May 2022 17:05:31 -0300 Subject: [PATCH 23/33] Edge bundle to node 14.19 Vercel runs 14.19.1 (I've checked it manually) --- packages/integrations/vercel/src/edge/adapter.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/integrations/vercel/src/edge/adapter.ts b/packages/integrations/vercel/src/edge/adapter.ts index 72c26c05581b..8be0193f62f1 100644 --- a/packages/integrations/vercel/src/edge/adapter.ts +++ b/packages/integrations/vercel/src/edge/adapter.ts @@ -1,5 +1,4 @@ import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; - import { fileURLToPath } from 'url'; import esbuild from 'esbuild'; @@ -51,7 +50,7 @@ export default function vercelEdge(): AstroIntegration { outfile: entryPath, inject: [fileURLToPath(new URL('./shim.js', import.meta.url))], bundle: true, - target: 'node14', + target: 'node14.19', format: 'esm', platform: 'browser', allowOverwrite: true, From 5d6e273c5d9f5245d0f845ead48ee3fd076bbd40 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Fri, 6 May 2022 14:50:41 -0300 Subject: [PATCH 24/33] Re-added shim (#3304) --- packages/integrations/vercel/src/edge/shim.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/integrations/vercel/src/edge/shim.ts b/packages/integrations/vercel/src/edge/shim.ts index f7ac655bfcef..16af239f19c2 100644 --- a/packages/integrations/vercel/src/edge/shim.ts +++ b/packages/integrations/vercel/src/edge/shim.ts @@ -2,3 +2,5 @@ export let process = { argv: [], env: {}, }; + +export let global = { crypto: globalThis.crypto }; From af1be5672d2b54605b597f28abf3b4db30f46da5 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Fri, 6 May 2022 15:13:13 -0300 Subject: [PATCH 25/33] Added `node:` prefix --- packages/integrations/vercel/src/edge/adapter.ts | 2 +- packages/integrations/vercel/src/lib/fs.ts | 6 +++--- packages/integrations/vercel/src/serverless/adapter.ts | 1 - packages/integrations/vercel/src/serverless/entrypoint.ts | 2 +- .../integrations/vercel/src/serverless/request-transform.ts | 4 ++-- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/integrations/vercel/src/edge/adapter.ts b/packages/integrations/vercel/src/edge/adapter.ts index 8be0193f62f1..58fcb136662f 100644 --- a/packages/integrations/vercel/src/edge/adapter.ts +++ b/packages/integrations/vercel/src/edge/adapter.ts @@ -1,5 +1,5 @@ import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; -import { fileURLToPath } from 'url'; +import { fileURLToPath } from 'node:url'; import esbuild from 'esbuild'; import { writeJson, getVercelOutput } from '../lib/fs.js'; diff --git a/packages/integrations/vercel/src/lib/fs.ts b/packages/integrations/vercel/src/lib/fs.ts index b0677e8ce376..1dc7fb85ca31 100644 --- a/packages/integrations/vercel/src/lib/fs.ts +++ b/packages/integrations/vercel/src/lib/fs.ts @@ -1,6 +1,6 @@ -import type { PathLike } from 'fs'; -import * as fs from 'fs/promises'; -import { fileURLToPath } from 'url'; +import type { PathLike } from 'node:fs'; +import * as fs from 'node:fs/promises'; +import { fileURLToPath } from 'node:url'; import { nodeFileTrace } from '@vercel/nft'; export async function writeJson(path: PathLike, data: T) { diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index 2125cbf5a15c..f9432f56f3ee 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -1,5 +1,4 @@ import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; - import { writeJson, copyFunctionNFT, getVercelOutput } from '../lib/fs.js'; import { getRedirects } from '../lib/redirects.js'; diff --git a/packages/integrations/vercel/src/serverless/entrypoint.ts b/packages/integrations/vercel/src/serverless/entrypoint.ts index e32dbdd861ed..6ef7ccef9694 100644 --- a/packages/integrations/vercel/src/serverless/entrypoint.ts +++ b/packages/integrations/vercel/src/serverless/entrypoint.ts @@ -1,7 +1,7 @@ import type { SSRManifest } from 'astro'; import { App } from 'astro/app'; import { polyfill } from '@astrojs/webapi'; -import type { IncomingMessage, ServerResponse } from 'http'; +import type { IncomingMessage, ServerResponse } from 'node:http'; import { getRequest, setResponse } from './request-transform.js'; diff --git a/packages/integrations/vercel/src/serverless/request-transform.ts b/packages/integrations/vercel/src/serverless/request-transform.ts index 0a87ca6427dc..7cdb2550ab1f 100644 --- a/packages/integrations/vercel/src/serverless/request-transform.ts +++ b/packages/integrations/vercel/src/serverless/request-transform.ts @@ -1,5 +1,5 @@ -import { Readable } from 'stream'; -import type { IncomingMessage, ServerResponse } from 'http'; +import { Readable } from 'node:stream'; +import type { IncomingMessage, ServerResponse } from 'node:http'; /* Credits to the SvelteKit team From 649544ae3b5e524ee99881a5dab4a896201c3819 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Fri, 6 May 2022 16:43:42 -0300 Subject: [PATCH 26/33] Use the same bundling as Deno for Edge --- .../integrations/vercel/src/edge/adapter.ts | 27 ++++++++----------- .../vercel/src/edge/entrypoint.ts | 6 +++-- packages/integrations/vercel/src/edge/shim.ts | 6 +++-- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/packages/integrations/vercel/src/edge/adapter.ts b/packages/integrations/vercel/src/edge/adapter.ts index 58fcb136662f..664eb2c43cd7 100644 --- a/packages/integrations/vercel/src/edge/adapter.ts +++ b/packages/integrations/vercel/src/edge/adapter.ts @@ -1,6 +1,4 @@ import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; -import { fileURLToPath } from 'node:url'; -import esbuild from 'esbuild'; import { writeJson, getVercelOutput } from '../lib/fs.js'; import { getRedirects } from '../lib/redirects.js'; @@ -30,6 +28,17 @@ export default function vercelEdge(): AstroIntegration { setAdapter(getAdapter()); _config = config; }, + 'astro:build:setup': ({ vite, target }) => { + if (target === 'server') { + vite.resolve ||= {}; + vite.resolve.alias ||= {}; + const alias = vite.resolve.alias as Record; + alias['react-dom/server'] = 'react-dom/server.browser'; + vite.ssr = { + noExternal: true, + }; + } + }, 'astro:build:start': async ({ buildConfig }) => { if (String(process.env.ENABLE_VC_BUILD) !== '1') { throw new Error( @@ -42,20 +51,6 @@ export default function vercelEdge(): AstroIntegration { buildConfig.server = functionFolder = new URL('./functions/render.func/', _config.outDir); }, 'astro:build:done': async ({ routes }) => { - const entryPath = fileURLToPath(new URL(`./${serverEntry}`, functionFolder)); - - // Bundle dependencies - await esbuild.build({ - entryPoints: [entryPath], - outfile: entryPath, - inject: [fileURLToPath(new URL('./shim.js', import.meta.url))], - bundle: true, - target: 'node14.19', - format: 'esm', - platform: 'browser', - allowOverwrite: true, - }); - // Edge function config // https://vercel.com/docs/build-output-api/v3#vercel-primitives/edge-functions/configuration await writeJson(new URL(`./.vc-config.json`, functionFolder), { diff --git a/packages/integrations/vercel/src/edge/entrypoint.ts b/packages/integrations/vercel/src/edge/entrypoint.ts index 45ab97cd4885..af1496f602c2 100644 --- a/packages/integrations/vercel/src/edge/entrypoint.ts +++ b/packages/integrations/vercel/src/edge/entrypoint.ts @@ -1,12 +1,14 @@ +import './shim.js'; + import type { SSRManifest } from 'astro'; import { App } from 'astro/app'; export function createExports(manifest: SSRManifest) { const app = new App(manifest); - const handler = async (request: Request): Promise => { + const handler = async (request: Request): Promise => { if (app.match(request)) { - return app.render(request); + return await app.render(request); } return new Response(null, { diff --git a/packages/integrations/vercel/src/edge/shim.ts b/packages/integrations/vercel/src/edge/shim.ts index 16af239f19c2..4da6448be396 100644 --- a/packages/integrations/vercel/src/edge/shim.ts +++ b/packages/integrations/vercel/src/edge/shim.ts @@ -1,6 +1,8 @@ -export let process = { +// @ts-ignore +var process = { argv: [], env: {}, }; -export let global = { crypto: globalThis.crypto }; +// @ts-ignore +var global = { crypto: globalThis.crypto }; From 2716c851f0f716d74b20ed7c72740b8b8f24dd4a Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Fri, 6 May 2022 16:45:23 -0300 Subject: [PATCH 27/33] Remove esbuild --- packages/integrations/vercel/package.json | 3 +-- pnpm-lock.yaml | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/integrations/vercel/package.json b/packages/integrations/vercel/package.json index 47746f827cb8..e7f98b77e596 100644 --- a/packages/integrations/vercel/package.json +++ b/packages/integrations/vercel/package.json @@ -28,8 +28,7 @@ }, "dependencies": { "@astrojs/webapi": "^0.11.1", - "@vercel/nft": "^0.18.2", - "esbuild": "^0.14.38" + "@vercel/nft": "^0.18.2" }, "devDependencies": { "astro": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 10e73d7c08d0..27c0acd8838c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1471,11 +1471,9 @@ importers: '@vercel/nft': ^0.18.2 astro: workspace:* astro-scripts: workspace:* - esbuild: ^0.14.38 dependencies: '@astrojs/webapi': link:../../webapi '@vercel/nft': 0.18.2 - esbuild: 0.14.38 devDependencies: astro: link:../../astro astro-scripts: link:../../../scripts From f2fb587468c0960de6915d08f72cf68822c5e159 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Fri, 6 May 2022 16:52:48 -0300 Subject: [PATCH 28/33] Fixed shim --- packages/integrations/vercel/src/edge/shim.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/integrations/vercel/src/edge/shim.ts b/packages/integrations/vercel/src/edge/shim.ts index 4da6448be396..1a73feb39722 100644 --- a/packages/integrations/vercel/src/edge/shim.ts +++ b/packages/integrations/vercel/src/edge/shim.ts @@ -1,8 +1 @@ -// @ts-ignore -var process = { - argv: [], - env: {}, -}; - -// @ts-ignore -var global = { crypto: globalThis.crypto }; +process.argv = []; From 85eb0b1709bf88c9e2d5a28d718b4cb69838a600 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Fri, 6 May 2022 17:00:10 -0300 Subject: [PATCH 29/33] Moved nft --- packages/integrations/vercel/src/lib/fs.ts | 31 --------------- packages/integrations/vercel/src/lib/nft.ts | 38 +++++++++++++++++++ .../vercel/src/serverless/adapter.ts | 6 ++- 3 files changed, 42 insertions(+), 33 deletions(-) create mode 100644 packages/integrations/vercel/src/lib/nft.ts diff --git a/packages/integrations/vercel/src/lib/fs.ts b/packages/integrations/vercel/src/lib/fs.ts index 1dc7fb85ca31..e192ba554126 100644 --- a/packages/integrations/vercel/src/lib/fs.ts +++ b/packages/integrations/vercel/src/lib/fs.ts @@ -1,7 +1,5 @@ import type { PathLike } from 'node:fs'; import * as fs from 'node:fs/promises'; -import { fileURLToPath } from 'node:url'; -import { nodeFileTrace } from '@vercel/nft'; export async function writeJson(path: PathLike, data: T) { await fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); @@ -13,32 +11,3 @@ export async function emptyDir(dir: PathLike): Promise { } export const getVercelOutput = (root: URL) => new URL('./.vercel/output/', root); - -export async function copyFunctionNFT(root: URL, functionFolder: URL, serverEntry: string) { - const result = await nodeFileTrace([fileURLToPath(new URL(`./${serverEntry}`, functionFolder))], { - base: fileURLToPath(root), - }); - - for (const file of result.fileList) { - if (file.startsWith('.vercel/')) continue; - const origin = new URL(file, root); - const dest = new URL(file, functionFolder); - - const meta = await fs.stat(origin); - const isSymlink = (await fs.lstat(origin)).isSymbolicLink(); - - // Create directories - if (meta.isDirectory() && !isSymlink) { - await fs.mkdir(new URL('..', dest), { recursive: true }); - } else { - await fs.mkdir(new URL('.', dest), { recursive: true }); - } - - if (isSymlink) { - const link = await fs.readlink(origin); - await fs.symlink(link, dest, meta.isDirectory() ? 'dir' : 'file'); - } else { - await fs.copyFile(origin, dest); - } - } -} diff --git a/packages/integrations/vercel/src/lib/nft.ts b/packages/integrations/vercel/src/lib/nft.ts new file mode 100644 index 000000000000..d8842971404f --- /dev/null +++ b/packages/integrations/vercel/src/lib/nft.ts @@ -0,0 +1,38 @@ +import * as fs from 'node:fs/promises'; +import { fileURLToPath } from 'node:url'; +import { nodeFileTrace } from '@vercel/nft'; + +export async function copyDependenciesToFunction( + root: URL, + functionFolder: URL, + serverEntry: string +) { + const entryPath = fileURLToPath(new URL(`./${serverEntry}`, functionFolder)); + + const result = await nodeFileTrace([entryPath], { + base: fileURLToPath(root), + }); + + for (const file of result.fileList) { + if (file.startsWith('.vercel/')) continue; + const origin = new URL(file, root); + const dest = new URL(file, functionFolder); + + const meta = await fs.stat(origin); + const isSymlink = (await fs.lstat(origin)).isSymbolicLink(); + + // Create directories recursively + if (meta.isDirectory() && !isSymlink) { + await fs.mkdir(new URL('..', dest), { recursive: true }); + } else { + await fs.mkdir(new URL('.', dest), { recursive: true }); + } + + if (isSymlink) { + const link = await fs.readlink(origin); + await fs.symlink(link, dest, meta.isDirectory() ? 'dir' : 'file'); + } else { + await fs.copyFile(origin, dest); + } + } +} diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index f9432f56f3ee..640b3fa25e1c 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -1,5 +1,7 @@ import type { AstroAdapter, AstroConfig, AstroIntegration } from 'astro'; -import { writeJson, copyFunctionNFT, getVercelOutput } from '../lib/fs.js'; + +import { writeJson, getVercelOutput } from '../lib/fs.js'; +import { copyDependenciesToFunction } from '../lib/nft.js'; import { getRedirects } from '../lib/redirects.js'; const PACKAGE_NAME = '@astrojs/vercel/serverless'; @@ -40,7 +42,7 @@ export default function vercelEdge(): AstroIntegration { }, 'astro:build:done': async ({ routes }) => { // Copy necessary files (e.g. node_modules/) - await copyFunctionNFT(_config.root, functionFolder, serverEntry); + await copyDependenciesToFunction(_config.root, functionFolder, serverEntry); // Enable ESM // https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda/ From a48a859debb08ce5d315a5bcfad4ecf00ff657db Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Fri, 6 May 2022 18:30:08 -0300 Subject: [PATCH 30/33] Updated changeset --- .changeset/tiny-apes-shave.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/.changeset/tiny-apes-shave.md b/.changeset/tiny-apes-shave.md index 970396888882..78f78cce3136 100644 --- a/.changeset/tiny-apes-shave.md +++ b/.changeset/tiny-apes-shave.md @@ -3,10 +3,18 @@ --- -**Vercel Adapter v0.2** +**[BREAKING]** Now with Build Output API (v3)! [See the README to get started](https://github.com/withastro/astro/tree/main/packages/integrations/vercel#readme). -- Updated to Build Output API (v3) - - Make sure to rename the `ENABLE_FILE_SYSTEM_API` enviroment variable to `ENABLE_VC_BUILD`. - - The output folder changed from `.output` to `.vercel/output`. -- You can now deploy to the `edge`! See the README for more info. - `trailingSlash` redirects works without a `vercel.json` file: just configure them inside your `astro.config.mjs` +- Multiple deploy targets: `edge`, `serverless` and `static`! +- When building to `serverless`, your code isn't transpiled to CJS anymore. + +**Migrate from v0.1** + +1. Change the import inside `astro.config.mjs`: + ```diff + - import vercel from '@astrojs/vercel' + + import vercel from '@astrojs/vercel/serverless' + ``` +2. Rename the `ENABLE_FILE_SYSTEM_API` enviroment variable to `ENABLE_VC_BUILD`, as Vercel changed it. +3. The output folder changed from `.output` to `.vercel/output` — you may need to update your `.gitignore`. From df06593bf4efff1033d07207c948c3ffb67fd93b Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Fri, 6 May 2022 18:30:21 -0300 Subject: [PATCH 31/33] Added note about Edge --- packages/integrations/vercel/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/integrations/vercel/README.md b/packages/integrations/vercel/README.md index 45712cb18c98..a21d5523504b 100644 --- a/packages/integrations/vercel/README.md +++ b/packages/integrations/vercel/README.md @@ -45,16 +45,18 @@ vercel deploy --prebuilt You can deploy to different targes: -- `static`: generates a static website following Vercel's output formats, redirects, etc. -- `serverless`: SSR inside a [Node.js 14 function](https://vercel.com/docs/concepts/functions/serverless-functions). - `edge`: SSR inside a [Edge function](https://vercel.com/docs/concepts/functions/edge-functions). +- `serverless`: SSR inside a [Node.js 14 function](https://vercel.com/docs/concepts/functions/serverless-functions). +- `static`: generates a static website following Vercel's output formats, redirects, etc. + +> **Note**: deploying to the Edge has [its limitations](https://vercel.com/docs/concepts/functions/edge-functions#known-limitations) — they can't be more than 1 MB in size and they don't support native Node.js APIs, among others. You can change where to target by changing the import: ```js -import vercel from '@astrojs/vercel/static'; -import vercel from '@astrojs/vercel/serverless'; import vercel from '@astrojs/vercel/edge'; +import vercel from '@astrojs/vercel/serverless'; +import vercel from '@astrojs/vercel/static'; ``` From dd24191a8e6534dbb84d1487dfad31082d035000 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Fri, 6 May 2022 18:34:57 -0300 Subject: [PATCH 32/33] fix typo --- .changeset/tiny-apes-shave.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.changeset/tiny-apes-shave.md b/.changeset/tiny-apes-shave.md index 78f78cce3136..979650a6bd55 100644 --- a/.changeset/tiny-apes-shave.md +++ b/.changeset/tiny-apes-shave.md @@ -13,8 +13,8 @@ 1. Change the import inside `astro.config.mjs`: ```diff - - import vercel from '@astrojs/vercel' - + import vercel from '@astrojs/vercel/serverless' + - import vercel from '@astrojs/vercel'; + + import vercel from '@astrojs/vercel/serverless'; ``` -2. Rename the `ENABLE_FILE_SYSTEM_API` enviroment variable to `ENABLE_VC_BUILD`, as Vercel changed it. +2. Rename the `ENABLE_FILE_SYSTEM_API` environment variable to `ENABLE_VC_BUILD`, as Vercel changed it. 3. The output folder changed from `.output` to `.vercel/output` — you may need to update your `.gitignore`. From 34f73de41661d8c9708224337ff310da41b36bbe Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Mon, 9 May 2022 12:54:33 -0300 Subject: [PATCH 33/33] Added support for Node 16 (vercel/vercel#7772) --- packages/integrations/vercel/README.md | 14 +++++++++++++- .../integrations/vercel/src/serverless/adapter.ts | 8 ++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/integrations/vercel/README.md b/packages/integrations/vercel/README.md index a21d5523504b..a30617b67187 100644 --- a/packages/integrations/vercel/README.md +++ b/packages/integrations/vercel/README.md @@ -46,7 +46,7 @@ vercel deploy --prebuilt You can deploy to different targes: - `edge`: SSR inside a [Edge function](https://vercel.com/docs/concepts/functions/edge-functions). -- `serverless`: SSR inside a [Node.js 14 function](https://vercel.com/docs/concepts/functions/serverless-functions). +- `serverless`: SSR inside a [Node.js function](https://vercel.com/docs/concepts/functions/serverless-functions). - `static`: generates a static website following Vercel's output formats, redirects, etc. > **Note**: deploying to the Edge has [its limitations](https://vercel.com/docs/concepts/functions/edge-functions#known-limitations) — they can't be more than 1 MB in size and they don't support native Node.js APIs, among others. @@ -59,6 +59,18 @@ import vercel from '@astrojs/vercel/serverless'; import vercel from '@astrojs/vercel/static'; ``` +### Node.js version + +When deploying to `serverless` you can choose what version of Node.js you want to target: `12.x`, `14.x` or `16.x` (default). + +```js +import { defineConfig } from 'astro/config'; +import vercel from '@astrojs/vercel/serverless'; + +export default defineConfig({ + adapter: vercel({ nodeVersion: '14.x' }) +}); +``` ## Limitations diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index 640b3fa25e1c..babda1f84418 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -14,7 +14,11 @@ function getAdapter(): AstroAdapter { }; } -export default function vercelEdge(): AstroIntegration { +export interface Options { + nodeVersion?: '12.x' | '14.x' | '16.x'; +} + +export default function vercelEdge({ nodeVersion = '16.x' }: Options = {}): AstroIntegration { let _config: AstroConfig; let functionFolder: URL; let serverEntry: string; @@ -53,7 +57,7 @@ export default function vercelEdge(): AstroIntegration { // Serverless function config // https://vercel.com/docs/build-output-api/v3#vercel-primitives/serverless-functions/configuration await writeJson(new URL(`./.vc-config.json`, functionFolder), { - runtime: 'nodejs14.x', + runtime: `nodejs${nodeVersion}`, handler: serverEntry, launcherType: 'Nodejs', });