fix astro scoping of "@import" inside of style tags (#2656)
* fix astro scoping of "@import" inside of style tags * Create lovely-lies-dress.md * Update compile.ts * fix smoke test * Update package.json
This commit is contained in:
parent
ba49d3efc2
commit
fca6407318
3 changed files with 35 additions and 6 deletions
5
.changeset/lovely-lies-dress.md
Normal file
5
.changeset/lovely-lies-dress.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"astro": patch
|
||||
---
|
||||
|
||||
fix astro scoping of "@import" inside of style tags
|
|
@ -4,7 +4,7 @@
|
|||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev --experimental-static-build",
|
||||
"start": "astro dev",
|
||||
"start": "astro dev --experimental-static-build",
|
||||
"build": "astro build --experimental-static-build",
|
||||
"scan-build": "astro build",
|
||||
"preview": "astro preview"
|
||||
|
|
|
@ -9,11 +9,29 @@ import { transform } from '@astrojs/compiler';
|
|||
import { transformWithVite } from './styles.js';
|
||||
|
||||
type CompilationCache = Map<string, CompileResult>;
|
||||
type CompileResult = TransformResult & { rawCSSDeps: Set<string> };
|
||||
|
||||
/**
|
||||
* Note: this is currently needed because Astro is directly using a Vite internal CSS transform. This gives us
|
||||
* some nice features out of the box, but at the expense of also running Vite's CSS postprocessing build step,
|
||||
* which does some things that we don't like, like resolving/handling `@import` too early. This function pulls
|
||||
* out the `@import` tags to be added back later, and then finally handled correctly by Vite.
|
||||
*
|
||||
* In the future, we should remove this workaround and most likely implement our own Astro style handling without
|
||||
* having to hook into Vite's internals.
|
||||
*/
|
||||
function createImportPlaceholder(spec: string) {
|
||||
// Note: We keep this small so that we can attempt to exactly match the # of characters in the original @import.
|
||||
// This keeps sourcemaps accurate (to the best of our ability) at the intermediate step where this appears.
|
||||
// -> `@import '${spec}';`;
|
||||
return `/*IMPORT:${spec}*/`;
|
||||
}
|
||||
function safelyReplaceImportPlaceholder(code: string) {
|
||||
return code.replace(/\/\*IMPORT\:(.*?)\*\//g, `@import '$1';`);
|
||||
}
|
||||
|
||||
const configCache = new WeakMap<AstroConfig, CompilationCache>();
|
||||
|
||||
type CompileResult = TransformResult & { rawCSSDeps: Set<string> };
|
||||
|
||||
async function compile(config: AstroConfig, filename: string, source: string, viteTransform: TransformHook, opts: { ssr: boolean }): Promise<CompileResult> {
|
||||
// pages and layouts should be transformed as full documents (implicit <head> <body> etc)
|
||||
// everything else is treated as a fragment
|
||||
|
@ -44,9 +62,15 @@ async function compile(config: AstroConfig, filename: string, source: string, vi
|
|||
try {
|
||||
// In the static build, grab any @import as CSS dependencies for HMR.
|
||||
if (config.buildOptions.experimentalStaticBuild) {
|
||||
value.replace(/(?:@import)\s(?:url\()?\s?["\'](.*?)["\']\s?\)?(?:[^;]*);?/gi, (match, spec) => {
|
||||
value = value.replace(/(?:@import)\s(?:url\()?\s?["\'](.*?)["\']\s?\)?(?:[^;]*);?/gi, (match, spec) => {
|
||||
rawCSSDeps.add(spec);
|
||||
// If the language is CSS: prevent `@import` inlining to prevent scoping of imports.
|
||||
// Otherwise: Sass, etc. need to see imports for variables, so leave in for their compiler to handle.
|
||||
if (lang === '.css') {
|
||||
return createImportPlaceholder(spec);
|
||||
} else {
|
||||
return match;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -67,7 +91,7 @@ async function compile(config: AstroConfig, filename: string, source: string, vi
|
|||
map = result.map.toString();
|
||||
}
|
||||
}
|
||||
const code = result.code;
|
||||
const code = safelyReplaceImportPlaceholder(result.code);
|
||||
return { code, map };
|
||||
} catch (err) {
|
||||
// save error to throw in plugin context
|
||||
|
|
Loading…
Reference in a new issue