143 lines
4.6 KiB
JavaScript
143 lines
4.6 KiB
JavaScript
import path from "node:path";
|
|
import vue from "@vitejs/plugin-vue";
|
|
import { MagicString } from "@vue/compiler-sfc";
|
|
const VIRTUAL_MODULE_ID = "virtual:@astrojs/vue/app";
|
|
const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
function getRenderer() {
|
|
return {
|
|
name: "@astrojs/vue",
|
|
clientEntrypoint: "@astrojs/vue/client.js",
|
|
serverEntrypoint: "@astrojs/vue/server.js"
|
|
};
|
|
}
|
|
function getJsxRenderer() {
|
|
return {
|
|
name: "@astrojs/vue (jsx)",
|
|
clientEntrypoint: "@astrojs/vue/client.js",
|
|
serverEntrypoint: "@astrojs/vue/server.js"
|
|
};
|
|
}
|
|
function virtualAppEntrypoint(options) {
|
|
let isBuild;
|
|
let root;
|
|
let appEntrypoint;
|
|
return {
|
|
name: "@astrojs/vue/virtual-app",
|
|
config(_, { command }) {
|
|
isBuild = command === "build";
|
|
},
|
|
configResolved(config) {
|
|
root = config.root;
|
|
if (options?.appEntrypoint) {
|
|
appEntrypoint = options.appEntrypoint.startsWith(".") ? path.resolve(root, options.appEntrypoint) : options.appEntrypoint;
|
|
}
|
|
},
|
|
resolveId(id) {
|
|
if (id == VIRTUAL_MODULE_ID) {
|
|
return RESOLVED_VIRTUAL_MODULE_ID;
|
|
}
|
|
},
|
|
load(id) {
|
|
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
|
|
if (appEntrypoint) {
|
|
return `import * as mod from ${JSON.stringify(appEntrypoint)};
|
|
|
|
export const setup = async (app) => {
|
|
if ('default' in mod) {
|
|
await mod.default(app);
|
|
} else {
|
|
${!isBuild ? `console.warn("[@astrojs/vue] appEntrypoint \`" + ${JSON.stringify(
|
|
appEntrypoint
|
|
)} + "\` does not export a default function. Check out https://docs.astro.build/en/guides/integrations-guide/vue/#appentrypoint.");` : ""}
|
|
}
|
|
}`;
|
|
}
|
|
return `export const setup = () => {};`;
|
|
}
|
|
},
|
|
// Ensure that Vue components reference appEntrypoint directly
|
|
// This allows Astro to associate global styles imported in this file
|
|
// with the pages they should be injected to
|
|
transform(code, id) {
|
|
if (!appEntrypoint) return;
|
|
if (id.endsWith(".vue")) {
|
|
const s = new MagicString(code);
|
|
s.prepend(`import ${JSON.stringify(appEntrypoint)};
|
|
`);
|
|
return {
|
|
code: s.toString(),
|
|
map: s.generateMap({ hires: "boundary" })
|
|
};
|
|
}
|
|
}
|
|
};
|
|
}
|
|
async function getViteConfiguration(command, options) {
|
|
const vueOptions = {
|
|
...options,
|
|
template: {
|
|
...options?.template,
|
|
transformAssetUrls: false
|
|
}
|
|
};
|
|
vueOptions.compiler ??= await import("vue/compiler-sfc");
|
|
const config = {
|
|
optimizeDeps: {
|
|
// We add `vue` here as `@vitejs/plugin-vue` doesn't add it and we want to prevent
|
|
// re-optimization if the `vue` import is only encountered later.
|
|
include: ["@astrojs/vue/client.js", "vue"],
|
|
exclude: ["@astrojs/vue/server.js", VIRTUAL_MODULE_ID]
|
|
},
|
|
plugins: [vue(vueOptions), virtualAppEntrypoint(vueOptions)],
|
|
ssr: {
|
|
noExternal: ["vuetify", "vueperslides", "primevue"]
|
|
}
|
|
};
|
|
if (options?.jsx) {
|
|
const vueJsx = (await import("@vitejs/plugin-vue-jsx")).default;
|
|
const jsxOptions = typeof options.jsx === "object" ? options.jsx : void 0;
|
|
config.plugins?.push(vueJsx(jsxOptions));
|
|
}
|
|
if (command === "dev" && options?.devtools) {
|
|
const vueDevTools = (await import("vite-plugin-vue-devtools")).default;
|
|
const devToolsOptions = typeof options.devtools === "object" ? options.devtools : {};
|
|
config.plugins?.push(
|
|
vueDevTools({
|
|
...devToolsOptions,
|
|
appendTo: VIRTUAL_MODULE_ID
|
|
})
|
|
);
|
|
}
|
|
return config;
|
|
}
|
|
function index_default(options) {
|
|
return {
|
|
name: "@astrojs/vue",
|
|
hooks: {
|
|
"astro:config:setup": async ({ addRenderer, updateConfig, command }) => {
|
|
addRenderer(getRenderer());
|
|
if (options?.jsx) {
|
|
addRenderer(getJsxRenderer());
|
|
}
|
|
updateConfig({ vite: await getViteConfiguration(command, options) });
|
|
},
|
|
"astro:config:done": ({ logger, config }) => {
|
|
if (!options?.jsx) return;
|
|
const knownJsxRenderers = ["@astrojs/react", "@astrojs/preact", "@astrojs/solid-js"];
|
|
const enabledKnownJsxRenderers = config.integrations.filter(
|
|
(renderer) => knownJsxRenderers.includes(renderer.name)
|
|
);
|
|
if (enabledKnownJsxRenderers.length > 1 && !options?.include && !options?.exclude) {
|
|
logger.warn(
|
|
"More than one JSX renderer is enabled. This will lead to unexpected behavior unless you set the `include` or `exclude` option. See https://docs.astro.build/en/guides/integrations-guide/solid-js/#combining-multiple-jsx-frameworks for more information."
|
|
);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
export {
|
|
index_default as default,
|
|
getRenderer as getContainerRenderer
|
|
};
|