|
1 | 1 | import type { GetModuleInfo } from 'rollup';
|
2 |
| -import type { BuildOptions, ResolvedConfig, Plugin as VitePlugin } from 'vite'; |
| 2 | +import type { BuildOptions, ResolvedConfig, Rollup, Plugin as VitePlugin } from 'vite'; |
3 | 3 | import { isBuildableCSSRequest } from '../../../vite-plugin-astro-server/util.js';
|
4 | 4 | import type { BuildInternals } from '../internal.js';
|
5 | 5 | import type { AstroBuildPlugin, BuildTarget } from '../plugin.js';
|
6 | 6 | import type { PageBuildData, StaticBuildOptions, StylesheetAsset } from '../types.js';
|
7 | 7 |
|
8 | 8 | import { hasAssetPropagationFlag } from '../../../content/index.js';
|
| 9 | +import type { AstroPluginCssMetadata } from '../../../vite-plugin-astro/index.js'; |
9 | 10 | import * as assetName from '../css-asset-name.js';
|
10 | 11 | import {
|
11 | 12 | getParentExtendedModuleInfos,
|
@@ -155,6 +156,32 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
|
155 | 156 | },
|
156 | 157 | };
|
157 | 158 |
|
| 159 | + /** |
| 160 | + * This plugin is a port of https://github.com/vitejs/vite/pull/16058. It enables removing unused |
| 161 | + * scoped CSS from the bundle if the scoped target (e.g. Astro files) were not bundled. |
| 162 | + * Once/If that PR is merged, we can refactor this away, renaming `meta.astroCss` to `meta.vite`. |
| 163 | + */ |
| 164 | + const cssScopeToPlugin: VitePlugin = { |
| 165 | + name: 'astro:rollup-plugin-css-scope-to', |
| 166 | + renderChunk(_, chunk, __, meta) { |
| 167 | + for (const id in chunk.modules) { |
| 168 | + // If this CSS is scoped to its importers exports, check if those importers exports |
| 169 | + // are rendered in the chunks. If they are not, we can skip bundling this CSS. |
| 170 | + const modMeta = this.getModuleInfo(id)?.meta as AstroPluginCssMetadata | undefined; |
| 171 | + const cssScopeTo = modMeta?.astroCss?.cssScopeTo; |
| 172 | + if (cssScopeTo && !isCssScopeToRendered(cssScopeTo, Object.values(meta.chunks))) { |
| 173 | + // If this CSS is not used, delete it from the chunk modules so that Vite is unable |
| 174 | + // to trace that it's used |
| 175 | + delete chunk.modules[id]; |
| 176 | + const moduleIdsIndex = chunk.moduleIds.indexOf(id); |
| 177 | + if (moduleIdsIndex > -1) { |
| 178 | + chunk.moduleIds.splice(moduleIdsIndex, 1); |
| 179 | + } |
| 180 | + } |
| 181 | + } |
| 182 | + }, |
| 183 | + }; |
| 184 | + |
158 | 185 | const singleCssPlugin: VitePlugin = {
|
159 | 186 | name: 'astro:rollup-plugin-single-css',
|
160 | 187 | enforce: 'post',
|
@@ -246,7 +273,7 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
|
246 | 273 | },
|
247 | 274 | };
|
248 | 275 |
|
249 |
| - return [cssBuildPlugin, singleCssPlugin, inlineStylesheetsPlugin]; |
| 276 | + return [cssBuildPlugin, cssScopeToPlugin, singleCssPlugin, inlineStylesheetsPlugin]; |
250 | 277 | }
|
251 | 278 |
|
252 | 279 | /***** UTILITY FUNCTIONS *****/
|
@@ -294,3 +321,25 @@ function appendCSSToPage(
|
294 | 321 | }
|
295 | 322 | }
|
296 | 323 | }
|
| 324 | + |
| 325 | +/** |
| 326 | + * `cssScopeTo` is a map of `importer`s to its `export`s. This function iterate each `cssScopeTo` entries |
| 327 | + * and check if the `importer` and its `export`s exists in the final chunks. If at least one matches, |
| 328 | + * `cssScopeTo` is considered "rendered" by Rollup and we return true. |
| 329 | + */ |
| 330 | +function isCssScopeToRendered( |
| 331 | + cssScopeTo: Record<string, string[]>, |
| 332 | + chunks: Rollup.RenderedChunk[], |
| 333 | +) { |
| 334 | + for (const moduleId in cssScopeTo) { |
| 335 | + const exports = cssScopeTo[moduleId]; |
| 336 | + // Find the chunk that renders this `moduleId` and get the rendered module |
| 337 | + const renderedModule = chunks.find((c) => c.moduleIds.includes(moduleId))?.modules[moduleId]; |
| 338 | + // Return true if `renderedModule` exists and one of its exports is rendered |
| 339 | + if (renderedModule?.renderedExports.some((e) => exports.includes(e))) { |
| 340 | + return true; |
| 341 | + } |
| 342 | + } |
| 343 | + |
| 344 | + return false; |
| 345 | +} |
0 commit comments