mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-06 04:22:01 +00:00
docs(sveltekit): re-introduce speed insights (#9988)
This commit is contained in:
committed by
GitHub
parent
18ae78137c
commit
4280166df4
@@ -1,11 +1,10 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['eslint:recommended', 'prettier'],
|
||||
plugins: ['svelte3'],
|
||||
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
|
||||
extends: ['eslint:recommended', 'plugin:svelte/recommended', 'prettier'],
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020
|
||||
ecmaVersion: 2020,
|
||||
extraFileExtensions: ['.svelte']
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
engine-strict=true
|
||||
resolution-mode=highest
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
# create-svelte
|
||||
# SvelteKit Demo app
|
||||
|
||||
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
|
||||
The official demo app for SvelteKit, hosted on Vercel.
|
||||
|
||||
## Creating a project
|
||||
## Deploy Your Own
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fvercel%2Ftree%2Fmain%2Fexamples%2Fsveltekit-1&project-name=sveltekit-vercel&repository-name=sveltekit-vercel&demo-title=SvelteKit%20%2B%20Vercel&demo-url=https%3A%2F%2Fsveltekit-template.vercel.app%2F)
|
||||
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npm create svelte@latest
|
||||
|
||||
# create a new project in my-app
|
||||
npm create svelte@latest my-app
|
||||
```
|
||||
_Live Example: https://sveltekit-template.vercel.app_
|
||||
|
||||
## Developing
|
||||
|
||||
@@ -35,4 +29,8 @@ npm run build
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
||||
## Speed Insights
|
||||
|
||||
Once deployed on Vercel, you can benefit from [Speed Insights](https://vercel.com/docs/concepts/speed-insights) simply by navigating to Vercel's dashboard, clicking on the 'Speed Insights' tab, and enabling the product.
|
||||
|
||||
You will get data once your application will be re-deployed and will receive visitors.
|
||||
|
||||
@@ -16,19 +16,20 @@
|
||||
"@fontsource/fira-mono": "^4.5.10",
|
||||
"@neoconfetti/svelte": "^1.0.0",
|
||||
"@playwright/test": "^1.28.1",
|
||||
"@sveltejs/adapter-vercel": "^1.0.0",
|
||||
"@sveltejs/kit": "^1.0.0",
|
||||
"@sveltejs/adapter-vercel": "^3.0.0",
|
||||
"@sveltejs/kit": "^1.5.0",
|
||||
"@types/cookie": "^0.5.1",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-svelte3": "^4.0.0",
|
||||
"eslint-plugin-svelte": "^2.26.0",
|
||||
"prettier": "^2.8.0",
|
||||
"prettier-plugin-svelte": "^2.8.1",
|
||||
"svelte": "^3.54.0",
|
||||
"svelte-check": "^2.9.2",
|
||||
"typescript": "^4.9.3",
|
||||
"vite": "^4.0.0",
|
||||
"vitest": "^0.25.3"
|
||||
"svelte-check": "^3.0.1",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^4.3.0",
|
||||
"vitest": "^0.25.3",
|
||||
"web-vitals": "^3.3.1"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ const config = {
|
||||
command: 'npm run build && npm run preview',
|
||||
port: 4173
|
||||
},
|
||||
testDir: 'tests'
|
||||
testDir: 'tests',
|
||||
testMatch: /(.+\.)?(test|spec)\.[jt]s/
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
||||
786
examples/sveltekit-1/pnpm-lock.yaml
generated
786
examples/sveltekit-1/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
15
examples/sveltekit-1/src/app.d.ts
vendored
15
examples/sveltekit-1/src/app.d.ts
vendored
@@ -1,9 +1,12 @@
|
||||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
// and what to do when importing types
|
||||
declare namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface Platform {}
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface Platform {}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
|
||||
63
examples/sveltekit-1/src/lib/vitals.js
Normal file
63
examples/sveltekit-1/src/lib/vitals.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import { onCLS, onFCP, onFID, onLCP, onTTFB } from 'web-vitals';
|
||||
|
||||
const vitalsUrl = 'https://vitals.vercel-analytics.com/v1/vitals';
|
||||
|
||||
function getConnectionSpeed() {
|
||||
// @ts-ignore
|
||||
return navigator?.connection?.effectiveType ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("web-vitals").Metric} metric
|
||||
* @param {{ params: { [s: string]: any; } | ArrayLike<any>; path: string; analyticsId: string; debug: boolean; }} options
|
||||
*/
|
||||
function sendToAnalytics(metric, options) {
|
||||
const page = Object.entries(options.params).reduce(
|
||||
(acc, [key, value]) => acc.replace(value, `[${key}]`),
|
||||
options.path
|
||||
);
|
||||
|
||||
const body = {
|
||||
dsn: options.analyticsId,
|
||||
id: metric.id,
|
||||
page,
|
||||
href: location.href,
|
||||
event_name: metric.name,
|
||||
value: metric.value.toString(),
|
||||
speed: getConnectionSpeed()
|
||||
};
|
||||
|
||||
if (options.debug) {
|
||||
console.log('[Web Vitals]', metric.name, JSON.stringify(body, null, 2));
|
||||
}
|
||||
|
||||
const blob = new Blob([new URLSearchParams(body).toString()], {
|
||||
// This content type is necessary for `sendBeacon`
|
||||
type: 'application/x-www-form-urlencoded'
|
||||
});
|
||||
if (navigator.sendBeacon) {
|
||||
navigator.sendBeacon(vitalsUrl, blob);
|
||||
} else
|
||||
fetch(vitalsUrl, {
|
||||
body: blob,
|
||||
method: 'POST',
|
||||
credentials: 'omit',
|
||||
keepalive: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} options
|
||||
*/
|
||||
export function webVitals(options) {
|
||||
try {
|
||||
console.log(`[Web Vitals] for page ${options.path}`);
|
||||
onFID((metric) => sendToAnalytics(metric, options));
|
||||
onTTFB((metric) => sendToAnalytics(metric, options));
|
||||
onLCP((metric) => sendToAnalytics(metric, options));
|
||||
onCLS((metric) => sendToAnalytics(metric, options));
|
||||
onFCP((metric) => sendToAnalytics(metric, options));
|
||||
} catch (err) {
|
||||
console.error(`[Web Vitals] for page ${options.path}`, err);
|
||||
}
|
||||
}
|
||||
6
examples/sveltekit-1/src/routes/+layout.server.js
Normal file
6
examples/sveltekit-1/src/routes/+layout.server.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import { env } from '$env/dynamic/private';
|
||||
|
||||
/** @type {import('./$types').LayoutServerLoad} */
|
||||
export function load() {
|
||||
return { analyticsId: env.VERCEL_ANALYTICS_ID };
|
||||
}
|
||||
@@ -1,6 +1,20 @@
|
||||
<script>
|
||||
import { browser } from '$app/environment';
|
||||
import { page } from '$app/stores';
|
||||
import { webVitals } from '$lib/vitals';
|
||||
import Header from './Header.svelte';
|
||||
import './styles.css';
|
||||
|
||||
/** @type {import('./$types').LayoutServerData} */
|
||||
export let data;
|
||||
|
||||
$: if (browser && data?.analyticsId) {
|
||||
webVitals({
|
||||
path: $page.url.pathname,
|
||||
params: $page.params,
|
||||
analyticsId: data.analyticsId
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="app">
|
||||
|
||||
@@ -107,11 +107,11 @@
|
||||
<a class="how-to-play" href="/sverdle/how-to-play">How to play</a>
|
||||
|
||||
<div class="grid" class:playing={!won} class:bad-guess={form?.badGuess}>
|
||||
{#each Array(6) as _, row}
|
||||
{#each Array.from(Array(6).keys()) as row (row)}
|
||||
{@const current = row === i}
|
||||
<h2 class="visually-hidden">Row {row + 1}</h2>
|
||||
<div class="row" class:current>
|
||||
{#each Array(5) as _, column}
|
||||
{#each Array.from(Array(5).keys()) as column (column)}
|
||||
{@const answer = data.answers[row]?.[column]}
|
||||
{@const value = data.guesses[row]?.[column] ?? ''}
|
||||
{@const selected = current && column === data.guesses[row].length}
|
||||
|
||||
@@ -2,5 +2,5 @@ import { expect, test } from '@playwright/test';
|
||||
|
||||
test('about page has expected h1', async ({ page }) => {
|
||||
await page.goto('/about');
|
||||
expect(await page.textContent('h1')).toBe('About this app');
|
||||
await expect(page.getByRole('heading', { name: 'About this app' })).toBeVisible();
|
||||
});
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
/** @type {import('vite').UserConfig} */
|
||||
const config = {
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()],
|
||||
test: {
|
||||
include: ['src/**/*.{test,spec}.{js,ts}']
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user