Bunch of website stuff
This commit is contained in:
@ -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) => {
|
||||
|
50
modules/server/CloudFlare.js
Normal file
50
modules/server/CloudFlare.js
Normal 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`)
|
@ -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}/>)
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user