Skip to content

Commit

Permalink
fix: issues with hmr (#42)
Browse files Browse the repository at this point in the history
* fix: issues with hmr

* fix: issue with new tags not discovered during hmr
  • Loading branch information
DylanPiercey authored Jan 11, 2023
1 parent d4cdd67 commit f3962a9
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changeset/dull-seals-behave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@marko/vite": patch
---

Fix issue with hot module reloading virtual dependencies.
5 changes: 5 additions & 0 deletions .changeset/shaggy-llamas-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@marko/vite": patch
---

Fix issue with new tags not discovered during HMR.
68 changes: 50 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,24 @@ interface ServerManifest {
chunksNeedingAssets: string[];
}

interface VirtualFile {
code: string;
map?: any;
}

type DeferredPromise<T> = Promise<T> & {
resolve: (value: T) => void;
reject: (error: Error) => void;
};

const normalizePath =
path.sep === "\\"
? (id: string) => id.replace(/\\/g, "/")
: (id: string) => id;
const virtualFiles = new Map<string, { code: string; map?: any }>();
const virtualFiles = new Map<
string,
VirtualFile | DeferredPromise<VirtualFile>
>();
const queryReg = /\?marko-.+$/;
const browserEntryQuery = "?marko-browser-entry";
const serverEntryQuery = "?marko-server-entry";
Expand All @@ -62,14 +75,13 @@ const manifestFileName = "manifest.json";
const markoExt = ".marko";
const htmlExt = ".html";
const resolveOpts = { skipSelf: true };
const cache = new Map<string, Compiler.CompileResult>();
const cache = new Map<unknown, unknown>();
const thisFile =
typeof __filename === "string" ? __filename : fileURLToPath(import.meta.url);

export default function markoPlugin(opts: Options = {}): vite.Plugin[] {
let compiler: typeof Compiler;
const { runtimeId, linked = true } = opts;

const baseConfig: Compiler.Config = {
cache,
runtimeId,
Expand Down Expand Up @@ -97,10 +109,8 @@ export default function markoPlugin(opts: Options = {}): vite.Plugin[] {

if (devServer) {
const prev = virtualFiles.get(id);
if (prev && prev.code !== dep.code) {
devServer.moduleGraph.invalidateModule(
devServer.moduleGraph.getModuleById(id)!
);
if (isDeferredPromise(prev)) {
prev.resolve(dep);
}
}

Expand Down Expand Up @@ -224,6 +234,8 @@ export default function markoPlugin(opts: Options = {}): vite.Plugin[] {
devServer.watcher.on("all", (type, filename) => {
if (type === "unlink") {
entrySources.delete(filename);
transformWatchFiles.delete(filename);
transformOptionalFiles.delete(filename);
}

for (const [id, files] of transformWatchFiles) {
Expand All @@ -233,24 +245,28 @@ export default function markoPlugin(opts: Options = {}): vite.Plugin[] {
}

if (type === "add" || type === "unlink") {
let clearedCache = false;
for (const [id, files] of transformOptionalFiles) {
if (anyMatch(files, filename)) {
if (!clearedCache) {
baseConfig.cache!.clear();
clearedCache = true;
}
devServer.watcher.emit("change", id);
}
}
}
});
},

handleHotUpdate(ctx) {
compiler.taglib.clearCaches();
baseConfig.cache!.clear();

for (const mod of ctx.modules) {
if (mod.id && virtualFiles.has(mod.id)) {
virtualFiles.set(mod.id, createDeferredPromise());
}
}
},

async buildStart(inputOptions) {
if (isBuild && linked && !isSSRBuild) {
// Is this needed?
//this.addWatchFile(serverMetaFile);

try {
serverManifest = JSON.parse(
(await store.get(manifestFileName))!
Expand Down Expand Up @@ -433,7 +449,7 @@ export default function markoPlugin(opts: Options = {}): vite.Plugin[] {
let { code } = compiled;

if (query !== browserEntryQuery && devServer) {
code += `\nif (import.meta.hot) import.meta.hot.accept();`;
code += `\nif (import.meta.hot) import.meta.hot.accept(() => {});`;
}

if (devServer) {
Expand All @@ -443,7 +459,7 @@ export default function markoPlugin(opts: Options = {}): vite.Plugin[] {
path.sep +
(templateName === "index" ? "" : `${templateName}.`);

for (const file of meta.watchFiles!) {
for (const file of meta.watchFiles) {
this.addWatchFile(file);
}

Expand All @@ -454,7 +470,7 @@ export default function markoPlugin(opts: Options = {}): vite.Plugin[] {
`${optionalFilePrefix}marko-tag.json`,
]);

transformWatchFiles.set(id, meta.watchFiles!);
transformWatchFiles.set(id, meta.watchFiles);
}
return { code, map, meta: isBuild ? { source } : undefined };
},
Expand Down Expand Up @@ -604,6 +620,22 @@ function getBasenameWithoutExt(file: string): string {
return file.slice(baseStart, extStart);
}

function createDeferredPromise<T>() {
let resolve!: (value: T) => void;
let reject!: (error: Error) => void;
const promise = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
}) as DeferredPromise<T>;
promise.resolve = resolve;
promise.reject = reject;
return promise;
}

function isDeferredPromise<T>(obj: unknown): obj is DeferredPromise<T> {
return typeof (obj as Promise<T>)?.then === "function";
}

function isEmpty(obj: unknown) {
for (const _ in obj as Record<string, unknown>) {
return false;
Expand Down

0 comments on commit f3962a9

Please sign in to comment.