UNPKG

@opengis/vite-page

Version:

Vite SSR Multi Page plugin

92 lines (71 loc) 3.52 kB
import fs from 'node:fs'; import path from 'node:path'; import url from "url"; import { config, clean2originalUrl, applyHook } from './utils.js'; const root = process.cwd(); const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); async function getData(route, ctx) { const fileData = config.root + `/pages/${route.name}/data.js`; const check = config.files.find(el => el.includes(route.name) && el.includes('data.js')); if (!check) return; const { default: fn } = await import('file://' + path.join(root, fileData)); const data = await fn({ ...route, ...ctx }); return data; } export default async function renderPage({ url: originalUrl, vite, data: dataOrigin, root: rootOriginal, ctx = {}, page, seo, template: t1 }) { if (originalUrl === '/favicon.ico') return ''; const viteRoot = rootOriginal || config.root; // preambles from @vitejs/plugin-react const indexFile = vite && fs.existsSync(viteRoot + '/index.html') ? viteRoot + '/index.html' : __dirname + '/src/index.html'; const templateHTML = !vite ? fs.readFileSync('./' + viteRoot + '/dist/client/index.html', 'utf-8') : await vite.transformIndexHtml(originalUrl, fs.readFileSync(indexFile, 'utf-8')); // required, and provides efficient invalidation similar to HMR. const { render, getRoute, routes } = !vite ? await import('file://' + root + '/' + viteRoot + '/dist/server/entry-server.js') : await vite.ssrLoadModule('/src/entry-server.js'); // check config.routes //const jsonRoute = config.routes?.find(el => el.path == decodeURIComponent(originalUrl.substring(1))); // clean URL // const r1 = /*jsonRoute ||*/ await getRoute(originalUrl); const url = originalUrl; // get Route const route = await getRoute(dataOrigin?.template || t1 || url, true); // detect Template const template = t1 || route.name; // hook const hookData = dataOrigin || await applyHook('preRender', { url, route }) || {}; // settings const setting = config.files.find(el => el.includes(route.name + '/setting.json')) const settingData = setting ? JSON.parse(fs.readFileSync(config.root + `/pages/${route.name}/setting.json`)) : null; // ctx Object.assign(ctx, { originalUrl, url, path: url.split('?')[0], query: route.query, template }); // data route.setting = settingData || dataOrigin || {}; const data = route?.name ? await getData(route, ctx) || {} : {}; try { const { html: appHtml, preloadLinks, headTags, htmlAttrs, bodyAttrs, initialState, } = await render({ url, template, data, ctx, page, seo, ...settingData, ...hookData }) // 5. Inject the app-rendered HTML into the template. const html = templateHTML.replace(`<!--ssr-outlet-->`, () => appHtml) .replace('<!--head-tags-->', headTags) .replace(' ${htmlAttrs}', htmlAttrs) .replace(' ${bodyAttrs}', bodyAttrs) .replace('<!--preload-links-->', preloadLinks) .replace('<!--app-html-->', appHtml) .replace('window.__pinia = {};', `window.__pinia = ${initialState}; window.ctx=${JSON.stringify(ctx)}`) return html; } catch (err) { console.log(err); return "server error"; } // 6. Send the rendered HTML back. }