@opengis/vite-page

0.0.23 • Public • Published

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

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

// 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);
})
<!-- context -->
<template>
user: {{ $user }}
settings: {{ $settings }}
ssr: {{ $ssr }}
url: {{ $url }}
</template>
Server Fastify Example
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);
  }
});
vite.config.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()],
})
index.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>

Page Example

/site/pages/demo 
- page.vue
- data.js
// data.js - use backend data & function
export default function (page) {
    return { title: 1 }
}
<!-- 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>

Readme

Keywords

Package Sidebar

Install

npm i @opengis/vite-page

Weekly Downloads

39

Version

0.0.23

License

ISC

Unpacked Size

20.8 kB

Total Files

20

Last publish

Collaborators

  • evheniihavryliuk
  • andrii.cherin
  • setebosu
  • rapax.deus
  • mchernenko
  • serebasikk
  • aponasko
  • farizov_maxim
  • bohdana_usenko