From 2e8726feec2e0d6ba8bd4db941009986e8e34141 Mon Sep 17 00:00:00 2001 From: Chris <7249920+chriswdmr@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:02:11 +0200 Subject: [PATCH] [@astrojs/vercel] Individually enable Speed Insights and Web Analytics (#8021) * Individually enable Speed Insights and Web Analytics * Update pnpm-lock.yaml * Remove .only on tests * Fix build * Move `beforeSend` out of config * Address feedback from review * Update README.md * Add back the `analytics` property and add deprecation warning when used * Add migration guide for the deprecated `analytics` property * Update packages/integrations/vercel/README.md Co-authored-by: Sarah Rainsberger * Update README.md * Fix external dependency issue * Simplify plugin and reduce scope * Update .changeset/sixty-teachers-tap.md Co-authored-by: Emanuele Stoppa * Apply feedback from review * Move exposeEnv to speed-insights since it's only used there --------- Co-authored-by: Sarah Rainsberger Co-authored-by: Matthew Phillips Co-authored-by: Emanuele Stoppa --- .changeset/sixty-teachers-tap.md | 26 +++++++++++ packages/integrations/vercel/README.md | 37 ++++++++++++--- packages/integrations/vercel/package.json | 2 +- .../src/lib/{env.ts => speed-insights.ts} | 14 ++++++ .../vercel/src/lib/web-analytics.ts | 30 ++++++++++++ .../vercel/src/serverless/adapter.ts | 43 +++++++++++++---- .../src/{analytics.ts => speed-insights.ts} | 33 ++++++------- .../integrations/vercel/src/static/adapter.ts | 39 +++++++++++++--- packages/integrations/vercel/src/types.d.ts | 3 ++ .../output-as-server/astro.config.mjs | 10 ++++ .../output-as-server/package.json | 9 ++++ .../output-as-server/src/pages/one.astro | 8 ++++ .../output-as-server/src/pages/two.astro | 8 ++++ .../output-as-static/astro.config.mjs | 10 ++++ .../output-as-static/package.json | 9 ++++ .../output-as-static/src/pages/one.astro | 8 ++++ .../output-as-static/src/pages/two.astro | 8 ++++ .../output-as-static/astro.config.mjs | 10 ++++ .../output-as-static/package.json | 9 ++++ .../output-as-static/src/pages/one.astro | 8 ++++ .../output-as-static/src/pages/two.astro | 8 ++++ .../vercel/test/speed-insights.test.js | 46 +++++++++++++++++++ .../vercel/test/web-analytics.test.js | 25 ++++++++++ pnpm-lock.yaml | 36 +++++++++++++++ 24 files changed, 402 insertions(+), 37 deletions(-) create mode 100644 .changeset/sixty-teachers-tap.md rename packages/integrations/vercel/src/lib/{env.ts => speed-insights.ts} (68%) create mode 100644 packages/integrations/vercel/src/lib/web-analytics.ts rename packages/integrations/vercel/src/{analytics.ts => speed-insights.ts} (60%) create mode 100644 packages/integrations/vercel/src/types.d.ts create mode 100644 packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/astro.config.mjs create mode 100644 packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/package.json create mode 100644 packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/src/pages/one.astro create mode 100644 packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/src/pages/two.astro create mode 100644 packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/astro.config.mjs create mode 100644 packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/package.json create mode 100644 packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/src/pages/one.astro create mode 100644 packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/src/pages/two.astro create mode 100644 packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/astro.config.mjs create mode 100644 packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/package.json create mode 100644 packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/src/pages/one.astro create mode 100644 packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/src/pages/two.astro create mode 100644 packages/integrations/vercel/test/speed-insights.test.js create mode 100644 packages/integrations/vercel/test/web-analytics.test.js diff --git a/.changeset/sixty-teachers-tap.md b/.changeset/sixty-teachers-tap.md new file mode 100644 index 000000000..122557751 --- /dev/null +++ b/.changeset/sixty-teachers-tap.md @@ -0,0 +1,26 @@ +--- +'@astrojs/vercel': minor +--- + +Enable Vercel Speed Insights and Vercel Web Analytics individually. +Deprecates the `analytics` property in `astro.config.mjs` in favor of `speedInsights` and `webAnalytics`. + +If you're using the `analytics` property, you'll need to update your config to use the new properties: + +```diff +// astro.config.mjs +export default defineConfig({ + adapter: vercel({ +- analytics: true, ++ webAnalytics: { ++ enabled: true ++ }, ++ speedInsights: { ++ enabled: true ++ } + }) +}); +``` + +Allow configuration of Web Analytics with all available configuration options. +Bumps @vercel/analytics package to the latest version. diff --git a/packages/integrations/vercel/README.md b/packages/integrations/vercel/README.md index db3a52a03..7776c2b30 100644 --- a/packages/integrations/vercel/README.md +++ b/packages/integrations/vercel/README.md @@ -85,13 +85,13 @@ vercel deploy --prebuilt To configure this adapter, pass an object to the `vercel()` function call in `astro.config.mjs`: -### analytics +### Web Analytics -**Type:** `boolean`
-**Available for:** Serverless, Static
-**Added in:** `@astrojs/vercel@3.1.0` +**Type:** `VercelWebAnalyticsConfig`
+**Available for:** Serverless, Edge, Static
+**Added in:** `@astrojs/vercel@3.8.0` -You can enable [Vercel Analytics](https://vercel.com/analytics) (including Web Vitals and Audiences) by setting `analytics: true`. This will inject Vercel’s tracking scripts into all your pages. +You can enable [Vercel Web Analytics](https://vercel.com/docs/concepts/analytics) by setting `webAnalytics: { enabled: true }`. This will inject Vercel’s tracking scripts into all of your pages. ```js // astro.config.mjs @@ -101,7 +101,32 @@ import vercel from '@astrojs/vercel/serverless'; export default defineConfig({ output: 'server', adapter: vercel({ - analytics: true, + webAnalytics: { + enabled: true, + }, + }), +}); +``` + +### Speed Insights + +You can enable [Vercel Speed Insights](https://vercel.com/docs/concepts/speed-insights) by setting `speedInsights: { enabled: true }`. This will collect and send Web Vital data to Vercel. + +**Type:** `VercelSpeedInsightsConfig`
+**Available for:** Serverless, Edge, Static
+**Added in:** `@astrojs/vercel@3.8.0` + +```js +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import vercel from '@astrojs/vercel/serverless'; + +export default defineConfig({ + output: 'server', + adapter: vercel({ + speedInsights: { + enabled: true, + }, }), }); ``` diff --git a/packages/integrations/vercel/package.json b/packages/integrations/vercel/package.json index 34bbb269b..60c0878f1 100644 --- a/packages/integrations/vercel/package.json +++ b/packages/integrations/vercel/package.json @@ -22,7 +22,7 @@ "./serverless": "./dist/serverless/adapter.js", "./serverless/entrypoint": "./dist/serverless/entrypoint.js", "./static": "./dist/static/adapter.js", - "./analytics": "./dist/analytics.js", + "./speed-insights": "./dist/speed-insights.js", "./build-image-service": "./dist/image/build-service.js", "./dev-image-service": "./dist/image/dev-service.js", "./squoosh-dev-service": "./dist/image/squoosh-dev-service.js", diff --git a/packages/integrations/vercel/src/lib/env.ts b/packages/integrations/vercel/src/lib/speed-insights.ts similarity index 68% rename from packages/integrations/vercel/src/lib/env.ts rename to packages/integrations/vercel/src/lib/speed-insights.ts index 01d8c76a5..8e3639536 100644 --- a/packages/integrations/vercel/src/lib/env.ts +++ b/packages/integrations/vercel/src/lib/speed-insights.ts @@ -1,3 +1,17 @@ +export type VercelSpeedInsightsConfig = { + enabled: boolean; +}; + +export function getSpeedInsightsViteConfig(enabled?: boolean) { + if (enabled) { + return { + define: exposeEnv(['VERCEL_ANALYTICS_ID']), + }; + } + + return {}; +} + /** * While Vercel adds the `PUBLIC_` prefix for their `VERCEL_` env vars by default, some env vars * like `VERCEL_ANALYTICS_ID` aren't, so handle them here so that it works correctly in runtime. diff --git a/packages/integrations/vercel/src/lib/web-analytics.ts b/packages/integrations/vercel/src/lib/web-analytics.ts new file mode 100644 index 000000000..d6ee4d78d --- /dev/null +++ b/packages/integrations/vercel/src/lib/web-analytics.ts @@ -0,0 +1,30 @@ +export type VercelWebAnalyticsConfig = { + enabled: boolean; +}; + +export async function getInjectableWebAnalyticsContent({ + mode, +}: { + mode: 'development' | 'production'; +}) { + const base = `window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };`; + + if (mode === 'development') { + return ` + ${base} + var script = document.createElement('script'); + script.defer = true; + script.src = 'https://cdn.vercel-insights.com/v1/script.debug.js'; + var head = document.querySelector('head'); + head.appendChild(script); + `; + } + + return `${base} + var script = document.createElement('script'); + script.defer = true; + script.src = '/_vercel/insights/script.js'; + var head = document.querySelector('head'); + head.appendChild(script); + `; +} diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index 22785abf5..12fb2caa7 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -15,10 +15,17 @@ import { type DevImageService, type VercelImageConfig, } from '../image/shared.js'; -import { exposeEnv } from '../lib/env.js'; import { getVercelOutput, removeDir, writeJson } from '../lib/fs.js'; import { copyDependenciesToFunction } from '../lib/nft.js'; import { getRedirects } from '../lib/redirects.js'; +import { + getSpeedInsightsViteConfig, + type VercelSpeedInsightsConfig, +} from '../lib/speed-insights.js'; +import { + getInjectableWebAnalyticsContent, + type VercelWebAnalyticsConfig, +} from '../lib/web-analytics.js'; import { generateEdgeMiddleware } from './middleware.js'; const PACKAGE_NAME = '@astrojs/vercel/serverless'; @@ -64,9 +71,14 @@ function getAdapter({ } export interface VercelServerlessConfig { + /** + * @deprecated + */ + analytics?: boolean; + webAnalytics?: VercelWebAnalyticsConfig; + speedInsights?: VercelSpeedInsightsConfig; includeFiles?: string[]; excludeFiles?: string[]; - analytics?: boolean; imageService?: boolean; imagesConfig?: VercelImageConfig; devImageService?: DevImageService; @@ -75,9 +87,11 @@ export interface VercelServerlessConfig { } export default function vercelServerless({ + analytics, + webAnalytics, + speedInsights, includeFiles, excludeFiles, - analytics, imageService, imagesConfig, devImageService = 'sharp', @@ -131,12 +145,25 @@ export default function vercelServerless({ return { name: PACKAGE_NAME, hooks: { - 'astro:config:setup': ({ command, config, updateConfig, injectScript }) => { - if (command === 'build' && analytics) { - injectScript('page', 'import "@astrojs/vercel/analytics"'); + 'astro:config:setup': async ({ command, config, updateConfig, injectScript, logger }) => { + if (webAnalytics?.enabled || analytics) { + if (analytics) { + logger.warn( + `The \`analytics\` property is deprecated. Please use the new \`webAnalytics\` and \`speedInsights\` properties instead.` + ); + } + + injectScript( + 'head-inline', + await getInjectableWebAnalyticsContent({ + mode: command === 'dev' ? 'development' : 'production', + }) + ); + } + if (command === 'build' && (speedInsights?.enabled || analytics)) { + injectScript('page', 'import "@astrojs/vercel/speed-insights"'); } const outDir = getVercelOutput(config.root); - const viteDefine = exposeEnv(['VERCEL_ANALYTICS_ID']); updateConfig({ outDir, build: { @@ -145,7 +172,7 @@ export default function vercelServerless({ server: new URL('./dist/', config.root), }, vite: { - define: viteDefine, + ...getSpeedInsightsViteConfig(speedInsights?.enabled || analytics), ssr: { external: ['@vercel/nft'], }, diff --git a/packages/integrations/vercel/src/analytics.ts b/packages/integrations/vercel/src/speed-insights.ts similarity index 60% rename from packages/integrations/vercel/src/analytics.ts rename to packages/integrations/vercel/src/speed-insights.ts index 95dee83e3..cd2ae7fe8 100644 --- a/packages/integrations/vercel/src/analytics.ts +++ b/packages/integrations/vercel/src/speed-insights.ts @@ -1,8 +1,7 @@ -import { inject } from '@vercel/analytics'; import type { Metric } from 'web-vitals'; -import { getCLS, getFCP, getFID, getLCP, getTTFB } from 'web-vitals'; +import { onCLS, onFCP, onFID, onLCP, onTTFB } from 'web-vitals'; -const vitalsUrl = 'https://vitals.vercel-analytics.com/v1/vitals'; +const SPEED_INSIGHTS_INTAKE = 'https://vitals.vercel-analytics.com/v1/vitals'; type Options = { path: string; analyticsId: string }; @@ -14,7 +13,7 @@ const getConnectionSpeed = () => { : ''; }; -const sendToAnalytics = (metric: Metric, options: Options) => { +const sendToSpeedInsights = (metric: Metric, options: Options) => { const body = { dsn: options.analyticsId, id: metric.id, @@ -28,9 +27,9 @@ const sendToAnalytics = (metric: Metric, options: Options) => { type: 'application/x-www-form-urlencoded', }); if (navigator.sendBeacon) { - navigator.sendBeacon(vitalsUrl, blob); + navigator.sendBeacon(SPEED_INSIGHTS_INTAKE, blob); } else - fetch(vitalsUrl, { + fetch(SPEED_INSIGHTS_INTAKE, { body: blob, method: 'POST', credentials: 'omit', @@ -38,27 +37,29 @@ const sendToAnalytics = (metric: Metric, options: Options) => { }); }; -function webVitals() { +function collectWebVitals() { const analyticsId = (import.meta as any).env.PUBLIC_VERCEL_ANALYTICS_ID; + if (!analyticsId) { - console.error('[Analytics] VERCEL_ANALYTICS_ID not found'); + console.error('[Speed Insights] VERCEL_ANALYTICS_ID not found'); return; } + const options: Options = { path: window.location.pathname, analyticsId }; + try { - getFID((metric) => sendToAnalytics(metric, options)); - getTTFB((metric) => sendToAnalytics(metric, options)); - getLCP((metric) => sendToAnalytics(metric, options)); - getCLS((metric) => sendToAnalytics(metric, options)); - getFCP((metric) => sendToAnalytics(metric, options)); + onFID((metric) => sendToSpeedInsights(metric, options)); + onTTFB((metric) => sendToSpeedInsights(metric, options)); + onLCP((metric) => sendToSpeedInsights(metric, options)); + onCLS((metric) => sendToSpeedInsights(metric, options)); + onFCP((metric) => sendToSpeedInsights(metric, options)); } catch (err) { - console.error('[Analytics]', err); + console.error('[Speed Insights]', err); } } const mode = (import.meta as any).env.MODE as 'development' | 'production'; -inject({ mode }); if (mode === 'production') { - webVitals(); + collectWebVitals(); } diff --git a/packages/integrations/vercel/src/static/adapter.ts b/packages/integrations/vercel/src/static/adapter.ts index 27bc2fe2d..df2995c37 100644 --- a/packages/integrations/vercel/src/static/adapter.ts +++ b/packages/integrations/vercel/src/static/adapter.ts @@ -6,10 +6,17 @@ import { type DevImageService, type VercelImageConfig, } from '../image/shared.js'; -import { exposeEnv } from '../lib/env.js'; import { emptyDir, getVercelOutput, writeJson } from '../lib/fs.js'; import { isServerLikeOutput } from '../lib/prerender.js'; import { getRedirects } from '../lib/redirects.js'; +import { + getSpeedInsightsViteConfig, + type VercelSpeedInsightsConfig, +} from '../lib/speed-insights.js'; +import { + getInjectableWebAnalyticsContent, + type VercelWebAnalyticsConfig, +} from '../lib/web-analytics.js'; const PACKAGE_NAME = '@astrojs/vercel/static'; @@ -34,7 +41,12 @@ function getAdapter(): AstroAdapter { } export interface VercelStaticConfig { + /** + * @deprecated + */ analytics?: boolean; + webAnalytics?: VercelWebAnalyticsConfig; + speedInsights?: VercelSpeedInsightsConfig; imageService?: boolean; imagesConfig?: VercelImageConfig; devImageService?: DevImageService; @@ -42,6 +54,8 @@ export interface VercelStaticConfig { export default function vercelStatic({ analytics, + webAnalytics, + speedInsights, imageService, imagesConfig, devImageService = 'sharp', @@ -51,12 +65,25 @@ export default function vercelStatic({ return { name: '@astrojs/vercel', hooks: { - 'astro:config:setup': ({ command, config, injectScript, updateConfig }) => { - if (command === 'build' && analytics) { - injectScript('page', 'import "@astrojs/vercel/analytics"'); + 'astro:config:setup': async ({ command, config, injectScript, updateConfig, logger }) => { + if (webAnalytics?.enabled || analytics) { + if (analytics) { + logger.warn( + `The \`analytics\` property is deprecated. Please use the new \`webAnalytics\` and \`speedInsights\` properties instead.` + ); + } + + injectScript( + 'head-inline', + await getInjectableWebAnalyticsContent({ + mode: command === 'dev' ? 'development' : 'production', + }) + ); + } + if (command === 'build' && (speedInsights?.enabled || analytics)) { + injectScript('page', 'import "@astrojs/vercel/speed-insights"'); } const outDir = new URL('./static/', getVercelOutput(config.root)); - const viteDefine = exposeEnv(['VERCEL_ANALYTICS_ID']); updateConfig({ outDir, build: { @@ -64,7 +91,7 @@ export default function vercelStatic({ redirects: false, }, vite: { - define: viteDefine, + ...getSpeedInsightsViteConfig(speedInsights?.enabled || analytics), }, ...getAstroImageConfig( imageService, diff --git a/packages/integrations/vercel/src/types.d.ts b/packages/integrations/vercel/src/types.d.ts new file mode 100644 index 000000000..1c5b8d2db --- /dev/null +++ b/packages/integrations/vercel/src/types.d.ts @@ -0,0 +1,3 @@ +import type { AnalyticsProps } from '@vercel/analytics'; + +export type VercelWebAnalyticsBeforeSend = AnalyticsProps['beforeSend']; diff --git a/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/astro.config.mjs b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/astro.config.mjs new file mode 100644 index 000000000..b505034ce --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/astro.config.mjs @@ -0,0 +1,10 @@ +import { defineConfig } from 'astro/config'; +import vercel from '@astrojs/vercel/serverless'; + +export default defineConfig({ + adapter: vercel({ + speedInsights: { + enabled: true + } + }) +}); diff --git a/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/package.json b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/package.json new file mode 100644 index 000000000..4c6867fd3 --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/astro-vercel-with-speed-insights-enabled-output-as-server", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/vercel": "workspace:*", + "astro": "workspace:*" + } +} \ No newline at end of file diff --git a/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/src/pages/one.astro b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/src/pages/one.astro new file mode 100644 index 000000000..0c7fb90a7 --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/src/pages/one.astro @@ -0,0 +1,8 @@ + + + One + + +

One

+ + diff --git a/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/src/pages/two.astro b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/src/pages/two.astro new file mode 100644 index 000000000..e7ba9910e --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server/src/pages/two.astro @@ -0,0 +1,8 @@ + + + Two + + +

Two

+ + diff --git a/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/astro.config.mjs b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/astro.config.mjs new file mode 100644 index 000000000..a38f1e939 --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/astro.config.mjs @@ -0,0 +1,10 @@ +import { defineConfig } from 'astro/config'; +import vercel from '@astrojs/vercel/static'; + +export default defineConfig({ + adapter: vercel({ + speedInsights: { + enabled: true + } + }) +}); diff --git a/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/package.json b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/package.json new file mode 100644 index 000000000..0022e1e92 --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/astro-vercel-with-speed-insights-enabled-output-as-static", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/vercel": "workspace:*", + "astro": "workspace:*" + } +} diff --git a/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/src/pages/one.astro b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/src/pages/one.astro new file mode 100644 index 000000000..0c7fb90a7 --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/src/pages/one.astro @@ -0,0 +1,8 @@ + + + One + + +

One

+ + diff --git a/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/src/pages/two.astro b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/src/pages/two.astro new file mode 100644 index 000000000..e7ba9910e --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static/src/pages/two.astro @@ -0,0 +1,8 @@ + + + Two + + +

Two

+ + diff --git a/packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/astro.config.mjs b/packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/astro.config.mjs new file mode 100644 index 000000000..395cc9478 --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/astro.config.mjs @@ -0,0 +1,10 @@ +import { defineConfig } from 'astro/config'; +import vercel from '@astrojs/vercel/static'; + +export default defineConfig({ + adapter: vercel({ + webAnalytics: { + enabled: true + } + }) +}); diff --git a/packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/package.json b/packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/package.json new file mode 100644 index 000000000..c54ef16c7 --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/astro-vercel-with-web-analytics-enabled-output-as-static", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/vercel": "workspace:*", + "astro": "workspace:*" + } +} diff --git a/packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/src/pages/one.astro b/packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/src/pages/one.astro new file mode 100644 index 000000000..0c7fb90a7 --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/src/pages/one.astro @@ -0,0 +1,8 @@ + + + One + + +

One

+ + diff --git a/packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/src/pages/two.astro b/packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/src/pages/two.astro new file mode 100644 index 000000000..e7ba9910e --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static/src/pages/two.astro @@ -0,0 +1,8 @@ + + + Two + + +

Two

+ + diff --git a/packages/integrations/vercel/test/speed-insights.test.js b/packages/integrations/vercel/test/speed-insights.test.js new file mode 100644 index 000000000..7cf2ae778 --- /dev/null +++ b/packages/integrations/vercel/test/speed-insights.test.js @@ -0,0 +1,46 @@ +import { loadFixture } from './test-utils.js'; +import { expect } from 'chai'; + +describe('Vercel Speed Insights', () => { + describe('output: server', () => { + /** @type {import('./test-utils.js').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/with-speed-insights-enabled/output-as-server/', + output: 'server', + }); + await fixture.build(); + }); + + it('ensures that Vercel Speed Insights is present in the bundle', async () => { + const [page] = await fixture.readdir('../.vercel/output/static/_astro'); + + const bundle = await fixture.readFile(`../.vercel/output/static/_astro/${page}`); + + expect(bundle).to.contain('https://vitals.vercel-analytics.com/v1/vitals'); + }); + }); + + describe('output: static', () => { + /** @type {import('./test-utils.js').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/with-speed-insights-enabled/output-as-static/', + output: 'static', + }); + await fixture.build(); + }); + + it('ensures that Vercel Speed Insights is present in the bundle', async () => { + const [page] = await fixture.readdir('../.vercel/output/static/_astro'); + + const bundle = await fixture.readFile(`../.vercel/output/static/_astro/${page}`); + + expect(bundle).to.contain('https://vitals.vercel-analytics.com/v1/vitals'); + }); + }); +}); diff --git a/packages/integrations/vercel/test/web-analytics.test.js b/packages/integrations/vercel/test/web-analytics.test.js new file mode 100644 index 000000000..b728fae4c --- /dev/null +++ b/packages/integrations/vercel/test/web-analytics.test.js @@ -0,0 +1,25 @@ +import { loadFixture } from './test-utils.js'; +import { expect } from 'chai'; + +describe('Vercel Web Analytics', () => { + describe('output: static', () => { + /** @type {import('./test-utils.js').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/with-web-analytics-enabled/output-as-static/', + output: 'static', + }); + await fixture.build(); + }); + + it('ensures that Vercel Web Analytics is present in the header', async () => { + const pageOne = await fixture.readFile('../.vercel/output/static/one/index.html'); + const pageTwo = await fixture.readFile('../.vercel/output/static/two/index.html'); + + expect(pageOne).to.contain('/_vercel/insights/script.js'); + expect(pageTwo).to.contain('/_vercel/insights/script.js'); + }); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e178a0ee9..66287ebc7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4840,6 +4840,42 @@ importers: specifier: workspace:* version: link:../../../../../astro + packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server: + dependencies: + '@astrojs/vercel': + specifier: workspace:* + version: link:../../../.. + astro: + specifier: workspace:* + version: link:../../../../../../astro + + packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-static: + dependencies: + '@astrojs/vercel': + specifier: workspace:* + version: link:../../../.. + astro: + specifier: workspace:* + version: link:../../../../../../astro + + packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-server: + dependencies: + '@astrojs/vercel': + specifier: workspace:* + version: link:../../../.. + astro: + specifier: workspace:* + version: link:../../../../../../astro + + packages/integrations/vercel/test/fixtures/with-web-analytics-enabled/output-as-static: + dependencies: + '@astrojs/vercel': + specifier: workspace:* + version: link:../../../.. + astro: + specifier: workspace:* + version: link:../../../../../../astro + packages/integrations/vercel/test/hosted/hosted-astro-project: dependencies: '@astrojs/vercel':