@opengis/vite-page
Version:
Vite SSR Multi Page plugin
92 lines (71 loc) • 3.52 kB
JavaScript
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.
}