Add fine-grained HMR support (#2649)

* feat: add fine-grained HMR support

* chore: lint

* chore: lint

* fix: handle hmr with custom event handler

* refactor: cleanup hmr script
This commit is contained in:
Nate Moore 2022-02-24 13:11:18 -06:00 committed by GitHub
parent 0cffbfff39
commit 5091d788f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 37 additions and 36 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Add fine-grained HMR support for Astro files

View file

@ -85,8 +85,8 @@
"htmlparser2": "^7.1.2",
"kleur": "^4.1.4",
"magic-string": "^0.25.7",
"micromorph": "^0.0.2",
"mime": "^3.0.0",
"morphdom": "^2.6.1",
"parse5": "^6.0.1",
"path-to-regexp": "^6.2.0",
"postcss": "^8.3.8",

View file

@ -1,38 +1,20 @@
if (import.meta.hot) {
const parser = new DOMParser();
import.meta.hot.on('astro:reload', async ({ html }: { html: string }) => {
const { default: morphdom } = await import('morphdom');
import.meta.hot.on('astro:update', async ({ file }) => {
const { default: diff } = await import('micromorph');
// eslint-disable-next-line no-console
console.log(`[vite] hot updated: ${file}`);
const html = await fetch(`${window.location}`).then(res => res.text());
const doc = parser.parseFromString(html, 'text/html');
morphdom(document.head, doc.head, {
onBeforeElUpdated(fromEl, toEl) {
// Do not update identical tags
if (fromEl.isEqualNode(toEl)) {
return false;
}
// Do not update <link> or <script> tags
// to avoid re-fetching their contents
if (fromEl.tagName === toEl.tagName && (toEl.tagName === 'LINK' || toEl.tagName === 'SCRIPT')) {
return false;
}
return true;
},
});
morphdom(document.body, doc.body, {
onBeforeElUpdated(fromEl, toEl) {
if (fromEl.localName === 'astro-root') {
return fromEl.getAttribute('uid') !== toEl.getAttribute('uid');
}
if (fromEl.isEqualNode(toEl)) {
return false;
}
return true;
},
});
// Match incoming islands to current state
for (const root of doc.querySelectorAll('astro-root')) {
const uid = root.getAttribute('uid');
const current = document.querySelector(`astro-root[uid="${uid}"]`);
if (current) {
root.innerHTML = current?.innerHTML;
}
}
diff(document, doc);
});
}

View file

@ -112,7 +112,6 @@ async function handleRequest(
routeCache: routeCache,
viteServer: viteServer,
});
info(logging, 'astro', msg.req({ url: pathname, statusCode, reqTime: performance.now() - reqStart }));
writeHtmlResponse(res, statusCode, html);
} catch (_err: any) {
info(logging, 'astro', msg.req({ url: pathname, statusCode: 500 }));

View file

@ -1,7 +1,10 @@
import type { AstroConfig } from '../@types/astro';
import type { LogOptions } from '../core/logger.js';
import type { ViteDevServer, ModuleNode, HmrContext } from 'vite';
import type { PluginContext as RollupPluginContext, ResolvedId } from 'rollup';
import { invalidateCompilation, isCached } from './compile.js';
import { logger } from '../core/logger.js'
import { green } from 'kleur/colors';
interface TrackCSSDependenciesOptions {
viteDevServer: ViteDevServer | null;
@ -43,7 +46,7 @@ export async function trackCSSDependencies(this: RollupPluginContext, opts: Trac
}
}
export function handleHotUpdate(ctx: HmrContext, config: AstroConfig) {
export function handleHotUpdate(ctx: HmrContext, config: AstroConfig, logging: LogOptions) {
// Invalidate the compilation cache so it recompiles
invalidateCompilation(config, ctx.file);
@ -70,5 +73,12 @@ export function handleHotUpdate(ctx: HmrContext, config: AstroConfig) {
invalidateCompilation(config, file);
}
if (ctx.file.endsWith('.astro')) {
const file = ctx.file.replace(config.projectRoot.pathname, '/');
logger.info('astro', green('hmr'), `${file}`)
ctx.server.ws.send({ type: "custom", event: "astro:update", data: { file } })
return []
}
return Array.from(filtered);
}

View file

@ -199,7 +199,7 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu
}
},
async handleHotUpdate(context) {
return handleHotUpdate(context, config);
return handleHotUpdate(context, config, logging);
},
};
}

View file

@ -5867,6 +5867,11 @@ micromatch@^4.0.2, micromatch@^4.0.4:
braces "^3.0.1"
picomatch "^2.2.3"
micromorph@^0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/micromorph/-/micromorph-0.0.2.tgz#5cfbaea66ae5fb8629c8041897e88d9e827afc2f"
integrity sha512-hfy/OA8rtwI/vPRm4L6a3/u6uDvqsPmTok7pPmtfv2a7YfaTVfxd9HX2Kdn/SZ8rGMKkKVJ9A0WcBnzs0bjLXw==
mime@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"