UNPKG

astro

Version:

Astro is a modern site builder with web best practices, performance, and DX front-of-mind.

52 lines (51 loc) • 2.12 kB
import { readFile } from "node:fs/promises"; import { transform } from "@astrojs/compiler-rs"; /** * Replaces Vite's regex-based `.astro` dependency scan with the scripts the Astro compiler hoists, * which are the same scripts `vite-plugin-astro` serves as `?astro&type=script` modules. Markup-like * text in frontmatter or template expressions is never mistaken for a script, and scripts Astro * renders inline (`is:inline`, or any attribute other than `src`) are not scanned. * * @see https://github.com/withastro/astro/issues/18068 */ export function rolldownAstroClientScanPlugin() { const scripts = new Map(); return { name: "astro:client-dep-scan", resolveId(source, importer) { if (scripts.has(source)) return source; const parentScript = importer && scripts.get(importer); if (parentScript) { return this.resolve(source, parentScript.importer, { skipSelf: true }); } }, async load(id) { const script = scripts.get(id); if (script) { // The scan's TypeScript transform drops unused imports, but Astro's tsconfig enables // `verbatimModuleSyntax`, so they are still requested at runtime. const imports = this.parse(script.code, { lang: "ts" }).body.flatMap((node) => node.type === "ImportDeclaration" && node.importKind !== "type" ? [`\nimport ${JSON.stringify(node.source.value)};`] : []); return { code: script.code + imports.join(""), moduleType: "ts" }; } if (!id.endsWith(".astro")) return; const { scripts: hoisted } = transform(await readFile(id, "utf-8"), { filename: id }); const code = hoisted.map((hoistedScript, index) => { if (hoistedScript.type === "external") return `import ${JSON.stringify(hoistedScript.src)};`; // The `.ts` extension lets Vite's scan transform for `import.meta.glob` run on the script. const scriptId = `${id}?astro-client-dep-scan=${index}&lang.ts`; scripts.set(scriptId, { code: hoistedScript.code, importer: id }); return `import ${JSON.stringify(scriptId)};`; }); return { code: [...code, "export default {};"].join("\n"), moduleType: "js" }; } }; }