Byte Ebi's Logo

Byte Ebi 🍤

A Bit everyday A Byte every week

Enhancing SEO for SPA with Prerender

Addressing SEO challenges for CSR web pages, demonstrating both self-hosted and SaaS solutions

Ray

A Single Page Application (SPA) website utilizes Client-Side Rendering (CSR) to render its content.
Upon initial loading, the server only returns the root component, and subsequent data is fetched through API interactions.
However, for web crawlers responsible for ranking websites, the content obtained during crawling may appear empty.
While Google claims that their crawler executes JavaScript, other search engines may not necessarily do so.
To address this issue, a Prerender service is employed to achieve pre-rendering for web crawlers, optimizing search results.

Prerender

The principle involves setting up an internal headless Chrome to achieve pre-rendering of the webpage.

Two methods for using Prerender will be introduced below:

For self-hosting, a reverse proxy needs to be established.
Upon incoming requests, the user agent is checked. If it is a bot, the request is sent to the self-hosted Prerender service.
The service itself includes a headless Chrome, allowing rendering of HTML to be returned.
If it’s a regular user, the request is forwarded to the frontend server without rendering.

Using the Prerender.io SaaS service comes with limitations and may require payment if exceeding the free usage limits. However, it eliminates the need for self-management and setup. The advantage of self-hosting is greater flexibility in configuration.

Both solutions can be evaluated based on the use case.
If opting for the Prerender.io solution, configuration can only be done when the website is already online.

Self-hosted

Package: Prerender The documentation is quite clear, and the setup is straightforward. Below is a step-by-step demonstration.

1. Installation

Create a folder, for convenience, let’s call it prerender.
Inside the folder, enter the command in the terminal:

npm install prerender

This completes the installation.

2. Configuration

In the prerender folder, create a file named server.js.

const prerender = require('prerender');
const server = prerender();
server.start();

3. Start

Enter the command in the terminal to start the service.

node server.js

The service will start on localhost at port 3000. If your service is also running on port 3000, choose a different port.

While your frontend project is running, open the terminal and enter:

curl "https://www.google.com.tw/" # Your SPA project URL

You will receive an empty DOM with only the root component, as the JS for fetching component content has not been executed.
This is a reason for poor SEO in SPAs. Although Google claims that their crawler executes JS, other search engines may not.

Now comes the magic moment. Open the terminal and enter:

curl "http://localhost:3000/render?url=https://www.google.com.tw/" # Your SPA project URL

You will get a large package of rendered results!
The preceding URL is the Prerender service address, and the parameter includes your project URL.
Prerender internally starts a headless Chrome to render the page and then returns the result.

Cache Configuration

Usually, when you self-host a Prerender service, it will re-render the page each time a request is made.
However, in practice, frequent re-rendering is unnecessary.
This can be optimized by setting up caching to retain rendered results for a certain period.

Cache package used: prerender-memory-cache

1. Installation

In the terminal, enter the command in the prerender folder:

npm install prerender-memory-cache --save

2. Configuration

Open the server.js file in the prerender folder and add the configuration declaration before server.start();;

server.use(require('prerender-memory-cache'))

That’s it. The second request should use the cached result.

3. Parameters

You can also set parameters in the prerender folder using the terminal.

Cache Maximum Number of Items

export CACHE_MAXSIZE=1000

default: 100

Cache Lifespan (seconds)

export CACHE_TTL=600

default: 60

4. Testing

After setting the lifespan, use the terminal to test:

curl "http://localhost:3000/render?url=http://localhost:3030/" # Your SPA project URL

打完第一次之後,去修改自己專案的一些內容(footer, title 之類)
確認用瀏覽器直接造訪畫面有出現變更
接著再重新使用終端機測試,應該會出現舊的 HTML 內容

這就證明他是使用快取的內容,而不是請求一來就重新渲染
所以剛剛才會建議修改 footer 或是 title,因為比較好確認

After the first test, modify some content in your project (footer, title, etc.) and confirm the changes by directly visiting the page in the browser. Then, retest using the terminal. You should see the old HTML content.
This proves that it is using the cached content rather than re-rendering with each request.

Online Service Pricing Plans

Below is an example using Cloudflare Workers to set up the Prerender.io service.
This is because the frontend project seems to have its own Nginx service, and I don’t want to intervene too much.

Besides, I’ve heard that Cloudflare Workers are powerful. It’s like a proxy at the forefront, so it can do many things.
Although I’ve never had the chance to use it, it seems like a good opportunity.

Prerender.io Pricing Plans

prerender price

Cloudflare Workers Pricing Plans

cloudflare workers price

Configuration

Go to the Prerender page, click on Install middleware and select the cloudflare option.

prerender settings

The official documentation has been updated.
Just follow the instructions in the document, and even those who can’t code can configure it confidently!
Follow the document and pictures for Cloudflare Integration .

Open the sample configuration file as prompted: prerender/prerender-cloudflare-worker .
You’ll see the index.js example. The only things to change are API_KEY and PRERENDERED_DOMAINS.

  • API_KEY:The token in the top left corner of the Prerender.io dashboard.
  • PRERENDERED_DOMAINS:The target domain for which routing rules will be set later.

Create a Cloudflare worker and paste the configuration file.
Ordinary Workers can be tested using the provided playground by Cloudflare, but since we’re using a third-party service, it must be verified by Prerender to take effect.
Therefore, testing with the playground here is not possible.

After configuring the worker, open the Worker tab and choose Add route.

cloudflare workers settings

Next, set the Request Limit Failure Mode.

Open Failure (Continue) means that if the Worker fails when a request comes in, it will go directly to the service.
Close Failure (Block) will throw an error page, preventing users from continuing to access.
Since we don’t want the website to be inaccessible when reaching the free plan limit and not pre-rendering content doesn’t affect the website’s functionality, choose to skip the Worker and execute it directly in case of failure.
After all, it’s just for pre-rendering, and it doesn’t matter if crawlers can’t access it this time; they can come back next time.

cloudflare new route

The routing rules should match the URL you set in the Worker configuration.
After setting it up, remember to go back to Prerender.io and click “Next” to complete the verification.
Then, wait for the verification to be completed.

Usually, after clicking “Verify,” the verification results will appear after a few seconds.
If you want to simulate the result obtained when crawling after verification, you can use:

curl -A Googlebot "https://{your-online-service-url}"

This simulates the result obtained by the Googlebot crawler.
Since we specified a specific user agent in the Worker’s Nginx configuration file, the Cloudflare Worker will determine whether to forward it to the Prerender.io service for processing.

Without the -A Googlebot parameter, it won’t forward for rendering.
It will return the CSR result that regular users would get, which is the unrendered webpage content.

Recent Posts

Categories

Tags