0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00

Fix HMR in MDX deps in Content Collections (#9956)

Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev>
Co-authored-by: bluwy <bjornlu.dev@gmail.com>
This commit is contained in:
Matthew Phillips 2024-02-06 09:56:22 -05:00 committed by GitHub
parent 6e30bef652
commit 81acac24a3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 124 additions and 10 deletions

View file

@ -0,0 +1,5 @@
---
"astro": patch
---
Fixes HMR for MDX dependencies in Content Collections

View file

@ -0,0 +1,32 @@
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = testFactory({ root: './fixtures/content-collections/' });
let devServer;
test.beforeAll(async ({ astro }) => {
devServer = await astro.startDevServer();
});
test.afterAll(async ({ astro }) => {
await devServer.stop();
astro.resetAllFiles();
});
test.describe('Content Collections', () => {
test('HMR', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/'));
await astro.editFile('./src/components/MyComponent.astro', (original) =>
original.replace('red', 'green')
);
const h1 = page.locator('#my-heading');
await expect(h1, 'should have green color').toHaveCSS(
'color',
'rgb(0, 128, 0)'
);
});
});

View file

@ -0,0 +1,9 @@
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
// https://astro.build/config
export default defineConfig({
integrations: [
mdx(),
],
});

View file

@ -0,0 +1,9 @@
{
"name": "@e2e/content-collections",
"version": "0.0.0",
"private": true,
"dependencies": {
"@astrojs/mdx": "workspace:*",
"astro": "workspace:*"
}
}

View file

@ -0,0 +1,10 @@
<h1 id="my-heading">
Some text here
</h1>
<style>
h1 {
color: red;
}
</style>

View file

@ -0,0 +1,6 @@
---
---
import MyComponent from '../../components/MyComponent.astro';
<MyComponent />

View file

@ -0,0 +1,8 @@
---
import { getEntryBySlug } from 'astro:content'
const post = await getEntryBySlug('posts', 'post-1')
const { Content } = await post.render();
---
<Content/>

View file

@ -64,13 +64,29 @@ export function astroContentAssetPropagationPlugin({
if (!devModuleLoader.getModuleById(basePath)?.ssrModule) {
await devModuleLoader.import(basePath);
}
const { styles, urls } = await getStylesForURL(pathToFileURL(basePath), devModuleLoader);
const {
styles,
urls,
crawledFiles: styleCrawledFiles,
} = await getStylesForURL(pathToFileURL(basePath), devModuleLoader);
const hoistedScripts = await getScriptsForURL(
pathToFileURL(basePath),
settings.config.root,
devModuleLoader
);
const { scripts: hoistedScripts, crawledFiles: scriptCrawledFiles } =
await getScriptsForURL(pathToFileURL(basePath), settings.config.root, devModuleLoader);
// Register files we crawled to be able to retrieve the rendered styles and scripts,
// as when they get updated, we need to re-transform ourselves.
// We also only watch files within the user source code, as changes in node_modules
// are usually also ignored by Vite.
for (const file of styleCrawledFiles) {
if (!file.includes('node_modules')) {
this.addWatchFile(file);
}
}
for (const file of scriptCrawledFiles) {
if (!file.includes('node_modules')) {
this.addWatchFile(file);
}
}
stringifiedLinks = JSON.stringify([...urls]);
stringifiedStyles = JSON.stringify(styles.map((s) => s.content));

View file

@ -41,6 +41,7 @@ export interface ModuleLoader {
export interface ModuleNode {
id: string | null;
url: string;
file: string | null;
ssrModule: Record<string, any> | null;
ssrTransformResult: {
deps?: string[];

View file

@ -13,12 +13,16 @@ interface ImportedStyle {
export async function getStylesForURL(
filePath: URL,
loader: ModuleLoader
): Promise<{ urls: Set<string>; styles: ImportedStyle[] }> {
): Promise<{ urls: Set<string>; styles: ImportedStyle[]; crawledFiles: Set<string> }> {
const importedCssUrls = new Set<string>();
// Map of url to injected style object. Use a `url` key to deduplicate styles
const importedStylesMap = new Map<string, ImportedStyle>();
const crawledFiles = new Set<string>();
for await (const importedModule of crawlGraph(loader, viteID(filePath), true)) {
if (importedModule.file) {
crawledFiles.add(importedModule.file);
}
if (isBuildableCSSRequest(importedModule.url)) {
// In dev, we inline all styles if possible
let css = '';
@ -60,5 +64,6 @@ export async function getStylesForURL(
return {
urls: importedCssUrls,
styles: [...importedStylesMap.values()],
crawledFiles,
};
}

View file

@ -393,7 +393,7 @@ async function getScriptsAndStyles({ pipeline, filePath }: GetScriptsAndStylesPa
const settings = pipeline.getSettings();
const mode = pipeline.getEnvironment().mode;
// Add hoisted script tags
const scripts = await getScriptsForURL(filePath, settings.config.root, moduleLoader);
const { scripts } = await getScriptsForURL(filePath, settings.config.root, moduleLoader);
// Inject HMR scripts
if (isPage(filePath, settings) && mode === 'development') {

View file

@ -9,12 +9,16 @@ export async function getScriptsForURL(
filePath: URL,
root: URL,
loader: ModuleLoader
): Promise<Set<SSRElement>> {
): Promise<{ scripts: Set<SSRElement>; crawledFiles: Set<string> }> {
const elements = new Set<SSRElement>();
const crawledFiles = new Set<string>();
const rootID = viteID(filePath);
const modInfo = loader.getModuleInfo(rootID);
addHoistedScripts(elements, modInfo, root);
for await (const moduleNode of crawlGraph(loader, rootID, true)) {
if (moduleNode.file) {
crawledFiles.add(moduleNode.file);
}
const id = moduleNode.id;
if (id) {
const info = loader.getModuleInfo(id);
@ -22,7 +26,7 @@ export async function getScriptsForURL(
}
}
return elements;
return { scripts: elements, crawledFiles };
}
function addHoistedScripts(set: Set<SSRElement>, info: ModuleInfo | null, root: URL) {

View file

@ -935,6 +935,15 @@ importers:
specifier: workspace:*
version: link:../../..
packages/astro/e2e/fixtures/content-collections:
dependencies:
'@astrojs/mdx':
specifier: workspace:*
version: link:../../../../integrations/mdx
astro:
specifier: workspace:*
version: link:../../..
packages/astro/e2e/fixtures/css:
dependencies:
astro: