• Stars
    star
    173
  • Rank 220,124 (Top 5 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 6 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Boost SEO by prerendering your Vue application. Powered by prerender-spa-plugin.

vue-cli-plugin-prerender-spa

Add prerender-spa-plugin into your Vue application with zero configuration.

Looking for a co-maintainer: I'm continuing to maintain this project, hoever I still would like help on some of the issues, and generally to help me keep this plugin going as it's getting more and more popular. If you think you can help, file and issue for maintainship!

Support requests: Vue has a Discord server and I often lurk in there. And while there is a support label in the Issues, GitHub isn't the place for support requests and should be directed to me in the Vue Land Discord server.

Install

Add prerendering to your Vue application with:

vue add prerender-spa

or by searching for prerender-spa in the Vue UI plugins.

You'll be asked a few questions, detailed below, to which the default answers are the most common options.

The main option to fit to your needs is the list of routes to pre-render. Specify them as a comma-separated list:

? Which routes to pre-render? (list them separated by a comma) /,/about,/contact

Options list

Pre-rendered routes

? Which routes to pre-render? (list them separated by a comma) /

Specify a list of routes to pre-render. By default only the index page is pre- rendered, which should cover most SPAs. If your project uses vue-router, you can specify a list of routes that do not depend on dynamic content (like user uploaded data, public profiles, etc.). For example you can add your about page as well as a contact page - those will load faster, and will be indexed by bots who do not execute JavaScript, improving Search Engines rankings.

Note that if you want to also pre-render user generated content, you will have to switch to Server-Side Rendering, there are no other options.

What it does to your project

The list of routes is split into an array and passed into the Webpack plugin. The routes aren't checked for existence or even duplicates, just split into an array and sent to the PrerenderSPAPlugin instance.

Event-triggered snapshot

? Use a render event to trigger the snapshot? Yes

Use a document event to signal prerender-spa-plugin to trigger a snapshot of the DOM and save it. By default the renderer waits until DOMContentLoaded to take a snapshot of the DOM. But it is still recommended that you control the snapshot trigger - no surprise waiting for hours for your build before realizing what's happening.

What it does to your project

When enabling the event-based snapshot trigger, it will tell PrerenderSPAPlugin to listen for an x-app-rendered event. Your main file is then modified to add a mounted() hook where the event will fire. Note that it doesn't check if the hook is already present, nor does it parses the file; it just looks for the line starting with render: (minus whitespaces) and inserts the mounted() hook below. If you already have the hook set up, or if your render() function on the main file is longer than one line, it will break your Vue entrypoint. A better injection routine is planned, but for now, it covers a vast majority of projects where the main file isn't touched.

Use a headless browser for rendering

? Use a headless browser to render the application? (recommended) Yes

This option is there for debugging purposes, but should be left enabled otherwise. Not using a headless browser will open a Chrome window when building with your app running inside, then close once the snapshot has been taken. Since the plugin configuration object isn't available, it is available here.

What it does to your project

The headless value of the configuration object is set to the answer to the question.

Only pre-render for production builds

? Only use prerendering for production builds? (recommended) Yes

Only load the pre-rendering plugin when building for production. This is strongly recommended as the plugin, spawning an instance of the Chrome browser, adds significant time to the build process. Development builds should be snappy and not memory-intensive; which is exactly what this plugin does to your build.

However, there may be cases where you want to test the pre-rendering itself, and switching to a production build isn't the solution - you may then turn off that option.

Indirect options

Parallel / Mutli-threaded

This option is configured from within the Vue CLI itself, but serves to a whole host of plugins to determine whether to turn on parallel jobs / multi-threading.

This plugin uses it to tell prerender-spa-plugin to render pages concurrently (meaning in parallel) or not by setting the maxConcurrentRoutes parameter to either 1 or 4, if the build is respectively single-threaded or multi-threaded.

Custom configuration

After being invoked, the plugin saves a file named .prerender-spa.json in the root directory of the project; where you can specify custom options for the Puppeteer renderer. It will be merged, and its options will overwrite those set by the plugin itself.

Other way to set custom configuration for the Puppeteer renderer is to use customRendererConfig dictionary of possible Puppeteer launch options.

Example configuration of debugging your site with Chrome DevTools opened automatically:

// vue.config.js

module.exports = {
  pluginOptions: {
    prerenderSpa: {
      registry: undefined,
      renderRoutes: [
        '/',
        '/about'
      ],
      useRenderEvent: true,
      onlyProduction: true,
      
      headless: false, // <- this could also be inside the customRendererConfig
      customRendererConfig: 
      {
        args: ["--auto-open-devtools-for-tabs"]
      }
    }
  }
}

User post processing function

Pupeteer allows to postprocess the HTML after it's been snapshot, and the plugin allows you to provide your own function if you need to.

Add a postProcess option into your vue.config.js file to provide a custom post-processing function to run on every build.

Example configuration:

// vue.config.js

module.exports = {
  pluginOptions: {
    prerenderSpa: {
      registry: undefined,
      renderRoutes: [
        '/',
        '/about'
      ],
      useRenderEvent: true,
      headless: true,
      onlyProduction: true,
      postProcess: route => {
        // Defer scripts and tell Vue it's been server rendered to trigger hydration
        route.html = route.html
          .replace(/<script (.*?)>/g, '<script $1 defer>')
          .replace('id="app"', 'id="app" data-server-rendered="true"');
        return route;
      }
    }
  }
}

Contributing

You are very welcome to contribute. To ask for a feature, or submit a bug, use the Issues list. If you want to contribute a feature yourself, first submit an Issue, work on your code, and add a Pull Request, referencing your issue in the PR message. This way the isse can serve as a mean to discuss the feature, and the Pull Request is where we can review the code and talk specificities.

In all cases, follow the templates carefully, in order to maximize information throughput.

Notices

Backend routing configuration for deployments

Since the index.html is now (most likely, depending on your list of routes) pre-rendered, pointing to it from another path will lead to whiteflashing as the pre-rendered content (of the index page) will not match the expected content of the route (say from an about page). For this reason, the plugin outputs another file called app.html that doesn't get pre-rendered. For better user experience, it is recommended to route non-prerendered routes to this file instead of the default index.html.

Here's an example nginx configuration snippet:

location / {
try_files $uri $uri/index.html $uri.html /app.html;
}

And an example Firebase configuration (taken from https://stackoverflow.com/a/51218261):

"rewrites": [
  {
    "source": "**",
    "destination": "/app.html"
  },
  {
    "source": "/",
    "destination": "/index.html"
  }
]

CI/CD workflows

Because the prerender-spa-plugin uses a headless Chrome instance, your regular node:latest Docker image will not chug your build correctly; you need system dependencies and configuration that might not be efficient to add to the job itself - rather, it is recommended to switch to a Node.js + Puppeteer image where you can just use your install && build workflow without any additional configuration. I personally use the alekzonder/puppeteer image.

If you do decide on using alekzonder/puppeteer and you want to install global npm packages. The following commands can be used prior to the installation of your required global package to ensure that you do not receive an EACCES: permission denied, access '/usr/local/lib/node_modules' error. I have tested this using Gitlab CI.

- mkdir ~/.npm-global
- npm config set prefix '~/.npm-global'
- npm install -g @vue/cli-service-global

Compatibility with other Vue CLI plugins

This plugin should be compatible with any plugin that doesn't add a mounted() hook into the Vue entrypoint in your main.{js,ts} file, as this is the only file it updates, and only if you choose an event-based snapshot trigger.

More Repositories

1

preact-bulma

Preact components for the Bulma CSS project.
TypeScript
27
star
2

valib

Library of reusable blocks for musical DSP.
Rust
18
star
3

vstminihost

VST mini-host for debugging purposes
Rust
11
star
4

bevy-kira-components

Experimental Bevy <-> Kira integration crate
Rust
9
star
5

interflow

Unified and opinionated audio I/O for Rust
Rust
8
star
6

latentwt

Generate wavetables, with AI.
Vue
7
star
7

p-waves

Ground-breaking component-based audio player for the web
TypeScript
6
star
8

ts404

Screamer guitar pedal emulation
Rust
5
star
9

nih-reverb

Diffusion delay design for anything from simple delays to washed out reverbs.
Rust
5
star
10

HTML5-Visualizer

HTML5 basic visualizer - Oscilloscope and Spectrum
JavaScript
4
star
11

reconvolve

Create convolution impulse response from frequency sweep inputs
Python
4
star
12

yawr

Yet Another WAVE Reader (and writer)
Rust
4
star
13

xay

An automatic build system for 95% of projects.
C
2
star
14

kOS-IDE

This is an external tool for KSP's mod kOS that allows syntax highlighting, variable tracking and other stuff.
C#
2
star
15

preact-combinations

Pass an array of value per props; get the element rendered as all possible combinations of those props.
TypeScript
2
star
16

home-manager

Personal configuration of Nix's home-manager utility that manages dotfiles and configuration of apps
Nix
2
star
17

rs-rational

Rust structure for irreducible fractions.
Rust
1
star
18

Reshade-SE-Lens-Flare

Post-process Lens Flare shader, originally created for Space Engine.
FLUX
1
star
19

libnotify-terminal

Linux CLI notifier with user interactions using libnotify and zenity.
Python
1
star
20

blog-preact

TypeScript
1
star
21

ml-difflist

Differential list implementation in OCaml
OCaml
1
star
22

xay.net

An automatic build system for 95% of projects
C
1
star
23

blender_io_earth_studio

Import Google Earth Studio scenes into Blender.
Python
1
star
24

nixfiles

Nix
1
star
25

node-gir-typedef

TypeScript .d.ts generator for the GObject Introspection Repository
TypeScript
1
star
26

octave.rs

Rust analyzer and language server for Octave
Rust
1
star
27

ig_projet

C
1
star
28

com.github.Alacritty

Flatpak package for Alacritty
Rust
1
star
29

node-libnotify-terminal

libnotify-terminal, ported to nodejs.
TypeScript
1
star
30

mna

A SymPy module for Modified Nodal Analysis
Jupyter Notebook
1
star
31

python-call

Thread-based, JS-like asynchronous calls for Python. Works in both Python 2.7 and Python 3.5+.
Python
1
star
32

eva_gen

Mini language targeting EVA assembly.
Python
1
star
33

raytracer.rs

A raytracer personal project, from "Raytracing in one Weekend" as the base
Rust
1
star
34

grapher

HTML5 Canvas-based plotting using Ecsy and Preact
TypeScript
1
star
35

rust-meson

Meson parser and analyzer, written in Rust.
Rust
1
star
36

codeanon-lab

JupyterHub Docker configuration for CodeAnon
Python
1
star
37

buffers

Collection of unified buffers from stdio, file and memory buffers.
Rust
1
star
38

mume-cli

A CLI that packages mume - allowing you to process your Markdown-enhanced files from any editor.
TypeScript
1
star
39

preact-cli-experiment

Experiments on a Preact CLI with proper modularity
TypeScript
1
star
40

minigc.rs

Toy interpreter with mark n' sweep GC
Rust
1
star
41

rsfdn

Feedback Delay Networks in Rust
Rust
1
star
42

TileMaker

Little tool that takes a satellite image and outputs Orbiter surface tiles
C#
1
star
43

ferret

Vectorial-based search engine
Rust
1
star