renderer.mjs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. import { createRenderer, getRequestDependencies, getPreloadLinks, getPrefetchLinks } from 'file:///Users/yuxin/local/code/ccdw-website/node_modules/.pnpm/vue-bundle-renderer@2.1.1/node_modules/vue-bundle-renderer/dist/runtime.mjs';
  2. import { getResponseStatusText, getResponseStatus, getQuery, createError, appendResponseHeader } from 'file:///Users/yuxin/local/code/ccdw-website/node_modules/.pnpm/h3@1.15.3/node_modules/h3/dist/index.mjs';
  3. import { joinRelativeURL, joinURL, withoutTrailingSlash } from 'file:///Users/yuxin/local/code/ccdw-website/node_modules/.pnpm/ufo@1.6.1/node_modules/ufo/dist/index.mjs';
  4. import { renderToString } from 'file:///Users/yuxin/local/code/ccdw-website/node_modules/.pnpm/vue@3.5.14_typescript@5.8.3/node_modules/vue/server-renderer/index.mjs';
  5. import { u as useRuntimeConfig, a as useStorage, d as defineRenderHandler, g as getRouteRules, b as useNitroApp } from '../nitro/nitro.mjs';
  6. import { createHead as createHead$1, propsToString, renderSSRHead } from 'file:///Users/yuxin/local/code/ccdw-website/node_modules/.pnpm/unhead@2.0.9/node_modules/unhead/dist/server.mjs';
  7. import { stringify, uneval } from 'file:///Users/yuxin/local/code/ccdw-website/node_modules/.pnpm/devalue@5.1.1/node_modules/devalue/index.js';
  8. import { walkResolver } from 'file:///Users/yuxin/local/code/ccdw-website/node_modules/.pnpm/unhead@2.0.9/node_modules/unhead/dist/utils.mjs';
  9. import { toValue, isRef, hasInjectionContext, inject, ref, watchEffect, getCurrentInstance, onBeforeUnmount, onDeactivated, onActivated } from 'file:///Users/yuxin/local/code/ccdw-website/node_modules/.pnpm/vue@3.5.14_typescript@5.8.3/node_modules/vue/index.mjs';
  10. import { DeprecationsPlugin, PromisesPlugin, TemplateParamsPlugin, AliasSortingPlugin } from 'file:///Users/yuxin/local/code/ccdw-website/node_modules/.pnpm/unhead@2.0.9/node_modules/unhead/dist/plugins.mjs';
  11. const VueResolver = (_, value) => {
  12. return isRef(value) ? toValue(value) : value;
  13. };
  14. const headSymbol = "usehead";
  15. function vueInstall(head) {
  16. const plugin = {
  17. install(app) {
  18. app.config.globalProperties.$unhead = head;
  19. app.config.globalProperties.$head = head;
  20. app.provide(headSymbol, head);
  21. }
  22. };
  23. return plugin.install;
  24. }
  25. function injectHead() {
  26. if (hasInjectionContext()) {
  27. const instance = inject(headSymbol);
  28. if (!instance) {
  29. throw new Error("useHead() was called without provide context, ensure you call it through the setup() function.");
  30. }
  31. return instance;
  32. }
  33. throw new Error("useHead() was called without provide context, ensure you call it through the setup() function.");
  34. }
  35. function useHead(input, options = {}) {
  36. const head = options.head || injectHead();
  37. return head.ssr ? head.push(input || {}, options) : clientUseHead(head, input, options);
  38. }
  39. function clientUseHead(head, input, options = {}) {
  40. const deactivated = ref(false);
  41. let entry;
  42. watchEffect(() => {
  43. const i = deactivated.value ? {} : walkResolver(input, VueResolver);
  44. if (entry) {
  45. entry.patch(i);
  46. } else {
  47. entry = head.push(i, options);
  48. }
  49. });
  50. const vm = getCurrentInstance();
  51. if (vm) {
  52. onBeforeUnmount(() => {
  53. entry.dispose();
  54. });
  55. onDeactivated(() => {
  56. deactivated.value = true;
  57. });
  58. onActivated(() => {
  59. deactivated.value = false;
  60. });
  61. }
  62. return entry;
  63. }
  64. function createHead(options = {}) {
  65. const head = createHead$1({
  66. ...options,
  67. propResolvers: [VueResolver]
  68. });
  69. head.install = vueInstall(head);
  70. return head;
  71. }
  72. const appHead = {"meta":[{"name":"viewport","content":"width=device-width, initial-scale=1"},{"charset":"utf-8"}],"link":[],"style":[],"script":[{"src":"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9165036986914822","async":true,"crossorigin":"anonymous"}],"noscript":[]};
  73. const appRootTag = "div";
  74. const appRootAttrs = {"id":"__nuxt"};
  75. const appTeleportTag = "div";
  76. const appTeleportAttrs = {"id":"teleports"};
  77. const appId = "nuxt-app";
  78. function baseURL() {
  79. return useRuntimeConfig().app.baseURL;
  80. }
  81. function buildAssetsDir() {
  82. return useRuntimeConfig().app.buildAssetsDir;
  83. }
  84. function buildAssetsURL(...path) {
  85. return joinRelativeURL(publicAssetsURL(), buildAssetsDir(), ...path);
  86. }
  87. function publicAssetsURL(...path) {
  88. const app = useRuntimeConfig().app;
  89. const publicBase = app.cdnURL || app.baseURL;
  90. return path.length ? joinRelativeURL(publicBase, ...path) : publicBase;
  91. }
  92. const APP_ROOT_OPEN_TAG = `<${appRootTag}${propsToString(appRootAttrs)}>`;
  93. const APP_ROOT_CLOSE_TAG = `</${appRootTag}>`;
  94. const getServerEntry = () => import('../build/server.mjs').then((r) => r.default || r);
  95. const getClientManifest = () => import('../build/client.manifest.mjs').then((r) => r.default || r).then((r) => typeof r === "function" ? r() : r);
  96. const getSSRRenderer = lazyCachedFunction(async () => {
  97. const manifest = await getClientManifest();
  98. if (!manifest) {
  99. throw new Error("client.manifest is not available");
  100. }
  101. const createSSRApp = await getServerEntry();
  102. if (!createSSRApp) {
  103. throw new Error("Server bundle is not available");
  104. }
  105. const options = {
  106. manifest,
  107. renderToString: renderToString$1,
  108. buildAssetsURL
  109. };
  110. const renderer = createRenderer(createSSRApp, options);
  111. async function renderToString$1(input, context) {
  112. const html = await renderToString(input, context);
  113. return APP_ROOT_OPEN_TAG + html + APP_ROOT_CLOSE_TAG;
  114. }
  115. return renderer;
  116. });
  117. const getSPARenderer = lazyCachedFunction(async () => {
  118. const manifest = await getClientManifest();
  119. const spaTemplate = await import('../virtual/_virtual_spa-template.mjs').then((r) => r.template).catch(() => "").then((r) => {
  120. {
  121. return APP_ROOT_OPEN_TAG + r + APP_ROOT_CLOSE_TAG;
  122. }
  123. });
  124. const options = {
  125. manifest,
  126. renderToString: () => spaTemplate,
  127. buildAssetsURL
  128. };
  129. const renderer = createRenderer(() => () => {
  130. }, options);
  131. const result = await renderer.renderToString({});
  132. const renderToString = (ssrContext) => {
  133. const config = useRuntimeConfig(ssrContext.event);
  134. ssrContext.modules ||= /* @__PURE__ */ new Set();
  135. ssrContext.payload.serverRendered = false;
  136. ssrContext.config = {
  137. public: config.public,
  138. app: config.app
  139. };
  140. return Promise.resolve(result);
  141. };
  142. return {
  143. rendererContext: renderer.rendererContext,
  144. renderToString
  145. };
  146. });
  147. function lazyCachedFunction(fn) {
  148. let res = null;
  149. return () => {
  150. if (res === null) {
  151. res = fn().catch((err) => {
  152. res = null;
  153. throw err;
  154. });
  155. }
  156. return res;
  157. };
  158. }
  159. function getRenderer(ssrContext) {
  160. return ssrContext.noSSR ? getSPARenderer() : getSSRRenderer();
  161. }
  162. const getSSRStyles = lazyCachedFunction(() => import('../build/styles.mjs').then((r) => r.default || r));
  163. const getEntryIds = () => getClientManifest().then((r) => Object.values(r).filter(
  164. (r2) => (
  165. // @ts-expect-error internal key set by CSS inlining configuration
  166. r2._globalCSS
  167. )
  168. ).map((r2) => r2.src));
  169. const payloadCache = useStorage("internal:nuxt:prerender:payload") ;
  170. useStorage("internal:nuxt:prerender:island") ;
  171. useStorage("internal:nuxt:prerender:island-props") ;
  172. function renderPayloadResponse(ssrContext) {
  173. return {
  174. body: stringify(splitPayload(ssrContext).payload, ssrContext._payloadReducers) ,
  175. statusCode: getResponseStatus(ssrContext.event),
  176. statusMessage: getResponseStatusText(ssrContext.event),
  177. headers: {
  178. "content-type": "application/json;charset=utf-8" ,
  179. "x-powered-by": "Nuxt"
  180. }
  181. };
  182. }
  183. function renderPayloadJsonScript(opts) {
  184. const contents = opts.data ? stringify(opts.data, opts.ssrContext._payloadReducers) : "";
  185. const payload = {
  186. "type": "application/json",
  187. "innerHTML": contents,
  188. "data-nuxt-data": appId,
  189. "data-ssr": !(opts.ssrContext.noSSR)
  190. };
  191. {
  192. payload.id = "__NUXT_DATA__";
  193. }
  194. if (opts.src) {
  195. payload["data-src"] = opts.src;
  196. }
  197. const config = uneval(opts.ssrContext.config);
  198. return [
  199. payload,
  200. {
  201. innerHTML: `window.__NUXT__={};window.__NUXT__.config=${config}`
  202. }
  203. ];
  204. }
  205. function splitPayload(ssrContext) {
  206. const { data, prerenderedAt, ...initial } = ssrContext.payload;
  207. return {
  208. initial: { ...initial, prerenderedAt },
  209. payload: { data, prerenderedAt }
  210. };
  211. }
  212. const unheadOptions = {
  213. disableDefaults: true,
  214. disableCapoSorting: false,
  215. plugins: [DeprecationsPlugin, PromisesPlugin, TemplateParamsPlugin, AliasSortingPlugin],
  216. };
  217. const PRERENDER_NO_SSR_ROUTES = /* @__PURE__ */ new Set(["/index.html", "/200.html", "/404.html"]);
  218. function createSSRContext(event) {
  219. const ssrContext = {
  220. url: event.path,
  221. event,
  222. runtimeConfig: useRuntimeConfig(event),
  223. noSSR: event.context.nuxt?.noSSR || (PRERENDER_NO_SSR_ROUTES.has(event.path) ),
  224. head: createHead(unheadOptions),
  225. error: false,
  226. nuxt: void 0,
  227. /* NuxtApp */
  228. payload: {},
  229. _payloadReducers: /* @__PURE__ */ Object.create(null),
  230. modules: /* @__PURE__ */ new Set()
  231. };
  232. {
  233. ssrContext.payload.prerenderedAt = Date.now();
  234. }
  235. return ssrContext;
  236. }
  237. function setSSRError(ssrContext, error) {
  238. ssrContext.error = true;
  239. ssrContext.payload = { error };
  240. ssrContext.url = error.url;
  241. }
  242. async function renderInlineStyles(usedModules) {
  243. const styleMap = await getSSRStyles();
  244. const inlinedStyles = /* @__PURE__ */ new Set();
  245. for (const mod of usedModules) {
  246. if (mod in styleMap && styleMap[mod]) {
  247. for (const style of await styleMap[mod]()) {
  248. inlinedStyles.add(style);
  249. }
  250. }
  251. }
  252. return Array.from(inlinedStyles).map((style) => ({ innerHTML: style }));
  253. }
  254. const renderSSRHeadOptions = {"omitLineBreaks":false};
  255. globalThis.__buildAssetsURL = buildAssetsURL;
  256. globalThis.__publicAssetsURL = publicAssetsURL;
  257. const HAS_APP_TELEPORTS = !!(appTeleportAttrs.id);
  258. const APP_TELEPORT_OPEN_TAG = HAS_APP_TELEPORTS ? `<${appTeleportTag}${propsToString(appTeleportAttrs)}>` : "";
  259. const APP_TELEPORT_CLOSE_TAG = HAS_APP_TELEPORTS ? `</${appTeleportTag}>` : "";
  260. const PAYLOAD_URL_RE = /^[^?]*\/_payload.json(?:\?.*)?$/ ;
  261. const PAYLOAD_FILENAME = "_payload.json" ;
  262. const renderer = defineRenderHandler(async (event) => {
  263. const nitroApp = useNitroApp();
  264. const ssrError = event.path.startsWith("/__nuxt_error") ? getQuery(event) : null;
  265. if (ssrError && !("__unenv__" in event.node.req)) {
  266. throw createError({
  267. statusCode: 404,
  268. statusMessage: "Page Not Found: /__nuxt_error"
  269. });
  270. }
  271. const ssrContext = createSSRContext(event);
  272. const headEntryOptions = { mode: "server" };
  273. ssrContext.head.push(appHead, headEntryOptions);
  274. if (ssrError) {
  275. ssrError.statusCode &&= Number.parseInt(ssrError.statusCode);
  276. setSSRError(ssrContext, ssrError);
  277. }
  278. const isRenderingPayload = PAYLOAD_URL_RE.test(ssrContext.url);
  279. if (isRenderingPayload) {
  280. const url = ssrContext.url.substring(0, ssrContext.url.lastIndexOf("/")) || "/";
  281. ssrContext.url = url;
  282. event._path = event.node.req.url = url;
  283. if (await payloadCache.hasItem(url)) {
  284. return payloadCache.getItem(url);
  285. }
  286. }
  287. const routeOptions = getRouteRules(event);
  288. if (routeOptions.ssr === false) {
  289. ssrContext.noSSR = true;
  290. }
  291. const _PAYLOAD_EXTRACTION = !ssrContext.noSSR;
  292. const payloadURL = _PAYLOAD_EXTRACTION ? joinURL(ssrContext.runtimeConfig.app.cdnURL || ssrContext.runtimeConfig.app.baseURL, ssrContext.url.replace(/\?.*$/, ""), PAYLOAD_FILENAME) + "?" + ssrContext.runtimeConfig.app.buildId : void 0;
  293. const renderer = await getRenderer(ssrContext);
  294. {
  295. for (const id of await getEntryIds()) {
  296. ssrContext.modules.add(id);
  297. }
  298. }
  299. const _rendered = await renderer.renderToString(ssrContext).catch(async (error) => {
  300. if (ssrContext._renderResponse && error.message === "skipping render") {
  301. return {};
  302. }
  303. const _err = !ssrError && ssrContext.payload?.error || error;
  304. await ssrContext.nuxt?.hooks.callHook("app:error", _err);
  305. throw _err;
  306. });
  307. const inlinedStyles = !ssrContext._renderResponse && !isRenderingPayload ? await renderInlineStyles(ssrContext.modules ?? []) : [];
  308. await ssrContext.nuxt?.hooks.callHook("app:rendered", { ssrContext, renderResult: _rendered });
  309. if (ssrContext._renderResponse) {
  310. return ssrContext._renderResponse;
  311. }
  312. if (ssrContext.payload?.error && !ssrError) {
  313. throw ssrContext.payload.error;
  314. }
  315. if (isRenderingPayload) {
  316. const response = renderPayloadResponse(ssrContext);
  317. {
  318. await payloadCache.setItem(ssrContext.url, response);
  319. }
  320. return response;
  321. }
  322. if (_PAYLOAD_EXTRACTION) {
  323. appendResponseHeader(event, "x-nitro-prerender", joinURL(ssrContext.url.replace(/\?.*$/, ""), PAYLOAD_FILENAME));
  324. await payloadCache.setItem(withoutTrailingSlash(ssrContext.url), renderPayloadResponse(ssrContext));
  325. }
  326. const NO_SCRIPTS = routeOptions.noScripts;
  327. const { styles, scripts } = getRequestDependencies(ssrContext, renderer.rendererContext);
  328. if (_PAYLOAD_EXTRACTION && !NO_SCRIPTS) {
  329. ssrContext.head.push({
  330. link: [
  331. { rel: "preload", as: "fetch", crossorigin: "anonymous", href: payloadURL }
  332. ]
  333. }, headEntryOptions);
  334. }
  335. if (ssrContext._preloadManifest && !NO_SCRIPTS) {
  336. ssrContext.head.push({
  337. link: [
  338. { rel: "preload", as: "fetch", fetchpriority: "low", crossorigin: "anonymous", href: buildAssetsURL(`builds/meta/${ssrContext.runtimeConfig.app.buildId}.json`) }
  339. ]
  340. }, { ...headEntryOptions, tagPriority: "low" });
  341. }
  342. if (inlinedStyles.length) {
  343. ssrContext.head.push({ style: inlinedStyles });
  344. }
  345. const link = [];
  346. for (const resource of Object.values(styles)) {
  347. link.push({ rel: "stylesheet", href: renderer.rendererContext.buildAssetsURL(resource.file), crossorigin: "" });
  348. }
  349. if (link.length) {
  350. ssrContext.head.push({ link }, headEntryOptions);
  351. }
  352. if (!NO_SCRIPTS) {
  353. ssrContext.head.push({
  354. link: getPreloadLinks(ssrContext, renderer.rendererContext)
  355. }, headEntryOptions);
  356. ssrContext.head.push({
  357. link: getPrefetchLinks(ssrContext, renderer.rendererContext)
  358. }, headEntryOptions);
  359. ssrContext.head.push({
  360. script: _PAYLOAD_EXTRACTION ? renderPayloadJsonScript({ ssrContext, data: splitPayload(ssrContext).initial, src: payloadURL }) : renderPayloadJsonScript({ ssrContext, data: ssrContext.payload })
  361. }, {
  362. ...headEntryOptions,
  363. // this should come before another end of body scripts
  364. tagPosition: "bodyClose",
  365. tagPriority: "high"
  366. });
  367. }
  368. if (!routeOptions.noScripts) {
  369. ssrContext.head.push({
  370. script: Object.values(scripts).map((resource) => ({
  371. type: resource.module ? "module" : null,
  372. src: renderer.rendererContext.buildAssetsURL(resource.file),
  373. defer: resource.module ? null : true,
  374. // if we are rendering script tag payloads that import an async payload
  375. // we need to ensure this resolves before executing the Nuxt entry
  376. tagPosition: "head",
  377. crossorigin: ""
  378. }))
  379. }, headEntryOptions);
  380. }
  381. const { headTags, bodyTags, bodyTagsOpen, htmlAttrs, bodyAttrs } = await renderSSRHead(ssrContext.head, renderSSRHeadOptions);
  382. const htmlContext = {
  383. htmlAttrs: htmlAttrs ? [htmlAttrs] : [],
  384. head: normalizeChunks([headTags]),
  385. bodyAttrs: bodyAttrs ? [bodyAttrs] : [],
  386. bodyPrepend: normalizeChunks([bodyTagsOpen, ssrContext.teleports?.body]),
  387. body: [
  388. _rendered.html,
  389. APP_TELEPORT_OPEN_TAG + (HAS_APP_TELEPORTS ? joinTags([ssrContext.teleports?.[`#${appTeleportAttrs.id}`]]) : "") + APP_TELEPORT_CLOSE_TAG
  390. ],
  391. bodyAppend: [bodyTags]
  392. };
  393. await nitroApp.hooks.callHook("render:html", htmlContext, { event });
  394. return {
  395. body: renderHTMLDocument(htmlContext),
  396. statusCode: getResponseStatus(event),
  397. statusMessage: getResponseStatusText(event),
  398. headers: {
  399. "content-type": "text/html;charset=utf-8",
  400. "x-powered-by": "Nuxt"
  401. }
  402. };
  403. });
  404. function normalizeChunks(chunks) {
  405. return chunks.filter(Boolean).map((i) => i.trim());
  406. }
  407. function joinTags(tags) {
  408. return tags.join("");
  409. }
  410. function joinAttrs(chunks) {
  411. if (chunks.length === 0) {
  412. return "";
  413. }
  414. return " " + chunks.join(" ");
  415. }
  416. function renderHTMLDocument(html) {
  417. return `<!DOCTYPE html><html${joinAttrs(html.htmlAttrs)}><head>${joinTags(html.head)}</head><body${joinAttrs(html.bodyAttrs)}>${joinTags(html.bodyPrepend)}${joinTags(html.body)}${joinTags(html.bodyAppend)}</body></html>`;
  418. }
  419. const renderer$1 = /*#__PURE__*/Object.freeze({
  420. __proto__: null,
  421. default: renderer
  422. });
  423. export { buildAssetsURL as a, baseURL as b, headSymbol as h, renderer$1 as r, useHead as u };
  424. //# sourceMappingURL=renderer.mjs.map