UNPKG

@opengis/vite-page

Version:

Vite SSR Multi Page plugin

198 lines (161 loc) 4.35 kB
# Vite Page Multi page ssr vite plugin based on folder - using pinia, vue-router, vite ## Features - auto routing based on file structure - backend data preload - nested route - flexible by design - high perfomance ## Structure ```bash site # root vite folder - pages/ - demo/ # /demo - page.vue # vue page component - data.js # backend data optional - news+id/ # /news/:id? - page.vue # vue page component - data.js # backend data optional - src/ - main.js # main app, use 3d party library - App.vue # Root Component - vite.config.js - index.html # main page ``` > Demo in git examples directory ## Usage `npm i @opengis/vite-page` ```js // server.js import renderPage from '@opengis/vite-mpa/renderPage.js'; fastify.get('*', async (req, reply) => { const url = req.originalUrl; const html = await renderPage({ url, vite, page: {}, // {{ page }} optional template: 'news', // pages template name optional seo: { title: page?.title, meta: { description: 'my description', keywords: 'my keywords' } }, // seo title + meta optional root: 'site', ctx: { user: null, settings: {}} }) reply.headers({ 'Cache-Control': 'public, no-cache' }) .type('text/html') .send(html); }) ``` ```vue <!-- context --> <template> user: {{ $user }} settings: {{ $settings }} ssr: {{ $ssr }} url: {{ $url }} </template> ```` <details> <summary>Server Fastify Example</summary> ```js import fs from 'node:fs' import path from 'node:path' import Fastify from 'fastify'; import { createServer as createViteServer, defineConfig } from 'vite'; import renderPage from '@opengis/vite-mpa/renderPage.js'; const fastify = Fastify(); const isProd = process.env.NODE_ENV === 'production'; const vite = !isProd ? await createViteServer({ root: 'site', server: { middlewareMode: true }, }) : null; fastify.addHook('onRequest', async (req, reply) => { if (isProd) return; // const { user } = req.session?.passport || {}; const next = () => new Promise((resolve) => { vite.middlewares(req.raw, reply.raw, () => resolve()); }); await next(); }); fastify.get('/assets/:file', async (req, reply) => { const stream = fs.createReadStream(`site/dist/client/assets/${req.params.file}`); return stream; }); fastify.get('*', async (req, reply) => { const url = req.originalUrl; const html = await renderPage({ url, vite, root: 'site' }) reply.headers({ 'Cache-Control': 'public, no-cache' }) .type('text/html') .send(html); }) fastify.listen({ host: '0.0.0.0', port: process.env.PORT || 3000 }, (err) => { if (err) { fastify.log.error(err); process.exit(1); } }); ``` </details> <details> <summary>vite.config.js</summary> ```js import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import cms from '@opengis/vite-page/plugin.js'; export default defineConfig({ plugins: [vue(), cms()], }) ``` </details> <details> <summary>index.html</summary> ```html <!DOCTYPE html> <html ${htmlAttrs}> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <!--head-tags--> <!--preload-links--> </head> <body ${bodyAttrs}> <div id="app"><!--app-html--></div> <script>window.__pinia = {};</script> <script type="module" src="/src/entry-client.js"></script> </body> </html> ``` </details> ## Page Example ```bash /site/pages/demo - page.vue - data.js ``` ```js // data.js - use backend data & function export default function (page) { return { title: 1 } } ``` ```vue <!-- page.vue --> <script lang="js"> import { computed, defineComponent, reactive } from "vue"; import { useStore } from "/src/store.js"; export default defineComponent({ name: "Demo", setup() { const store = useStore(); const title = computed(() => store.data.title); const state = reactive({ count: 0 }); return { state, title }; }, }); </script> <template> <h1 class="title">DEMO {{ title }}</h1> <button @click="state.count++">count is: {{ state.count }}</button> </template> ```