domco
Version:
Minimal Full-Stack JavaScript
91 lines (90 loc) • 3.71 kB
JavaScript
import { dirNames, fileNames } from "../../constants/index.js";
import { getChunk } from "../../util/manifest/index.js";
import fs from "node:fs/promises";
import path from "node:path";
/**
* Creates the `client:page` virtual module.
*
* @returns Vite plugin
*/
export const pagePlugin = () => {
const pageId = "client:page";
const resolvedPageId = `\0${pageId}`;
let devServer;
/** Watched page filePaths. */
const watched = new Set();
return {
name: `domco:${pageId}`,
configureServer(server) {
devServer = server;
},
resolveId(id) {
if (id.startsWith(pageId)) {
// don't return the resolved id here, needs to be the full path.
return `\0${id}`;
}
},
async load(id, _options) {
if (id.startsWith(resolvedPageId)) {
let pathName = id.slice(resolvedPageId.length);
// remove trailing slash
if (pathName.endsWith("/"))
pathName = pathName.slice(0, -1);
if (!pathName)
pathName = "/";
let chunk;
let html;
if (devServer) {
// read from src and transform
const src = path.join(dirNames.src.client, pathName, fileNames.page);
chunk = {
tags: "",
src: {
// src relative to src/
src, // this is the html file in prod
file: "", // this is a js file in prod, so empty here instead of the html
assets: [],
module: [],
preload: [],
style: [],
dynamic: [],
},
};
// add base
const filePath = path.join(dirNames.src.base, src);
if (!watched.has(filePath)) {
// add listeners if they are not already there
watched.add(filePath);
devServer.watcher.on("all", (_event, fp) => {
if (fp.endsWith(filePath)) {
const mod = devServer.moduleGraph.getModuleById(id);
if (mod)
devServer.reloadModule(mod);
}
});
}
try {
html = await fs.readFile(filePath, "utf-8");
html = await devServer.transformIndexHtml(pathName, html);
}
catch (error) {
html = "";
if (error instanceof Error) {
this.warn(error.message);
}
else {
this.warn(`Could not read and transform \`${filePath}\``);
}
}
}
else {
chunk = await getChunk({ pathName, error: this.error, page: true });
// read from client output
html = await fs.readFile(path.join(dirNames.out.base, dirNames.out.client.base, dirNames.src.client, pathName, fileNames.page), "utf-8");
}
return (`export const html = ${JSON.stringify(html)};\n` +
`export const chunk = ${JSON.stringify(chunk)}\n`);
}
},
};
};