Skip to content

Commit

Permalink
fix(dev): avoid css hash mismatch by applying custom css hash even fo…
Browse files Browse the repository at this point in the history
…r prebundling
  • Loading branch information
dominikg committed Jul 27, 2024
1 parent c1e2a80 commit 7c0a7ba
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/twenty-walls-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/vite-plugin-svelte': patch
---

fix(dev): make sure custom cssHash is applied consistently even for prebundled components to avoid hash mismatches during hydration
20 changes: 17 additions & 3 deletions packages/vite-plugin-svelte/src/utils/esbuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { readFileSync } from 'node:fs';
import * as svelte from 'svelte/compiler';
import { log } from './log.js';
import { toESBuildError } from './error.js';
import { safeBase64Hash } from './hash.js';
import { buildFilenameNormalizer } from './id.js';

/**
* @typedef {NonNullable<import('vite').DepOptimizationOptions['esbuildOptions']>} EsbuildOptions
Expand All @@ -26,6 +28,7 @@ export function esbuildSveltePlugin(options) {
const filter = /\.svelte(?:\?.*)?$/;
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection | undefined} */
let statsCollection;
const normalizeFilename = buildFilenameNormalizer(options.root);
build.onStart(() => {
statsCollection = options.stats?.startCollection('prebundle library components', {
logResult: (c) => c.stats.length > 1
Expand All @@ -34,7 +37,12 @@ export function esbuildSveltePlugin(options) {
build.onLoad({ filter }, async ({ path: filename }) => {
const code = readFileSync(filename, 'utf8');
try {
const contents = await compileSvelte(options, { filename, code }, statsCollection);
const contents = await compileSvelte(
options,
{ filename, code },
normalizeFilename,
statsCollection
);
return { contents };
} catch (e) {
return { errors: [toESBuildError(e, options)] };
Expand All @@ -49,11 +57,12 @@ export function esbuildSveltePlugin(options) {

/**
* @param {import('../types/options.d.ts').ResolvedOptions} options
* @param {{ filename: string; code: string }} input
* @param {{ filename: string, code: string }} input
* @param {(filename: string) => string} normalizeFilename
* @param {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection} [statsCollection]
* @returns {Promise<string>}
*/
async function compileSvelte(options, { filename, code }, statsCollection) {
async function compileSvelte(options, { filename, code }, normalizeFilename, statsCollection) {
let css = options.compilerOptions.css;
if (css !== 'injected') {
// TODO ideally we'd be able to externalize prebundled styles too, but for now always put them in the js
Expand All @@ -68,6 +77,11 @@ async function compileSvelte(options, { filename, code }, statsCollection) {
generate: 'client'
};

if (compileOptions.hmr && options.emitCss) {
const hash = `s-${safeBase64Hash(normalizeFilename(filename))}`;
compileOptions.cssHash = () => hash;
}

let preprocessed;

if (options.preprocess) {
Expand Down
11 changes: 11 additions & 0 deletions packages/vite-plugin-svelte/src/utils/id.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,17 @@ function normalize(filename, normalizedRoot) {
return stripRoot(normalizePath(filename), normalizedRoot);
}

/**
* create a normalizer function for root
*
* @param {string} root
* @returns {function(filename: string): string}
*/
export function buildFilenameNormalizer(root) {
const normalizedRoot = normalizePath(root);
return (filename) => normalize(filename, normalizedRoot);
}

/**
* @param {string} filename
* @param {string} root
Expand Down

0 comments on commit 7c0a7ba

Please sign in to comment.