SEO with your favorite CLI or static site generator

5 years ago

This project provides a barebones SEO integration with CLI projects like create-react-app and angular-cli. Both of these projects are excellent and will build a static site, but neither one provides a way to render meta tags. This means search engines like Google and Bing and social sites like LinkedIn, Facebook, Twitter, etc. won't be able to use them for indexing or sharing content appropriately. This project provides some some patterns and code for getting this to work properly.

Installation

Note While you can install and run this project by itself, it is really meant to be integrated with other CLI tools that generate static sites. (See below)

npm install

Running the project

npm run server-install
npm run start-deploy

Integration and Running on CLI projects

The following are based on create-react-app or angular-cli, but you can use similar steps with other CLI projects or static site generators. Essentially anything that builds out an index.html and related minified and compressed files.

Installing

After creating your using create-react-app or angular-cli, do the following:

  • Copy the server directory
  • Copy the scripts values from package.json
  • Copy build.js
  • Add the following to .gitignore:
/deploy
/server/node_modules
  • Install fs-extra for coping directories.
npm install fs-extra --save-dev
  • Optional - To test basic routing, copy and paste the links in build\index.html

Running

  • Run the following scripts. Both CLIs use the first for building. The second two are for testing the Express app locally.
npm run build
npm run server-install
npm run start-deploy

Building

npm run build
npmr run build-deploy

File Structure


build.js

Creates a deploy directory using files copied from the client build directory and server directory

Attention See notes in code. By default this handles either create-react-app or angular-cli, but this code should be removed if you know what you're using.


package.json

Three npm scripts are used by the project:

  1. build-deploy - creates a deploy folder and copies the CLI build folder and the server folder. This is your deployment package.
  2. server-install - (optional) - installs server packages to test locally.
  3. start-deploy - builds and starts locally. Run previous step if using this option.

server directory

Contains all server side Express code:

app.js - Express server which relies on a custom view engine (seoViewEngine.js) for rendering the meta tags. (Note: I kept this as minimal as possible. Consider Express Generator or Koa for something more sophisticated.)

Note: You may need to tweak the isStatic method as necessary depending on the underlying tool you're using.

seoViewEngine.js - custom Express view engine for reading from the seoData.js file and adding meta tags to index.html. You may notice I use Object.assign over object destructuring here since this may not be available in the Node version you're using. Also, if your SEO data is static, you could make this more performant by adding simple caching logic here.

seoData.js - This contains a title prefix and then URL paths that specify a title and meta properties for each. All paths inherit from the default path, so they can override or ignore specific properties.

package.json - This is used by the host environment where this is hosted. It is optimized for use in Heroku, though you can make tweaks if necessary. I did end up having to add qs as a dependency as this was a problem with the version of Node being used.


Deployment

One you have built the project, deployment should be pretty straight-forward. The package.json includes a postinstall npm script and an engines configuration which you can tweak.

Heroku: If you are using Heroku's awesome GitHub integration, you can simply push a subtree to your GitHub repository, and then use manual or automatic deployments. I typically use the following script which creates a deploy subtree which I can deploy with.

git subtree push --prefix dist origin deploy

Testing

Testing SEO can often be tricky due to caching, but the following SEO Validators are very helpful. I would highly recommend validating some variable dummy paths first until you can get it right. The Facebook debugger is by far the best one and will provide good feedback on what to fix.


Client Side SEO

This project is focused on server side rendering of meta tags, but you still need to update this on the client side if you're using a SPA. You will want to update the title and may rely on sharing libraries that read the meta tags. Here are two code snippets for you can use to integrate with client side routing events.

Note - Since this project does not handle this, you will notice in SPAS that the values don't update when changing the page. You can refresh the page to see the server rendered change.

updateMetaTag(attribute, attributeValue, contentValue) {
  let htmlElement: document.querySelector('meta[' + attribute + '=\'' + attributeValue + '\']');
  if (!htmlElement) {
    htmlElement = document.createElement('meta');
    htmlElement.setAttribute(attribute, attributeValue);
    htmlElement.setAttribute('content', contentValue);
    document.head.appendChild(htmlElement);
  } else {
    htmlElement.setAttribute('content', contentValue);
  }
}

updateTitle(title) {
    this.title.setTitle(title);
    let htmlElement: document.querySelector('meta[title]');
    if (!htmlElement) {
      htmlElement = document.createElement('meta');
      htmlElement.setAttribute('title', title);
    } else {
      htmlElement.setAttribute('title', title);
    }
  }

Note: If you're using React, checkout NFL's open source project react-helmet


Screenshot


Source Code

CLI Specific Examples

The following are two basic examples using create-react-app and angular-cli.


CLI Recommendations

There are many ways to handle SEO and if you'd prefer a server rendered or isomorphic app, you might check out Zeit Next for React or Angular's Universal. Both of these are great alternatives, though as of this date, neither integrates with the CLI platforms above.

I'd also recommend checking Angular's issue tracker and React's documentation for other recommendations. This project is similar to what you'll find in React's recommendation.

Angular CLI - SEO Guidance and/or Solution? React - Generating Dynamic Meta Tags on the Server
Discuss on Twitter