mirror of
https://github.com/withastro/astro.git
synced 2025-01-06 22:10:10 -05:00
Prevent ?inline and ?raw CSS from being bundled as CSS (#6161)
* Prevent ?inline and ?raw CSS from being bundled as CSS * Add a changeset * oopts * Replace use of isCSSRequest
This commit is contained in:
parent
460f9e7329
commit
f6fc662c3c
13 changed files with 123 additions and 26 deletions
5
.changeset/big-rocks-do.md
Normal file
5
.changeset/big-rocks-do.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Prevent ?inline and ?raw CSS from being bundled as CSS
|
|
@ -2,7 +2,7 @@ import * as crypto from 'node:crypto';
|
|||
import * as npath from 'node:path';
|
||||
import type { GetModuleInfo } from 'rollup';
|
||||
import { Plugin as VitePlugin, ResolvedConfig, transformWithEsbuild } from 'vite';
|
||||
import { isCSSRequest } from '../../render/util.js';
|
||||
import { isBuildableCSSRequest } from '../../render/dev/util.js';
|
||||
import type { BuildInternals } from '../internal';
|
||||
import type { AstroBuildPlugin } from '../plugin';
|
||||
import type { PageBuildData, StaticBuildOptions } from '../types';
|
||||
|
@ -66,7 +66,7 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[]
|
|||
after(id, meta) {
|
||||
// For CSS, create a hash of all of the pages that use it.
|
||||
// This causes CSS to be built into shared chunks when used by multiple pages.
|
||||
if (isCSSRequest(id)) {
|
||||
if (isBuildableCSSRequest(id)) {
|
||||
for (const [pageInfo] of walkParentInfos(id, {
|
||||
getModuleInfo: meta.getModuleInfo,
|
||||
})) {
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { ModuleLoader } from '../../module-loader/index';
|
|||
import path from 'path';
|
||||
import { RuntimeMode } from '../../../@types/astro.js';
|
||||
import { viteID } from '../../util.js';
|
||||
import { STYLE_EXTENSIONS } from '../util.js';
|
||||
import { isCSSRequest } from './util.js';
|
||||
import { crawlGraph } from './vite.js';
|
||||
|
||||
/** Given a filePath URL, crawl Vite’s module graph to find all style imports. */
|
||||
|
@ -16,8 +16,7 @@ export async function getStylesForURL(
|
|||
const importedStylesMap = new Map<string, string>();
|
||||
|
||||
for await (const importedModule of crawlGraph(loader, viteID(filePath), true)) {
|
||||
const ext = path.extname(importedModule.url).toLowerCase();
|
||||
if (STYLE_EXTENSIONS.has(ext)) {
|
||||
if (isCSSRequest(importedModule.url)) {
|
||||
let ssrModule: Record<string, any>;
|
||||
try {
|
||||
// The SSR module is possibly not loaded. Load it if it's null.
|
||||
|
|
9
packages/astro/src/core/render/dev/util.ts
Normal file
9
packages/astro/src/core/render/dev/util.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { isCSSRequest } from 'vite';
|
||||
|
||||
const rawRE = /(?:\?|&)raw(?:&|$)/;
|
||||
const inlineRE = /(?:\?|&)inline\b/;
|
||||
|
||||
export { isCSSRequest };
|
||||
|
||||
export const isBuildableCSSRequest = (request: string): boolean => isCSSRequest(request) &&
|
||||
!rawRE.test(request) && !inlineRE.test(request);
|
|
@ -4,7 +4,7 @@ import npath from 'path';
|
|||
import { PROPAGATED_ASSET_FLAG } from '../../../content/consts.js';
|
||||
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from '../../constants.js';
|
||||
import { unwrapId } from '../../util.js';
|
||||
import { STYLE_EXTENSIONS } from '../util.js';
|
||||
import { isCSSRequest } from './util.js';
|
||||
|
||||
/**
|
||||
* List of file extensions signalling we can (and should) SSR ahead-of-time
|
||||
|
@ -43,7 +43,7 @@ export async function* crawlGraph(
|
|||
}
|
||||
if (id === entry.id) {
|
||||
scanned.add(id);
|
||||
const entryIsStyle = STYLE_EXTENSIONS.has(npath.extname(id));
|
||||
const entryIsStyle = isCSSRequest(id);
|
||||
for (const importedModule of entry.importedModules) {
|
||||
// some dynamically imported modules are *not* server rendered in time
|
||||
// to only SSR modules that we can safely transform, we check against
|
||||
|
@ -57,7 +57,7 @@ export async function* crawlGraph(
|
|||
// Tools like Tailwind might add HMR dependencies as `importedModules`
|
||||
// but we should skip them--they aren't really imported. Without this,
|
||||
// every hoisted script in the project is added to every page!
|
||||
if (entryIsStyle && !STYLE_EXTENSIONS.has(npath.extname(importedModulePathname))) {
|
||||
if (entryIsStyle && !isCSSRequest(importedModulePathname)) {
|
||||
continue;
|
||||
}
|
||||
if (fileExtensionsToSSR.has(npath.extname(importedModulePathname))) {
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
// https://vitejs.dev/guide/features.html#css-pre-processors
|
||||
export const STYLE_EXTENSIONS = new Set([
|
||||
'.css',
|
||||
'.pcss',
|
||||
'.postcss',
|
||||
'.scss',
|
||||
'.sass',
|
||||
'.styl',
|
||||
'.stylus',
|
||||
'.less',
|
||||
]);
|
||||
|
||||
const cssRe = new RegExp(
|
||||
`\\.(${Array.from(STYLE_EXTENSIONS)
|
||||
.map((s) => s.slice(1))
|
||||
.join('|')})($|\\?)`
|
||||
);
|
||||
export const isCSSRequest = (request: string): boolean => cssRe.test(request);
|
28
packages/astro/test/css-inline.test.js
Normal file
28
packages/astro/test/css-inline.test.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { expect } from 'chai';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { loadFixture } from './test-utils.js';
|
||||
|
||||
describe('Importing raw/inlined CSS', () => {
|
||||
let fixture;
|
||||
|
||||
before(async () => {
|
||||
fixture = await loadFixture({
|
||||
root: './fixtures/css-inline/',
|
||||
});
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
it('?inline is imported as a string', async () => {
|
||||
const html = await fixture.readFile('/index.html');
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
expect($('#inline').text()).to.contain('tomato');
|
||||
});
|
||||
|
||||
it('?raw is imported as a string', async () => {
|
||||
const html = await fixture.readFile('/index.html');
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
expect($('#raw').text()).to.contain('plum');
|
||||
});
|
||||
});
|
8
packages/astro/test/fixtures/css-inline/package.json
vendored
Normal file
8
packages/astro/test/fixtures/css-inline/package.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "@test/css-inline",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"astro": "workspace:*"
|
||||
}
|
||||
}
|
3
packages/astro/test/fixtures/css-inline/src/inline.css
vendored
Normal file
3
packages/astro/test/fixtures/css-inline/src/inline.css
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: tomato;
|
||||
}
|
35
packages/astro/test/fixtures/css-inline/src/layouts/Layout.astro
vendored
Normal file
35
packages/astro/test/fixtures/css-inline/src/layouts/Layout.astro
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
export interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props;
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
<style is:global>
|
||||
:root {
|
||||
--accent: 124, 58, 237;
|
||||
--accent-gradient: linear-gradient(45deg, rgb(var(--accent)), #da62c4 30%, white 60%);
|
||||
}
|
||||
html {
|
||||
font-family: system-ui, sans-serif;
|
||||
background-color: #F6F6F6;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
||||
</style>
|
19
packages/astro/test/fixtures/css-inline/src/pages/index.astro
vendored
Normal file
19
packages/astro/test/fixtures/css-inline/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import inline from '../inline.css?inline';
|
||||
import raw from '../raw.css?raw';
|
||||
---
|
||||
<Layout title="Welcome to Astro.">
|
||||
<main>
|
||||
<h1>Welcome to Astro</h1>
|
||||
<p>
|
||||
This are some `?inline` styles to show as object:
|
||||
</p>
|
||||
<p id="inline">
|
||||
{inline}
|
||||
</p>
|
||||
<p id="raw">
|
||||
{raw}
|
||||
</p>
|
||||
</main>
|
||||
</Layout>
|
3
packages/astro/test/fixtures/css-inline/src/raw.css
vendored
Normal file
3
packages/astro/test/fixtures/css-inline/src/raw.css
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
main {
|
||||
background: plum;
|
||||
}
|
|
@ -1690,6 +1690,12 @@ importers:
|
|||
packages/astro/test/fixtures/css-assets/packages/font-awesome:
|
||||
specifiers: {}
|
||||
|
||||
packages/astro/test/fixtures/css-inline:
|
||||
specifiers:
|
||||
astro: workspace:*
|
||||
dependencies:
|
||||
astro: link:../../..
|
||||
|
||||
packages/astro/test/fixtures/css-no-code-split:
|
||||
specifiers:
|
||||
astro: workspace:*
|
||||
|
|
Loading…
Reference in a new issue