ntsd / sveltekit-html-minifier

Sveltekit Adapter to Minify the preload HTML page
https://www.npmjs.com/package/sveltekit-html-minifier
MIT License
5 stars 1 forks source link

Notes for using with Vercel adapter, plus an alternative solution #5

Open leoj3n opened 5 months ago

leoj3n commented 5 months ago

Here are some hopefully helpful notes if you are just getting started with this and using Vercel adapter...

Having a root +layout.js like:

export const prerender = true;

And a svelte.config.js like:

import adapter from '@sveltejs/adapter-vercel';
import htmlMinifierAdaptor from "sveltekit-html-minifier";

/** @type {import('@sveltejs/kit').Config} */
const config = {
    kit: {
        adapter: htmlMinifierAdaptor(adapter(), { pages: ".svelte-kit/output" }),
    }
};

export default config;

I was getting an error like:

[...]
.svelte-kit/output/server/index.js                                      92.07 kB

Run npm run preview to preview your production build locally.

> Using sveltekit-html-minifier, @sveltejs/adapter-vercel
  ✔ done
✓ built in 10.85s
node:fs:601
  handleErrorFromBinding(ctx);
  ^

Error: ENOENT: no such file or directory, open '.svelte-kit/output/index.html'

So, I changed the config to:

import adapter from '@sveltejs/adapter-vercel';
import htmlMinifierAdaptor from "sveltekit-html-minifier";

/** @type {import('@sveltejs/kit').Config} */
const config = {
    kit: {
        adapter: htmlMinifierAdaptor(adapter(), { pages: ".svelte-kit/output/prerendered/pages" }),
    }
};

export default config;

Notice svelte-kit/output/prerendered/pages vs what I tried originally .svelte-kit/output.

This made it work; just thought I'd share if it helps anyone else using Vercel adapter.

Also note I learned you have to be using export const prerender = true; or else there is nothing to minify during "prerender".

Furthermore, I found this alternate method working using the html-minifier package directly in ./src/hooks.server.ts:

// ./src/hooks.server.ts
import { i18n } from '$lib/i18n';
import { minify } from 'html-minifier';
import { building } from '$app/environment';
import { sequence } from '@sveltejs/kit/hooks';

const minification_options = {
    collapseBooleanAttributes: true,
    collapseWhitespace: true,
    conservativeCollapse: true,
    decodeEntities: true,
    html5: true,
    ignoreCustomComments: [/^#/],
    minifyCSS: true,
    minifyJS: true,
    removeAttributeQuotes: true,
    removeComments: false, // some hydration code needs comments, so leave them in
    removeOptionalTags: true,
    removeRedundantAttributes: true,
    removeScriptTypeAttributes: true,
    removeStyleLinkTypeAttributes: true,
    sortAttributes: true,
    sortClassName: true
};

/** @type {import('@sveltejs/kit').Handle} */
async function minify_handle({ event, resolve }) {
    let page = '';

    return resolve(event, {
        transformPageChunk: ({ html, done }) => {
            page += html;
            if (done) {
                return building ? minify(page, minification_options) : page;
            }
        }
    });
}

export const handle = sequence(i18n.handle(), minify_handle);

I think using this adapter plugin is a bit more elegant than that however.

Just sharing if it helps anyone, so feel free to make it a closed issue; and thanks for sharing this adapter adapter.

ntsd commented 5 months ago

Thank you for sharing. The adaptor only works with prerender because it will minify the rendered HTML page. If The prerender is false It will render during the SSR response the hooks way should be correct. Thank you for clarifying I will not in the README