Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify HMR handling #5811

Merged
merged 10 commits into from
Jan 11, 2023
Merged

Simplify HMR handling #5811

merged 10 commits into from
Jan 11, 2023

Conversation

bluwy
Copy link
Member

@bluwy bluwy commented Jan 10, 2023

Changes

Simplifies vite-plugin-astro's resolveId hook. It looks like we were adding special cases there to get HMR working, but I found it possible to do less. I'll elaborate more in the review comments below.

Testing

Existing tests that cover the HMR behaviour should pass. I checked the git history and made sure or edge case changes we have did have tests, so this should be safe.

Docs

n/a. internal change.

@changeset-bot
Copy link

changeset-bot bot commented Jan 10, 2023

🦋 Changeset detected

Latest commit: b005ea6

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added the pkg: astro Related to the core `astro` package (scope) label Jan 10, 2023
@github-actions github-actions bot added the 🚨 action Modifies GitHub Actions label Jan 10, 2023
@github-actions github-actions bot removed the 🚨 action Modifies GitHub Actions label Jan 10, 2023
@bluwy bluwy added the feat: hmr Related to HMR (scope) label Jan 11, 2023
@@ -37,7 +35,7 @@ export async function compile({
// use `sourcemap: "both"` so that sourcemap is included in the code
// result passed to esbuild, but also available in the catch handler.
transformResult = await transform(source, {
moduleId,
moduleId: filename,
pathname: filename,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found the filename and the moduleId passed are always the same (absolute paths or virtual ids). They could only differ in the resolveId hook, but since we're compiling in the transform hook, it doesn't affect us.

In a future compiler PR, I'll merge moduleId and pathname options into one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So filename is the module ID right? To do head propagation we rely on the moduleId being passed to the compiler to match what is found in the module graph. Just want to make sure that is still going to be happening here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, I tested it and saw it's always identical, even for virtual files. I think the unit test should cover if not as I was able to get it to fail when I pass the wrong id during manual testing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did another quick review, and I think this part I guess I'm slightly unsure:

filename: context.file,
id: context.modules[0]?.id ?? undefined,

When you added the context.modules[0]?.id, is it because it differs from context.file? If I understand the module graph right, Vite's code should have them equal in most case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I did that out of "correctness" rather than a concern about context.file. So I think we can go with the change for now and see what happens.

Comment on lines -62 to -63
// note: don’t claim .astro files with resolveId() — it prevents Vite from transpiling the final JS (import.meta.glob, etc.)
async resolveId(id, from, opts) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire resolveId hook is removed in favour of the next review comment.

Comment on lines +186 to +195
const normalPlugin: vite.Plugin = {
name: 'astro:build:normal',
resolveId(id) {
// If Vite resolver can't resolve the Astro request, it's likely a virtual Astro file, fallback here instead
const parsedId = parseAstroRequest(id);
if (parsedId.query.astro) {
return id;
}
},
};
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... Continuing. This resolveId hook should cover all our cases instead.

The reason we can remove the pre plugin resolveId completely is because the paths can already be resolved by Vite's resolver plugin. Pre plugins run before Vite's resolver. Previously we try to resolve it ourselves, and the edge cases compound because we had to emulate the Vite resolver algorithm to get the flow right (which isn't feasible)

Now we let Vite handle instead, and only catch those that don't work with a normal plugin, which runs after Vite's resolver.

@@ -196,20 +132,14 @@ export default function astro({ settings, logging }: AstroPluginOptions): vite.P
return;
}

const filename = normalizeFilename(parsedId.filename, config);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other diffs, you'll see that I had removed normalizeFilename. That's because normalizeFilename was previously used to emulate Vite's resolver algorithm, and only needed in a pre plugins resolveId.

Since this is a transform hook, we can remove it as it's already normalized by Vite.

async load(id, opts) {
const parsedId = parseAstroRequest(id);
const query = parsedId.query;
if (!query.astro) {
return null;
}
// For CSS / hoisted scripts, the main Astro module should already be cached
const filename = normalizeFilename(parsedId.filename, config);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still needs a normalizeFilename in load as it may receive a root-relative path, like /src/components/Foo.astro. This seems to only happen in tests (likely the mocked fs used?), but I leave it here for now just in case.

@bluwy bluwy marked this pull request as ready for review January 11, 2023 12:54
Copy link
Contributor

@bholmesdev bholmesdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need HMoRe quality PRs like this 👏
Learned a bit about Vite's resolveId hook as well. Making a note of that. Change seems good assuming tests pass.

@matthewp matthewp merged commit ec09bb6 into main Jan 11, 2023
@matthewp matthewp deleted the try-simplify-hmr branch January 11, 2023 18:51
@FDiskas
Copy link

FDiskas commented Jul 14, 2023

HMR (Hot Module Replacement) vs LR (Live Reload) - misused keyword? even on an empty project, there is no such thing as HMR - on each change page reloads only.

So HMR does not work. Try changing Hello within the component and it should change without reloading the main page.
https://stackblitz.com/edit/github-m9axad-vp3ckj?file=src%2Fpages%2Findex.astro,src%2Fcomponents%2FCard.astro

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: hmr Related to HMR (scope) pkg: astro Related to the core `astro` package (scope)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants