Fix importing CSS packages in frontmatter (#3537)

* Fix importing CSS packages in frontmatter

* Formatting

* Only update if the source code contains the import

* Consolidate the two plugins

* we do need a pre and a post

* Adds a changeset
This commit is contained in:
Matthew Phillips 2022-06-06 18:26:15 -04:00 committed by GitHub
parent 88974f8b40
commit 51c60de76c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 121 additions and 64 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fixes imported CSS packages in frontmatter

View file

@ -130,7 +130,7 @@
"strip-ansi": "^7.0.1",
"supports-esm": "^1.0.0",
"tsconfig-resolver": "^3.0.1",
"vite": "^2.9.9",
"vite": "^2.9.10",
"yargs-parser": "^21.0.1",
"zod": "^3.17.3"
},

View file

@ -1,4 +1,4 @@
import type { GetModuleInfo, ModuleInfo } from 'rollup';
import type { GetModuleInfo, ModuleInfo, OutputChunk } from 'rollup';
import { BuildInternals } from '../core/build/internal';
import type { PageBuildData } from '../core/build/types';
@ -76,25 +76,6 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[]
{
name: CSS_PLUGIN_NAME,
configResolved(resolvedConfig) {
// Our plugin needs to run before `vite:css-post` because we have to modify
// The bundles before vite:css-post sees them. We can remove this code
// after this bug is fixed: https://github.com/vitejs/vite/issues/8330
const plugins = resolvedConfig.plugins as VitePlugin[];
const viteCSSPostIndex = resolvedConfig.plugins.findIndex(
(p) => p.name === 'vite:css-post'
);
if (viteCSSPostIndex !== -1) {
// Move our plugin to be right before this one.
const ourIndex = plugins.findIndex((p) => p.name === CSS_PLUGIN_NAME);
const ourPlugin = plugins[ourIndex];
// Remove us from where we are now and place us right before the viteCSSPost plugin
plugins.splice(ourIndex, 1);
plugins.splice(viteCSSPostIndex - 1, 0, ourPlugin);
}
},
outputOptions(outputOptions) {
const manualChunks = outputOptions.manualChunks || Function.prototype;
outputOptions.manualChunks = function (id, ...args) {
@ -157,21 +138,8 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[]
}
}
}
if (chunk.type === 'chunk') {
// This simply replaces single quotes with double quotes because the vite:css-post
// plugin only works with single for some reason. This code can be removed
// When the Vite bug is fixed: https://github.com/vitejs/vite/issues/8330
const exp = new RegExp(
`(\\bimport\\s*)[']([^']*(?:[a-z]+\.[0-9a-z]+\.m?js))['](;\n?)`,
'g'
);
chunk.code = chunk.code.replace(exp, (_match, begin, chunkPath, end) => {
return begin + '"' + chunkPath + '"' + end;
});
}
}
},
}
},
{
name: CSS_MINIFY_PLUGIN_NAME,
@ -190,10 +158,40 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[]
});
output.source = minifiedCSS;
}
} else if (output.type === 'chunk') {
// vite:css-post removes "pure CSS" JavaScript chunks, that is chunks that only contain a comment
// about it being a CSS module. We need to keep these chunks around because Astro
// re-imports all modules as their namespace `import * as module1 from 'some/path';
// in order to determine if one of them is a side-effectual web component.
// If we ever get rid of that feature, the code below can be removed.
for(const [imp, bindings] of Object.entries(output.importedBindings)) {
if(imp.startsWith('chunks/') && !bundle[imp] && output.code.includes(imp)) {
// This just creates an empty chunk module so that the main entry module
// that is importing it doesn't break.
const depChunk: OutputChunk = {
type: 'chunk',
fileName: imp,
name: imp,
facadeModuleId: imp,
code: `/* Pure CSS chunk ${imp} */ ${bindings.map(b => `export const ${b} = {};`)}`,
dynamicImports: [],
implicitlyLoadedBefore: [],
importedBindings: {},
imports: [],
referencedFiles: [],
exports: Array.from(bindings),
isDynamicEntry: false,
isEntry: false,
isImplicitEntry: false,
modules: {},
};
bundle[imp] = depChunk;
}
}
}
}
}
},
},
}
}
];
}

View file

@ -0,0 +1,9 @@
{
"name": "@test/astro-fontsource-package",
"version": "0.0.0",
"private": true,
"dependencies": {
"@fontsource/montserrat": "4.5.11",
"astro": "workspace:*"
}
}

View file

@ -0,0 +1,13 @@
---
import "@fontsource/montserrat";
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Astro</title>
</head>
<body>
<h1>Astro</h1>
</body>
</html>

View file

@ -0,0 +1,20 @@
import { expect } from 'chai';
import * as cheerio from 'cheerio';
import { loadFixture } from './test-utils.js';
describe('@fontsource/* packages', () => {
let fixture;
before(async () => {
fixture = await loadFixture({ root: './fixtures/fontsource-package/' });
await fixture.build();
});
it('can be imported in frontmatter', async () => {
const html = await fixture.readFile('/index.html');
const $ = cheerio.load(html);
const assetPath = $('link').attr('href');
const css = await fixture.readFile(assetPath);
expect(css).to.contain('Montserrat');
});
});

View file

@ -542,7 +542,7 @@ importers:
strip-ansi: ^7.0.1
supports-esm: ^1.0.0
tsconfig-resolver: ^3.0.1
vite: ^2.9.9
vite: ^2.9.10
yargs-parser: ^21.0.1
zod: ^3.17.3
dependencies:
@ -599,7 +599,7 @@ importers:
strip-ansi: 7.0.1
supports-esm: 1.0.0
tsconfig-resolver: 3.0.1
vite: 2.9.9_sass@1.52.2
vite: 2.9.10_sass@1.52.2
yargs-parser: 21.0.1
zod: 3.17.3
devDependencies:
@ -1367,6 +1367,14 @@ importers:
'@astrojs/vue': link:../../../../integrations/vue
astro: link:../../..
packages/astro/test/fixtures/fontsource-package:
specifiers:
'@fontsource/montserrat': 4.5.11
astro: workspace:*
dependencies:
'@fontsource/montserrat': 4.5.11
astro: link:../../..
packages/astro/test/fixtures/legacy-build:
specifiers:
'@astrojs/vue': workspace:*
@ -3895,6 +3903,10 @@ packages:
- supports-color
dev: true
/@fontsource/montserrat/4.5.11:
resolution: {integrity: sha512-XAYZmprnZDVSLIeEiB3evVG2JD+yoR9aT+I6LCOcwZFQ6ro9UPpopDncqoqwv+j5M0/UjyAP6ov70+L/fmP8Gg==}
dev: false
/@formatjs/ecma402-abstract/1.11.4:
resolution: {integrity: sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==}
dependencies:
@ -13592,6 +13604,31 @@ packages:
- supports-color
dev: true
/vite/2.9.10_sass@1.52.2:
resolution: {integrity: sha512-TwZRuSMYjpTurLqXspct+HZE7ONiW9d+wSWgvADGxhDPPyoIcNywY+RX4ng+QpK30DCa1l/oZgi2PLZDibhzbQ==}
engines: {node: '>=12.2.0'}
hasBin: true
peerDependencies:
less: '*'
sass: '*'
stylus: '*'
peerDependenciesMeta:
less:
optional: true
sass:
optional: true
stylus:
optional: true
dependencies:
esbuild: 0.14.42
postcss: 8.4.14
resolve: 1.22.0
rollup: 2.75.5
sass: 1.52.2
optionalDependencies:
fsevents: 2.3.2
dev: false
/vite/2.9.9:
resolution: {integrity: sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew==}
engines: {node: '>=12.2.0'}
@ -13616,31 +13653,6 @@ packages:
fsevents: 2.3.2
dev: false
/vite/2.9.9_sass@1.52.2:
resolution: {integrity: sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew==}
engines: {node: '>=12.2.0'}
hasBin: true
peerDependencies:
less: '*'
sass: '*'
stylus: '*'
peerDependenciesMeta:
less:
optional: true
sass:
optional: true
stylus:
optional: true
dependencies:
esbuild: 0.14.42
postcss: 8.4.14
resolve: 1.22.0
rollup: 2.75.5
sass: 1.52.2
optionalDependencies:
fsevents: 2.3.2
dev: false
/vm2/3.9.9:
resolution: {integrity: sha512-xwTm7NLh/uOjARRBs8/95H0e8fT3Ukw5D/JJWhxMbhKzNh1Nu981jQKvkep9iKYNxzlVrdzD0mlBGkDKZWprlw==}
engines: {node: '>=6.0'}