Improve SEO by pre-rendering all HTML pages

* Change all internal links to use URLs ending in `/`
* Add the prerender script which uses PhantomJS to pre-render the
  HTML for all possible pages in the system
* Change the build process to incorporate the pre-rendered files
* Update the sitemap script to generate the new URLs
This commit is contained in:
Andrew Miner
2015-03-06 22:31:39 -08:00
parent a9dc4e3a26
commit 6c7274c38c
2121 changed files with 195933 additions and 3118 deletions
+3 -3
View File
@@ -2,7 +2,7 @@
export AWS_CONFIG_FILE="$HOME/Documents/CraftingGuide/aws.config"
DIST="./dist"
ROOT="./dist"
SITE="crafting-guide.com"
TARGET=""
while [[ "$1" != "" ]]; do
@@ -19,9 +19,9 @@ if [[ "$TARGET" == "" ]]; then
fi
if [[ "$TARGET" == "new" ]]; then
find "$DIST" -name ".DS_Store" | xargs rm
find "$ROOT" -name ".DS_Store" | xargs rm
grunt clean dist
s3cmd sync -r --delete-removed --add-header="cache-control:max-age=1800" "$DIST/" "s3://new.$SITE/"
s3cmd sync -r --delete-removed --add-header="cache-control:max-age=1800" "$ROOT/" "s3://new.$SITE/"
grunt clean build
elif [[ "$TARGET" == "promote" ]]; then
aws s3 sync "s3://new.$SITE" "s3://$SITE" --delete
+40
View File
@@ -0,0 +1,40 @@
#!/bin/bash
OUTPUT_DIR='./prerender'
SCRIPT='/tmp/phantomjs_render.coffee'
SITEMAP_FILE='./src/pages/sitemap.txt'
cat > $SCRIPT <<END
url = require('system').args[1]
page = require('webpage').create()
path = "#{url}".replace(/http:\/\/[^/]*/, '').replace(/^\//, '').replace(/\/$/, '')
localUrl = "http://localhost:8000/#{path}"
page.open localUrl, (status)->
if status isnt 'success'
console.error "Could not load #{url}"
phantom.exit(1)
setTimeout (->
console.log page.content
phantom.exit(0)
), 5000
END
./scripts/sitemap > $SITEMAP_FILE
cat $SITEMAP_FILE | while read URL; do
OUTPUT_FILE=$(sed 's/http:\/\/[^/]*\///' <<< $URL)
OUTPUT_FILE="$OUTPUT_DIR/$OUTPUT_FILE/index.html"
OUTPUT_FILE=$(sed 's/\/\//\//' <<< $OUTPUT_FILE)
if [[ ! -e "$OUTPUT_FILE" ]]; then
mkdir -p $(dirname "$OUTPUT_FILE")
echo "prerendering $URL into $OUTPUT_FILE"
phantomjs --web-security=false --load-images=false $SCRIPT "$URL" >"$OUTPUT_FILE" 2>/dev/null
else
echo "Skipping $URL..."
fi
done
rm $SCRIPT
-51
View File
@@ -1,51 +0,0 @@
#!/usr/bin/env phantomjs --web-security=false
fs = require 'fs'
system = require 'system'
webPage = require 'webpage'
if system.args.length isnt 2
console.error 'USAGE: prerender <path>'
phantom.exit 1
########################################################################################################################
urlsFileName = system.args[1]
urls = fs.read(urlsFileName).split('\n')
outputDir = 'prerender'
currentPage = null
currentOutputPath = null
renderTime = 5000
urls = (url.trim() for url in urls when url.trim().length > 0)
if not fs.exists outputDir
fs.makeDirectory outputDir
startNextPage = ->
url = urls.pop()
if !url then phantom.exit()
path = "#{url}".replace(/http:\/\/[^/]*/, '').replace(/^\//, '')
url = "http://localhost:8000/#{path}"
currentOutputPath = "#{outputDir}/#{path}"
currentOutputPath = "#{outputDir}/index.html" if currentOutputPath is ''
if not fs.exists currentOutputPath
currentPage = webPage.create()
console.log "Opening #{url}..."
currentPage.open url, completePage()
else
setTimeout startNextPage, 0
completePage = (status)->
if status is 'fail'
console.error "Could not load #{url}"
startNextPage()
setTimeout (->
fs.write currentOutputPath, currentPage.content, 'w'
startNextPage()
), renderTime
startNextPage()
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env coffee
#
# Crafting Guide - serve-prerendered
#
# Copyright (c) 2014-2015 by Redwood Labs
# All rights reserved.
#
express = require 'express'
path = require 'path'
########################################################################################################################
ROOT = './dist'
########################################################################################################################
app = express()
app.get '*', (request, response)->
effectivePath = request.path.replace /\/$/, '/index.html'
extension = path.extname(effectivePath)
contentType = {
'.css': 'text/css'
'.html': 'text/html'
'.js': 'text/javascript'
'.json': 'application/json'
'.map': 'application/json'
'.png': 'image/png'
'.ttf': 'application/octet-stream'
'.scss': 'text/css'
}[extension]
console.log ">>> #{effectivePath}"
response.set 'Content-Type', contentType
setTimeout (-> response.sendFile effectivePath, root:ROOT), 100 # post files after a short delay
server = app.listen 8001, ->
console.log "listening at: #{server.address().address}:#{server.address().port}"
+2 -5
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env coffee
#
# Crafting Guide - server
# Crafting Guide - serve-build
#
# Copyright (c) 2014-2015 by Redwood Labs
# All rights reserved.
@@ -45,10 +45,7 @@ app.get '*', (request, response)->
console.log ">>> #{request.path}"
response.set 'Content-Type', contentType
sendFile = -> response.sendFile request.path, root:ROOT
setTimeout sendFile, 100 # change the zero to post files after a short delay
response.sendFile request.path, root:ROOT
server = app.listen 8000, ->
console.log "listening at: #{server.address().address}:#{server.address().port}"
+6 -6
View File
@@ -19,10 +19,10 @@ itemSlugs = {}
base = 'http://crafting-guide.com'
urls = [
base
"#{base}/configure"
"#{base}/browse"
"#{base}/craft"
"#{base}/"
"#{base}/configure/"
"#{base}/browse/"
"#{base}/craft/"
]
for modSlug in fs.readdirSync './src/data'
@@ -41,11 +41,11 @@ for modSlug in fs.readdirSync './src/data'
itemSlugs[item.slug] = item.slug
for modSlug in _.values(modSlugs).sort()
urls.push base + "/browse/#{modSlug}"
urls.push base + "/browse/#{modSlug}/"
for key in _.keys(itemSlugs).sort()
itemSlug = itemSlugs[key]
urls.push base + "/browse/#{itemSlug.mod}/#{itemSlug.item}"
urls.push base + "/browse/#{itemSlug.mod}/#{itemSlug.item}/"
for url in urls
console.log url