diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..2e92947
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,26 @@
+{
+ "parser": "babel-eslint",
+ "plugins": [
+ "import",
+ "react"
+ ],
+ "env": {
+ "es6": true,
+ "node": true
+ },
+ "extends": [
+ "eslint:recommended",
+ "plugin:import/errors",
+ "plugin:react/recommended"
+ ],
+ "settings": {
+ "import/resolver": "webpack"
+ },
+ "rules": {
+ "array-bracket-spacing": [ 2, "always" ],
+ "eqeqeq": [ 2, "smart" ],
+ "prefer-arrow-callback": 2,
+ "react/no-danger": 0,
+ "semi": [ 2, "never" ]
+ }
+}
diff --git a/modules/client/.eslintrc b/modules/client/.eslintrc
new file mode 100644
index 0000000..e5a34ae
--- /dev/null
+++ b/modules/client/.eslintrc
@@ -0,0 +1,5 @@
+{
+ "env": {
+ "browser": true
+ }
+}
diff --git a/modules/client/components/Layout.js b/modules/client/components/Layout.js
index b8551f9..4a128d1 100644
--- a/modules/client/components/Layout.js
+++ b/modules/client/components/Layout.js
@@ -4,6 +4,11 @@ import { findDOMNode } from 'react-dom'
import Window from './Window'
class Layout extends React.Component {
+ static propTypes = {
+ location: PropTypes.object,
+ children: PropTypes.node
+ }
+
state = {
underlineLeft: 0,
underlineWidth: 0,
diff --git a/modules/client/components/NumberTextInput.js b/modules/client/components/NumberTextInput.js
index bcc9ca3..02fab47 100644
--- a/modules/client/components/NumberTextInput.js
+++ b/modules/client/components/NumberTextInput.js
@@ -5,7 +5,8 @@ class NumberTextInput extends React.Component {
static propTypes = {
value: PropTypes.number,
parseNumber: PropTypes.func,
- formatNumber: PropTypes.func
+ formatNumber: PropTypes.func,
+ onChange: PropTypes.func
}
static defaultProps = {
diff --git a/modules/client/components/Stats.js b/modules/client/components/Stats.js
index b8ed506..c5f1540 100644
--- a/modules/client/components/Stats.js
+++ b/modules/client/components/Stats.js
@@ -1,5 +1,4 @@
import React, { PropTypes } from 'react'
-import { findDOMNode } from 'react-dom'
import formatBytes from 'byte-size'
import formatDate from 'date-fns/format'
import parseDate from 'date-fns/parse'
@@ -21,8 +20,12 @@ const addValues = (a, b) => {
}
class Stats extends React.Component {
+ static propTypes = {
+ stats: PropTypes.object
+ }
+
static defaultProps = {
- stats: window.NPMCDN_STATS
+ stats: window.npmcdnStats
}
state = {
@@ -83,13 +86,13 @@ class Stats extends React.Component {
})
topContinents.forEach(continent => {
- const name = ContinentsIndex[continent]
+ const continentName = ContinentsIndex[continent]
const { countries, requests, bandwidth } = continentData[continent]
if (bandwidth !== 0) {
regionRows.push(
- {ContinentsIndex[continent]} |
+ {continentName} |
{formatNumber(requests)} ({formatPercent(requests / totalRequests)}%) |
{formatBytes(bandwidth)} ({formatPercent(bandwidth / totalBandwidth)}%) |
diff --git a/modules/server/AssetsUtils.js b/modules/server/AssetsUtils.js
index f4f7da5..c79ebe2 100644
--- a/modules/server/AssetsUtils.js
+++ b/modules/server/AssetsUtils.js
@@ -31,6 +31,29 @@ const createBundle = (webpackStats) => {
}
}
+/**
+ * An express middleware that sets req.manifest from the build manifest
+ * in the given file. Should be used in production to get consistent hashes.
+ */
+export const assetsManifest = (webpackManifestFile) => {
+ let manifest
+ try {
+ manifest = JSON.parse(fs.readFileSync(webpackManifestFile, 'utf8'))
+ } catch (error) {
+ invariant(
+ false,
+ 'assetsManifest middleware cannot read the manifest file "%s"; ' +
+ 'do `npm run build` before starting the server',
+ webpackManifestFile
+ )
+ }
+
+ return (req, res, next) => {
+ req.manifest = manifest
+ next()
+ }
+}
+
/**
* An express middleware that sets req.bundle from the build
* info in the given stats file. Should be used in production.
diff --git a/modules/server/MainController.js b/modules/server/MainController.js
index c98751b..ae26f13 100644
--- a/modules/server/MainController.js
+++ b/modules/server/MainController.js
@@ -26,11 +26,15 @@ const fetchStats = (callback) => {
}
export const sendHomePage = (req, res, next) => {
+ const chunks = [ 'vendor', 'home' ]
const props = {
- styles: req.bundle.getStyleAssets([ 'vendor', 'home' ]),
- scripts: req.bundle.getScriptAssets([ 'vendor', 'home' ])
+ styles: req.bundle.getStyleAssets(chunks),
+ scripts: req.bundle.getScriptAssets(chunks)
}
+ if (req.manifest)
+ props.webpackManifest = req.manifest
+
fetchStats((error, stats) => {
if (error) {
next(error)
diff --git a/modules/server/ServerConfig.js b/modules/server/ServerConfig.js
index 0100c75..130f043 100644
--- a/modules/server/ServerConfig.js
+++ b/modules/server/ServerConfig.js
@@ -2,10 +2,12 @@ import path from 'path'
export const id = 1
export const port = parseInt(process.env.PORT, 10) || 5000
-export const timeout = parseInt(process.env.TIMEOUT, 10) || 20000
+export const webpackConfig = require('../../webpack.config')
export const statsFile = path.resolve(__dirname, '../../stats.json')
export const publicDir = path.resolve(__dirname, '../../public')
-export const webpackConfig = require('../../webpack.config')
+export const manifestFile = path.resolve(publicDir, '__assets__/chunk-manifest.json')
+export const timeout = parseInt(process.env.TIMEOUT, 10) || 20000
+export const maxAge = process.env.MAX_AGE || '365d'
export const registryURL = process.env.REGISTRY_URL || 'https://registry.npmjs.org'
export const bowerBundle = process.env.BOWER_BUNDLE || '/bower.zip'
diff --git a/modules/server/components/HomePage.js b/modules/server/components/HomePage.js
index f006c88..264c51f 100644
--- a/modules/server/components/HomePage.js
+++ b/modules/server/components/HomePage.js
@@ -2,33 +2,39 @@ import React, { PropTypes } from 'react'
class HomePage extends React.Component {
static propTypes = {
+ webpackManifest: PropTypes.object,
styles: PropTypes.arrayOf(PropTypes.string),
scripts: PropTypes.arrayOf(PropTypes.string),
stats: PropTypes.object
}
static defaultProps = {
+ webpackManifest: {},
styles: [],
scripts: [],
stats: {}
}
- render = () => {
- const { styles, scripts, stats } = this.props
+ render() {
+ const { webpackManifest, styles, scripts, stats } = this.props
return (
+
npmcdn
- {styles.map(style => )}
-
+