import nodeFs from "node:fs";
import { fileURLToPath } from "node:url";
import * as vite from "vite";
import { crawlFrameworkPkgs } from "vitefu";
import astroAssetsPlugin from "../assets/vite-plugin-assets.js";
import {
astroContentAssetPropagationPlugin,
astroContentImportPlugin,
astroContentVirtualModPlugin
} from "../content/index.js";
import astroPostprocessVitePlugin from "../vite-plugin-astro-postprocess/index.js";
import { vitePluginAstroServer } from "../vite-plugin-astro-server/index.js";
import astroVitePlugin from "../vite-plugin-astro/index.js";
import configAliasVitePlugin from "../vite-plugin-config-alias/index.js";
import envVitePlugin from "../vite-plugin-env/index.js";
import astroHeadPlugin from "../vite-plugin-head/index.js";
import htmlVitePlugin from "../vite-plugin-html/index.js";
import { astroInjectEnvTsPlugin } from "../vite-plugin-inject-env-ts/index.js";
import astroIntegrationsContainerPlugin from "../vite-plugin-integrations-container/index.js";
import jsxVitePlugin from "../vite-plugin-jsx/index.js";
import astroLoadFallbackPlugin from "../vite-plugin-load-fallback/index.js";
import markdownVitePlugin from "../vite-plugin-markdown/index.js";
import astroScannerPlugin from "../vite-plugin-scanner/index.js";
import astroScriptsPlugin from "../vite-plugin-scripts/index.js";
import astroScriptsPageSSRPlugin from "../vite-plugin-scripts/page-ssr.js";
import { vitePluginSSRManifest } from "../vite-plugin-ssr-manifest/index.js";
import { joinPaths } from "./path.js";
const ALWAYS_NOEXTERNAL = [
// This is only because Vite's native ESM doesn't resolve "exports" correctly.
"astro",
// Vite fails on nested `.astro` imports without bundling
"astro/components",
// Handle recommended nanostores. Only @nanostores/preact is required from our testing!
// Full explanation and related bug report: https://github.com/withastro/astro/pull/3667
"@nanostores/preact",
// fontsource packages are CSS that need to be processed
"@fontsource/*"
];
const ONLY_DEV_EXTERNAL = [
// Imported by `
` which is processed by Vite
"shiki",
// Imported by `@astrojs/prism` which exposes `` that is processed by Vite
"prismjs/components/index.js",
// Imported by `astro/assets` -> `packages/astro/src/core/logger/core.ts`
"string-width"
];
async function createVite(commandConfig, { settings, logging, mode, command, fs = nodeFs }) {
var _a, _b;
const astroPkgsConfig = await crawlFrameworkPkgs({
root: fileURLToPath(settings.config.root),
isBuild: mode === "build",
viteUserConfig: settings.config.vite,
isFrameworkPkgByJson(pkgJson) {
var _a2, _b2, _c, _d, _e;
if (((_a2 = pkgJson == null ? void 0 : pkgJson.astro) == null ? void 0 : _a2.external) === true) {
return false;
}
return (
// Attempt: package relies on `astro`. ✅ Definitely an Astro package
((_b2 = pkgJson.peerDependencies) == null ? void 0 : _b2.astro) || ((_c = pkgJson.dependencies) == null ? void 0 : _c.astro) || // Attempt: package is tagged with `astro` or `astro-component`. ✅ Likely a community package
((_d = pkgJson.keywords) == null ? void 0 : _d.includes("astro")) || ((_e = pkgJson.keywords) == null ? void 0 : _e.includes("astro-component")) || // Attempt: package is named `astro-something` or `@scope/astro-something`. ✅ Likely a community package
/^(@[^\/]+\/)?astro\-/.test(pkgJson.name)
);
},
isFrameworkPkgByName(pkgName) {
const isNotAstroPkg = isCommonNotAstro(pkgName);
if (isNotAstroPkg) {
return false;
} else {
return void 0;
}
}
});
const commonConfig = {
cacheDir: fileURLToPath(new URL("./node_modules/.vite/", settings.config.root)),
// using local caches allows Astro to be used in monorepos, etc.
clearScreen: false,
// we want to control the output, not Vite
logLevel: "warn",
// log warnings and errors only
appType: "custom",
optimizeDeps: {
entries: ["src/**/*"],
exclude: ["astro", "node-fetch"]
},
plugins: [
configAliasVitePlugin({ settings }),
astroLoadFallbackPlugin({ fs, root: settings.config.root }),
astroVitePlugin({ settings, logging }),
astroScriptsPlugin({ settings }),
// The server plugin is for dev only and having it run during the build causes
// the build to run very slow as the filewatcher is triggered often.
mode !== "build" && vitePluginAstroServer({ settings, logging, fs }),
envVitePlugin({ settings }),
markdownVitePlugin({ settings, logging }),
htmlVitePlugin(),
jsxVitePlugin({ settings, logging }),
astroPostprocessVitePlugin(),
mode === "dev" && astroIntegrationsContainerPlugin({ settings, logging }),
astroScriptsPageSSRPlugin({ settings }),
astroHeadPlugin(),
astroScannerPlugin({ settings }),
astroInjectEnvTsPlugin({ settings, logging, fs }),
astroContentVirtualModPlugin({ settings }),
astroContentImportPlugin({ fs, settings }),
astroContentAssetPropagationPlugin({ mode, settings }),
vitePluginSSRManifest(),
settings.config.experimental.assets ? [astroAssetsPlugin({ settings, logging, mode })] : []
],
publicDir: fileURLToPath(settings.config.publicDir),
root: fileURLToPath(settings.config.root),
envPrefix: ((_a = settings.config.vite) == null ? void 0 : _a.envPrefix) ?? "PUBLIC_",
define: {
"import.meta.env.SITE": settings.config.site ? JSON.stringify(settings.config.site) : "undefined"
},
server: {
hmr: process.env.NODE_ENV === "test" || process.env.NODE_ENV === "production" ? false : void 0,
// disable HMR for test
// handle Vite URLs
proxy: {
// add proxies here
},
watch: {
// Prevent watching during the build to speed it up
ignored: mode === "build" ? ["**"] : void 0
}
},
resolve: {
alias: [
{
// This is needed for Deno compatibility, as the non-browser version
// of this module depends on Node `crypto`
find: "randombytes",
replacement: "randombytes/browser"
},
{
// Typings are imported from 'astro' (e.g. import { Type } from 'astro')
find: /^astro$/,
replacement: fileURLToPath(new URL("../@types/astro", import.meta.url))
}
],
conditions: ["astro"],
// Astro imports in third-party packages should use the same version as root
dedupe: ["astro"]
},
ssr: {
noExternal: [...ALWAYS_NOEXTERNAL, ...astroPkgsConfig.ssr.noExternal],
external: [...mode === "dev" ? ONLY_DEV_EXTERNAL : [], ...astroPkgsConfig.ssr.external]
}
};
const assetsPrefix = settings.config.build.assetsPrefix;
if (assetsPrefix) {
commonConfig.experimental = {
renderBuiltUrl(filename, { type }) {
if (type === "asset") {
return joinPaths(assetsPrefix, filename);
}
}
};
}
let result = commonConfig;
if (command && ((_b = settings.config.vite) == null ? void 0 : _b.plugins)) {
let { plugins, ...rest } = settings.config.vite;
const applyToFilter = command === "build" ? "serve" : "build";
const applyArgs = [
{ ...settings.config.vite, mode },
{ command: command === "dev" ? "serve" : command, mode }
];
plugins = plugins.flat(Infinity).filter((p) => {
if (!p || (p == null ? void 0 : p.apply) === applyToFilter) {
return false;
}
if (typeof p.apply === "function") {
return p.apply(applyArgs[0], applyArgs[1]);
}
return true;
});
result = vite.mergeConfig(result, { ...rest, plugins });
} else {
result = vite.mergeConfig(result, settings.config.vite || {});
}
result = vite.mergeConfig(result, commandConfig);
if (result.plugins) {
sortPlugins(result.plugins);
}
result.customLogger = vite.createLogger(result.logLevel ?? "warn");
return result;
}
function isVitePlugin(plugin) {
return Boolean(plugin == null ? void 0 : plugin.hasOwnProperty("name"));
}
function findPluginIndexByName(pluginOptions, name) {
return pluginOptions.findIndex(function(pluginOption) {
return isVitePlugin(pluginOption) && pluginOption.name === name;
});
}
function sortPlugins(pluginOptions) {
const mdxPluginIndex = findPluginIndexByName(pluginOptions, "@mdx-js/rollup");
if (mdxPluginIndex === -1)
return;
const jsxPluginIndex = findPluginIndexByName(pluginOptions, "astro:jsx");
const mdxPlugin = pluginOptions[mdxPluginIndex];
pluginOptions.splice(mdxPluginIndex, 1);
pluginOptions.splice(jsxPluginIndex, 0, mdxPlugin);
}
const COMMON_DEPENDENCIES_NOT_ASTRO = [
"autoprefixer",
"react",
"react-dom",
"preact",
"preact-render-to-string",
"vue",
"svelte",
"solid-js",
"lit",
"cookie",
"dotenv",
"esbuild",
"eslint",
"jest",
"postcss",
"prettier",
"astro",
"tslib",
"typescript",
"vite"
];
const COMMON_PREFIXES_NOT_ASTRO = [
"@webcomponents/",
"@fontsource/",
"@postcss-plugins/",
"@rollup/",
"@astrojs/renderer-",
"@types/",
"@typescript-eslint/",
"eslint-",
"jest-",
"postcss-plugin-",
"prettier-plugin-",
"remark-",
"rehype-",
"rollup-plugin-",
"vite-plugin-"
];
function isCommonNotAstro(dep) {
return COMMON_DEPENDENCIES_NOT_ASTRO.includes(dep) || COMMON_PREFIXES_NOT_ASTRO.some(
(prefix) => prefix.startsWith("@") ? dep.startsWith(prefix) : dep.substring(dep.lastIndexOf("/") + 1).startsWith(prefix)
// check prefix omitting @scope/
);
}
export {
createVite
};