Bunch of website stuff

This commit is contained in:
Michael Jackson
2016-05-20 11:58:58 -07:00
parent 7e29e21483
commit 87524d4947
25 changed files with 784 additions and 162 deletions

View File

@ -2,30 +2,32 @@ import fs from 'fs'
import invariant from 'invariant'
import webpack from 'webpack'
const createAssets = (webpackStats) => {
const createBundle = (webpackStats) => {
const { publicPath, assetsByChunkName } = webpackStats
const createURL = (asset) =>
webpackStats.publicPath + asset
publicPath + asset
const getAssets = (chunkName = 'main') => {
const assets = webpackStats.assetsByChunkName[chunkName] || []
return Array.isArray(assets) ? assets : [ assets ]
}
const getAssets = (chunks = [ 'main' ]) =>
(Array.isArray(chunks) ? chunks : [ chunks ]).reduce((memo, chunk) => (
memo.concat(assetsByChunkName[chunk] || [])
), [])
const getScriptURLs = (chunkName = 'main') =>
getAssets(chunkName)
const getScriptAssets = (...args) =>
getAssets(...args)
.filter(asset => (/\.js$/).test(asset))
.map(createURL)
const getStyleURLs = (chunkName = 'main') =>
getAssets(chunkName)
const getStyleAssets = (...args) =>
getAssets(...args)
.filter(asset => (/\.css$/).test(asset))
.map(createURL)
return {
createURL,
getAssets,
getScriptURLs,
getStyleURLs
getScriptAssets,
getStyleAssets
}
}
@ -46,7 +48,7 @@ export const staticAssets = (webpackStatsFile) => {
)
}
const assets = createAssets(stats)
const assets = createBundle(stats)
return (req, res, next) => {
req.assets = assets
@ -62,7 +64,7 @@ export const staticAssets = (webpackStatsFile) => {
export const assetsCompiler = (webpackCompiler) => {
let assets
webpackCompiler.plugin('done', (stats) => {
assets = createAssets(stats.toJson())
assets = createBundle(stats.toJson())
})
return (req, res, next) => {

View File

@ -0,0 +1,50 @@
import 'isomorphic-fetch'
import { createStack, createFetch, header, base, query, parseJSON, onResponse } from 'http-client'
import invariant from 'invariant'
const CloudFlareKey = process.env.CLOUDFLARE_KEY
const CloudFlareEmail = process.env.CLOUDFLARE_EMAIL
invariant(
CloudFlareKey,
'Missing $CLOUDFLARE_KEY environment variable'
)
invariant(
CloudFlareEmail,
'Missing $CLOUDFLARE_EMAIL environment variable'
)
const createRangeQuery = (since, until) =>
query({
since: since.toISOString(),
until: until.toISOString()
})
const createNameQuery = (name) =>
query({ name })
const getResult = () =>
createStack(
parseJSON(),
onResponse(response => response.jsonData.result)
)
const commonStack = createStack(
header('X-Auth-Key', CloudFlareKey),
header('X-Auth-Email', CloudFlareEmail),
base('https://api.cloudflare.com/client/v4'),
getResult()
)
export const getZones = (domainName) =>
createFetch(
commonStack,
createNameQuery(domainName)
)('/zones')
export const getZoneAnalyticsDashboard = (zone, since, until) =>
createFetch(
commonStack,
createRangeQuery(since, until)
)(`/zones/${zone.id}/analytics/dashboard`)

View File

@ -1,16 +1,43 @@
import React from 'react'
import { renderToStaticMarkup } from 'react-dom/server'
import { getZones, getZoneAnalyticsDashboard } from './CloudFlare'
import HomePage from './components/HomePage'
const OneMinute = 1000 * 60
const ThirtyDays = OneMinute * 60 * 24 * 30
const DOCTYPE = '<!DOCTYPE html>'
export const sendHomePage = (req, res) => {
const fetchStats = (callback) => {
if (process.env.NODE_ENV === 'development') {
callback(null, require('./stats.json'))
} else {
getZones('npmcdn.com')
.then(zones => {
const zone = zones[0]
const since = new Date(Date.now() - ThirtyDays)
const until = new Date(Date.now() - OneMinute)
return getZoneAnalyticsDashboard(zone, since, until).then(result => {
callback(null, result)
})
})
.catch(callback)
}
}
export const sendHomePage = (req, res, next) => {
const props = {
styles: req.assets.getStyleURLs('home'),
scripts: req.assets.getScriptURLs('home')
styles: req.assets.getStyleAssets([ 'vendor', 'home' ]),
scripts: req.assets.getScriptAssets([ 'vendor', 'home' ])
}
res.send(
DOCTYPE + renderToStaticMarkup(<HomePage {...props}/>)
)
fetchStats((error, stats) => {
if (error) {
next(error)
} else {
res.send(
DOCTYPE + renderToStaticMarkup(<HomePage {...props} stats={stats}/>)
)
}
})
}

View File

@ -1,22 +1,20 @@
import React, { PropTypes } from 'react'
const assetType = PropTypes.string
class HomePage extends React.Component {
static propTypes = {
styles: PropTypes.arrayOf(PropTypes.string),
scripts: PropTypes.arrayOf(PropTypes.string),
stats: PropTypes.object
}
const HomePage = React.createClass({
propTypes: {
styles: PropTypes.arrayOf(assetType),
scripts: PropTypes.arrayOf(assetType)
},
static defaultProps = {
styles: [],
scripts: [],
stats: {}
}
getDefaultProps() {
return {
styles: [],
scripts: []
}
},
render() {
const { styles, scripts } = this.props
render = () => {
const { styles, scripts, stats } = this.props
return (
<html>
@ -26,6 +24,7 @@ const HomePage = React.createClass({
<meta name="timestamp" content={(new Date).toISOString()}/>
<title>npmcdn</title>
{styles.map(style => <link key={style} rel="stylesheet" href={style}/>)}
<script dangerouslySetInnerHTML={{ __html: `window.NPMCDN_STATS=${JSON.stringify(stats)}` }}/>
</head>
<body>
<div id="app"/>
@ -34,6 +33,6 @@ const HomePage = React.createClass({
</html>
)
}
})
}
export default HomePage