UNPKG

astro

Version:

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

104 lines (103 loc) • 3.37 kB
import { createRequire } from "node:module"; /** * Browser name mapping from Vite target format to lightningcss target format. * Matches Vite's internal `map` object in `convertTargets`. */ const BROWSER_MAP = { chrome: "chrome", edge: "edge", firefox: "firefox", hermes: false, ie: "ie", ios: "ios_saf", node: false, opera: "opera", rhino: false, safari: "safari" }; const VERSION_RE = /\d/; /** * Converts Vite target strings (e.g. `["safari15", "chrome100"]`) to * lightningcss target format (e.g. `{ safari: 983040, chrome: 6553600 }`). * * This replicates Vite's internal `convertTargets` function, which is not exported. */ function convertTargets(target) { if (!target) return {}; const targets = {}; const entries = Array.isArray(target) ? target : [target]; for (const entry of entries) { if (entry === "esnext") continue; const index = entry.search(VERSION_RE); if (index >= 0) { const browserName = entry.slice(0, index); const browser = BROWSER_MAP[browserName]; if (browser === false) continue; if (browser) { const [major, minor = 0] = entry.slice(index).split(".").map((v) => Number.parseInt(v, 10)); if (!isNaN(major) && !isNaN(minor)) { const version = major << 16 | minor << 8; if (!targets[browser] || version < targets[browser]) { targets[browser] = version; } } } } } return targets; } /** * Vite plugin that applies CSS target lowering without minification. * * Vite's `finalizeCss` only applies CSS target lowering (via lightningcss) when * `config.build.cssMinify` is truthy, because target lowering and minification * are coupled in `minifyCSS`. When users set `minify: false`, Astro forces * `cssMinify: false`, which disables target lowering for all CSS. * * This plugin fills that gap: when `cssMinify` is falsy and a CSS target is * configured, it runs lightningcss with `minify: false` on all CSS assets in * `generateBundle`, applying target lowering without minification. */ export function pluginCssTargetLowering() { let resolvedConfig; return { name: "astro:css-target-lowering", enforce: "post", configResolved(config) { resolvedConfig = config; }, async generateBundle(_outputOptions, bundle) { // Only apply when cssMinify is disabled and a CSS target is configured if (resolvedConfig.build.cssMinify) return; const cssTarget = resolvedConfig.build.cssTarget; if (!cssTarget) return; const targets = convertTargets(cssTarget); if (Object.keys(targets).length === 0) return; // Resolve lightningcss from Vite's dependencies (it's not a direct Astro dep) let lcssTransform; try { const requireFromVite = createRequire(import.meta.resolve("vite")); lcssTransform = requireFromVite("lightningcss").transform; } catch { // If lightningcss is not available, skip silently return; } for (const [, asset] of Object.entries(bundle)) { if (asset.type !== "asset") continue; if (!asset.fileName.endsWith(".css")) continue; if (typeof asset.source !== "string") continue; try { const result = lcssTransform({ ...resolvedConfig.css?.lightningcss, targets, cssModules: undefined, filename: asset.fileName, code: Buffer.from(asset.source), minify: false }); asset.source = new TextDecoder().decode(result.code); } catch {} } } }; }