We're live-coding on Twitch! Join us!
Server-Side Rendering with Vue and Cloudflare Workers

Server-Side Rendering with Vue and Cloudflare Workers

Code

A few weeks ago, Scotch.io gave me the push to experiment with Cloudflare Workers and Vue server-side rendering. The experiment was a success, and I’m happy to report the findings.

In this article, we will publish a full-featured, server-side rendered (SSR) Vue application to Cloudflare Workers. But before we begin, let’s talk about what exactly are Cloudflare Workers, define server-side rendering and compare this setup to a more conventional load-balanced architecture.

How do Cloudflare Workers work?

Part of a growing edge computing trend, Cloudflare Workers, allows us to push JavaScript code to edge locations in 194 cities across 90 countries. Rather than orchestrating containers or virtual machines, Cloudflare Workers’ deal with isolates. Isolates are lightweight sandboxes for our code that, in turn, are managed by the V8 JavaScript and WebAssembly engine - used by Chromium and Node.js. This model practically eliminates the cold starts and overheads associated with the virtual machine or container model.

What is Server-Side Rendering?

Quite a lot of things happen when the user navigates to a website. The browser resolves the website domain name, initiates a TCP connection, sends an HTTP request to the webserver, receives the HTTP response.

The HTTP response, if there were no errors, contains the web page’s HTML content. It is at this stage that server-side rendering makes a difference. Without SSR, the browser gets a blank web page and sends out requests for JavaScript, CSS, and other assets. While the user is waiting, the browser receives, parses, and executes the JavaScript code, that in turn, renders the application.

With server-side rendering, the browser receives and renders the full HTML page from the webserver. This avoids the wait time needed to download, parse, and execute the JavaScript code in the browser. When the JavaScript application is loaded, it re(hydrates) or reuses the existing DOM tree and takes over the navigation and rendering.

Are there alternatives to Cloudflare Workers?

The closest alternative to Cloudflare Workers is AWS Lambda@Edge. AWS Lambda@Edge differs in a few key aspects: it features fewer edge locations, and it runs Node.js rather than the V8 engine, which contributes to longer cold start times.

The commonly deployed server-side rendering architecture consists of load balancer(s) distributing incoming traffic to several containerized or virtualized Node.js processes. If we were to match the Cloudflare Workers or AWS Lambda@Edge, we’d have to deploy this setup to every relevant region and availability zone. Cloudflare Workers do all this work for us.

Essential Reading: Learn React from Scratch! (2019 Edition)

Step-by-step instructions

To publish a server-rendered Vue application to Cloudflare, you’ll need a few things:

  • A Cloudflare account with Workers Unlimited plan, it costs $0.50 / million requests per month, with a minimum charge of $5 / month.
  • A Node.js installation running locally on your machine, and access to the command-line.

Make sure that you have the latest versions of Vue Cli and Cloudflare Wrangler:

$ npm i -g @cloudflare/wrangler @vue/cli

Note the Cloudflare Global API key and Workers Account Id. You can find the Global API key on the bottom of the Api Tokens page. The Workers Account Id is on the right sidebar of the Workers Overview Dashboard ; you may need to scroll down.

Next configure the Workers CLI, it will ask for the account email and the Global API key.

$ wrangler config
Enter Email:
foo@bar.com
Enter api key:
123456abcdef

Let’s clone the template I prepared. It is a modified Vue CLI project that follows the Server-Side Rendering Guide as closely as possible.

$ git clone https://github.com/l5x/vue-ssr-cloudflare-workers-template.git
$ cd vue-ssr-cloudflare-workers-template
$ npm install

wrangler.toml is the Cloudflare Workers configuration file. Update the account_id field and run:

$ npm run publish
...
 Built successfully, built project size is 554 KiB.
 Successfully published your script to https://vue-ssr-cloudflare-workers.YOUR-SUBDOMAIN.workers.dev

And that’s it. You should have a working server-side rendered Vue application with vue-router, vuex, (re)hydration, dynamic imports, critical CSS, and asset injection. Let’s go over the project’s structure and key configuration files.

client.config.js extends the Vue CLI webpack configuration, adds the VueSSRClientPlugin, and removes the HtmlWebpackPlugin and the PreloadWebpackPlugin. The entry for this build is src/entry-client.js.

worker.config.js extends the Vue CLI webpack configuration, removes the HtmlWebpackPlugin, PreloadWebpackPlugin, babel-loader, sets the correct environment variables, enables optimizeSSR in vue-loader options, filters out non-JavaScript assets and concatenates the output into a single file. The entry for this build is src/entry-worker.js.

vendor/vue-server-renderer/basic.js is a modified Vue Bundle Renderer that works in Cloudflare Workers’ environment. It only supports the renderToString method. See this commit for details.

src/entry-worker.js is the entry-point for the Cloudflare Workers. The Worker starts by subscribing to incoming requests i.e., listening to fetch events. For each incoming request, it checks if there are static assets available that match the request URL. If there is a match, Cloudflare Worker Sites responds with the static asset. If the request URL did not match any static assets, the Vue application takes over and matches the request URL to routes defined in src/router/index.js.

Next up

The setup described in this article should give you a good starting point. Next time we will add caching with Cloudflare Workers KV to this setup. Reach out to me on twitter. I’m happy to help with this or a similar topic.

Like this article? Follow @mcnmr on Twitter