How to use transformIndexHtml to transform app.html
? · sveltejs/kit · Discussion #8269 (original) (raw)
I had this problem. This is how you solve it.
- you hook the server.hooks system.
- you inject a vite plugin that do transformPageChunk and call transformIndexHtml
vite.config.ts
import { sveltekit } from '@sveltejs/kit/vite' import { defineConfig } from 'vite' import { colorSuitePlugin } from 'tailwindcss-color-suite' import { hookTransformIndexHtmlPlugin } from './hookTransformIndexHtmlPlugin'
export default defineConfig({ plugins: [ sveltekit(), colorSuitePlugin(), // this is the plugin that uses transformIndexHtml, it was made with vue hookTransformIndexHtmlPlugin(), ] });
svelte.config.js
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; import hookHooks from './hookHookConfig'
/** @type {import('@sveltejs/kit').Config} */ const config = { preprocess: vitePreprocess(),
kit: {
prerender: {
}
}
};
export default hookHooks(config);
hookHookConfig.js
import { mergeConfig } from 'vite';
/**
@param {import('@sveltejs/kit').Config} [svelteKitConfig]
@returns {import('@sveltejs/kit').Config} */ export function hookHooks(svelteKitConfig) { const outDir = svelteKitConfig?.kit?.outDir ?? '.svelte-kit' const currentHook =
${outDir}/generated/hooks.server.mjs
const previousHook = svelteKitConfig?.kit?.files?.hooks?.server ?? 'src/hooks.server'globalThis.__hook_hooks = { currentHook, previousHook, }
/** @type {import('@sveltejs/kit').Config} */ const overrides = { kit: { files: { hooks: { server: currentHook } } }, }
return mergeConfig(svelteKitConfig, overrides);
}
hookTransformIndexHtmlPlugin.ts
import type { Plugin } from 'vite' import fs from 'fs' import path from 'path'
// taken from /@sveltejs/kit/src/utils/filesystem.js function resolve_entry(entry: string) { if (fs.existsSync(entry)) { const stats = fs.statSync(entry); const index = path.join(entry, 'index'); if (stats.isDirectory() && fs.existsSync(index)) { return resolve_entry(index); } return entry; } else { const dir = path.dirname(entry); if (fs.existsSync(dir)) { const base = path.basename(entry); const files = fs.readdirSync(dir); const found = files.find((file) => file.replace(/.(js|ts)$/, '') === base); if (found) return path.join(dir, found); } } return null; }
export function hookTransformIndexHtmlPlugin(): Plugin { return { name: 'hook-sveltekit-transformIndexHtml',
configureServer(server) {
const hookConfig = (globalThis as any).__hook_hooks
hookConfig.transformIndexHtml = server.transformIndexHtml
const handler =
`async ({ event, resolve }) => await resolve(event, {
transformPageChunk: async ({ html }) => {
const transform = globalThis.__hook_hooks.transformIndexHtml
if (!transform) return html
// vite has a lot of extra plugins we have to defeat them
// look at devHtmlTransformFn
let patchedHtml = await globalThis.__hook_hooks.transformIndexHtml('', '<html><head></head><body></body></html>', '');
patchedHtml = patchedHtml.replace('<script type="module" src="/@vite/client"></script>', '');
// now we patch the changes
return html
.replace('</head>', patchedHtml.match(/<head>([\\s\\S]*?)<\\/head>/)?.[0] || '</head>')
.replace('</body>', patchedHtml.match(/<body>([\\s\\S]*?)<\\/body>/)?.[0] || '</body>');
},
});
`
let combinedHooksContent
const currentHook = path.resolve(hookConfig.currentHook)
const previousHook = resolve_entry(hookConfig.previousHook)
if (previousHook && fs.existsSync(previousHook)) {
const currentDir = path.dirname(currentHook)
const hookPath = path.relative(currentDir, previousHook).replace(/\\/g, '/')
combinedHooksContent = `
import { sequence } from '@sveltejs/kit/hooks';
import * as userHooks from ${JSON.stringify(hookPath)};
const customHandle = ${handler}
export const handle = sequence(customHandle, userHooks.handle);
export default { ...userHooks, handle };
`
} else {
combinedHooksContent = `
export const handle = ${handler}
`;
}
combinedHooksContent = `
// this file is auto-generated
${combinedHooksContent}
`
fs.mkdirSync(path.dirname(hookConfig.currentHook), { recursive: true })
fs.writeFileSync(hookConfig.currentHook, combinedHooksContent)
},
};
}
Please provide a way for plugins to add hooks, that would solve this problem on the plugins part.
Also it would be nice it we had the server instance in the request.