193 lines
7.1 KiB
JavaScript
193 lines
7.1 KiB
JavaScript
![]() |
import { extname } from "node:path";
|
||
|
import { pathToFileURL } from "node:url";
|
||
|
import { moduleIsTopLevelPage, walkParentInfos } from "../core/build/graph.js";
|
||
|
import { getPageDataByViteID } from "../core/build/internal.js";
|
||
|
import { createViteLoader } from "../core/module-loader/vite.js";
|
||
|
import { joinPaths, prependForwardSlash } from "../core/path.js";
|
||
|
import { getStylesForURL } from "../core/render/dev/css.js";
|
||
|
import { getScriptsForURL } from "../core/render/dev/scripts.js";
|
||
|
import {
|
||
|
CONTENT_RENDER_FLAG,
|
||
|
LINKS_PLACEHOLDER,
|
||
|
PROPAGATED_ASSET_FLAG,
|
||
|
SCRIPTS_PLACEHOLDER,
|
||
|
STYLES_PLACEHOLDER
|
||
|
} from "./consts.js";
|
||
|
import { hasContentFlag } from "./utils.js";
|
||
|
function astroContentAssetPropagationPlugin({
|
||
|
mode,
|
||
|
settings
|
||
|
}) {
|
||
|
let devModuleLoader;
|
||
|
return {
|
||
|
name: "astro:content-asset-propagation",
|
||
|
enforce: "pre",
|
||
|
async resolveId(id, importer, opts) {
|
||
|
if (hasContentFlag(id, CONTENT_RENDER_FLAG)) {
|
||
|
const base = id.split("?")[0];
|
||
|
for (const { extensions, handlePropagation = true } of settings.contentEntryTypes) {
|
||
|
if (handlePropagation && extensions.includes(extname(base))) {
|
||
|
return this.resolve(`${base}?${PROPAGATED_ASSET_FLAG}`, importer, {
|
||
|
skipSelf: true,
|
||
|
...opts
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
return this.resolve(base, importer, { skipSelf: true, ...opts });
|
||
|
}
|
||
|
},
|
||
|
configureServer(server) {
|
||
|
if (mode === "dev") {
|
||
|
devModuleLoader = createViteLoader(server);
|
||
|
}
|
||
|
},
|
||
|
async transform(_, id, options) {
|
||
|
var _a;
|
||
|
if (hasContentFlag(id, PROPAGATED_ASSET_FLAG)) {
|
||
|
const basePath = id.split("?")[0];
|
||
|
let stringifiedLinks, stringifiedStyles, stringifiedScripts;
|
||
|
if ((options == null ? void 0 : options.ssr) && devModuleLoader) {
|
||
|
if (!((_a = devModuleLoader.getModuleById(basePath)) == null ? void 0 : _a.ssrModule)) {
|
||
|
await devModuleLoader.import(basePath);
|
||
|
}
|
||
|
const { stylesMap, urls } = await getStylesForURL(
|
||
|
pathToFileURL(basePath),
|
||
|
devModuleLoader,
|
||
|
"development"
|
||
|
);
|
||
|
const hoistedScripts = await getScriptsForURL(
|
||
|
pathToFileURL(basePath),
|
||
|
settings.config.root,
|
||
|
devModuleLoader
|
||
|
);
|
||
|
stringifiedLinks = JSON.stringify([...urls]);
|
||
|
stringifiedStyles = JSON.stringify([...stylesMap.values()]);
|
||
|
stringifiedScripts = JSON.stringify([...hoistedScripts]);
|
||
|
} else {
|
||
|
stringifiedLinks = JSON.stringify(LINKS_PLACEHOLDER);
|
||
|
stringifiedStyles = JSON.stringify(STYLES_PLACEHOLDER);
|
||
|
stringifiedScripts = JSON.stringify(SCRIPTS_PLACEHOLDER);
|
||
|
}
|
||
|
const code = `
|
||
|
async function getMod() {
|
||
|
return import(${JSON.stringify(basePath)});
|
||
|
}
|
||
|
const collectedLinks = ${stringifiedLinks};
|
||
|
const collectedStyles = ${stringifiedStyles};
|
||
|
const collectedScripts = ${stringifiedScripts};
|
||
|
const defaultMod = { __astroPropagation: true, getMod, collectedLinks, collectedStyles, collectedScripts };
|
||
|
export default defaultMod;
|
||
|
`;
|
||
|
return { code, map: { mappings: "" } };
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
function astroConfigBuildPlugin(options, internals) {
|
||
|
let ssrPluginContext = void 0;
|
||
|
return {
|
||
|
build: "ssr",
|
||
|
hooks: {
|
||
|
"build:before": ({ build }) => {
|
||
|
return {
|
||
|
vitePlugin: {
|
||
|
name: "astro:content-build-plugin",
|
||
|
generateBundle() {
|
||
|
if (build === "ssr") {
|
||
|
ssrPluginContext = this;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
},
|
||
|
"build:post": ({ ssrOutputs, clientOutputs, mutate }) => {
|
||
|
var _a, _b;
|
||
|
const outputs = ssrOutputs.flatMap((o) => o.output);
|
||
|
const prependBase = (src) => {
|
||
|
if (options.settings.config.build.assetsPrefix) {
|
||
|
return joinPaths(options.settings.config.build.assetsPrefix, src);
|
||
|
} else {
|
||
|
return prependForwardSlash(joinPaths(options.settings.config.base, src));
|
||
|
}
|
||
|
};
|
||
|
for (const chunk of outputs) {
|
||
|
if (chunk.type === "chunk" && (chunk.code.includes(LINKS_PLACEHOLDER) || chunk.code.includes(SCRIPTS_PLACEHOLDER))) {
|
||
|
let entryStyles = /* @__PURE__ */ new Set();
|
||
|
let entryLinks = /* @__PURE__ */ new Set();
|
||
|
let entryScripts = /* @__PURE__ */ new Set();
|
||
|
for (const id of Object.keys(chunk.modules)) {
|
||
|
for (const [pageInfo] of walkParentInfos(id, ssrPluginContext)) {
|
||
|
if (moduleIsTopLevelPage(pageInfo)) {
|
||
|
const pageViteID = pageInfo.id;
|
||
|
const pageData = getPageDataByViteID(internals, pageViteID);
|
||
|
if (!pageData)
|
||
|
continue;
|
||
|
const _entryCss = (_a = pageData.propagatedStyles) == null ? void 0 : _a.get(id);
|
||
|
const _entryScripts = (_b = pageData.propagatedScripts) == null ? void 0 : _b.get(id);
|
||
|
if (_entryCss) {
|
||
|
for (const value of _entryCss) {
|
||
|
if (value.type === "inline")
|
||
|
entryStyles.add(value.content);
|
||
|
if (value.type === "external")
|
||
|
entryLinks.add(value.src);
|
||
|
}
|
||
|
}
|
||
|
if (_entryScripts) {
|
||
|
for (const value of _entryScripts) {
|
||
|
entryScripts.add(value);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
let newCode = chunk.code;
|
||
|
if (entryStyles.size) {
|
||
|
newCode = newCode.replace(
|
||
|
JSON.stringify(STYLES_PLACEHOLDER),
|
||
|
JSON.stringify(Array.from(entryStyles))
|
||
|
);
|
||
|
}
|
||
|
if (entryLinks.size) {
|
||
|
newCode = newCode.replace(
|
||
|
JSON.stringify(LINKS_PLACEHOLDER),
|
||
|
JSON.stringify(Array.from(entryLinks).map(prependBase))
|
||
|
);
|
||
|
}
|
||
|
if (entryScripts.size) {
|
||
|
const entryFileNames = /* @__PURE__ */ new Set();
|
||
|
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: prependBase(src),
|
||
|
type: "module"
|
||
|
},
|
||
|
children: ""
|
||
|
}))
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
mutate(chunk, "server", newCode);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
export {
|
||
|
astroConfigBuildPlugin,
|
||
|
astroContentAssetPropagationPlugin
|
||
|
};
|