How to use transformIndexHtml to transform app.html? · sveltejs/kit · Discussion #8269 (original) (raw)

I had this problem. This is how you solve it.

  1. you hook the server.hooks system.
  2. 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';

/**

}

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.