question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Doc/Tuto] Example of prerendering for vue.

See original GitHub issue

Hi,

I made a simple landing page with vue 3 and vuejs, and would like to prerender it for seo and performance (and usage with netlify form).

I was looking for an existing solution, but didn’t find anything, so I’ve dug in the builder of vite and made my own script. I tried to make it as simple as possible, and at the end it’s pretty straightforward, but I’ve spent few hours to understand vite and rollup build, and I think it can be of interest to some people (you can start from there for SSR too).

I share it in the issue to keep a record, but I think it can be good to add some documentation about prerendering and ssr with vite and vue3.

Please feel free to give me your feedbacks, so we can improve it.

Prerendering with vite and vue3

Update you main.js file

// main.js
import { createApp as createClientApp, createSSRApp } from 'vue'

import './assets/main.css'
import App from './App.vue'

const inBrowser = typeof window !== 'undefined'

// We export a function that will create a standard app in dev, but a ssr app for production.
// To enable hydration on the client, use createSSRApp instead of createApp to create your app instance (separate imports allows hydration logic to be tree-shakeable for apps that do not require hydration).

export const createApp = () => (
  process.env.NODE_ENV === 'production'
    ? createSSRApp(App)
    : createClientApp(App)
)

// When in browser, we create and mount the app like before.
if (inBrowser) {
  createApp().mount('#app')
}

Add a build.js file

const { ssrBuild, build } = require('vite')
const { resolve } = require('path')
const { writeFileSync, rmdirSync } = require('fs')
const renderer = require('@vue/server-renderer')

const build = async () => {
  const outDir = resolve(process.cwd(), 'dist')
  const tmpDir = resolve(process.cwd(), 'dist/tmp')

  // Classic client build. Output assets, and index.html. Returns chunks and generated html.
  const clientResult = await build({ outDir })

  // Build for server side (imports are replaced by requires, and no assets)
  await ssrBuild({
    outDir: tmpDir,

	// Important to keep the export createApp in the main.js. 
    rollupInputOptions: {
      input: { index: 'src/main.js' },
      preserveEntrySignatures: 'allow-extension',
    },
  })

  // We import our main.js createApp from the new server flavored built file.
  const { createApp } = require(tmpDir)

  // Render the html of the app, and insert it in the generated index.html built for client side.
  const content = await renderer.renderToString(createApp()) 
  const indexPath = resolve(outDir, 'index.html')
  const indexOutput = clientResult.html.replace(
    '<div id="app">',
    `<div id="app" data-server-rendered="true">${content}`,
  )

  // Write the new file and remove the server build, we don't need it anymore.
  writeFileSync(indexPath, indexOutput)

  rmdirSync(tmpDir, { recursive: true })

  console.log('🎉 Page generated!')
  process.exit()
}

build().catch((e) => {
  console.error(e)
  process.exit(1)
})

Update you build script.

-    "build": "cross-env NODE_ENV=production vite build"
+    "build": "cross-env NODE_ENV=production node build.js"

Have fun! 🎉 (and please share me your thoughts!)

Moreover, I’ve only one file here, but next step could be to generate several pages depending of routes.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:4
  • Comments:10 (9 by maintainers)

github_iconTop GitHub Comments

2reactions
arpowerscommented, Nov 19, 2020

It’s for a next-gen framework, Factor 7

1reaction
arpowerscommented, Nov 19, 2020

You don’t think that it’s fundamentally important to match your development and production environments?

Hydration and pre-fetching are error-prone enough where I don’t feel comfortable developing without SSR.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Vue.js SEO-Friendly SPAs: Tips, Tools & Prerender Example
Learn how to build a Vue.js SEO-friendly SPA with prerendering, server-side rendering & other general SEO tips. Live prerender demo ...
Read more >
Pre-Render A Vue.js App (With Node Or Laravel)
In this article we'll explore how pre-rendering works with Vue.js and look at two examples; one with a Node.js project, one with a...
Read more >
Vue SEO Tutorial with Prerendering - YouTube
Written tutorial: https://goo.gl/iqb74TClick SUBSCRIBE if you enjoyed it!https://coursetro.comIn this tutorial, I will show you how to ...
Read more >
How to build a pre-rendered, SEO-friendly Vue.js app - Medium
Our Vue.js example: a quick, SEO-friendly e-commerce app ... Another thing to install now is the prerender-spa-plugin , which will allow you ...
Read more >
A Simple Pre-Rendered Web App Using Vue + Nuxt - mtlynch.io
Fortunately, there's an alternative to server-side rendering: pre-rendering. Instead of rendering pages on-demand in response to HTTP requests, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found