Pre-Rendering VueJS-Based SPAs

by Thomas Urban

Until now single page applications (SPA) have issues with SEO. This includes SPAs built with VueJS. However, several solutions are available to handle those issues in developing with VueJS. This includes prerendering and server-side rendering. In most cases prerendering is a sufficient solution so bots will fetch documents properly stuffed with all their content so search engines are capable of crawling it without having to run Javascript code first.

Several tutorials on this issue are available online, e.g. this and this. However, we've run into follow-up issues of our own.

Renaming Root Element

Your VueJS application is attached to an element of the HTML document usually selected by its ID. Current application templates use #app for this. The same ID is used in root element of your application's root template. By changing the latter prerendered pages won't contain any element matching the former, thus prerendered pages will basically render properly, but fail to start their intended behaviour. Console won't generate any output regarding some error or warning in this situation.

Fixing this is simple: either don't change the ID applied to root element of your application's root template or change it in both places: the application's root template and the static index.html file deployed with the application by default.

Routing Documents

Basically your application's initial view might be available at root / or /index.html. However, this is causing trouble with prerendering it. All prerendered documents are written to the build's output directory. The route / or /index.html would require to write file index.html into output directory. However, the prerendering part of build script will reject to replace any existing file there. In early stage of building application the index.html file is created as a copy of same file in folder with static assets of your application, e.g. public/. Thus the build fails, in our case without providing any particular error message.

Fixing this issue requires to use different route for inital view and have requests for / redirected there. E.g. consider providing the initial view at URL /overview or /dashboard instead. This results in prerendered version written to file overview/index.html or dashboard/index.html.

File Names in Routes

You might want to pretend your application's routes addressing some (HTML) files. This is basically possible, but due to the static post processing function included with vue-cli-plugin-prerender-spa plugin all routes are converted into folders each containing another file named index.html. Providing this in a production setup will result in URLs /your/route.html/. Note the trailing forward slash.

This issue might be fixed by simply omitting the attempt to fake file names in routes in the first place unless the plugin gets revised to support a rewriting like included with this example:

// Remove /index.html from the output path if the dir name ends with a .html file extension.
// For example: /dist/dir/special.html/index.html -> /dist/dir/special.html
if (renderedRoute.route.endsWith('.html')) {
    renderedRoute.outputPath = path.join(__dirname, 'dist', renderedRoute.route)

Go back