diff --git a/.babelrc b/.babelrc
index 6f19a631..900da0c0 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,6 +1,6 @@
{
"presets": [
- "latest",
+ "env",
"react"
],
"plugins": [
diff --git a/bin/next b/bin/next
index 8654d788..79f635b7 100755
--- a/bin/next
+++ b/bin/next
@@ -1,9 +1,10 @@
#!/usr/bin/env node
-import { join } from 'path'
+import { join, resolve } from 'path'
import { spawn } from 'cross-spawn'
import { watchFile } from 'fs'
import pkg from '../../package.json'
+import getConfig from '../server/config'
if (pkg.peerDependencies) {
Object.keys(pkg.peerDependencies).forEach(dependency => {
@@ -78,9 +79,10 @@ const startProcess = () => {
}
let proc = startProcess()
+const { pagesDirectory = resolve(process.cwd(), 'pages') } = getConfig(process.cwd())
if (cmd === 'dev') {
- watchFile(join(process.cwd(), 'next.config.js'), (cur, prev) => {
+ watchFile(`${resolve(pagesDirectory, '..')}/next.config.js`, (cur, prev) => {
if (cur.size > 0 || prev.size > 0) {
console.log('\n> Found a change in next.config.js, restarting the server...')
// Don't listen to 'close' now since otherwise parent gets killed by listener
diff --git a/client/index.js b/client/index.js
index 48bffab9..cbf237c4 100644
--- a/client/index.js
+++ b/client/index.js
@@ -24,12 +24,13 @@ const {
pathname,
query,
buildId,
- chunks
+ chunks,
+ assetPrefix
},
location
} = window
-const pageLoader = new PageLoader(buildId)
+const pageLoader = new PageLoader(buildId, assetPrefix)
window.__NEXT_LOADED_PAGES__.forEach(({ route, fn }) => {
pageLoader.registerPage(route, fn)
})
diff --git a/client/webpack-hot-middleware-client.js b/client/webpack-hot-middleware-client.js
index 38b55df6..f97c5853 100644
--- a/client/webpack-hot-middleware-client.js
+++ b/client/webpack-hot-middleware-client.js
@@ -1,4 +1,4 @@
-import webpackHotMiddlewareClient from 'webpack-hot-middleware/client?overlay=false&reload=true'
+import webpackHotMiddlewareClient from 'webpack-hot-middleware/client?overlay=false&reload=true&path=/_next/webpack-hmr'
import Router from '../lib/router'
export default () => {
diff --git a/examples/parameterized-routing/server.js b/examples/parameterized-routing/server.js
index 35a42482..1089d526 100644
--- a/examples/parameterized-routing/server.js
+++ b/examples/parameterized-routing/server.js
@@ -12,14 +12,16 @@ const match = route('/blog/:id')
app.prepare()
.then(() => {
createServer((req, res) => {
- const { pathname } = parse(req.url)
+ const { pathname, query } = parse(req.url, true)
const params = match(pathname)
if (params === false) {
handle(req, res)
return
}
-
- app.render(req, res, '/blog', params)
+ // assigning `query` into the params means that we still
+ // get the query string passed to our application
+ // i.e. /blog/foo?show-comments=true
+ app.render(req, res, '/blog', Object.assign(params, query))
})
.listen(3000, (err) => {
if (err) throw err
diff --git a/examples/with-global-stylesheet/README.md b/examples/with-global-stylesheet/README.md
index 2576c371..53cd30b8 100644
--- a/examples/with-global-stylesheet/README.md
+++ b/examples/with-global-stylesheet/README.md
@@ -37,7 +37,7 @@ Another babel plugin [module-resolver](https://github.com/tleunen/babel-plugin-m
The `sass-loader` is configured with `includePaths: ['styles', 'node_modules']` so that your scss can `@import` from those places, again without relative paths, for maximum convenience and ability to use npm-published libraries. Furthermore, `glob` paths are also supported, so one could for example add `'node_modules/@material/*'` to the `includePaths`, which would make [material-components-web](https://github.com/material-components/material-components-web) (if you'd like) even easier to work with.
-Furthermore, PostCSS is used to [pre-process](https://blog.madewithenvy.com/webpack-2-postcss-cssnext-fdcd2fd7d0bd#.r6t2d0smy) both `css` and `scss` stylesheets, the latter after Sass pre-processing. This is to illustrate `@import 'normalize.css';` from `node_modules` thanks to `postcss-easy-import`. [Autoprefixer](https://github.com/postcss/autoprefixer) is also added as a "best practice". Consider [cssnext](http://cssnext.io) instead, which includes `autoprefixer` as well as many other CSS spec features.
+Furthermore, PostCSS is used to [pre-process](https://medium.com/@ddprrt/deconfusing-pre-and-post-processing-d68e3bd078a3) both `css` and `scss` stylesheets, the latter after Sass pre-processing. This is to illustrate `@import 'normalize.css';` from `node_modules` thanks to `postcss-easy-import`. [Autoprefixer](https://github.com/postcss/autoprefixer) is also added as a "best practice". Consider [cssnext](http://cssnext.io) instead, which includes `autoprefixer` as well as many other CSS spec features.
This project shows how you can set it up. Have a look at:
- .babelrc
diff --git a/examples/with-pretty-url-routing/package.json b/examples/with-pretty-url-routing/package.json
index 6ecb3fb5..3080fbb7 100644
--- a/examples/with-pretty-url-routing/package.json
+++ b/examples/with-pretty-url-routing/package.json
@@ -8,6 +8,7 @@
"express": "^4.15.2",
"next": "^2.0.0",
"next-url-prettifier": "^1.0.2",
+ "prop-types": "^15.5.6",
"react": "^15.4.2",
"react-dom": "^15.4.2"
}
diff --git a/examples/with-pretty-url-routing/pages/greeting.js b/examples/with-pretty-url-routing/pages/greeting.js
index e4fe354f..03b9d4fb 100644
--- a/examples/with-pretty-url-routing/pages/greeting.js
+++ b/examples/with-pretty-url-routing/pages/greeting.js
@@ -1,4 +1,5 @@
import React from 'react'
+import PropTypes from 'prop-types'
import {Link} from 'next-url-prettifier'
import {Router} from '../routes'
@@ -29,6 +30,6 @@ export default class GreetingPage extends React.Component {
}
GreetingPage.propTypes = {
- lang: React.PropTypes.string,
- name: React.PropTypes.string
+ lang: PropTypes.string,
+ name: PropTypes.string
}
diff --git a/lib/app.js b/lib/app.js
index 2cc4d575..f8d33cee 100644
--- a/lib/app.js
+++ b/lib/app.js
@@ -1,4 +1,5 @@
-import React, { Component, PropTypes } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import { AppContainer } from 'react-hot-loader'
import shallowEquals from './shallow-equals'
import { warn } from './utils'
diff --git a/lib/head.js b/lib/head.js
index ea580942..6200efe4 100644
--- a/lib/head.js
+++ b/lib/head.js
@@ -1,9 +1,10 @@
import React from 'react'
+import PropTypes from 'prop-types'
import sideEffect from './side-effect'
class Head extends React.Component {
static contextTypes = {
- headManager: React.PropTypes.object
+ headManager: PropTypes.object
}
render () {
diff --git a/lib/link.js b/lib/link.js
index 87c4c32f..547161e7 100644
--- a/lib/link.js
+++ b/lib/link.js
@@ -1,5 +1,6 @@
import { resolve, format, parse } from 'url'
-import React, { Component, Children, PropTypes } from 'react'
+import React, { Component, Children } from 'react'
+import PropTypes from 'prop-types'
import Router from './router'
import { warn, execOnce, getLocationOrigin } from './utils'
diff --git a/lib/page-loader.js b/lib/page-loader.js
index 9b4459b9..100eef60 100644
--- a/lib/page-loader.js
+++ b/lib/page-loader.js
@@ -4,8 +4,10 @@ import mitt from 'mitt'
const webpackModule = module
export default class PageLoader {
- constructor (buildId) {
+ constructor (buildId, assetPrefix) {
this.buildId = buildId
+ this.assetPrefix = assetPrefix
+
this.pageCache = {}
this.pageLoadedHandlers = {}
this.pageRegisterEvents = mitt()
@@ -59,7 +61,7 @@ export default class PageLoader {
route = this.normalizeRoute(route)
const script = document.createElement('script')
- const url = `/_next/${encodeURIComponent(this.buildId)}/page${route}`
+ const url = `${this.assetPrefix}/_next/${encodeURIComponent(this.buildId)}/page${route}`
script.src = url
script.type = 'text/javascript'
script.onerror = () => {
diff --git a/lib/router/router.js b/lib/router/router.js
index 5272030e..8b1a4263 100644
--- a/lib/router/router.js
+++ b/lib/router/router.js
@@ -81,8 +81,8 @@ export default class Router {
if (route !== this.route) return
+ const { pathname, query } = this
const url = window.location.href
- const { pathname, query } = parse(url, true)
this.events.emit('routeChangeStart', url)
const routeInfo = await this.getRouteInfo(route, pathname, query, url)
diff --git a/package.json b/package.json
index 013a3918..2de899ff 100644
--- a/package.json
+++ b/package.json
@@ -1,13 +1,10 @@
{
"name": "next",
- "version": "2.0.1",
+ "version": "2.1.1",
"description": "Minimalistic framework for server-rendered React applications",
"main": "./dist/server/next.js",
"license": "MIT",
"repository": "zeit/next.js",
- "publishConfig": {
- "tag": "beta"
- },
"files": [
"dist",
"babel.js",
@@ -57,17 +54,19 @@
"babel-plugin-transform-es2015-modules-commonjs": "6.24.0",
"babel-plugin-transform-object-rest-spread": "6.22.0",
"babel-plugin-transform-react-jsx-source": "6.22.0",
- "babel-plugin-transform-react-remove-prop-types": "0.3.2",
+ "babel-plugin-transform-react-remove-prop-types": "0.4.0",
"babel-plugin-transform-runtime": "6.22.0",
- "babel-preset-latest": "6.24.0",
+ "babel-preset-env": "1.3.3",
"babel-preset-react": "6.23.0",
"babel-runtime": "6.23.0",
"babel-template": "6.24.1",
"case-sensitive-paths-webpack-plugin": "2.0.0",
"cross-spawn": "5.1.0",
"del": "2.2.2",
+ "etag": "1.8.0",
+ "fresh": "0.5.0",
"friendly-errors-webpack-plugin": "1.5.0",
- "glob": "^7.1.1",
+ "glob": "7.1.1",
"glob-promise": "3.1.0",
"htmlescape": "1.1.1",
"http-status": "1.0.1",
@@ -82,6 +81,7 @@
"mz": "2.6.0",
"path-match": "1.2.4",
"pkg-up": "1.0.0",
+ "prop-types": "15.5.7",
"react-hot-loader": "3.0.0-beta.6",
"send": "0.15.1",
"source-map-support": "0.4.14",
@@ -97,14 +97,14 @@
"write-file-webpack-plugin": "4.0.0"
},
"devDependencies": {
- "babel-eslint": "7.2.0",
+ "babel-eslint": "7.2.2",
"babel-jest": "18.0.0",
"babel-plugin-istanbul": "4.1.1",
"babel-plugin-transform-remove-strict-mode": "0.0.2",
"babel-preset-es2015": "6.24.0",
"benchmark": "2.1.4",
"cheerio": "0.22.0",
- "chromedriver": "2.28.0",
+ "chromedriver": "2.29.0",
"coveralls": "2.13.0",
"cross-env": "4.0.0",
"fly": "2.0.5",
@@ -118,8 +118,8 @@
"node-fetch": "1.6.3",
"node-notifier": "5.1.2",
"nyc": "10.2.0",
- "react": "15.4.2",
- "react-dom": "15.4.2",
+ "react": "15.5.3",
+ "react-dom": "15.5.3",
"standard": "9.0.2",
"wd": "1.2.0"
},
diff --git a/readme.md b/readme.md
index cadc8e78..bc2e0439 100644
--- a/readme.md
+++ b/readme.md
@@ -11,6 +11,7 @@ Next.js is a minimalistic framework for server-rendered React applications.
- [How to use](#how-to-use)
+ - [Getting Started](#getting-started)
- [Setup](#setup)
- [Automatic code splitting](#automatic-code-splitting)
- [CSS](#css)
@@ -33,9 +34,9 @@ Next.js is a minimalistic framework for server-rendered React applications.
- [Custom configuration](#custom-configuration)
- [Customizing webpack config](#customizing-webpack-config)
- [Customizing babel config](#customizing-babel-config)
+ - [CDN support with Asset Prefix](#cdn-support-with-asset-prefix)
- [Production deployment](#production-deployment)
- [FAQ](#faq)
-- [Roadmap](#roadmap)
- [Contributing](#contributing)
- [Authors](#authors)
@@ -43,6 +44,10 @@ Next.js is a minimalistic framework for server-rendered React applications.
## How to use
+### Getting Started
+
+A step by step interactive guide of next features is available at [learnnextjs.com](https://learnnextjs.com/)
+
### Setup
Install it:
@@ -298,7 +303,7 @@ The component `` can also receive an URL object and it will automatically
// pages/index.js
import Link from 'next/link'
export default () => (
-
Click here to read more
+
)
```
@@ -700,6 +705,20 @@ Here's an example `.babelrc` file:
}
```
+### CDN support with Asset Prefix
+
+To set up a CDN, you can set up the `assetPrefix` setting and configure your CDN's origin to resolve to the domain that Next.js is hosted on.
+
+```js
+const isProd = process.NODE_ENV === 'production'
+module.exports = {
+ // You may only need to add assetPrefix in the production.
+ assetPrefix: isProd ? 'https://cdn.mydomain.com' : ''
+}
+```
+
+Note: Next.js will automatically use that prefix the scripts it loads, but this has no effect whatsoever on `/static`. If you want to serve those assets over the CDN, you'll have to introduce the prefix yourself. One way of introducing a prefix that works inside your components and varies by environment is documented [in this example](https://github.com/zeit/next.js/tree/master/examples/with-universal-configuration).
+
## Production deployment
To deploy, instead of running `next`, you want to build for production usage ahead of time. Therefore, building and starting are separate commands:
@@ -840,10 +859,6 @@ As we were researching options for server-rendering React that didn’t involve
-## Roadmap
-
-Our Roadmap towards 2.0.0 [is public](https://github.com/zeit/next.js/wiki/Roadmap#nextjs-200).
-
## Contributing
Please see our [contributing.md](./contributing.md)
diff --git a/server/build/babel/preset.js b/server/build/babel/preset.js
index 2590c2cc..61e3e371 100644
--- a/server/build/babel/preset.js
+++ b/server/build/babel/preset.js
@@ -13,8 +13,8 @@ const plugins = envPlugins[process.env.NODE_ENV] || []
module.exports = {
presets: [
- [require.resolve('babel-preset-latest'), {
- 'es2015': { modules: false }
+ [require.resolve('babel-preset-env'), {
+ modules: false
}],
require.resolve('babel-preset-react')
],
diff --git a/server/build/index.js b/server/build/index.js
index 95195460..e13d36ff 100644
--- a/server/build/index.js
+++ b/server/build/index.js
@@ -1,6 +1,5 @@
import { tmpdir } from 'os'
import { join } from 'path'
-import getConfig from '../config'
import fs from 'mz/fs'
import uuid from 'uuid'
import del from 'del'
@@ -14,10 +13,8 @@ export default async function build (dir) {
try {
await runCompiler(compiler)
-
- // Pass in both the buildDir and the dir to retrieve config
- await writeBuildStats(buildDir, dir)
- await writeBuildId(buildDir, dir)
+ await writeBuildStats(buildDir)
+ await writeBuildId(buildDir)
} catch (err) {
console.error(`> Failed to build on ${buildDir}`)
throw err
@@ -48,24 +45,22 @@ function runCompiler (compiler) {
})
}
-async function writeBuildStats (buildDir, dir) {
- const dist = getConfig(dir).distDir
+async function writeBuildStats (dir) {
// Here we can't use hashes in webpack chunks.
// That's because the "app.js" is not tied to a chunk.
// It's created by merging a few assets. (commons.js and main.js)
// So, we need to generate the hash ourself.
const assetHashMap = {
'app.js': {
- hash: await md5File(join(buildDir, dist, 'app.js'))
+ hash: await md5File(join(dir, '.next', 'app.js'))
}
}
- const buildStatsPath = join(buildDir, dist, 'build-stats.json')
+ const buildStatsPath = join(dir, '.next', 'build-stats.json')
await fs.writeFile(buildStatsPath, JSON.stringify(assetHashMap), 'utf8')
}
-async function writeBuildId (buildDir, dir) {
- const dist = getConfig(dir).distDir
- const buildIdPath = join(buildDir, dist, 'BUILD_ID')
+async function writeBuildId (dir) {
+ const buildIdPath = join(dir, '.next', 'BUILD_ID')
const buildId = uuid.v4()
await fs.writeFile(buildIdPath, buildId, 'utf8')
}
diff --git a/server/build/replace.js b/server/build/replace.js
index 1679ba25..22ff9e4a 100644
--- a/server/build/replace.js
+++ b/server/build/replace.js
@@ -4,10 +4,9 @@ import getConfig from '../config'
export default async function replaceCurrentBuild (dir, buildDir) {
const dist = getConfig(dir).distDir
- const buildDist = getConfig(buildDir).distDir
const _dir = join(dir, dist)
- const _buildDir = join(buildDir, dist)
- const oldDir = join(buildDir, `${buildDist}.old`)
+ const _buildDir = join(buildDir, '.next')
+ const oldDir = join(buildDir, '.next.old')
try {
await move(_dir, oldDir)
diff --git a/server/build/webpack.js b/server/build/webpack.js
index 2c38cc4a..bb70f4d1 100644
--- a/server/build/webpack.js
+++ b/server/build/webpack.js
@@ -37,7 +37,7 @@ export default async function createCompiler (dir, { dev = false, quiet = false,
const mainJS = dev
? require.resolve('../../client/next-dev') : require.resolve('../../client/next')
- let minChunks
+ let totalPages
const entry = async () => {
const entries = {
@@ -69,8 +69,7 @@ export default async function createCompiler (dir, { dev = false, quiet = false,
}
}
- // calculate minChunks of CommonsChunkPlugin for later use
- minChunks = Math.max(2, pages.filter((p) => p !== documentPage).length)
+ totalPages = pages.filter((p) => p !== documentPage).length
return entries
}
@@ -102,9 +101,8 @@ export default async function createCompiler (dir, { dev = false, quiet = false,
return module.context && module.context.indexOf('node_modules') >= 0
}
- // NOTE: it depends on the fact that the entry funtion is always called
- // before applying CommonsChunkPlugin
- return count >= minChunks
+ // Move modules used in at-least 1/2 of the total pages into commons.
+ return count >= totalPages * 0.5
}
}),
// This chunk contains all the webpack related code. So, all the changes
@@ -268,10 +266,10 @@ export default async function createCompiler (dir, { dev = false, quiet = false,
context: dir,
entry,
output: {
- path: join(buildDir || dir, config.distDir),
+ path: buildDir ? join(buildDir, '.next') : join(dir, config.distDir),
filename: '[name]',
libraryTarget: 'commonjs2',
- publicPath: '/_webpack/',
+ publicPath: '/_next/webpack/',
strictModuleExceptionHandling: true,
devtoolModuleFilenameTemplate ({ resourcePath }) {
const hash = createHash('sha1')
diff --git a/server/config.js b/server/config.js
index 5a70252c..bc5059f5 100644
--- a/server/config.js
+++ b/server/config.js
@@ -6,7 +6,8 @@ const cache = new Map()
const defaultConfig = {
webpack: null,
poweredByHeader: true,
- distDir: '.next'
+ distDir: '.next',
+ assetPrefix: ''
}
export default function getConfig (dir) {
diff --git a/server/document.js b/server/document.js
index a9d81830..ef21c7b8 100644
--- a/server/document.js
+++ b/server/document.js
@@ -1,4 +1,5 @@
-import React, { Component, PropTypes } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import htmlescape from 'htmlescape'
import flush from 'styled-jsx/server'
@@ -35,14 +36,14 @@ export class Head extends Component {
getChunkPreloadLink (filename) {
const { __NEXT_DATA__ } = this.context._documentProps
- let { buildStats } = __NEXT_DATA__
+ let { buildStats, assetPrefix } = __NEXT_DATA__
const hash = buildStats ? buildStats[filename].hash : '-'
return (
)
@@ -65,12 +66,13 @@ export class Head extends Component {
}
getPreloadDynamicChunks () {
- const { chunks } = this.context._documentProps
+ const { chunks, __NEXT_DATA__ } = this.context._documentProps
+ let { assetPrefix } = __NEXT_DATA__
return chunks.map((chunk) => (
))
@@ -78,11 +80,11 @@ export class Head extends Component {
render () {
const { head, styles, __NEXT_DATA__ } = this.context._documentProps
- const { pathname, buildId } = __NEXT_DATA__
+ const { pathname, buildId, assetPrefix } = __NEXT_DATA__
return
-
-
+
+
{this.getPreloadDynamicChunks()}
{this.getPreloadMainLinks()}
{(head || []).map((h, i) => React.cloneElement(h, { key: i }))}
@@ -115,13 +117,13 @@ export class NextScript extends Component {
getChunkScript (filename, additionalProps = {}) {
const { __NEXT_DATA__ } = this.context._documentProps
- let { buildStats } = __NEXT_DATA__
+ let { buildStats, assetPrefix } = __NEXT_DATA__
const hash = buildStats ? buildStats[filename].hash : '-'
return (
)
@@ -145,7 +147,8 @@ export class NextScript extends Component {
}
getDynamicChunks () {
- const { chunks } = this.context._documentProps
+ const { chunks, __NEXT_DATA__ } = this.context._documentProps
+ let { assetPrefix } = __NEXT_DATA__
return (
{chunks.map((chunk) => (
@@ -153,7 +156,7 @@ export class NextScript extends Component {
async
key={chunk}
type='text/javascript'
- src={`/_webpack/chunks/${chunk}`}
+ src={`${assetPrefix}/_next/webpack/chunks/${chunk}`}
/>
))}
@@ -162,7 +165,7 @@ export class NextScript extends Component {
render () {
const { staticMarkup, __NEXT_DATA__, chunks } = this.context._documentProps
- const { pathname, buildId } = __NEXT_DATA__
+ const { pathname, buildId, assetPrefix } = __NEXT_DATA__
__NEXT_DATA__.chunks = chunks
@@ -183,8 +186,8 @@ export class NextScript extends Component {
}
`
}} />}
-
-
+
+
{staticMarkup ? null : this.getDynamicChunks()}
{staticMarkup ? null : this.getScripts()}
diff --git a/server/hot-reloader.js b/server/hot-reloader.js
index ebb17d3f..6ecc7232 100644
--- a/server/hot-reloader.js
+++ b/server/hot-reloader.js
@@ -139,7 +139,7 @@ export default class HotReloader {
} : {}
this.webpackDevMiddleware = webpackDevMiddleware(compiler, {
- publicPath: '/_webpack/',
+ publicPath: '/_next/webpack/',
noInfo: true,
quiet: true,
clientLogLevel: 'warning',
@@ -147,7 +147,10 @@ export default class HotReloader {
...windowsSettings
})
- this.webpackHotMiddleware = webpackHotMiddleware(compiler, { log: false })
+ this.webpackHotMiddleware = webpackHotMiddleware(compiler, {
+ path: '/_next/webpack-hmr',
+ log: false
+ })
this.onDemandEntries = onDemandEntryHandler(this.webpackDevMiddleware, compiler, {
dir: this.dir,
dev: true,
diff --git a/server/index.js b/server/index.js
index 6078d962..568baae2 100644
--- a/server/index.js
+++ b/server/index.js
@@ -18,6 +18,11 @@ import getConfig from './config'
// We need to go up one more level since we are in the `dist` directory
import pkg from '../../package'
+const internalPrefixes = [
+ /^\/_next\//,
+ /^\/static\//
+]
+
export default class Server {
constructor ({ dir = '.', dev = false, staticMarkup = false, quiet = false } = {}) {
this.dir = resolve(dir)
@@ -36,31 +41,34 @@ export default class Server {
dir: this.dir,
hotReloader: this.hotReloader,
buildStats: this.buildStats,
- buildId: this.buildId
+ buildId: this.buildId,
+ assetPrefix: this.config.assetPrefix.replace(/\/$/, '')
}
this.defineRoutes()
}
- getRequestHandler () {
- return (req, res, parsedUrl) => {
- // Parse url if parsedUrl not provided
- if (!parsedUrl) {
- parsedUrl = parseUrl(req.url, true)
- }
-
- // Parse the querystring ourselves if the user doesn't handle querystring parsing
- if (typeof parsedUrl.query === 'string') {
- parsedUrl.query = parseQs(parsedUrl.query)
- }
-
- return this.run(req, res, parsedUrl)
- .catch((err) => {
- if (!this.quiet) console.error(err)
- res.statusCode = 500
- res.end(STATUS_CODES[500])
- })
+ handleRequest (req, res, parsedUrl) {
+ // Parse url if parsedUrl not provided
+ if (!parsedUrl) {
+ parsedUrl = parseUrl(req.url, true)
}
+
+ // Parse the querystring ourselves if the user doesn't handle querystring parsing
+ if (typeof parsedUrl.query === 'string') {
+ parsedUrl.query = parseQs(parsedUrl.query)
+ }
+
+ return this.run(req, res, parsedUrl)
+ .catch((err) => {
+ if (!this.quiet) console.error(err)
+ res.statusCode = 500
+ res.end(STATUS_CODES[500])
+ })
+ }
+
+ getRequestHandler () {
+ return this.handleRequest.bind(this)
}
async prepare () {
@@ -92,7 +100,7 @@ export default class Server {
},
// This is to support, webpack dynamic imports in production.
- '/_webpack/chunks/:name': async (req, res, params) => {
+ '/_next/webpack/chunks/:name': async (req, res, params) => {
res.setHeader('Cache-Control', 'max-age=365000000, immutable')
const p = join(this.dir, '.next', 'chunks', params.name)
await this.serveStatic(req, res, p)
@@ -215,12 +223,16 @@ export default class Server {
}
}
- async render (req, res, pathname, query) {
+ async render (req, res, pathname, query, parsedUrl) {
+ if (this.isInternalUrl(req)) {
+ return this.handleRequest(req, res, parsedUrl)
+ }
+
if (this.config.poweredByHeader) {
res.setHeader('X-Powered-By', `Next.js ${pkg.version}`)
}
const html = await this.renderToHTML(req, res, pathname, query)
- return sendHTML(res, html, req.method)
+ return sendHTML(req, res, html, req.method)
}
async renderToHTML (req, res, pathname, query) {
@@ -248,7 +260,7 @@ export default class Server {
async renderError (err, req, res, pathname, query) {
const html = await this.renderErrorToHTML(err, req, res, pathname, query)
- return sendHTML(res, html, req.method)
+ return sendHTML(req, res, html, req.method)
}
async renderErrorToHTML (err, req, res, pathname, query) {
@@ -291,6 +303,16 @@ export default class Server {
}
}
+ isInternalUrl (req) {
+ for (const prefix of internalPrefixes) {
+ if (prefix.test(req.url)) {
+ return true
+ }
+ }
+
+ return false
+ }
+
readBuildId () {
const buildIdPath = join(this.dir, this.dist, 'BUILD_ID')
const buildId = fs.readFileSync(buildIdPath, 'utf8')
diff --git a/server/render.js b/server/render.js
index 454a8061..5b674860 100644
--- a/server/render.js
+++ b/server/render.js
@@ -2,6 +2,8 @@ import { join } from 'path'
import { createElement } from 'react'
import { renderToString, renderToStaticMarkup } from 'react-dom/server'
import send from 'send'
+import generateETag from 'etag'
+import fresh from 'fresh'
import requireModule from './require'
import getConfig from './config'
import resolvePath from './resolve'
@@ -14,7 +16,7 @@ import { flushChunks } from '../lib/dynamic'
export async function render (req, res, pathname, query, opts) {
const html = await renderToHTML(req, res, pathname, opts)
- sendHTML(res, html, req.method)
+ sendHTML(req, res, html, req.method)
}
export function renderToHTML (req, res, pathname, query, opts) {
@@ -23,7 +25,7 @@ export function renderToHTML (req, res, pathname, query, opts) {
export async function renderError (err, req, res, pathname, query, opts) {
const html = await renderErrorToHTML(err, req, res, query, opts)
- sendHTML(res, html, req.method)
+ sendHTML(req, res, html, req.method)
}
export function renderErrorToHTML (err, req, res, pathname, query, opts = {}) {
@@ -36,6 +38,7 @@ async function doRender (req, res, pathname, query, {
buildId,
buildStats,
hotReloader,
+ assetPrefix,
dir = process.cwd(),
dev = false,
staticMarkup = false
@@ -95,6 +98,7 @@ async function doRender (req, res, pathname, query, {
query,
buildId,
buildStats,
+ assetPrefix,
err: (err && dev) ? errorToJSON(err) : null
},
dev,
@@ -148,9 +152,17 @@ export async function renderScriptError (req, res, page, error, customFields, op
`)
}
-export function sendHTML (res, html, method) {
+export function sendHTML (req, res, html, method) {
if (res.finished) return
+ const etag = generateETag(html)
+ if (fresh(req.headers, { etag })) {
+ res.statusCode = 304
+ res.end()
+ return
+ }
+
+ res.setHeader('ETag', etag)
res.setHeader('Content-Type', 'text/html')
res.setHeader('Content-Length', Buffer.byteLength(html))
res.end(method === 'HEAD' ? null : html)
diff --git a/test/integration/basic/test/misc.js b/test/integration/basic/test/misc.js
index 29926790..3eb1e602 100644
--- a/test/integration/basic/test/misc.js
+++ b/test/integration/basic/test/misc.js
@@ -1,4 +1,5 @@
/* global describe, test, expect */
+import fetch from 'node-fetch'
export default function (context) {
describe('Misc', () => {
@@ -12,5 +13,14 @@ export default function (context) {
const html = await context.app.renderToHTML({}, res, '/finish-response', {})
expect(html).toBeFalsy()
})
+
+ test('allow etag header support', async () => {
+ const url = `http://localhost:${context.appPort}/stateless`
+ const etag = (await fetch(url)).headers.get('ETag')
+
+ const headers = { 'If-None-Match': etag }
+ const res2 = await fetch(url, { headers })
+ expect(res2.status).toBe(304)
+ })
})
}
diff --git a/test/integration/basic/test/xpowered-by.js b/test/integration/basic/test/xpowered-by.js
index d0108b0b..253fbc1d 100644
--- a/test/integration/basic/test/xpowered-by.js
+++ b/test/integration/basic/test/xpowered-by.js
@@ -4,7 +4,7 @@ import { pkg } from 'next-test-utils'
export default function ({ app }) {
describe('X-Powered-By header', () => {
test('set it by default', async () => {
- const req = { url: '/stateless' }
+ const req = { url: '/stateless', headers: {} }
const headers = {}
const res = {
setHeader (key, value) {
@@ -18,7 +18,7 @@ export default function ({ app }) {
})
test('do not set it when poweredByHeader==false', async () => {
- const req = { url: '/stateless' }
+ const req = { url: '/stateless', headers: {} }
const originalConfigValue = app.config.poweredByHeader
app.config.poweredByHeader = false
const res = {
diff --git a/yarn.lock b/yarn.lock
index de75ba66..4f017f93 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -289,15 +289,14 @@ babel-core@6.24.0, babel-core@^6.0.0, babel-core@^6.24.0, babel-core@^6.3.0:
slash "^1.0.0"
source-map "^0.5.0"
-babel-eslint@7.2.0:
- version "7.2.0"
- resolved "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.2.0.tgz#8941514b9dead06f0df71b29d5d5b193a92ee0ae"
+babel-eslint@7.2.2:
+ version "7.2.2"
+ resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.2.tgz#0da2cbe6554fd0fb069f19674f2db2f9c59270ff"
dependencies:
babel-code-frame "^6.22.0"
babel-traverse "^6.23.1"
babel-types "^6.23.0"
babylon "^6.16.1"
- lodash "^4.17.4"
babel-generator@6.24.0, babel-generator@^6.18.0, babel-generator@^6.24.0:
version "6.24.0"
@@ -504,7 +503,7 @@ babel-plugin-syntax-class-properties@^6.8.0:
version "6.13.0"
resolved "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
-babel-plugin-syntax-dynamic-import@^6.18.0:
+babel-plugin-syntax-dynamic-import@6.18.0:
version "6.18.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da"
@@ -557,7 +556,7 @@ babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-block-scoping@^6.22.0:
+babel-plugin-transform-es2015-block-scoping@^6.22.0, babel-plugin-transform-es2015-block-scoping@^6.23.0:
version "6.23.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.23.0.tgz#e48895cf0b375be148cd7c8879b422707a053b51"
dependencies:
@@ -567,7 +566,7 @@ babel-plugin-transform-es2015-block-scoping@^6.22.0:
babel-types "^6.23.0"
lodash "^4.2.0"
-babel-plugin-transform-es2015-classes@^6.22.0:
+babel-plugin-transform-es2015-classes@^6.22.0, babel-plugin-transform-es2015-classes@^6.23.0:
version "6.23.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.23.0.tgz#49b53f326202a2fd1b3bbaa5e2edd8a4f78643c1"
dependencies:
@@ -588,7 +587,7 @@ babel-plugin-transform-es2015-computed-properties@^6.22.0:
babel-runtime "^6.22.0"
babel-template "^6.22.0"
-babel-plugin-transform-es2015-destructuring@^6.22.0:
+babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0:
version "6.23.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
dependencies:
@@ -601,7 +600,7 @@ babel-plugin-transform-es2015-duplicate-keys@^6.22.0:
babel-runtime "^6.22.0"
babel-types "^6.22.0"
-babel-plugin-transform-es2015-for-of@^6.22.0:
+babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0:
version "6.23.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
dependencies:
@@ -621,7 +620,7 @@ babel-plugin-transform-es2015-literals@^6.22.0:
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-modules-amd@^6.24.0:
+babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.0:
version "6.24.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.0.tgz#a1911fb9b7ec7e05a43a63c5995007557bcf6a2e"
dependencies:
@@ -629,7 +628,7 @@ babel-plugin-transform-es2015-modules-amd@^6.24.0:
babel-runtime "^6.22.0"
babel-template "^6.22.0"
-babel-plugin-transform-es2015-modules-commonjs@6.24.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.0:
+babel-plugin-transform-es2015-modules-commonjs@6.24.0, babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.0:
version "6.24.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.0.tgz#e921aefb72c2cc26cb03d107626156413222134f"
dependencies:
@@ -638,7 +637,7 @@ babel-plugin-transform-es2015-modules-commonjs@6.24.0, babel-plugin-transform-es
babel-template "^6.23.0"
babel-types "^6.23.0"
-babel-plugin-transform-es2015-modules-systemjs@^6.22.0:
+babel-plugin-transform-es2015-modules-systemjs@^6.22.0, babel-plugin-transform-es2015-modules-systemjs@^6.23.0:
version "6.23.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.23.0.tgz#ae3469227ffac39b0310d90fec73bfdc4f6317b0"
dependencies:
@@ -646,7 +645,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.22.0:
babel-runtime "^6.22.0"
babel-template "^6.23.0"
-babel-plugin-transform-es2015-modules-umd@^6.24.0:
+babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.0:
version "6.24.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.0.tgz#fd5fa63521cae8d273927c3958afd7c067733450"
dependencies:
@@ -661,7 +660,7 @@ babel-plugin-transform-es2015-object-super@^6.22.0:
babel-helper-replace-supers "^6.22.0"
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-parameters@^6.22.0:
+babel-plugin-transform-es2015-parameters@^6.22.0, babel-plugin-transform-es2015-parameters@^6.23.0:
version "6.23.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz#3a2aabb70c8af945d5ce386f1a4250625a83ae3b"
dependencies:
@@ -699,7 +698,7 @@ babel-plugin-transform-es2015-template-literals@^6.22.0:
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-typeof-symbol@^6.22.0:
+babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0:
version "6.23.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
dependencies:
@@ -763,9 +762,9 @@ babel-plugin-transform-react-jsx@^6.23.0:
babel-plugin-syntax-jsx "^6.8.0"
babel-runtime "^6.22.0"
-babel-plugin-transform-react-remove-prop-types@0.3.2:
- version "0.3.2"
- resolved "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.3.2.tgz#6da8d834c6d7ad8ab02f956509790cfaa01ffe19"
+babel-plugin-transform-react-remove-prop-types@0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.0.tgz#f63840e7953563d661be8c647b094d74d7363f17"
babel-plugin-transform-regenerator@^6.22.0:
version "6.22.0"
@@ -790,7 +789,41 @@ babel-plugin-transform-strict-mode@^6.22.0:
babel-runtime "^6.22.0"
babel-types "^6.22.0"
-babel-preset-es2015@6.24.0, babel-preset-es2015@^6.24.0:
+babel-preset-env@1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.3.3.tgz#5913407784e3d98de2aa814a3ef9059722b34e0b"
+ dependencies:
+ babel-plugin-check-es2015-constants "^6.22.0"
+ babel-plugin-syntax-trailing-function-commas "^6.22.0"
+ babel-plugin-transform-async-to-generator "^6.22.0"
+ babel-plugin-transform-es2015-arrow-functions "^6.22.0"
+ babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
+ babel-plugin-transform-es2015-block-scoping "^6.23.0"
+ babel-plugin-transform-es2015-classes "^6.23.0"
+ babel-plugin-transform-es2015-computed-properties "^6.22.0"
+ babel-plugin-transform-es2015-destructuring "^6.23.0"
+ babel-plugin-transform-es2015-duplicate-keys "^6.22.0"
+ babel-plugin-transform-es2015-for-of "^6.23.0"
+ babel-plugin-transform-es2015-function-name "^6.22.0"
+ babel-plugin-transform-es2015-literals "^6.22.0"
+ babel-plugin-transform-es2015-modules-amd "^6.22.0"
+ babel-plugin-transform-es2015-modules-commonjs "^6.23.0"
+ babel-plugin-transform-es2015-modules-systemjs "^6.23.0"
+ babel-plugin-transform-es2015-modules-umd "^6.23.0"
+ babel-plugin-transform-es2015-object-super "^6.22.0"
+ babel-plugin-transform-es2015-parameters "^6.23.0"
+ babel-plugin-transform-es2015-shorthand-properties "^6.22.0"
+ babel-plugin-transform-es2015-spread "^6.22.0"
+ babel-plugin-transform-es2015-sticky-regex "^6.22.0"
+ babel-plugin-transform-es2015-template-literals "^6.22.0"
+ babel-plugin-transform-es2015-typeof-symbol "^6.23.0"
+ babel-plugin-transform-es2015-unicode-regex "^6.22.0"
+ babel-plugin-transform-exponentiation-operator "^6.22.0"
+ babel-plugin-transform-regenerator "^6.22.0"
+ browserslist "^1.4.0"
+ invariant "^2.2.2"
+
+babel-preset-es2015@6.24.0:
version "6.24.0"
resolved "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.0.tgz#c162d68b1932696e036cd3110dc1ccd303d2673a"
dependencies:
@@ -819,19 +852,6 @@ babel-preset-es2015@6.24.0, babel-preset-es2015@^6.24.0:
babel-plugin-transform-es2015-unicode-regex "^6.22.0"
babel-plugin-transform-regenerator "^6.22.0"
-babel-preset-es2016@^6.22.0:
- version "6.22.0"
- resolved "https://registry.npmjs.org/babel-preset-es2016/-/babel-preset-es2016-6.22.0.tgz#b061aaa3983d40c9fbacfa3743b5df37f336156c"
- dependencies:
- babel-plugin-transform-exponentiation-operator "^6.22.0"
-
-babel-preset-es2017@^6.22.0:
- version "6.22.0"
- resolved "https://registry.npmjs.org/babel-preset-es2017/-/babel-preset-es2017-6.22.0.tgz#de2f9da5a30c50d293fb54a0ba15d6ddc573f0f2"
- dependencies:
- babel-plugin-syntax-trailing-function-commas "^6.22.0"
- babel-plugin-transform-async-to-generator "^6.22.0"
-
babel-preset-flow@^6.23.0:
version "6.23.0"
resolved "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d"
@@ -850,14 +870,6 @@ babel-preset-jest@^19.0.0:
dependencies:
babel-plugin-jest-hoist "^19.0.0"
-babel-preset-latest@6.24.0:
- version "6.24.0"
- resolved "https://registry.npmjs.org/babel-preset-latest/-/babel-preset-latest-6.24.0.tgz#a68d20f509edcc5d7433a48dfaebf7e4f2cd4cb7"
- dependencies:
- babel-preset-es2015 "^6.24.0"
- babel-preset-es2016 "^6.22.0"
- babel-preset-es2017 "^6.22.0"
-
babel-preset-react@6.23.0:
version "6.23.0"
resolved "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.23.0.tgz#eb7cee4de98a3f94502c28565332da9819455195"
@@ -888,6 +900,16 @@ babel-runtime@6.23.0, babel-runtime@^6.18.0, babel-runtime@^6.20.0, babel-runtim
core-js "^2.4.0"
regenerator-runtime "^0.10.0"
+babel-template@6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.24.1.tgz#04ae514f1f93b3a2537f2a0f60a5a45fb8308333"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-traverse "^6.24.1"
+ babel-types "^6.24.1"
+ babylon "^6.11.0"
+ lodash "^4.2.0"
+
babel-template@^6.16.0, babel-template@^6.22.0, babel-template@^6.23.0, babel-template@^6.7.0:
version "6.23.0"
resolved "https://registry.npmjs.org/babel-template/-/babel-template-6.23.0.tgz#04d4f270adbb3aa704a8143ae26faa529238e638"
@@ -898,16 +920,6 @@ babel-template@^6.16.0, babel-template@^6.22.0, babel-template@^6.23.0, babel-te
babylon "^6.11.0"
lodash "^4.2.0"
-babel-template@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.24.1.tgz#04ae514f1f93b3a2537f2a0f60a5a45fb8308333"
- dependencies:
- babel-runtime "^6.22.0"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
- babylon "^6.11.0"
- lodash "^4.2.0"
-
babel-traverse@6.21.0:
version "6.21.0"
resolved "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.21.0.tgz#69c6365804f1a4f69eb1213f85b00a818b8c21ad"
@@ -1111,6 +1123,13 @@ browserify-zlib@^0.1.4:
dependencies:
pako "~0.2.0"
+browserslist@^1.4.0:
+ version "1.7.7"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9"
+ dependencies:
+ caniuse-db "^1.0.30000639"
+ electron-to-chromium "^1.2.7"
+
bser@1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169"
@@ -1181,6 +1200,10 @@ camelcase@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
+caniuse-db@^1.0.30000639:
+ version "1.0.30000650"
+ resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000650.tgz#615f564d367533d32b82d72ada09661e75386bab"
+
case-sensitive-paths-webpack-plugin@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.0.0.tgz#60142d7d0beabdb35676ef0aeace3027da0578ba"
@@ -1242,9 +1265,9 @@ chokidar@^1.4.3, chokidar@^1.6.1:
optionalDependencies:
fsevents "^1.0.0"
-chromedriver@2.28.0:
- version "2.28.0"
- resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-2.28.0.tgz#ea0c383621dd27db340c612b85fe39414c16ec79"
+chromedriver@2.29.0:
+ version "2.29.0"
+ resolved "https://registry.npmjs.org/chromedriver/-/chromedriver-2.29.0.tgz#e3fd8b3c08dce2562b80ef1b0b846597659d0cc3"
dependencies:
adm-zip "^0.4.7"
kew "^0.7.0"
@@ -1703,6 +1726,10 @@ ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+electron-to-chromium@^1.2.7:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.3.tgz#651eb63fe89f39db70ffc8dbd5d9b66958bc6a0e"
+
elegant-spinner@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
@@ -1981,7 +2008,7 @@ esutils@^2.0.0, esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
-etag@~1.8.0:
+etag@1.8.0, etag@~1.8.0:
version "1.8.0"
resolved "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz#6f631aef336d6c46362b51764044ce216be3c051"
@@ -2066,9 +2093,9 @@ fb-watchman@^2.0.0:
dependencies:
bser "^2.0.0"
-fbjs@^0.8.1, fbjs@^0.8.4:
- version "0.8.9"
- resolved "https://registry.npmjs.org/fbjs/-/fbjs-0.8.9.tgz#180247fbd347dcc9004517b904f865400a0c8f14"
+fbjs@^0.8.9:
+ version "0.8.12"
+ resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.12.tgz#10b5d92f76d45575fd63a217d4ea02bea2f8ed04"
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
@@ -2340,17 +2367,7 @@ glob-promise@3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/glob-promise/-/glob-promise-3.1.0.tgz#198882a3817be7dc2c55f92623aa9e7b3f82d1eb"
-glob@^6.0.1:
- version "6.0.4"
- resolved "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22"
- dependencies:
- inflight "^1.0.4"
- inherits "2"
- minimatch "2 || 3"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1:
+glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1:
version "7.1.1"
resolved "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
dependencies:
@@ -2361,6 +2378,16 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1:
once "^1.3.0"
path-is-absolute "^1.0.0"
+glob@^6.0.1:
+ version "6.0.4"
+ resolved "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22"
+ dependencies:
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "2 || 3"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
global@^4.3.0:
version "4.3.1"
resolved "https://registry.npmjs.org/global/-/global-4.3.1.tgz#5f757908c7cbabce54f386ae440e11e26b7916df"
@@ -2613,7 +2640,7 @@ interpret@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c"
-invariant@^2.2.0:
+invariant@^2.2.0, invariant@^2.2.2:
version "2.2.2"
resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
dependencies:
@@ -4042,6 +4069,18 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
+prop-types@15.5.7:
+ version "15.5.7"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.7.tgz#231c4f29cdd82e355011d4889386ca9059544dd1"
+ dependencies:
+ fbjs "^0.8.9"
+
+prop-types@^15.5.2, prop-types@~15.5.0:
+ version "15.5.6"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.6.tgz#797a915b1714b645ebb7c5d6cc690346205bd2aa"
+ dependencies:
+ fbjs "^0.8.9"
+
prr@~0.0.0:
version "0.0.0"
resolved "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"
@@ -4112,13 +4151,14 @@ react-deep-force-update@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/react-deep-force-update/-/react-deep-force-update-2.0.1.tgz#4f7f6c12c3e7de42f345992a3c518236fa1ecad3"
-react-dom@15.4.2:
- version "15.4.2"
- resolved "https://registry.npmjs.org/react-dom/-/react-dom-15.4.2.tgz#015363f05b0a1fd52ae9efdd3a0060d90695208f"
+react-dom@15.5.3:
+ version "15.5.3"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.5.3.tgz#2ee127ce942df55da53111ae303316e68072b5c5"
dependencies:
- fbjs "^0.8.1"
+ fbjs "^0.8.9"
loose-envify "^1.1.0"
object-assign "^4.1.0"
+ prop-types "~15.5.0"
react-hot-loader@3.0.0-beta.6:
version "3.0.0-beta.6"
@@ -4137,13 +4177,14 @@ react-proxy@^3.0.0-alpha.0:
dependencies:
lodash "^4.6.1"
-react@15.4.2:
- version "15.4.2"
- resolved "https://registry.npmjs.org/react/-/react-15.4.2.tgz#41f7991b26185392ba9bae96c8889e7e018397ef"
+react@15.5.3:
+ version "15.5.3"
+ resolved "https://registry.yarnpkg.com/react/-/react-15.5.3.tgz#84055382c025dec4e3b902bb61a8697cc79c1258"
dependencies:
- fbjs "^0.8.4"
+ fbjs "^0.8.9"
loose-envify "^1.1.0"
object-assign "^4.1.0"
+ prop-types "^15.5.2"
read-pkg-up@^1.0.1:
version "1.0.1"