Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/workflows/lighthouse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ jobs:
run: |
npm install
npm run build
env:
AIRTABLE_BASE: ${{ secrets.AIRTABLE_BASE }}
AIRTABLE_TABLE: ${{ secrets.AIRTABLE_TABLE }}
AIRTABLE_TOKEN: ${{ secrets.AIRTABLE_TOKEN }}
- name: run Lighthouse CI
run: |
npm install -g @lhci/cli@0.14.x
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ node_modules
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
.fonts
.fonts
.wrangler
26 changes: 6 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
},
"devDependencies": {
"@poppanator/sveltekit-svg": "^5.0.0-svelte5.5",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/adapter-cloudflare": "^4.7.2",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^4.0.0-next.6",
Expand Down
7 changes: 6 additions & 1 deletion src/hooks.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import type { Handle } from '@sveltejs/kit';
const PRELOADED_FONTS = [TextFontURL];

export const handle: Handle = async ({ event, resolve }) => {
const response = await resolve(event);
// Also disable JS preloading in prerendered files
const response = await resolve(event, {
preload({ type }) {
return type != 'js' && type != 'asset';
}
});

// Disable JS preloading. This took hours to find.
// I hate web development.
Expand Down
1 change: 1 addition & 0 deletions src/routes/+layout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const prerender = true;
1 change: 0 additions & 1 deletion src/routes/+page.js

This file was deleted.

2 changes: 1 addition & 1 deletion src/routes/api/background.svg/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const GET = async ({ request }: { request: Request }) => {
headers: {
Vary: 'Width, Viewport-Width, Sec-CH-Width, Sec-CH-Viewport-Width, Sec-CH-Viewport-Height, Sec-CH-UA-Mobile',
'Content-Type': 'image/svg+xml',
'Cache-Control': 'public, max-age=604800'
'Cache-Control': 'immutable, max-age=31536000'
}
});
};
2 changes: 2 additions & 0 deletions src/routes/email/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { createSubscribeToken } from '$lib/jwt';
import { sendEmail } from '$lib/emails/email';
import table from '$lib/airtable';

export const prerender = false;

export const actions = {
default: async ({ url, request }) => {
const data = await request.formData();
Expand Down
2 changes: 2 additions & 0 deletions src/routes/email/subscribe/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { validateSubscribeToken } from '$lib/jwt';
import { redirect, type Actions } from '@sveltejs/kit';
import table from '$lib/airtable';

export const prerender = false;

export const actions = {
default: async ({ url }) => {
const token = url.searchParams.get('token');
Expand Down
2 changes: 2 additions & 0 deletions src/routes/email/unsubscribe/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { validateUnsubscribeToken } from '$lib/jwt';
import { redirect } from '@sveltejs/kit';
import table from '$lib/airtable';

export const prerender = false;

export const load: PageServerLoad = async ({ url }) => {
const token = url.searchParams.get('token');

Expand Down
2 changes: 1 addition & 1 deletion svelte.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import adapter from '@sveltejs/adapter-auto';
import adapter from '@sveltejs/adapter-cloudflare';
import { sveltePreprocess } from 'svelte-preprocess';

/** @type {import('@sveltejs/kit').Config} */
Expand Down
27 changes: 0 additions & 27 deletions vite.config.js

This file was deleted.

182 changes: 182 additions & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig, type Plugin, type ResolvedConfig } from 'vite';
import svg from '@poppanator/sveltekit-svg';

let HEADERS = `
/*
Accept-CH: Width, Viewport-Width, Sec-CH-Width, Sec-CH-Viewport-Width, Sec-CH-Viewport-Height, Sec-CH-UA-Mobile
`.trim();
let ROUTE_PATH = '/src/routes';
let ALWAYS_PRELOADED_BUNDLED = [
{
file: 'src/lib/fonts/DMSans.text.woff2',
as: 'font'
}
];
let ALWAYS_PRELOADED_STATIC = [
{
path: '/api/background.svg',
as: 'image'
}
];

let config: ResolvedConfig;
const plugin: Plugin = {
name: 'generate-headers',

configResolved(resolvedConfig) {
console.log(resolvedConfig);
config = resolvedConfig;
},

async generateBundle(options, bundle, isWrite) {
let baseFsPath = config.root + ROUTE_PATH;
console.log(`Using base path ${baseFsPath}`);

let fileToAssetMap: Record<string, Set<string>> = {};
let pathToCssMap: Record<string, Set<string>> = {};
let layoutFiles: Set<string> = new Set();

for (const chunk of Object.values(bundle)) {
if (chunk.type === 'asset') {
for (const name of chunk.originalFileNames) {
fileToAssetMap[name] = new Set<string>([...(fileToAssetMap[name] || []), chunk.fileName]);
}
}

if (chunk.type !== 'chunk' || !chunk.isDynamicEntry || !chunk.isEntry) {
continue;
}

// Get CSS files
let cssFiles = new Set<string>();
chunk.viteMetadata?.importedCss?.forEach((file) => cssFiles.add(file));

for (const imported of chunk.imports) {
let importedChunk = bundle[imported];

if (importedChunk.type !== 'chunk') {
continue;
}

importedChunk.viteMetadata?.importedCss?.forEach((file) => cssFiles.add(file));
}

// Get path
let path = null;
for (const alias of chunk.moduleIds) {
if (!alias.startsWith(baseFsPath)) {
continue;
}

if (alias.endsWith('/+layout.svelte')) {
cssFiles.forEach((file) => layoutFiles.add(file));
break;
}

if (!alias.endsWith('/+page.svelte')) {
continue;
}

path = alias.replace(baseFsPath, '').replace('+page.svelte', '');
if (path !== '/') {
// Remove trailing slash like SvelteKit does
path = path.replace(/\/$/, '');
}
}

if (path === null) {
this.warn(`Failed to determine path for chunk ${chunk.fileName} (moduleIds: ${chunk.moduleIds})`);
continue;
}

pathToCssMap[path] = cssFiles;
}

let alwaysIncluded = [...ALWAYS_PRELOADED_STATIC];

for (const toResolve of ALWAYS_PRELOADED_BUNDLED) {
const resolved = fileToAssetMap[toResolve.file];
if (resolved === undefined) {
console.log(fileToAssetMap);
return this.error(`Failed to resolve file ${toResolve.file}`);
}

for (const file of resolved.keys()) {
alwaysIncluded.push({
path: file,
as: toResolve.as
});
}
}

for (const file of layoutFiles.keys()) {
alwaysIncluded.push({
path: file,
as: 'style'
})
}

let headerOutput = `${HEADERS}\n\n# generated by generate-headers plugin`;

for (const [path, files] of Object.entries(pathToCssMap)) {
headerOutput += `\n${path}\n Link: `;
const headers = [...alwaysIncluded];

for (const file of files) {
headers.push({
path: file,
as: 'style'
});
}

headerOutput += headers
.map((v) => {
let header = `<${v.path}>; rel="preload"; as="${v.as}"; nopush`;
if (v.as === 'font') {
header += '; crossorigin="anonymous"';
}
return header;
})
.join(',');
headerOutput += '\n';
}

console.log(headerOutput);

this.emitFile({
type: 'asset',
fileName: '_headers',
source: headerOutput
});
}
};

export default defineConfig({
plugins: [
sveltekit(),
svg({
svgoOptions: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false // Why is this on by default!?
}
}
}
]
}
}),
plugin
],
build: {
cssMinify: 'lightningcss',
modulePreload: {
resolveDependencies(url, deps, context) {
return deps.filter((dep) => !dep.endsWith('.js'));
}
}
}
});
Loading