node package manager
Loosely couple your services. Use Orgs to version and reuse your code. Create a free org »

prerender-seo

prerender-seo

Prerender HTML files using PhantomJS. Let search engine crawlers capture the right content, not just <div id="app"></div> stuff. The Most common user scenario are React and Vue rendered page.

Install

npm install prerender-seo --save-dev

Usage

const path = require('path')
const prerenderSEO = require('../lib')
 
const files = [
  '/index.html'
]
 
prerenderSEO(
  path.resolve(__dirname, './dist'),
  '#app',
  files,
  {
    // options
  }
)

Test

The test case use a vue-cli generated project

npm run test

Options

Name Type Default Description
sourceDir {String} - Source directory of static files
mountNode {String} - Dom Element Selector the application mount on
files {Array} - HTML Files to prerender
options.destDir {String} *_prerender Destination directory to store the result
options.proxyTable {Array} [] Proxy to forward any http request that match the config
options.ignoreError {Boolean} false Define whether ignore all errors during the Phantomjs process.
options.resourceTimeout {Number} 15000 Define the timeout of any resource
options.resourceIntercept {Array} [] Define the regular expression of any resource will be aborted
options.XSSAuditingEnabled {Boolean} false Defines whether load requests should be monitored for cross-site scripting attempts

sourceDir

{
  sourceDir: path.resolve(__dirname, '../dist')
}

mountNode

Make sure your application root component contain a mount node wrapper. React and Vue will replace the mount node with render content, in case the mount node get replaced at the first time of prerender.

Root.vue

<template>
  <div id="app"></div>
</template>

prerender.js

{
  mountNode: '#app'
}

files

{
  files: [
    'index.html',
    'about.html',
    'product.html'
  ]
}
 

options.destDir

Define the destination directory. If you want to replace the source directory, just set the same path as sourceDir.

{
  sourceDir: path.resolve(__dirname, '../dist'),
  mountNode: '#app',
  files: [
    'index.html',
    'about.html',
    'product.html'
  ],
  {
    destDir: path.resolve(__dirname, '../dist')
  }
}

options.proxyTable

{
  sourceDir: path.resolve(__dirname, '../dist'),
  mountNode: '#app',
  files: [
    'index.html',
    'about.html',
    'product.html'
  ],
  {
    proxyTable: {
      context: '/api',
      proxy: {
        host: 'example.com',
        port: '80',
        protocol: 'http'
      }
    }
  }
}

options.ignoreError

{
  sourceDir: path.resolve(__dirname, '../dist'),
  mountNode: '#app',
  files: [
    'index.html',
    'about.html',
    'product.html'
  ],
  {
    ignoreError: true
  }
}

options.resourceTimeout

Define the timeout after which any resource requested will stop trying and proceed with other parts of the page. (in milli-secs)

{
  sourceDir: path.resolve(__dirname, '../dist'),
  mountNode: '#app',
  files: [
    'index.html',
    'about.html',
    'product.html'
  ],
  {
    resourceTimeout: 35000
  }
}

options.resourceIntercept

Define the regular expression to match any resource url will be aborted before request. The left hand in the array is RegExp pattern, the right hand is RegExp flag.

{
  sourceDir: path.resolve(__dirname, '../dist'),
  mountNode: '#app',
  files: [
    'index.html',
    'about.html',
    'product.html'
  ],
  {
    resourceIntercept: [
      ['hm.baidu.com', 'g'],
      ['/api/tokenAttach', 'g']
    ]
  }
}

options.XSSAuditingEnabled

{
  sourceDir: path.resolve(__dirname, '../dist'),
  mountNode: '#app',
  files: [
    'index.html',
    'about.html',
    'product.html'
  ],
  {
    XSSAuditingEnabled: true
  }
}

License

The MIT License (MIT). Please see License File for more information.