From f8198a48212ea08a8cf7cc89cb5ccd4781eba3ad Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 7 Feb 2023 09:13:43 -0500 Subject: [PATCH 1/4] Prevent ?inline and ?raw CSS from being bundled as CSS --- packages/astro/src/core/render/util.ts | 7 +++- packages/astro/test/css-inline.test.js | 28 +++++++++++++++ .../test/fixtures/css-inline/package.json | 8 +++++ .../test/fixtures/css-inline/src/inline.css | 3 ++ .../css-inline/src/layouts/Layout.astro | 35 +++++++++++++++++++ .../fixtures/css-inline/src/pages/index.astro | 19 ++++++++++ .../test/fixtures/css-inline/src/raw.css | 3 ++ pnpm-lock.yaml | 6 ++++ 8 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 packages/astro/test/css-inline.test.js create mode 100644 packages/astro/test/fixtures/css-inline/package.json create mode 100644 packages/astro/test/fixtures/css-inline/src/inline.css create mode 100644 packages/astro/test/fixtures/css-inline/src/layouts/Layout.astro create mode 100644 packages/astro/test/fixtures/css-inline/src/pages/index.astro create mode 100644 packages/astro/test/fixtures/css-inline/src/raw.css diff --git a/packages/astro/src/core/render/util.ts b/packages/astro/src/core/render/util.ts index 2dddc49b0b97..bc969191a27c 100644 --- a/packages/astro/src/core/render/util.ts +++ b/packages/astro/src/core/render/util.ts @@ -15,4 +15,9 @@ const cssRe = new RegExp( .map((s) => s.slice(1)) .join('|')})($|\\?)` ); -export const isCSSRequest = (request: string): boolean => cssRe.test(request); + +const rawRE = /(?:\?|&)raw(?:&|$)/; +const inlineRE = /(?:\?|&)inline\b/; + +export const isCSSRequest = (request: string): boolean => cssRe.test(request) && + !rawRE.test(request) && inlineRE.test(request); diff --git a/packages/astro/test/css-inline.test.js b/packages/astro/test/css-inline.test.js new file mode 100644 index 000000000000..01d3133b8be2 --- /dev/null +++ b/packages/astro/test/css-inline.test.js @@ -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'); + }); +}); diff --git a/packages/astro/test/fixtures/css-inline/package.json b/packages/astro/test/fixtures/css-inline/package.json new file mode 100644 index 000000000000..5fce139475cd --- /dev/null +++ b/packages/astro/test/fixtures/css-inline/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/css-inline", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/css-inline/src/inline.css b/packages/astro/test/fixtures/css-inline/src/inline.css new file mode 100644 index 000000000000..ea8200bd9861 --- /dev/null +++ b/packages/astro/test/fixtures/css-inline/src/inline.css @@ -0,0 +1,3 @@ +body { + background: tomato; +} diff --git a/packages/astro/test/fixtures/css-inline/src/layouts/Layout.astro b/packages/astro/test/fixtures/css-inline/src/layouts/Layout.astro new file mode 100644 index 000000000000..f1a62a537b7d --- /dev/null +++ b/packages/astro/test/fixtures/css-inline/src/layouts/Layout.astro @@ -0,0 +1,35 @@ +--- +export interface Props { + title: string; +} + +const { title } = Astro.props; +--- + + + + + + + + + {title} + + + + + + diff --git a/packages/astro/test/fixtures/css-inline/src/pages/index.astro b/packages/astro/test/fixtures/css-inline/src/pages/index.astro new file mode 100644 index 000000000000..89a7288ae12a --- /dev/null +++ b/packages/astro/test/fixtures/css-inline/src/pages/index.astro @@ -0,0 +1,19 @@ +--- +import Layout from '../layouts/Layout.astro'; +import inline from '../inline.css?inline'; +import raw from '../raw.css?raw'; +--- + +
+

Welcome to Astro

+

+ This are some `?inline` styles to show as object: +

+

+ {inline} +

+

+ {raw} +

+
+
diff --git a/packages/astro/test/fixtures/css-inline/src/raw.css b/packages/astro/test/fixtures/css-inline/src/raw.css new file mode 100644 index 000000000000..916081876507 --- /dev/null +++ b/packages/astro/test/fixtures/css-inline/src/raw.css @@ -0,0 +1,3 @@ +main { + background: plum; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb87e5f4242a..7577d37e1d5c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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:* From 58cb41abc422564fbed04b1317e304ef16b9ee58 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 7 Feb 2023 09:14:53 -0500 Subject: [PATCH 2/4] Add a changeset --- .changeset/big-rocks-do.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/big-rocks-do.md diff --git a/.changeset/big-rocks-do.md b/.changeset/big-rocks-do.md new file mode 100644 index 000000000000..52b8a1e5dbc4 --- /dev/null +++ b/.changeset/big-rocks-do.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Prevent ?inline and ?raw CSS from being bundled as CSS From 83f18f8f324ee605f6d7d6318623d8501041cacc Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 7 Feb 2023 09:54:36 -0500 Subject: [PATCH 3/4] oopts --- packages/astro/src/core/render/util.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/astro/src/core/render/util.ts b/packages/astro/src/core/render/util.ts index bc969191a27c..928d742801f5 100644 --- a/packages/astro/src/core/render/util.ts +++ b/packages/astro/src/core/render/util.ts @@ -20,4 +20,4 @@ const rawRE = /(?:\?|&)raw(?:&|$)/; const inlineRE = /(?:\?|&)inline\b/; export const isCSSRequest = (request: string): boolean => cssRe.test(request) && - !rawRE.test(request) && inlineRE.test(request); + !rawRE.test(request) && !inlineRE.test(request); From b429a8a77e98ad2eb7386e22bfd37acee686266e Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 7 Feb 2023 10:07:52 -0500 Subject: [PATCH 4/4] Replace use of isCSSRequest --- .../src/core/build/plugins/plugin-css.ts | 4 ++-- packages/astro/src/core/render/dev/css.ts | 5 ++-- packages/astro/src/core/render/dev/util.ts | 9 ++++++++ packages/astro/src/core/render/dev/vite.ts | 6 ++--- packages/astro/src/core/render/util.ts | 23 ------------------- 5 files changed, 16 insertions(+), 31 deletions(-) create mode 100644 packages/astro/src/core/render/dev/util.ts delete mode 100644 packages/astro/src/core/render/util.ts diff --git a/packages/astro/src/core/build/plugins/plugin-css.ts b/packages/astro/src/core/build/plugins/plugin-css.ts index 0d57cfb5e668..9873ad8898be 100644 --- a/packages/astro/src/core/build/plugins/plugin-css.ts +++ b/packages/astro/src/core/build/plugins/plugin-css.ts @@ -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, })) { diff --git a/packages/astro/src/core/render/dev/css.ts b/packages/astro/src/core/render/dev/css.ts index 5667f705c818..9338c531c540 100644 --- a/packages/astro/src/core/render/dev/css.ts +++ b/packages/astro/src/core/render/dev/css.ts @@ -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(); 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; try { // The SSR module is possibly not loaded. Load it if it's null. diff --git a/packages/astro/src/core/render/dev/util.ts b/packages/astro/src/core/render/dev/util.ts new file mode 100644 index 000000000000..85bf3dec28f4 --- /dev/null +++ b/packages/astro/src/core/render/dev/util.ts @@ -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); diff --git a/packages/astro/src/core/render/dev/vite.ts b/packages/astro/src/core/render/dev/vite.ts index f927966b636f..a3f0b6437821 100644 --- a/packages/astro/src/core/render/dev/vite.ts +++ b/packages/astro/src/core/render/dev/vite.ts @@ -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))) { diff --git a/packages/astro/src/core/render/util.ts b/packages/astro/src/core/render/util.ts deleted file mode 100644 index 928d742801f5..000000000000 --- a/packages/astro/src/core/render/util.ts +++ /dev/null @@ -1,23 +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('|')})($|\\?)` -); - -const rawRE = /(?:\?|&)raw(?:&|$)/; -const inlineRE = /(?:\?|&)inline\b/; - -export const isCSSRequest = (request: string): boolean => cssRe.test(request) && - !rawRE.test(request) && !inlineRE.test(request);