Skip to content

Commit

Permalink
Prevent ?inline and ?raw CSS from being bundled as CSS (#6161)
Browse files Browse the repository at this point in the history
* Prevent ?inline and ?raw CSS from being bundled as CSS

* Add a changeset

* oopts

* Replace use of isCSSRequest
  • Loading branch information
matthewp authored Feb 7, 2023
1 parent 460f9e7 commit f6fc662
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 26 deletions.
5 changes: 5 additions & 0 deletions .changeset/big-rocks-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Prevent ?inline and ?raw CSS from being bundled as CSS
4 changes: 2 additions & 2 deletions packages/astro/src/core/build/plugins/plugin-css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
})) {
Expand Down
5 changes: 2 additions & 3 deletions packages/astro/src/core/render/dev/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand All @@ -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.
Expand Down
9 changes: 9 additions & 0 deletions packages/astro/src/core/render/dev/util.ts
Original file line number Diff line number Diff line change
@@ -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);
6 changes: 3 additions & 3 deletions packages/astro/src/core/render/dev/vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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))) {
Expand Down
18 changes: 0 additions & 18 deletions packages/astro/src/core/render/util.ts

This file was deleted.

28 changes: 28 additions & 0 deletions packages/astro/test/css-inline.test.js
Original file line number Diff line number Diff line change
@@ -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 changes: 8 additions & 0 deletions packages/astro/test/fixtures/css-inline/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@test/css-inline",
"version": "0.0.0",
"private": true,
"dependencies": {
"astro": "workspace:*"
}
}
3 changes: 3 additions & 0 deletions packages/astro/test/fixtures/css-inline/src/inline.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
body {
background: tomato;
}
35 changes: 35 additions & 0 deletions packages/astro/test/fixtures/css-inline/src/layouts/Layout.astro
Original file line number Diff line number Diff line change
@@ -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 changes: 19 additions & 0 deletions packages/astro/test/fixtures/css-inline/src/pages/index.astro
Original file line number Diff line number Diff line change
@@ -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 changes: 3 additions & 0 deletions packages/astro/test/fixtures/css-inline/src/raw.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
main {
background: plum;
}
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f6fc662

Please sign in to comment.