Skip to content

Commit

Permalink
docs: Update docs and improve example API
Browse files Browse the repository at this point in the history
  • Loading branch information
frandiox committed Feb 12, 2021
1 parent ac1931c commit eefde90
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 24 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Create a normal [Vite](https://github.com/vitejs/vite) app.
1. Add `vite-ssr` with your package manager (direct dependency).
2. Import `vite-ssr/plugin.js` in your `vite.config.js` file (see [`vite.config.js`](./example/vite.config.js) for an example).
3. You can import `vite-ssr/entry-client.js` or `vite-ssr/entry-server.js` depending on you environment. Or you can directly import from `vite-ssr` to get the corresponding handler according to the running environment (client or server). See an example in [`main.js`](./example/src/main.js).
4. Run `vite-ssr build` for buildling your app. Then, you can import the built file in your backend (see [`node-server/index.js`](./example/node-server/index.js) for an example).
4. Run `vite-ssr build` for buildling your app. Then, you can import the built files in your backend (see [`node-server/index.js`](./example/node-server/index.js) for an example).

While rendering the first view, you can provide the initial state in `route.meta.state` and `vite-ssr` will take care of rehydration in the client. See [`main.js`](./example/src/main.js) for an example.

Expand All @@ -39,6 +39,5 @@ Run `yarn refresh` for moving latest version of `core` to `example/node_modules`
- ~~Export a build plugin so a project can be built using `vite build` (not sure if it's possible)~~
- [x] Make `src/main.js` file name configurable
- [ ] Support build options in CLI (currently only configurable via JS API)
- Rethink router requirement (currently it relies on `vue-router`)
- Support React? (PRs welcome)
- [ ] Support React
- Better docs
19 changes: 19 additions & 0 deletions example/node-server/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Example API

module.exports = [
{
route: '/api/getProps',
handler(req, res) {
const url = new URL('http://e.c' + req.originalUrl)
console.log('getProps', url.searchParams.toString())
res.end(
JSON.stringify({
server: true,
msg:
'This is page ' +
(url.searchParams.get('name') || '').toUpperCase(),
})
)
},
},
]
31 changes: 19 additions & 12 deletions example/node-server/index.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,44 @@
// This is a simple Node server that uses the built project.

global.fetch = require('node-fetch')
const path = require('path')
const express = require('express')

// This contains a list of static routes (assets)
const { ssr } = require('../dist/server/package.json')

// The manifest is required for preloading assets
const manifest = require('../dist/client/ssr-manifest.json')
const { default: handler } = require('../dist/server')

// This is the server renderer we just built
const { default: renderPage } = require('../dist/server')

const api = require('./api')

const server = express()

// Serve every static asset route
for (const asset of ssr.assets || []) {
server.use(
'/' + asset,
express.static(path.join(__dirname, '../dist/client/' + asset))
)
}

server.get('*', async (req, res) => {
if (req.path === '/api/getProps') {
console.log('getProps', req.query)
return res.end(
JSON.stringify({
server: true,
msg: 'This is page ' + (req.query.name || '').toUpperCase(),
})
)
}
// Custom API to get data for each page
// See src/main.js to see how this is called
api.forEach(({ route, handler }) => server.get(route, handler))

// Everything else is treated as a "rendering request"
server.get('*', async (req, res) => {
const url = req.protocol + '://' + req.get('host') + req.originalUrl
const { html } = await handler({

const { html } = await renderPage({
request: { ...req, url },
manifest,
preload: true,
})

res.end(html)
})

Expand Down
10 changes: 10 additions & 0 deletions example/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default viteSSR(
// The 'initialState' is only available in the browser and can be used to
// pass it to Vuex, for example, if you prefer to rely on stores rather than Page props.

// Before each route navigation we request the data needed for showing the page.
router.beforeEach(async (to, from, next) => {
if (process.env.NODE_ENV !== 'development' && to.meta.state) {
// This route has state already (from server) so it can be reused.
Expand All @@ -28,6 +29,15 @@ export default viteSSR(

const baseUrl = isClient ? '' : new URL(request.url).origin

// Explanation:
// The first rendering happens in the server. Therefore, when this code runs,
// the server makes a request to itself (running the code below) in order to
// get the current page props and use that response to render the HTML.
// The browser shows this HTML and rehydrates the application, turning it into
// an normal SPA. After that, subsequent route navigation runs this code below
// from the browser and get the new page props, which is this time rendered
// directly in the browser, as opposed to the first page rendering.

try {
// Get our page props from our custom API:
const res = await fetch(
Expand Down
21 changes: 12 additions & 9 deletions example/vite.config.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
const { defineConfig } = require('vite')
const viteSSR = require('vite-ssr/plugin')
const vue = require('@vitejs/plugin-vue')
const api = require('./node-server/api')

module.exports = {
plugins: [viteSSR(), vue()],
server: {
proxy: {
'/api': {
// This is the server in `node-site` directory
target: 'http://localhost:8080',
module.exports = defineConfig({
plugins: [
viteSSR(),
vue(),
{
// Mock API during development
configureServer({ app }) {
api.forEach(({ route, handler }) => app.use(route, handler))
},
},
},
}
],
})

0 comments on commit eefde90

Please sign in to comment.