237 lines
8.2 KiB
Plaintext
237 lines
8.2 KiB
Plaintext
|
import { join } from "node:path";
|
||
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
||
|
import { isFunctionPerRouteEnabled } from "../../../integrations/index.js";
|
||
|
import { isServerLikeOutput } from "../../../prerender/utils.js";
|
||
|
import { routeIsRedirect } from "../../redirects/index.js";
|
||
|
import { addRollupInput } from "../add-rollup-input.js";
|
||
|
import { eachPageFromAllPages } from "../internal.js";
|
||
|
import { SSR_MANIFEST_VIRTUAL_MODULE_ID } from "./plugin-manifest.js";
|
||
|
import { ASTRO_PAGE_MODULE_ID } from "./plugin-pages.js";
|
||
|
import { RENDERERS_MODULE_ID } from "./plugin-renderers.js";
|
||
|
import { getPathFromVirtualModulePageName, getVirtualModulePageNameFromPath } from "./util.js";
|
||
|
const SSR_VIRTUAL_MODULE_ID = "@astrojs-ssr-virtual-entry";
|
||
|
const RESOLVED_SSR_VIRTUAL_MODULE_ID = "\0" + SSR_VIRTUAL_MODULE_ID;
|
||
|
function vitePluginSSR(internals, adapter, options) {
|
||
|
return {
|
||
|
name: "@astrojs/vite-plugin-astro-ssr-server",
|
||
|
enforce: "post",
|
||
|
options(opts) {
|
||
|
return addRollupInput(opts, [SSR_VIRTUAL_MODULE_ID]);
|
||
|
},
|
||
|
resolveId(id) {
|
||
|
if (id === SSR_VIRTUAL_MODULE_ID) {
|
||
|
return RESOLVED_SSR_VIRTUAL_MODULE_ID;
|
||
|
}
|
||
|
},
|
||
|
async load(id) {
|
||
|
if (id === RESOLVED_SSR_VIRTUAL_MODULE_ID) {
|
||
|
const { allPages } = options;
|
||
|
const imports = [];
|
||
|
const contents = [];
|
||
|
const exports = [];
|
||
|
let i = 0;
|
||
|
const pageMap = [];
|
||
|
for (const [path, pageData] of eachPageFromAllPages(allPages)) {
|
||
|
if (routeIsRedirect(pageData.route)) {
|
||
|
continue;
|
||
|
}
|
||
|
const virtualModuleName = getVirtualModulePageNameFromPath(ASTRO_PAGE_MODULE_ID, path);
|
||
|
let module = await this.resolve(virtualModuleName);
|
||
|
if (module) {
|
||
|
const variable = `_page${i}`;
|
||
|
imports.push(`const ${variable} = () => import("${virtualModuleName}");`);
|
||
|
const pageData2 = internals.pagesByComponent.get(path);
|
||
|
if (pageData2) {
|
||
|
pageMap.push(`[${JSON.stringify(pageData2.component)}, ${variable}]`);
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
contents.push(`const pageMap = new Map([${pageMap.join(",")}]);`);
|
||
|
exports.push(`export { pageMap }`);
|
||
|
const ssrCode = generateSSRCode(options.settings.config, adapter);
|
||
|
imports.push(...ssrCode.imports);
|
||
|
contents.push(...ssrCode.contents);
|
||
|
return `${imports.join("\n")}${contents.join("\n")}${exports.join("\n")}`;
|
||
|
}
|
||
|
return void 0;
|
||
|
},
|
||
|
async generateBundle(_opts, bundle) {
|
||
|
for (const [, chunk] of Object.entries(bundle)) {
|
||
|
if (chunk.type === "asset") {
|
||
|
internals.staticFiles.add(chunk.fileName);
|
||
|
}
|
||
|
}
|
||
|
for (const [, chunk] of Object.entries(bundle)) {
|
||
|
if (chunk.type === "asset") {
|
||
|
continue;
|
||
|
}
|
||
|
if (chunk.modules[RESOLVED_SSR_VIRTUAL_MODULE_ID]) {
|
||
|
internals.ssrEntryChunk = chunk;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
function pluginSSR(options, internals) {
|
||
|
const ssr = isServerLikeOutput(options.settings.config);
|
||
|
const functionPerRouteEnabled = isFunctionPerRouteEnabled(options.settings.adapter);
|
||
|
return {
|
||
|
targets: ["server"],
|
||
|
hooks: {
|
||
|
"build:before": () => {
|
||
|
let vitePlugin = ssr && functionPerRouteEnabled === false ? vitePluginSSR(internals, options.settings.adapter, options) : void 0;
|
||
|
return {
|
||
|
enforce: "after-user-plugins",
|
||
|
vitePlugin
|
||
|
};
|
||
|
},
|
||
|
"build:post": async () => {
|
||
|
if (!ssr) {
|
||
|
return;
|
||
|
}
|
||
|
if (functionPerRouteEnabled) {
|
||
|
return;
|
||
|
}
|
||
|
if (!internals.ssrEntryChunk) {
|
||
|
throw new Error(`Did not generate an entry chunk for SSR`);
|
||
|
}
|
||
|
internals.ssrEntryChunk.fileName = options.settings.config.build.serverEntry;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
const SPLIT_MODULE_ID = "@astro-page-split:";
|
||
|
const RESOLVED_SPLIT_MODULE_ID = "\0@astro-page-split:";
|
||
|
function vitePluginSSRSplit(internals, adapter, options) {
|
||
|
const functionPerRouteEnabled = isFunctionPerRouteEnabled(options.settings.adapter);
|
||
|
return {
|
||
|
name: "@astrojs/vite-plugin-astro-ssr-split",
|
||
|
enforce: "post",
|
||
|
options(opts) {
|
||
|
if (functionPerRouteEnabled) {
|
||
|
const inputs = /* @__PURE__ */ new Set();
|
||
|
for (const [path, pageData] of eachPageFromAllPages(options.allPages)) {
|
||
|
if (routeIsRedirect(pageData.route)) {
|
||
|
continue;
|
||
|
}
|
||
|
inputs.add(getVirtualModulePageNameFromPath(SPLIT_MODULE_ID, path));
|
||
|
}
|
||
|
return addRollupInput(opts, Array.from(inputs));
|
||
|
}
|
||
|
},
|
||
|
resolveId(id) {
|
||
|
if (id.startsWith(SPLIT_MODULE_ID)) {
|
||
|
return "\0" + id;
|
||
|
}
|
||
|
},
|
||
|
async load(id) {
|
||
|
if (id.startsWith(RESOLVED_SPLIT_MODULE_ID)) {
|
||
|
const imports = [];
|
||
|
const contents = [];
|
||
|
const exports = [];
|
||
|
const path = getPathFromVirtualModulePageName(RESOLVED_SPLIT_MODULE_ID, id);
|
||
|
const virtualModuleName = getVirtualModulePageNameFromPath(ASTRO_PAGE_MODULE_ID, path);
|
||
|
let module = await this.resolve(virtualModuleName);
|
||
|
if (module) {
|
||
|
imports.push(`import * as pageModule from "${virtualModuleName}";`);
|
||
|
}
|
||
|
const ssrCode = generateSSRCode(options.settings.config, adapter);
|
||
|
imports.push(...ssrCode.imports);
|
||
|
contents.push(...ssrCode.contents);
|
||
|
exports.push("export { pageModule }");
|
||
|
return `${imports.join("\n")}${contents.join("\n")}${exports.join("\n")}`;
|
||
|
}
|
||
|
return void 0;
|
||
|
},
|
||
|
async generateBundle(_opts, bundle) {
|
||
|
for (const [, chunk] of Object.entries(bundle)) {
|
||
|
if (chunk.type === "asset") {
|
||
|
internals.staticFiles.add(chunk.fileName);
|
||
|
}
|
||
|
}
|
||
|
for (const [, chunk] of Object.entries(bundle)) {
|
||
|
if (chunk.type === "asset") {
|
||
|
continue;
|
||
|
}
|
||
|
for (const moduleKey of Object.keys(chunk.modules)) {
|
||
|
if (moduleKey.startsWith(RESOLVED_SPLIT_MODULE_ID)) {
|
||
|
internals.ssrSplitEntryChunks.set(moduleKey, chunk);
|
||
|
storeEntryPoint(moduleKey, options, internals, chunk.fileName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
function pluginSSRSplit(options, internals) {
|
||
|
const ssr = isServerLikeOutput(options.settings.config);
|
||
|
const functionPerRouteEnabled = isFunctionPerRouteEnabled(options.settings.adapter);
|
||
|
return {
|
||
|
targets: ["server"],
|
||
|
hooks: {
|
||
|
"build:before": () => {
|
||
|
let vitePlugin = ssr && functionPerRouteEnabled ? vitePluginSSRSplit(internals, options.settings.adapter, options) : void 0;
|
||
|
return {
|
||
|
enforce: "after-user-plugins",
|
||
|
vitePlugin
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
function generateSSRCode(config, adapter) {
|
||
|
const imports = [];
|
||
|
const contents = [];
|
||
|
let pageMap;
|
||
|
if (isFunctionPerRouteEnabled(adapter)) {
|
||
|
pageMap = "pageModule";
|
||
|
} else {
|
||
|
pageMap = "pageMap";
|
||
|
}
|
||
|
contents.push(`import * as adapter from '${adapter.serverEntrypoint}';
|
||
|
import { renderers } from '${RENDERERS_MODULE_ID}';
|
||
|
import { manifest as defaultManifest} from '${SSR_MANIFEST_VIRTUAL_MODULE_ID}';
|
||
|
const _manifest = Object.assign(defaultManifest, {
|
||
|
${pageMap},
|
||
|
renderers,
|
||
|
});
|
||
|
const _args = ${adapter.args ? JSON.stringify(adapter.args) : "undefined"};
|
||
|
|
||
|
${adapter.exports ? `const _exports = adapter.createExports(_manifest, _args);
|
||
|
${adapter.exports.map((name) => {
|
||
|
if (name === "default") {
|
||
|
return `const _default = _exports['default'];
|
||
|
export { _default as default };`;
|
||
|
} else {
|
||
|
return `export const ${name} = _exports['${name}'];`;
|
||
|
}
|
||
|
}).join("\n")}
|
||
|
` : ""}
|
||
|
const _start = 'start';
|
||
|
if(_start in adapter) {
|
||
|
adapter[_start](_manifest, _args);
|
||
|
}`);
|
||
|
return {
|
||
|
imports,
|
||
|
contents
|
||
|
};
|
||
|
}
|
||
|
function storeEntryPoint(moduleKey, options, internals, fileName) {
|
||
|
const componentPath = getPathFromVirtualModulePageName(RESOLVED_SPLIT_MODULE_ID, moduleKey);
|
||
|
for (const [page, pageData] of eachPageFromAllPages(options.allPages)) {
|
||
|
if (componentPath == page) {
|
||
|
const publicPath = fileURLToPath(options.settings.config.build.server);
|
||
|
internals.entryPoints.set(pageData.route, pathToFileURL(join(publicPath, fileName)));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
export {
|
||
|
RESOLVED_SPLIT_MODULE_ID,
|
||
|
RESOLVED_SSR_VIRTUAL_MODULE_ID,
|
||
|
SPLIT_MODULE_ID,
|
||
|
SSR_VIRTUAL_MODULE_ID,
|
||
|
pluginSSR,
|
||
|
pluginSSRSplit
|
||
|
};
|