diff --git a/.eslintrc.js b/.eslintrc.js index f6d5e65..763204a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -13,7 +13,8 @@ module.exports = { "semi": ["error", "never"], "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], "react/forbid-prop-types": [1, { "forbid": ["any"] }], - "camelcase": [0, "never"] + "camelcase": [0, "never"], + "global-require": [0], }, "globals": { "fetch": true, diff --git a/package.json b/package.json index 95e7707..60fa409 100644 --- a/package.json +++ b/package.json @@ -23,20 +23,32 @@ "style-loader": "^0.14.1", "url-loader": "^0.5.8", "webpack": "^2.2.1", - "webpack-dev-server": "^2.4.2" + "webpack-dev-server": "^2.4.2", + "webpack-manifest-plugin": "^1.1.0" }, "scripts": { - "lint": "eslint --fix src/", "build": "rimraf build/ && webpack -p", - "start": "webpack-dev-server --config webpack.config.dev.js" + "dev": "webpack-dev-server --config webpack.config.dev.js", + "lint": "eslint --fix src/ server.js", + "start": "export NODE_ENV=production NODE_SERVER=true && node server" }, "dependencies": { "babel-core": "^6.24.0", "babel-preset-es2015": "^6.24.0", + "babel-preset-react": "^6.23.0", + "babel-preset-stage-2": "^6.22.0", + "babel-register": "^6.24.0", + "express": "^4.15.2", + "ignore-styles": "^5.0.1", + "isomorphic-fetch": "^2.2.1", + "lru-cache": "^4.0.2", + "radium": "^0.18.2", "react": "^15.4.2", "react-dom": "^15.4.2", "react-hot-loader": "3.0.0-beta.6", "react-redux": "^5.0.3", + "react-router": "next", + "react-router-dom": "next", "redux": "^3.6.0", "redux-thunk": "^2.2.0" } diff --git a/server.js b/server.js new file mode 100644 index 0000000..221a63c --- /dev/null +++ b/server.js @@ -0,0 +1,75 @@ +require('babel-register')({ + extensions: ['.js'], + presets: ['es2015'], +}) +require('ignore-styles') +const express = require('express') +const LRU = require('lru-cache') +const { createElement } = require('react') +const { StaticRouter } = require('react-router') +const { Provider } = require('react-redux') +const { renderToString } = require('react-dom/server') + +const { htmlTemplate } = require('./src/index.html.js') +const manifest = require('./build/manifest.json') +const App = require('./src/components/app/app').default +const storeFactory = require('./src/store').default + +const app = express() +const cache = LRU({ + max: 11, + maxAge: 3600000, +}) + +function bootstrapApp(location, store, agent) { + const context = {} + const appEntry = createElement( + Provider, { store }, createElement( + StaticRouter, { location, context }, createElement( + App, { radiumConfig: { userAgent: agent } }))) + const appHTML = renderToString(appEntry) + return { appHTML, context } +} + +function checkCache(request, response, next) { + if (cache.has(request.url)) { + response.send(cache.get(request.url)) + return + } + + next() +} + +function handleSSRRequest(request, response) { + const store = storeFactory() + const unsubscribe = store.subscribe(() => { + const state = store.getState() + if (!state.robotData.isPending) { + unsubscribe() + const { appHTML } = bootstrapApp(request.url, store, request.headers['user-agent']) + const htmlResponse = htmlTemplate({ + jsPath: manifest['main.js'], + cssPath: manifest['main.css'], + preloadChunks: [manifest['profile.js']], + appHTML, + state, + }) + response.send(htmlResponse) + cache.set(request.url, htmlResponse) + } + }) + + const { context } = bootstrapApp(request.url, store, request.headers['user-agent']) + if (context.url) { + response.redirect(context.url) + unsubscribe() + return + } + store.dispatch({ type: 'INIT_SSR' }) +} + +app.use('/static', express.static('./build/static')) +app.use(checkCache) +app.use(handleSSRRequest) + +app.listen(8080) diff --git a/src/actions/index.js b/src/actions/index.js index c1207a9..f206cec 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,3 +1,4 @@ +import 'isomorphic-fetch' import { SET_SEARCH_TERM, GET_ROBOTS_IS_PENDING, @@ -11,7 +12,11 @@ export const setSearchTerm = term => ({ }) -export const getRobots = () => (dispatch) => { +export const getRobots = () => (dispatch, getState) => { + const state = getState() + if (state.robotData.robots.length >= 10) { + return + } dispatch({ type: GET_ROBOTS_IS_PENDING }) fetch('https://jsonplaceholder.typicode.com/users') diff --git a/src/components/app/app.js b/src/components/app/app.js index 434b09f..335b11e 100644 --- a/src/components/app/app.js +++ b/src/components/app/app.js @@ -1,16 +1,30 @@ import React from 'react' +import { Route, Switch, Redirect } from 'react-router-dom' +import Radium from 'radium' import './app.css' -// import RobotFilterViewContainer from '../../containers/robot-filter-view.container' -import RobotProfileViewContainer from '../../containers/robot-profile-view.container' +import RobotFilterViewContainer from '../../containers/robot-filter-view.container' +import Lazy from '../lazy' + +const robotProfileLoader = process.env.NODE_SERVER + ? cb => cb(require('../../containers/robot-profile-view.container').default) + : cb => require.ensure([], (require) => { + cb(require('../../containers/robot-profile-view.container').default) + }, 'profile') function App() { return (

RoboDex

- {/* */} - + + + } + /> + +
) } -export default App +export default Radium(App) diff --git a/src/components/card.js b/src/components/card.js index a35feb2..b4fe3ec 100644 --- a/src/components/card.js +++ b/src/components/card.js @@ -1,13 +1,16 @@ import React from 'react' +import { Link } from 'react-router-dom' const Card = ({ id, name, email }) => ( -
- {name} -
-

{name}

-

{email}

+ +
+ {name} +
+

{name}

+

{email}

+
-
+ ) Card.propTypes = { diff --git a/src/components/lazy.js b/src/components/lazy.js new file mode 100644 index 0000000..f21ac18 --- /dev/null +++ b/src/components/lazy.js @@ -0,0 +1,27 @@ +import React, { Component } from 'react' + +class Lazy extends Component { + componentWillMount() { + this.setState({ + component: null, + }) + + this.props.load((comp) => { + this.setState({ + component: comp, + }) + }) + } + + render() { + return this.state.component + ? + :

Loading component...

+ } +} + +Lazy.propTypes = { + load: React.PropTypes.func.isRequired, +} + +export default Lazy diff --git a/src/components/profile/profile-view.js b/src/components/profile/profile-view.js index d314b4b..8fcb90e 100644 --- a/src/components/profile/profile-view.js +++ b/src/components/profile/profile-view.js @@ -1,6 +1,11 @@ import React, { Component } from 'react' +import { Link } from 'react-router-dom' +import Radium from 'radium' import Profile from './profile' -import './profile.css' +import { + profilePage, + back, +} from './profile.css' class ProfileView extends Component { componentWillMount() { @@ -10,12 +15,15 @@ class ProfileView extends Component { render() { const { isPending, robot } = this.props return ( -
+ +
+ ◀ Back { (!isPending && robot) ? :

Loading...

} +
) } @@ -31,4 +39,4 @@ ProfileView.propTypes = { getRobots: React.PropTypes.func.isRequired, } -export default ProfileView +export default Radium(ProfileView) diff --git a/src/components/profile/profile.css b/src/components/profile/profile.css deleted file mode 100644 index 72458c1..0000000 --- a/src/components/profile/profile.css +++ /dev/null @@ -1,71 +0,0 @@ -.profilePage { - max-width:800px; - margin:0px auto; - text-align:left; -} - -.profile { - display: flex; - flex-direction: row; - justify-content: left; - align-items: center; - height: 100%; - -} - -.column { - height: 100px; - border: solid white 2px; -} - -.headshot { - width: 30vw; - height: 30vw; - text-align: center; - display: flex; - flex-direction: column; - background: #9eebcf; - border-radius:12px; -} - -.headshot h2 { - margin: 0; - flex-shrink: 1; - font-family: arial; - font-size: 2vw; -} - -.headshot img { - display: block; - margin: 8% auto; - background: white; - border-radius: 100%; - height: 20vw; - flex-grow: 1; -} - -.address { - width: calc(80% - 25vw); - height: 30vw; - text-align:left; - padding-left:30px; -} - -.address p { - margin:0px; -} - -.address .button { - margin:20px 0px; -} - -.button{ - display:inline-block; - padding:8px 16px; - border-radius:6px; - font-weight:700; - color:#ffffff; - background-color:#131313; - text-decoration:none; - margin:20px 0px; -} \ No newline at end of file diff --git a/src/components/profile/profile.css.js b/src/components/profile/profile.css.js new file mode 100644 index 0000000..5b2ea9c --- /dev/null +++ b/src/components/profile/profile.css.js @@ -0,0 +1,79 @@ +const lightGreen = '#9eebcf' + +export const profilePage = { + maxWidth: '800px', + margin: '0px auto', + textAlign: 'left', +} + +export const profile = { + justifyContent: 'left', + height: '100%', + flexDirection: 'row', + display: 'flex', +} + +export const column = { + border: 'solid white 2px', + height: '100px', +} + +export const headshot = { + textAlign: 'center', + background: lightGreen, + borderRadius: '12px', + display: 'flex', + flexDirection: 'column', + width: '30vw', + height: '30vw', +} + +export const headshotH2 = { + margin: 0, + fontFamily: 'arial', + fontSize: '2vw', + flexShrink: 1, +} + +export const headshotImg = { + display: 'block', + margin: '8% auto', + background: 'white', + borderRadius: '100%', + flexGrow: 1, + height: '20vw', +} + +export const address = { + height: '30vw', + textAlign: 'left', + paddingLeft: '30px', + width: 'calc(80% - 25vw)', +} + +export const addressP = { + margin: 0, +} + +export const back = { + display: 'inline-block', + textDecoration: 'none', + color: lightGreen, + fontWeight: 700, + marginBottom: '12px', +} + +export const button = { + display: 'inline-block', + padding: '8px 16px', + borderRadius: '6px', + fontWeight: 700, + color: '#ffffff', + backgroundColor: '#131313', + textDecoration: 'none', + margin: '20px 0px', + transition: 'all .2s ease-out', + ':hover': { + backgroundColor: lightGreen, + }, +} diff --git a/src/components/profile/profile.js b/src/components/profile/profile.js index e0b4559..9e2c250 100644 --- a/src/components/profile/profile.js +++ b/src/components/profile/profile.js @@ -1,22 +1,33 @@ import React from 'react' +import Radium from 'radium' +import { + profile, + column, + headshot, + headshotH2, + headshotImg, + address, + addressP, + button, +} from './profile.css' const Profile = ({ robot }) => ( -
-
+
+
- {robot.name} + {robot.name}
-

{robot.name}

+

{robot.name}

-
+

Address

-

+

{ robot.address.street},  { robot.address.suite}

-

{ robot.address.city}

-

{ robot.address.zipcode}

- Email +

{ robot.address.city}

+

{ robot.address.zipcode}

+ Email
) @@ -24,4 +35,4 @@ Profile.propTypes = { robot: React.PropTypes.object.isRequired, } -export default Profile +export default Radium(Profile) diff --git a/src/containers/robot-profile-view.container.js b/src/containers/robot-profile-view.container.js index 449092f..8b61bcb 100644 --- a/src/containers/robot-profile-view.container.js +++ b/src/containers/robot-profile-view.container.js @@ -3,7 +3,7 @@ import { getRobots } from '../actions' import ProfileView from '../components/profile/profile-view' const mapStateToProps = (state, ownProps) => { - const id = ownProps.id || 1 + const id = parseInt(ownProps.match.params.id, 10) || 1 const isPending = state.robotData.isPending let robot = null diff --git a/src/index.dev.js b/src/index.dev.js index b1b3ced..c62a50d 100644 --- a/src/index.dev.js +++ b/src/index.dev.js @@ -2,15 +2,17 @@ import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import { AppContainer } from 'react-hot-loader' - +import { BrowserRouter as Router } from 'react-router-dom' import App from './components/app/app' -import store from './store' +import storeFactory from './store' const render = (Component) => { ReactDOM.render( - - + + + + , document.getElementById('root'), diff --git a/src/index.html.js b/src/index.html.js new file mode 100644 index 0000000..58c8ee8 --- /dev/null +++ b/src/index.html.js @@ -0,0 +1,18 @@ +module.exports.htmlTemplate = ({ cssPath, jsPath, preloadChunks, appHTML, state }) => ` + + + + + + + ${preloadChunks.map(src => ``)} + react app + + +
${appHTML}
+ + + +` diff --git a/src/index.js b/src/index.js index 6aef7c5..b749f1b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,12 +1,14 @@ import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' +import { BrowserRouter as Router } from 'react-router-dom' import App from './components/app/app' -import store from './store' +import storeFactory from './store' ReactDOM.render( - - + + + + , - document.getElementById('root'), -) + document.getElementById('root')) diff --git a/src/store/index.js b/src/store/index.js index b3cd02e..7d2319f 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -2,4 +2,12 @@ import { createStore, applyMiddleware } from 'redux' import reduxThunk from 'redux-thunk' import appReducer from '../reducers' -export default createStore(appReducer, applyMiddleware(reduxThunk)) +let initialState + +try { + initialState = window.INITIAL_STATE + delete window.INITIAL_STATE +} catch (_) { + initialState = undefined +} +export default () => createStore(appReducer, initialState, applyMiddleware(reduxThunk)) diff --git a/webpack.config.js b/webpack.config.js index 64954be..5f4be94 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -2,6 +2,7 @@ const path = require('path') const webpack = require('webpack') const ExtractTextPlugin = require('extract-text-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') +const ManifestPlugin = require('webpack-manifest-plugin') const sharedRules = require('./config/webpack-rules') module.exports = { @@ -26,8 +27,11 @@ module.exports = { new ExtractTextPlugin({ filename: '/static/[name].[chunkhash].css' }), - new HtmlWebpackPlugin({ - template: './src/index.html' + new ManifestPlugin(), + new webpack.DefinePlugin({ + "process.env": { + NODE_SERVER: false + } }) ] } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index bdb6cc1..a3745d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -118,6 +118,10 @@ arr-flatten@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.1.tgz#e5ffe54d45e19f32f216e91eb99c8ce892bb604b" +array-find@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-find/-/array-find-1.0.0.tgz#6c8e286d11ed768327f8e62ecee87353ca3e78b8" + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -791,7 +795,7 @@ babel-preset-stage-3@^6.22.0: babel-plugin-transform-exponentiation-operator "^6.22.0" babel-plugin-transform-object-rest-spread "^6.22.0" -babel-register@^6.24.0: +babel-register, babel-register@^6.24.0: version "6.24.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.0.tgz#5e89f8463ba9970356d02eb07dabe3308b080cfd" dependencies: @@ -897,6 +901,10 @@ boom@2.x.x: dependencies: hoek "2.x.x" +bowser@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.6.0.tgz#37fc387b616cb6aef370dab4d6bd402b74c5c54d" + brace-expansion@^1.0.0: version "1.1.6" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" @@ -1925,6 +1933,10 @@ evp_bytestokey@^1.0.0: dependencies: create-hash "^1.1.1" +exenv@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.1.tgz#75de1c8dee02e952b102aa17f8875973e0df14f9" + exit-hook@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" @@ -1941,7 +1953,7 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" -express@^4.13.3: +express, express@^4.13.3: version "4.15.2" resolved "https://registry.yarnpkg.com/express/-/express-4.15.2.tgz#af107fc148504457f2dca9a6f2571d7129b97b35" dependencies: @@ -2131,6 +2143,16 @@ fresh@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e" +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -2242,7 +2264,7 @@ globby@^5.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -graceful-fs@^4.1.2: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -2304,6 +2326,16 @@ he@1.1.x: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" +history@^4.5.1, history@^4.6.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/history/-/history-4.6.1.tgz#911cf8eb65728555a94f2b12780a0c531a14d2fd" + dependencies: + invariant "^2.2.1" + loose-envify "^1.2.0" + resolve-pathname "^2.0.0" + value-equal "^0.2.0" + warning "^3.0.0" + hmac-drbg@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.0.tgz#3db471f45aae4a994a0688322171f51b8b91bee5" @@ -2430,6 +2462,10 @@ https-browserify@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" +hyphenate-style-name@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b" + iconv-lite@~0.4.13: version "0.4.15" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" @@ -2442,6 +2478,10 @@ ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" +ignore-styles: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ignore-styles/-/ignore-styles-5.0.1.tgz#b49ef2274bdafcd8a4880a966bfe38d1a0bf4671" + ignore@^3.2.0: version "3.2.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.6.tgz#26e8da0644be0bb4cb39516f6c79f0e0f4ffe48c" @@ -2477,6 +2517,13 @@ ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" +inline-style-prefixer@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-2.0.5.tgz#c153c7e88fd84fef5c602e95a8168b2770671fe7" + dependencies: + bowser "^1.0.0" + hyphenate-style-name "^1.0.1" + inquirer@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" @@ -2499,7 +2546,7 @@ interpret@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c" -invariant@^2.0.0, invariant@^2.2.0: +invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" dependencies: @@ -2690,7 +2737,7 @@ isobject@^2.0.0: dependencies: isarray "1.0.0" -isomorphic-fetch@^2.1.1: +isomorphic-fetch, isomorphic-fetch@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" dependencies: @@ -2767,6 +2814,12 @@ json5@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -2796,6 +2849,12 @@ kind-of@^3.0.2: dependencies: is-buffer "^1.0.2" +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + optionalDependencies: + graceful-fs "^4.1.9" + lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" @@ -2864,7 +2923,7 @@ lodash.uniq@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.6.1: +lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.6.1, "lodash@>=3.5 <5": version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -2872,7 +2931,7 @@ longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" -loose-envify@^1.0.0, loose-envify@^1.1.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" dependencies: @@ -2882,6 +2941,13 @@ lower-case@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" +lru-cache: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" + dependencies: + pseudomap "^1.0.1" + yallist "^2.0.0" + macaddress@^0.2.8: version "0.2.8" resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12" @@ -3286,6 +3352,12 @@ path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" +path-to-regexp@^1.5.3: + version "1.7.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + dependencies: + isarray "0.0.1" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -3640,6 +3712,10 @@ prr@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + public-encrypt@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6" @@ -3685,6 +3761,15 @@ querystringify@0.0.x: version "0.0.4" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-0.0.4.tgz#0cf7f84f9463ff0ae51c4c4b142d95be37724d9c" +radium: + version "0.18.2" + resolved "https://registry.yarnpkg.com/radium/-/radium-0.18.2.tgz#1e296966d0bcac6652085cbe84c7b8ed0196d7c1" + dependencies: + array-find "^1.0.0" + exenv "^1.2.1" + inline-style-prefixer "^2.0.5" + rimraf "^2.6.1" + randomatic@^1.1.3: version "1.1.6" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb" @@ -3756,6 +3841,33 @@ react-redux: lodash-es "^4.2.0" loose-envify "^1.1.0" +react-router-dom@next: + version "4.0.0-beta.8" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.0.0-beta.8.tgz#907a5a0a36e9190652c80f2feead0eadbbba262e" + dependencies: + history "^4.5.1" + react-router "^4.0.0-beta.8" + +react-router@^4.0.0-beta.8: + version "4.0.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.0.0.tgz#6532075231f0bb5077c2005c1d417ad6165b3997" + dependencies: + history "^4.6.0" + invariant "^2.2.2" + loose-envify "^1.3.1" + path-to-regexp "^1.5.3" + warning "^3.0.0" + +react-router@next: + version "4.0.0-beta.8" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.0.0-beta.8.tgz#368cfe540d23d5d23419b42fb915d465f268b66b" + dependencies: + history "^4.6.0" + invariant "^2.2.2" + loose-envify "^1.3.1" + path-to-regexp "^1.5.3" + warning "^3.0.0" + read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -3988,6 +4100,10 @@ resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" +resolve-pathname@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.0.2.tgz#e55c016eb2e9df1de98e85002282bfb38c630436" + resolve@^1.1.6: version "1.3.2" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.2.tgz#1f0442c9e0cbb8136e87b9305f932f46c7f28235" @@ -4007,7 +4123,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf, rimraf@^2.2.8, rimraf@2: +rimraf, rimraf@^2.2.8, rimraf@^2.6.1, rimraf@2: version "2.6.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" dependencies: @@ -4569,6 +4685,10 @@ validate-npm-package-license@^3.0.1: spdx-correct "~1.0.0" spdx-expression-parse "~1.0.0" +value-equal@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.2.0.tgz#4f41c60a3fc011139a2ec3d3340a8998ae8b69c0" + vary@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.0.tgz#e1e5affbbd16ae768dd2674394b9ad3022653140" @@ -4589,6 +4709,12 @@ vm-browserify@0.0.4: dependencies: indexof "0.0.1" +warning@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" + dependencies: + loose-envify "^1.0.0" + watchpack@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.3.1.tgz#7d8693907b28ce6013e7f3610aa2a1acf07dad87" @@ -4659,6 +4785,13 @@ webpack-dev-server: webpack-dev-middleware "^1.9.0" yargs "^6.0.0" +webpack-manifest-plugin: + version "1.1.0" + resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-1.1.0.tgz#6b6c718aade8a2537995784b46bd2e9836057caa" + dependencies: + fs-extra "^0.30.0" + lodash ">=3.5 <5" + webpack-sources@^0.1.0, webpack-sources@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.1.5.tgz#aa1f3abf0f0d74db7111c40e500b84f966640750" @@ -4735,6 +4868,10 @@ y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" +yallist@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + yargs-parser@^4.2.0: version "4.2.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c"