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
fix(i18n): don't make virtual modules no-op #10662
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"astro": patch | ||
--- | ||
|
||
Fixes a case where the `i18n` virtual module was transformed into a no-op function when some functions were used inside a non-prerendered page. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ import type { BuildInternals } from '../internal.js'; | |
import type { AstroBuildPlugin } from '../plugin.js'; | ||
import type { StaticBuildOptions } from '../types.js'; | ||
import { extendManualChunks } from './util.js'; | ||
import { ASTRO_VIRTUAL_MODULE } from '../../constants.js'; | ||
|
||
function vitePluginPrerender(opts: StaticBuildOptions, internals: BuildInternals): VitePlugin { | ||
return { | ||
|
@@ -13,12 +14,9 @@ function vitePluginPrerender(opts: StaticBuildOptions, internals: BuildInternals | |
outputOptions(outputOptions) { | ||
extendManualChunks(outputOptions, { | ||
after(id, meta) { | ||
// Split the Astro runtime into a separate chunk for readability | ||
if (id.includes('astro/dist/runtime')) { | ||
return 'astro'; | ||
} | ||
const pageInfo = internals.pagesByViteID.get(id); | ||
let hasSharedModules = false; | ||
let hasAstroVirtualModules = false; | ||
if (pageInfo) { | ||
// prerendered pages should be split into their own chunk | ||
// Important: this can't be in the `pages/` directory! | ||
|
@@ -43,12 +41,20 @@ function vitePluginPrerender(opts: StaticBuildOptions, internals: BuildInternals | |
// Given the previous statement, we only check if | ||
// - the module is a page, and it's not pre-rendered | ||
// - the module is the middleware | ||
// - the module belongs to our virtual modules, which belong to ` | ||
// If one of these conditions is met, we need a separate chunk | ||
for (const importer of moduleMeta.importedIds) { | ||
// we don't want to analyze the same module again, so we skip it | ||
if (importer !== id) { | ||
const importerModuleMeta = meta.getModuleInfo(importer); | ||
if (importerModuleMeta) { | ||
if ( | ||
importerModuleMeta.meta && | ||
importerModuleMeta.meta[ASTRO_VIRTUAL_MODULE] | ||
) { | ||
hasAstroVirtualModules = true; | ||
break; | ||
} | ||
// if the module is inside the pages | ||
if (importerModuleMeta.id.includes('/pages')) { | ||
// we check if it's not pre-rendered | ||
|
@@ -70,6 +76,7 @@ function vitePluginPrerender(opts: StaticBuildOptions, internals: BuildInternals | |
|
||
opts.allPages; | ||
pageInfo.hasSharedModules = hasSharedModules; | ||
pageInfo.hasAstroVirtualModule = hasAstroVirtualModules; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this property is only set when there is prerendering, is that right? If so there might be a better name for this, so people don't think it can be used elsewhere. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you have some suggestions? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure yet, what is the reason why prerendering needs special handling for virtual modules? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's the other way around, virtual modules need special treatment for prerendered pages. It seems that the static build takes the chunk that contains the virtual module and makes it a no-op. I'm not very familiar with the specifics of business logic though. |
||
pageInfo.route.prerender = true; | ||
return 'prerender'; | ||
} | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -374,7 +374,10 @@ async function cleanStaticOutput( | |||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||
const allStaticFiles = new Set(); | ||||||||||||||||||||||||||||||||||||
for (const pageData of eachPageData(internals)) { | ||||||||||||||||||||||||||||||||||||
if (pageData.route.prerender && !pageData.hasSharedModules) { | ||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||
pageData.route.prerender && | ||||||||||||||||||||||||||||||||||||
!(pageData.hasSharedModules || pageData.hasAstroVirtualModule) | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this part the actual fix of the issue? Can you explain why this is needed if so? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes this is part of the fix. This is where we collect the chunks, few lines below we clean them up by making them no-op: astro/packages/astro/src/core/build/static-build.ts Lines 397 to 413 in 317d18e
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok got it. It's a little confusing that this prerender specific logic is inlined into the build like this. What do you think about moving this to it's own function or something to improve readability? |
||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||
const { moduleSpecifier } = pageData; | ||||||||||||||||||||||||||||||||||||
const pageBundleId = internals.pageToBundleMap.get(moduleSpecifier); | ||||||||||||||||||||||||||||||||||||
const entryBundleId = internals.entrySpecifierToBundleMap.get(moduleSpecifier); | ||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's NOT part of the fix, but having this is here felt very out of place, and I moved it inside
plugin-chunks