Implement getting hoisted scripts for propagation
This commit is contained in:
parent
0ae1c91b8d
commit
0d57cafd04
6 changed files with 91 additions and 58 deletions
|
@ -2,7 +2,6 @@ export { createContentTypesGenerator } from './types-generator.js';
|
||||||
export { contentObservable, getContentPaths, getDotAstroTypeReference } from './utils.js';
|
export { contentObservable, getContentPaths, getDotAstroTypeReference } from './utils.js';
|
||||||
export {
|
export {
|
||||||
astroContentAssetPropagationPlugin,
|
astroContentAssetPropagationPlugin,
|
||||||
astroContentProdBundlePlugin,
|
|
||||||
} from './vite-plugin-content-assets.js';
|
} from './vite-plugin-content-assets.js';
|
||||||
export { astroContentServerPlugin } from './vite-plugin-content-server.js';
|
export { astroContentServerPlugin } from './vite-plugin-content-server.js';
|
||||||
export { astroContentVirtualModPlugin } from './vite-plugin-content-virtual-mod.js';
|
export { astroContentVirtualModPlugin } from './vite-plugin-content-virtual-mod.js';
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { pathToFileURL } from 'url';
|
import { pathToFileURL } from 'url';
|
||||||
|
import npath from 'node:path';
|
||||||
import type { Plugin } from 'vite';
|
import type { Plugin } from 'vite';
|
||||||
import { moduleIsTopLevelPage, walkParentInfos } from '../core/build/graph.js';
|
import { moduleIsTopLevelPage, walkParentInfos } from '../core/build/graph.js';
|
||||||
import { BuildInternals, getPageDataByViteID } from '../core/build/internal.js';
|
import { BuildInternals, getPageDataByViteID } from '../core/build/internal.js';
|
||||||
|
@ -14,6 +15,8 @@ import {
|
||||||
SCRIPTS_PLACEHOLDER,
|
SCRIPTS_PLACEHOLDER,
|
||||||
STYLES_PLACEHOLDER,
|
STYLES_PLACEHOLDER,
|
||||||
} from './consts.js';
|
} from './consts.js';
|
||||||
|
import type { RollupOutput, OutputChunk, StaticBuildOptions } from '../core/build/types';
|
||||||
|
import { prependForwardSlash } from '../core/path.js';
|
||||||
|
|
||||||
function isPropagatedAsset(viteId: string): boolean {
|
function isPropagatedAsset(viteId: string): boolean {
|
||||||
const url = new URL(viteId, 'file://');
|
const url = new URL(viteId, 'file://');
|
||||||
|
@ -73,67 +76,95 @@ export function astroContentAssetPropagationPlugin({ mode }: { mode: string }):
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function astroContentProdBundlePlugin({ internals }: { internals: BuildInternals }): Plugin {
|
export function astroConfigBuildPlugin(options: StaticBuildOptions, internals: BuildInternals): AstroBuildPlugin {
|
||||||
|
let ssrPluginContext: any = undefined;
|
||||||
return {
|
return {
|
||||||
name: 'astro:content-prod-bundle',
|
build: 'ssr',
|
||||||
async generateBundle(_options, bundle) {
|
hooks: {
|
||||||
for (const [_, chunk] of Object.entries(bundle)) {
|
'build:before': ({ build }) => {
|
||||||
if (
|
return {
|
||||||
chunk.type === 'chunk' &&
|
vitePlugin: {
|
||||||
(chunk.code.includes(LINKS_PLACEHOLDER) || chunk.code.includes(SCRIPTS_PLACEHOLDER))
|
name: 'astro:content-build-plugin',
|
||||||
) {
|
generateBundle() {
|
||||||
for (const id of Object.keys(chunk.modules)) {
|
if(build === 'ssr') {
|
||||||
for (const [pageInfo, depth, order] of walkParentInfos(id, this)) {
|
ssrPluginContext = this;
|
||||||
if (moduleIsTopLevelPage(pageInfo)) {
|
}
|
||||||
const pageViteID = pageInfo.id;
|
}
|
||||||
const pageData = getPageDataByViteID(internals, pageViteID);
|
},
|
||||||
if (!pageData) continue;
|
};
|
||||||
<<<<<<< HEAD
|
},
|
||||||
|
'build:post': ({ ssrOutputs, clientOutputs, mutate }) => {
|
||||||
|
const outputs = ssrOutputs.flatMap(o => o.output);
|
||||||
|
for (const chunk of outputs) {
|
||||||
|
if (
|
||||||
|
chunk.type === 'chunk' &&
|
||||||
|
(chunk.code.includes(LINKS_PLACEHOLDER) || chunk.code.includes(SCRIPTS_PLACEHOLDER))
|
||||||
|
) {
|
||||||
|
let entryCSS = new Set<string>();
|
||||||
|
let entryScripts = new Set<string>();
|
||||||
|
|
||||||
=======
|
for (const id of Object.keys(chunk.modules)) {
|
||||||
console.log({ pageData });
|
for (const [pageInfo] of walkParentInfos(id, ssrPluginContext)) {
|
||||||
>>>>>>> bdc0a6498 (updated)
|
if (moduleIsTopLevelPage(pageInfo)) {
|
||||||
const entryCss = pageData.contentCollectionCss?.get(id);
|
const pageViteID = pageInfo.id;
|
||||||
const entryScripts = pageData.propagatedScripts?.get(id);
|
const pageData = getPageDataByViteID(internals, pageViteID);
|
||||||
if (entryCss) {
|
if (!pageData) continue;
|
||||||
chunk.code = chunk.code.replace(
|
|
||||||
JSON.stringify(LINKS_PLACEHOLDER),
|
const _entryCss = pageData.contentCollectionCss?.get(id);
|
||||||
JSON.stringify([...entryCss])
|
const _entryScripts = pageData.propagatedScripts?.get(id);
|
||||||
);
|
if(_entryCss) {
|
||||||
}
|
for(const value of _entryCss) {
|
||||||
if (entryScripts) {
|
entryCSS.add(value);
|
||||||
<<<<<<< HEAD
|
}
|
||||||
=======
|
}
|
||||||
console.log({ entryScripts });
|
if(_entryScripts) {
|
||||||
>>>>>>> bdc0a6498 (updated)
|
for(const value of _entryScripts) {
|
||||||
chunk.code = chunk.code.replace(
|
entryScripts.add(value);
|
||||||
JSON.stringify(SCRIPTS_PLACEHOLDER),
|
}
|
||||||
JSON.stringify(
|
}
|
||||||
[...entryScripts].map((src) => ({
|
|
||||||
props: { src, type: 'module' },
|
|
||||||
children: '',
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let newCode = chunk.code;
|
||||||
|
if (entryCSS.size) {
|
||||||
|
newCode = newCode.replace(
|
||||||
|
JSON.stringify(LINKS_PLACEHOLDER),
|
||||||
|
JSON.stringify([...entryCSS])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (entryScripts.size) {
|
||||||
|
const entryFileNames = new Set<string>();
|
||||||
|
for(const output of clientOutputs) {
|
||||||
|
for(const clientChunk of output.output) {
|
||||||
|
if(clientChunk.type !== 'chunk') continue;
|
||||||
|
for(const [id] of Object.entries(clientChunk.modules)) {
|
||||||
|
if(entryScripts.has(id)) {
|
||||||
|
entryFileNames.add(clientChunk.fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newCode = newCode.replace(
|
||||||
|
JSON.stringify(SCRIPTS_PLACEHOLDER),
|
||||||
|
JSON.stringify(
|
||||||
|
[...entryFileNames].map((src) => ({
|
||||||
|
props: {
|
||||||
|
src: prependForwardSlash(npath.posix.join(
|
||||||
|
options.settings.config.base,
|
||||||
|
src
|
||||||
|
)),
|
||||||
|
type: 'module'
|
||||||
|
},
|
||||||
|
children: '',
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
mutate(chunk, 'server', newCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function astroConfigBuildPlugin(internals: BuildInternals): AstroBuildPlugin {
|
|
||||||
return {
|
|
||||||
build: 'ssr',
|
|
||||||
hooks: {
|
|
||||||
'build:before': () => {
|
|
||||||
return {
|
|
||||||
vitePlugin: astroContentProdBundlePlugin({ internals }),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ export function registerAllPlugins({ internals, options, register }: AstroBuildP
|
||||||
register(pluginPages(options, internals));
|
register(pluginPages(options, internals));
|
||||||
register(pluginCSS(options, internals));
|
register(pluginCSS(options, internals));
|
||||||
register(pluginPrerender(options, internals));
|
register(pluginPrerender(options, internals));
|
||||||
register(astroConfigBuildPlugin(internals));
|
register(astroConfigBuildPlugin(options, internals));
|
||||||
register(pluginHoistedScripts(options, internals));
|
register(pluginHoistedScripts(options, internals));
|
||||||
register(pluginSSR(options, internals));
|
register(pluginSSR(options, internals));
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,7 +179,7 @@ export function pluginAnalyzer(internals: BuildInternals): AstroBuildPlugin {
|
||||||
return {
|
return {
|
||||||
vitePlugin: vitePluginAnalyzer(internals),
|
vitePlugin: vitePluginAnalyzer(internals),
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -245,9 +245,12 @@ async function runPostBuildHooks(
|
||||||
clientReturn: Awaited<ReturnType<typeof clientBuild>>
|
clientReturn: Awaited<ReturnType<typeof clientBuild>>
|
||||||
) {
|
) {
|
||||||
const mutations = await container.runPostHook(ssrReturn, clientReturn);
|
const mutations = await container.runPostHook(ssrReturn, clientReturn);
|
||||||
|
const config = container.options.settings.config;
|
||||||
const buildConfig = container.options.settings.config.build;
|
const buildConfig = container.options.settings.config.build;
|
||||||
for (const [fileName, mutation] of mutations) {
|
for (const [fileName, mutation] of mutations) {
|
||||||
const root = mutation.build === 'server' ? buildConfig.server : buildConfig.client;
|
const root = config.output === 'server' ?
|
||||||
|
mutation.build === 'server' ? buildConfig.server : buildConfig.client :
|
||||||
|
config.outDir;
|
||||||
const fileURL = new URL(fileName, root);
|
const fileURL = new URL(fileName, root);
|
||||||
await fs.promises.mkdir(new URL('./', fileURL), { recursive: true });
|
await fs.promises.mkdir(new URL('./', fileURL), { recursive: true });
|
||||||
await fs.promises.writeFile(fileURL, mutation.code, 'utf-8');
|
await fs.promises.writeFile(fileURL, mutation.code, 'utf-8');
|
||||||
|
|
|
@ -46,7 +46,7 @@ describe('Content Collections - render()', () => {
|
||||||
// Includes hoisted script
|
// Includes hoisted script
|
||||||
expect(
|
expect(
|
||||||
[...allScripts].find((script) =>
|
[...allScripts].find((script) =>
|
||||||
$(script).text().includes('document.querySelector("#update-me")')
|
$(script).attr('src')?.includes('WithScripts')
|
||||||
),
|
),
|
||||||
'`WithScripts.astro` hoisted script missing from head.'
|
'`WithScripts.astro` hoisted script missing from head.'
|
||||||
).to.not.be.undefined;
|
).to.not.be.undefined;
|
||||||
|
|
Loading…
Add table
Reference in a new issue