1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Merge master into dynamic-import.

This commit is contained in:
Arunoda Susiripala 2017-04-18 21:42:21 +05:30
commit 90ea471aa7
27 changed files with 294 additions and 183 deletions

View file

@ -1,6 +1,6 @@
{ {
"presets": [ "presets": [
"latest", "env",
"react" "react"
], ],
"plugins": [ "plugins": [

View file

@ -1,9 +1,10 @@
#!/usr/bin/env node #!/usr/bin/env node
import { join } from 'path' import { join, resolve } from 'path'
import { spawn } from 'cross-spawn' import { spawn } from 'cross-spawn'
import { watchFile } from 'fs' import { watchFile } from 'fs'
import pkg from '../../package.json' import pkg from '../../package.json'
import getConfig from '../server/config'
if (pkg.peerDependencies) { if (pkg.peerDependencies) {
Object.keys(pkg.peerDependencies).forEach(dependency => { Object.keys(pkg.peerDependencies).forEach(dependency => {
@ -78,9 +79,10 @@ const startProcess = () => {
} }
let proc = startProcess() let proc = startProcess()
const { pagesDirectory = resolve(process.cwd(), 'pages') } = getConfig(process.cwd())
if (cmd === 'dev') { 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) { if (cur.size > 0 || prev.size > 0) {
console.log('\n> Found a change in next.config.js, restarting the server...') 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 // Don't listen to 'close' now since otherwise parent gets killed by listener

View file

@ -24,12 +24,13 @@ const {
pathname, pathname,
query, query,
buildId, buildId,
chunks chunks,
assetPrefix
}, },
location location
} = window } = window
const pageLoader = new PageLoader(buildId) const pageLoader = new PageLoader(buildId, assetPrefix)
window.__NEXT_LOADED_PAGES__.forEach(({ route, fn }) => { window.__NEXT_LOADED_PAGES__.forEach(({ route, fn }) => {
pageLoader.registerPage(route, fn) pageLoader.registerPage(route, fn)
}) })

View file

@ -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' import Router from '../lib/router'
export default () => { export default () => {

View file

@ -12,14 +12,16 @@ const match = route('/blog/:id')
app.prepare() app.prepare()
.then(() => { .then(() => {
createServer((req, res) => { createServer((req, res) => {
const { pathname } = parse(req.url) const { pathname, query } = parse(req.url, true)
const params = match(pathname) const params = match(pathname)
if (params === false) { if (params === false) {
handle(req, res) handle(req, res)
return return
} }
// assigning `query` into the params means that we still
app.render(req, res, '/blog', params) // 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) => { .listen(3000, (err) => {
if (err) throw err if (err) throw err

View file

@ -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. 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: This project shows how you can set it up. Have a look at:
- .babelrc - .babelrc

View file

@ -8,6 +8,7 @@
"express": "^4.15.2", "express": "^4.15.2",
"next": "^2.0.0", "next": "^2.0.0",
"next-url-prettifier": "^1.0.2", "next-url-prettifier": "^1.0.2",
"prop-types": "^15.5.6",
"react": "^15.4.2", "react": "^15.4.2",
"react-dom": "^15.4.2" "react-dom": "^15.4.2"
} }

View file

@ -1,4 +1,5 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import {Link} from 'next-url-prettifier' import {Link} from 'next-url-prettifier'
import {Router} from '../routes' import {Router} from '../routes'
@ -29,6 +30,6 @@ export default class GreetingPage extends React.Component {
} }
GreetingPage.propTypes = { GreetingPage.propTypes = {
lang: React.PropTypes.string, lang: PropTypes.string,
name: React.PropTypes.string name: PropTypes.string
} }

View file

@ -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 { AppContainer } from 'react-hot-loader'
import shallowEquals from './shallow-equals' import shallowEquals from './shallow-equals'
import { warn } from './utils' import { warn } from './utils'

View file

@ -1,9 +1,10 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import sideEffect from './side-effect' import sideEffect from './side-effect'
class Head extends React.Component { class Head extends React.Component {
static contextTypes = { static contextTypes = {
headManager: React.PropTypes.object headManager: PropTypes.object
} }
render () { render () {

View file

@ -1,5 +1,6 @@
import { resolve, format, parse } from 'url' 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 Router from './router'
import { warn, execOnce, getLocationOrigin } from './utils' import { warn, execOnce, getLocationOrigin } from './utils'

View file

@ -4,8 +4,10 @@ import mitt from 'mitt'
const webpackModule = module const webpackModule = module
export default class PageLoader { export default class PageLoader {
constructor (buildId) { constructor (buildId, assetPrefix) {
this.buildId = buildId this.buildId = buildId
this.assetPrefix = assetPrefix
this.pageCache = {} this.pageCache = {}
this.pageLoadedHandlers = {} this.pageLoadedHandlers = {}
this.pageRegisterEvents = mitt() this.pageRegisterEvents = mitt()
@ -59,7 +61,7 @@ export default class PageLoader {
route = this.normalizeRoute(route) route = this.normalizeRoute(route)
const script = document.createElement('script') 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.src = url
script.type = 'text/javascript' script.type = 'text/javascript'
script.onerror = () => { script.onerror = () => {

View file

@ -81,8 +81,8 @@ export default class Router {
if (route !== this.route) return if (route !== this.route) return
const { pathname, query } = this
const url = window.location.href const url = window.location.href
const { pathname, query } = parse(url, true)
this.events.emit('routeChangeStart', url) this.events.emit('routeChangeStart', url)
const routeInfo = await this.getRouteInfo(route, pathname, query, url) const routeInfo = await this.getRouteInfo(route, pathname, query, url)

View file

@ -1,13 +1,10 @@
{ {
"name": "next", "name": "next",
"version": "2.0.1", "version": "2.1.1",
"description": "Minimalistic framework for server-rendered React applications", "description": "Minimalistic framework for server-rendered React applications",
"main": "./dist/server/next.js", "main": "./dist/server/next.js",
"license": "MIT", "license": "MIT",
"repository": "zeit/next.js", "repository": "zeit/next.js",
"publishConfig": {
"tag": "beta"
},
"files": [ "files": [
"dist", "dist",
"babel.js", "babel.js",
@ -57,17 +54,19 @@
"babel-plugin-transform-es2015-modules-commonjs": "6.24.0", "babel-plugin-transform-es2015-modules-commonjs": "6.24.0",
"babel-plugin-transform-object-rest-spread": "6.22.0", "babel-plugin-transform-object-rest-spread": "6.22.0",
"babel-plugin-transform-react-jsx-source": "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-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-preset-react": "6.23.0",
"babel-runtime": "6.23.0", "babel-runtime": "6.23.0",
"babel-template": "6.24.1", "babel-template": "6.24.1",
"case-sensitive-paths-webpack-plugin": "2.0.0", "case-sensitive-paths-webpack-plugin": "2.0.0",
"cross-spawn": "5.1.0", "cross-spawn": "5.1.0",
"del": "2.2.2", "del": "2.2.2",
"etag": "1.8.0",
"fresh": "0.5.0",
"friendly-errors-webpack-plugin": "1.5.0", "friendly-errors-webpack-plugin": "1.5.0",
"glob": "^7.1.1", "glob": "7.1.1",
"glob-promise": "3.1.0", "glob-promise": "3.1.0",
"htmlescape": "1.1.1", "htmlescape": "1.1.1",
"http-status": "1.0.1", "http-status": "1.0.1",
@ -82,6 +81,7 @@
"mz": "2.6.0", "mz": "2.6.0",
"path-match": "1.2.4", "path-match": "1.2.4",
"pkg-up": "1.0.0", "pkg-up": "1.0.0",
"prop-types": "15.5.7",
"react-hot-loader": "3.0.0-beta.6", "react-hot-loader": "3.0.0-beta.6",
"send": "0.15.1", "send": "0.15.1",
"source-map-support": "0.4.14", "source-map-support": "0.4.14",
@ -97,14 +97,14 @@
"write-file-webpack-plugin": "4.0.0" "write-file-webpack-plugin": "4.0.0"
}, },
"devDependencies": { "devDependencies": {
"babel-eslint": "7.2.0", "babel-eslint": "7.2.2",
"babel-jest": "18.0.0", "babel-jest": "18.0.0",
"babel-plugin-istanbul": "4.1.1", "babel-plugin-istanbul": "4.1.1",
"babel-plugin-transform-remove-strict-mode": "0.0.2", "babel-plugin-transform-remove-strict-mode": "0.0.2",
"babel-preset-es2015": "6.24.0", "babel-preset-es2015": "6.24.0",
"benchmark": "2.1.4", "benchmark": "2.1.4",
"cheerio": "0.22.0", "cheerio": "0.22.0",
"chromedriver": "2.28.0", "chromedriver": "2.29.0",
"coveralls": "2.13.0", "coveralls": "2.13.0",
"cross-env": "4.0.0", "cross-env": "4.0.0",
"fly": "2.0.5", "fly": "2.0.5",
@ -118,8 +118,8 @@
"node-fetch": "1.6.3", "node-fetch": "1.6.3",
"node-notifier": "5.1.2", "node-notifier": "5.1.2",
"nyc": "10.2.0", "nyc": "10.2.0",
"react": "15.4.2", "react": "15.5.3",
"react-dom": "15.4.2", "react-dom": "15.5.3",
"standard": "9.0.2", "standard": "9.0.2",
"wd": "1.2.0" "wd": "1.2.0"
}, },

View file

@ -11,6 +11,7 @@ Next.js is a minimalistic framework for server-rendered React applications.
<!-- https://github.com/thlorenz/doctoc --> <!-- https://github.com/thlorenz/doctoc -->
- [How to use](#how-to-use) - [How to use](#how-to-use)
- [Getting Started](#getting-started)
- [Setup](#setup) - [Setup](#setup)
- [Automatic code splitting](#automatic-code-splitting) - [Automatic code splitting](#automatic-code-splitting)
- [CSS](#css) - [CSS](#css)
@ -33,9 +34,9 @@ Next.js is a minimalistic framework for server-rendered React applications.
- [Custom configuration](#custom-configuration) - [Custom configuration](#custom-configuration)
- [Customizing webpack config](#customizing-webpack-config) - [Customizing webpack config](#customizing-webpack-config)
- [Customizing babel config](#customizing-babel-config) - [Customizing babel config](#customizing-babel-config)
- [CDN support with Asset Prefix](#cdn-support-with-asset-prefix)
- [Production deployment](#production-deployment) - [Production deployment](#production-deployment)
- [FAQ](#faq) - [FAQ](#faq)
- [Roadmap](#roadmap)
- [Contributing](#contributing) - [Contributing](#contributing)
- [Authors](#authors) - [Authors](#authors)
@ -43,6 +44,10 @@ Next.js is a minimalistic framework for server-rendered React applications.
## How to use ## How to use
### Getting Started
A step by step interactive guide of next features is available at [learnnextjs.com](https://learnnextjs.com/)
### Setup ### Setup
Install it: Install it:
@ -298,7 +303,7 @@ The component `<Link>` can also receive an URL object and it will automatically
// pages/index.js // pages/index.js
import Link from 'next/link' import Link from 'next/link'
export default () => ( export default () => (
<div>Click <Link href={{ pathname: 'about', query: { name: 'Zeit' }}}<a>here</a></Link> to read more</div> <div>Click <Link href={{ pathname: 'about', query: { name: 'Zeit' }}}><a>here</a></Link> to read more</div>
) )
``` ```
@ -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 ## 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: 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 didnt involve
</details> </details>
## Roadmap
Our Roadmap towards 2.0.0 [is public](https://github.com/zeit/next.js/wiki/Roadmap#nextjs-200).
## Contributing ## Contributing
Please see our [contributing.md](./contributing.md) Please see our [contributing.md](./contributing.md)

View file

@ -13,8 +13,8 @@ const plugins = envPlugins[process.env.NODE_ENV] || []
module.exports = { module.exports = {
presets: [ presets: [
[require.resolve('babel-preset-latest'), { [require.resolve('babel-preset-env'), {
'es2015': { modules: false } modules: false
}], }],
require.resolve('babel-preset-react') require.resolve('babel-preset-react')
], ],

View file

@ -1,6 +1,5 @@
import { tmpdir } from 'os' import { tmpdir } from 'os'
import { join } from 'path' import { join } from 'path'
import getConfig from '../config'
import fs from 'mz/fs' import fs from 'mz/fs'
import uuid from 'uuid' import uuid from 'uuid'
import del from 'del' import del from 'del'
@ -14,10 +13,8 @@ export default async function build (dir) {
try { try {
await runCompiler(compiler) await runCompiler(compiler)
await writeBuildStats(buildDir)
// Pass in both the buildDir and the dir to retrieve config await writeBuildId(buildDir)
await writeBuildStats(buildDir, dir)
await writeBuildId(buildDir, dir)
} catch (err) { } catch (err) {
console.error(`> Failed to build on ${buildDir}`) console.error(`> Failed to build on ${buildDir}`)
throw err throw err
@ -48,24 +45,22 @@ function runCompiler (compiler) {
}) })
} }
async function writeBuildStats (buildDir, dir) { async function writeBuildStats (dir) {
const dist = getConfig(dir).distDir
// Here we can't use hashes in webpack chunks. // Here we can't use hashes in webpack chunks.
// That's because the "app.js" is not tied to a chunk. // 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) // It's created by merging a few assets. (commons.js and main.js)
// So, we need to generate the hash ourself. // So, we need to generate the hash ourself.
const assetHashMap = { const assetHashMap = {
'app.js': { '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') await fs.writeFile(buildStatsPath, JSON.stringify(assetHashMap), 'utf8')
} }
async function writeBuildId (buildDir, dir) { async function writeBuildId (dir) {
const dist = getConfig(dir).distDir const buildIdPath = join(dir, '.next', 'BUILD_ID')
const buildIdPath = join(buildDir, dist, 'BUILD_ID')
const buildId = uuid.v4() const buildId = uuid.v4()
await fs.writeFile(buildIdPath, buildId, 'utf8') await fs.writeFile(buildIdPath, buildId, 'utf8')
} }

View file

@ -4,10 +4,9 @@ import getConfig from '../config'
export default async function replaceCurrentBuild (dir, buildDir) { export default async function replaceCurrentBuild (dir, buildDir) {
const dist = getConfig(dir).distDir const dist = getConfig(dir).distDir
const buildDist = getConfig(buildDir).distDir
const _dir = join(dir, dist) const _dir = join(dir, dist)
const _buildDir = join(buildDir, dist) const _buildDir = join(buildDir, '.next')
const oldDir = join(buildDir, `${buildDist}.old`) const oldDir = join(buildDir, '.next.old')
try { try {
await move(_dir, oldDir) await move(_dir, oldDir)

View file

@ -37,7 +37,7 @@ export default async function createCompiler (dir, { dev = false, quiet = false,
const mainJS = dev const mainJS = dev
? require.resolve('../../client/next-dev') : require.resolve('../../client/next') ? require.resolve('../../client/next-dev') : require.resolve('../../client/next')
let minChunks let totalPages
const entry = async () => { const entry = async () => {
const entries = { const entries = {
@ -69,8 +69,7 @@ export default async function createCompiler (dir, { dev = false, quiet = false,
} }
} }
// calculate minChunks of CommonsChunkPlugin for later use totalPages = pages.filter((p) => p !== documentPage).length
minChunks = Math.max(2, pages.filter((p) => p !== documentPage).length)
return entries 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 return module.context && module.context.indexOf('node_modules') >= 0
} }
// NOTE: it depends on the fact that the entry funtion is always called // Move modules used in at-least 1/2 of the total pages into commons.
// before applying CommonsChunkPlugin return count >= totalPages * 0.5
return count >= minChunks
} }
}), }),
// This chunk contains all the webpack related code. So, all the changes // 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, context: dir,
entry, entry,
output: { output: {
path: join(buildDir || dir, config.distDir), path: buildDir ? join(buildDir, '.next') : join(dir, config.distDir),
filename: '[name]', filename: '[name]',
libraryTarget: 'commonjs2', libraryTarget: 'commonjs2',
publicPath: '/_webpack/', publicPath: '/_next/webpack/',
strictModuleExceptionHandling: true, strictModuleExceptionHandling: true,
devtoolModuleFilenameTemplate ({ resourcePath }) { devtoolModuleFilenameTemplate ({ resourcePath }) {
const hash = createHash('sha1') const hash = createHash('sha1')

View file

@ -6,7 +6,8 @@ const cache = new Map()
const defaultConfig = { const defaultConfig = {
webpack: null, webpack: null,
poweredByHeader: true, poweredByHeader: true,
distDir: '.next' distDir: '.next',
assetPrefix: ''
} }
export default function getConfig (dir) { export default function getConfig (dir) {

View file

@ -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 htmlescape from 'htmlescape'
import flush from 'styled-jsx/server' import flush from 'styled-jsx/server'
@ -35,14 +36,14 @@ export class Head extends Component {
getChunkPreloadLink (filename) { getChunkPreloadLink (filename) {
const { __NEXT_DATA__ } = this.context._documentProps const { __NEXT_DATA__ } = this.context._documentProps
let { buildStats } = __NEXT_DATA__ let { buildStats, assetPrefix } = __NEXT_DATA__
const hash = buildStats ? buildStats[filename].hash : '-' const hash = buildStats ? buildStats[filename].hash : '-'
return ( return (
<link <link
key={filename} key={filename}
rel='preload' rel='preload'
href={`/_next/${hash}/${filename}`} href={`${assetPrefix}/_next/${hash}/${filename}`}
as='script' as='script'
/> />
) )
@ -65,12 +66,13 @@ export class Head extends Component {
} }
getPreloadDynamicChunks () { getPreloadDynamicChunks () {
const { chunks } = this.context._documentProps const { chunks, __NEXT_DATA__ } = this.context._documentProps
let { assetPrefix } = __NEXT_DATA__
return chunks.map((chunk) => ( return chunks.map((chunk) => (
<link <link
key={chunk} key={chunk}
rel='preload' rel='preload'
href={`/_webpack/chunks/${chunk}`} href={`${assetPrefix}/_next/webpack/chunks/${chunk}`}
as='script' as='script'
/> />
)) ))
@ -78,11 +80,11 @@ export class Head extends Component {
render () { render () {
const { head, styles, __NEXT_DATA__ } = this.context._documentProps const { head, styles, __NEXT_DATA__ } = this.context._documentProps
const { pathname, buildId } = __NEXT_DATA__ const { pathname, buildId, assetPrefix } = __NEXT_DATA__
return <head> return <head>
<link rel='preload' href={`/_next/${buildId}/page${pathname}`} as='script' /> <link rel='preload' href={`${assetPrefix}/_next/${buildId}/page${pathname}`} as='script' />
<link rel='preload' href={`/_next/${buildId}/page/_error`} as='script' /> <link rel='preload' href={`${assetPrefix}/_next/${buildId}/page/_error`} as='script' />
{this.getPreloadDynamicChunks()} {this.getPreloadDynamicChunks()}
{this.getPreloadMainLinks()} {this.getPreloadMainLinks()}
{(head || []).map((h, i) => React.cloneElement(h, { key: i }))} {(head || []).map((h, i) => React.cloneElement(h, { key: i }))}
@ -115,13 +117,13 @@ export class NextScript extends Component {
getChunkScript (filename, additionalProps = {}) { getChunkScript (filename, additionalProps = {}) {
const { __NEXT_DATA__ } = this.context._documentProps const { __NEXT_DATA__ } = this.context._documentProps
let { buildStats } = __NEXT_DATA__ let { buildStats, assetPrefix } = __NEXT_DATA__
const hash = buildStats ? buildStats[filename].hash : '-' const hash = buildStats ? buildStats[filename].hash : '-'
return ( return (
<script <script
type='text/javascript' type='text/javascript'
src={`/_next/${hash}/${filename}`} src={`${assetPrefix}/_next/${hash}/${filename}`}
{...additionalProps} {...additionalProps}
/> />
) )
@ -145,7 +147,8 @@ export class NextScript extends Component {
} }
getDynamicChunks () { getDynamicChunks () {
const { chunks } = this.context._documentProps const { chunks, __NEXT_DATA__ } = this.context._documentProps
let { assetPrefix } = __NEXT_DATA__
return ( return (
<div> <div>
{chunks.map((chunk) => ( {chunks.map((chunk) => (
@ -153,7 +156,7 @@ export class NextScript extends Component {
async async
key={chunk} key={chunk}
type='text/javascript' type='text/javascript'
src={`/_webpack/chunks/${chunk}`} src={`${assetPrefix}/_next/webpack/chunks/${chunk}`}
/> />
))} ))}
</div> </div>
@ -162,7 +165,7 @@ export class NextScript extends Component {
render () { render () {
const { staticMarkup, __NEXT_DATA__, chunks } = this.context._documentProps const { staticMarkup, __NEXT_DATA__, chunks } = this.context._documentProps
const { pathname, buildId } = __NEXT_DATA__ const { pathname, buildId, assetPrefix } = __NEXT_DATA__
__NEXT_DATA__.chunks = chunks __NEXT_DATA__.chunks = chunks
@ -183,8 +186,8 @@ export class NextScript extends Component {
} }
` `
}} />} }} />}
<script async type='text/javascript' src={`/_next/${buildId}/page${pathname}`} /> <script async type='text/javascript' src={`${assetPrefix}/_next/${buildId}/page${pathname}`} />
<script async type='text/javascript' src={`/_next/${buildId}/page/_error`} /> <script async type='text/javascript' src={`${assetPrefix}/_next/${buildId}/page/_error`} />
{staticMarkup ? null : this.getDynamicChunks()} {staticMarkup ? null : this.getDynamicChunks()}
{staticMarkup ? null : this.getScripts()} {staticMarkup ? null : this.getScripts()}
</div> </div>

View file

@ -139,7 +139,7 @@ export default class HotReloader {
} : {} } : {}
this.webpackDevMiddleware = webpackDevMiddleware(compiler, { this.webpackDevMiddleware = webpackDevMiddleware(compiler, {
publicPath: '/_webpack/', publicPath: '/_next/webpack/',
noInfo: true, noInfo: true,
quiet: true, quiet: true,
clientLogLevel: 'warning', clientLogLevel: 'warning',
@ -147,7 +147,10 @@ export default class HotReloader {
...windowsSettings ...windowsSettings
}) })
this.webpackHotMiddleware = webpackHotMiddleware(compiler, { log: false }) this.webpackHotMiddleware = webpackHotMiddleware(compiler, {
path: '/_next/webpack-hmr',
log: false
})
this.onDemandEntries = onDemandEntryHandler(this.webpackDevMiddleware, compiler, { this.onDemandEntries = onDemandEntryHandler(this.webpackDevMiddleware, compiler, {
dir: this.dir, dir: this.dir,
dev: true, dev: true,

View file

@ -18,6 +18,11 @@ import getConfig from './config'
// We need to go up one more level since we are in the `dist` directory // We need to go up one more level since we are in the `dist` directory
import pkg from '../../package' import pkg from '../../package'
const internalPrefixes = [
/^\/_next\//,
/^\/static\//
]
export default class Server { export default class Server {
constructor ({ dir = '.', dev = false, staticMarkup = false, quiet = false } = {}) { constructor ({ dir = '.', dev = false, staticMarkup = false, quiet = false } = {}) {
this.dir = resolve(dir) this.dir = resolve(dir)
@ -36,31 +41,34 @@ export default class Server {
dir: this.dir, dir: this.dir,
hotReloader: this.hotReloader, hotReloader: this.hotReloader,
buildStats: this.buildStats, buildStats: this.buildStats,
buildId: this.buildId buildId: this.buildId,
assetPrefix: this.config.assetPrefix.replace(/\/$/, '')
} }
this.defineRoutes() this.defineRoutes()
} }
getRequestHandler () { handleRequest (req, res, parsedUrl) {
return (req, res, parsedUrl) => { // Parse url if parsedUrl not provided
// Parse url if parsedUrl not provided if (!parsedUrl) {
if (!parsedUrl) { parsedUrl = parseUrl(req.url, true)
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])
})
} }
// 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 () { async prepare () {
@ -92,7 +100,7 @@ export default class Server {
}, },
// This is to support, webpack dynamic imports in production. // 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') res.setHeader('Cache-Control', 'max-age=365000000, immutable')
const p = join(this.dir, '.next', 'chunks', params.name) const p = join(this.dir, '.next', 'chunks', params.name)
await this.serveStatic(req, res, p) 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) { if (this.config.poweredByHeader) {
res.setHeader('X-Powered-By', `Next.js ${pkg.version}`) res.setHeader('X-Powered-By', `Next.js ${pkg.version}`)
} }
const html = await this.renderToHTML(req, res, pathname, query) 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) { async renderToHTML (req, res, pathname, query) {
@ -248,7 +260,7 @@ export default class Server {
async renderError (err, req, res, pathname, query) { async renderError (err, req, res, pathname, query) {
const html = await this.renderErrorToHTML(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) { 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 () { readBuildId () {
const buildIdPath = join(this.dir, this.dist, 'BUILD_ID') const buildIdPath = join(this.dir, this.dist, 'BUILD_ID')
const buildId = fs.readFileSync(buildIdPath, 'utf8') const buildId = fs.readFileSync(buildIdPath, 'utf8')

View file

@ -2,6 +2,8 @@ import { join } from 'path'
import { createElement } from 'react' import { createElement } from 'react'
import { renderToString, renderToStaticMarkup } from 'react-dom/server' import { renderToString, renderToStaticMarkup } from 'react-dom/server'
import send from 'send' import send from 'send'
import generateETag from 'etag'
import fresh from 'fresh'
import requireModule from './require' import requireModule from './require'
import getConfig from './config' import getConfig from './config'
import resolvePath from './resolve' import resolvePath from './resolve'
@ -14,7 +16,7 @@ import { flushChunks } from '../lib/dynamic'
export async function render (req, res, pathname, query, opts) { export async function render (req, res, pathname, query, opts) {
const html = await renderToHTML(req, res, pathname, 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) { 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) { export async function renderError (err, req, res, pathname, query, opts) {
const html = await renderErrorToHTML(err, req, res, 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 = {}) { export function renderErrorToHTML (err, req, res, pathname, query, opts = {}) {
@ -36,6 +38,7 @@ async function doRender (req, res, pathname, query, {
buildId, buildId,
buildStats, buildStats,
hotReloader, hotReloader,
assetPrefix,
dir = process.cwd(), dir = process.cwd(),
dev = false, dev = false,
staticMarkup = false staticMarkup = false
@ -95,6 +98,7 @@ async function doRender (req, res, pathname, query, {
query, query,
buildId, buildId,
buildStats, buildStats,
assetPrefix,
err: (err && dev) ? errorToJSON(err) : null err: (err && dev) ? errorToJSON(err) : null
}, },
dev, 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 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-Type', 'text/html')
res.setHeader('Content-Length', Buffer.byteLength(html)) res.setHeader('Content-Length', Buffer.byteLength(html))
res.end(method === 'HEAD' ? null : html) res.end(method === 'HEAD' ? null : html)

View file

@ -1,4 +1,5 @@
/* global describe, test, expect */ /* global describe, test, expect */
import fetch from 'node-fetch'
export default function (context) { export default function (context) {
describe('Misc', () => { describe('Misc', () => {
@ -12,5 +13,14 @@ export default function (context) {
const html = await context.app.renderToHTML({}, res, '/finish-response', {}) const html = await context.app.renderToHTML({}, res, '/finish-response', {})
expect(html).toBeFalsy() 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)
})
}) })
} }

View file

@ -4,7 +4,7 @@ import { pkg } from 'next-test-utils'
export default function ({ app }) { export default function ({ app }) {
describe('X-Powered-By header', () => { describe('X-Powered-By header', () => {
test('set it by default', async () => { test('set it by default', async () => {
const req = { url: '/stateless' } const req = { url: '/stateless', headers: {} }
const headers = {} const headers = {}
const res = { const res = {
setHeader (key, value) { setHeader (key, value) {
@ -18,7 +18,7 @@ export default function ({ app }) {
}) })
test('do not set it when poweredByHeader==false', async () => { test('do not set it when poweredByHeader==false', async () => {
const req = { url: '/stateless' } const req = { url: '/stateless', headers: {} }
const originalConfigValue = app.config.poweredByHeader const originalConfigValue = app.config.poweredByHeader
app.config.poweredByHeader = false app.config.poweredByHeader = false
const res = { const res = {

195
yarn.lock
View file

@ -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" slash "^1.0.0"
source-map "^0.5.0" source-map "^0.5.0"
babel-eslint@7.2.0: babel-eslint@7.2.2:
version "7.2.0" version "7.2.2"
resolved "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.2.0.tgz#8941514b9dead06f0df71b29d5d5b193a92ee0ae" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.2.tgz#0da2cbe6554fd0fb069f19674f2db2f9c59270ff"
dependencies: dependencies:
babel-code-frame "^6.22.0" babel-code-frame "^6.22.0"
babel-traverse "^6.23.1" babel-traverse "^6.23.1"
babel-types "^6.23.0" babel-types "^6.23.0"
babylon "^6.16.1" babylon "^6.16.1"
lodash "^4.17.4"
babel-generator@6.24.0, babel-generator@^6.18.0, babel-generator@^6.24.0: babel-generator@6.24.0, babel-generator@^6.18.0, babel-generator@^6.24.0:
version "6.24.0" version "6.24.0"
@ -504,7 +503,7 @@ babel-plugin-syntax-class-properties@^6.8.0:
version "6.13.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" 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" version "6.18.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" 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: dependencies:
babel-runtime "^6.22.0" 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" 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" resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.23.0.tgz#e48895cf0b375be148cd7c8879b422707a053b51"
dependencies: dependencies:
@ -567,7 +566,7 @@ babel-plugin-transform-es2015-block-scoping@^6.22.0:
babel-types "^6.23.0" babel-types "^6.23.0"
lodash "^4.2.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" version "6.23.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.23.0.tgz#49b53f326202a2fd1b3bbaa5e2edd8a4f78643c1" resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.23.0.tgz#49b53f326202a2fd1b3bbaa5e2edd8a4f78643c1"
dependencies: dependencies:
@ -588,7 +587,7 @@ babel-plugin-transform-es2015-computed-properties@^6.22.0:
babel-runtime "^6.22.0" babel-runtime "^6.22.0"
babel-template "^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" version "6.23.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
dependencies: dependencies:
@ -601,7 +600,7 @@ babel-plugin-transform-es2015-duplicate-keys@^6.22.0:
babel-runtime "^6.22.0" babel-runtime "^6.22.0"
babel-types "^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" 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" resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
dependencies: dependencies:
@ -621,7 +620,7 @@ babel-plugin-transform-es2015-literals@^6.22.0:
dependencies: dependencies:
babel-runtime "^6.22.0" 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" 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" resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.0.tgz#a1911fb9b7ec7e05a43a63c5995007557bcf6a2e"
dependencies: dependencies:
@ -629,7 +628,7 @@ babel-plugin-transform-es2015-modules-amd@^6.24.0:
babel-runtime "^6.22.0" babel-runtime "^6.22.0"
babel-template "^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" 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" resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.0.tgz#e921aefb72c2cc26cb03d107626156413222134f"
dependencies: dependencies:
@ -638,7 +637,7 @@ babel-plugin-transform-es2015-modules-commonjs@6.24.0, babel-plugin-transform-es
babel-template "^6.23.0" babel-template "^6.23.0"
babel-types "^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" 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" resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.23.0.tgz#ae3469227ffac39b0310d90fec73bfdc4f6317b0"
dependencies: dependencies:
@ -646,7 +645,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.22.0:
babel-runtime "^6.22.0" babel-runtime "^6.22.0"
babel-template "^6.23.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" 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" resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.0.tgz#fd5fa63521cae8d273927c3958afd7c067733450"
dependencies: dependencies:
@ -661,7 +660,7 @@ babel-plugin-transform-es2015-object-super@^6.22.0:
babel-helper-replace-supers "^6.22.0" babel-helper-replace-supers "^6.22.0"
babel-runtime "^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" version "6.23.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz#3a2aabb70c8af945d5ce386f1a4250625a83ae3b" resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz#3a2aabb70c8af945d5ce386f1a4250625a83ae3b"
dependencies: dependencies:
@ -699,7 +698,7 @@ babel-plugin-transform-es2015-template-literals@^6.22.0:
dependencies: dependencies:
babel-runtime "^6.22.0" 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" 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" resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
dependencies: dependencies:
@ -763,9 +762,9 @@ babel-plugin-transform-react-jsx@^6.23.0:
babel-plugin-syntax-jsx "^6.8.0" babel-plugin-syntax-jsx "^6.8.0"
babel-runtime "^6.22.0" babel-runtime "^6.22.0"
babel-plugin-transform-react-remove-prop-types@0.3.2: babel-plugin-transform-react-remove-prop-types@0.4.0:
version "0.3.2" version "0.4.0"
resolved "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.3.2.tgz#6da8d834c6d7ad8ab02f956509790cfaa01ffe19" 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: babel-plugin-transform-regenerator@^6.22.0:
version "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-runtime "^6.22.0"
babel-types "^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" version "6.24.0"
resolved "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.0.tgz#c162d68b1932696e036cd3110dc1ccd303d2673a" resolved "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.0.tgz#c162d68b1932696e036cd3110dc1ccd303d2673a"
dependencies: 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-es2015-unicode-regex "^6.22.0"
babel-plugin-transform-regenerator "^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: babel-preset-flow@^6.23.0:
version "6.23.0" version "6.23.0"
resolved "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" 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: dependencies:
babel-plugin-jest-hoist "^19.0.0" 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: babel-preset-react@6.23.0:
version "6.23.0" version "6.23.0"
resolved "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.23.0.tgz#eb7cee4de98a3f94502c28565332da9819455195" 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" core-js "^2.4.0"
regenerator-runtime "^0.10.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: babel-template@^6.16.0, babel-template@^6.22.0, babel-template@^6.23.0, babel-template@^6.7.0:
version "6.23.0" version "6.23.0"
resolved "https://registry.npmjs.org/babel-template/-/babel-template-6.23.0.tgz#04d4f270adbb3aa704a8143ae26faa529238e638" 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" babylon "^6.11.0"
lodash "^4.2.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: babel-traverse@6.21.0:
version "6.21.0" version "6.21.0"
resolved "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.21.0.tgz#69c6365804f1a4f69eb1213f85b00a818b8c21ad" resolved "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.21.0.tgz#69c6365804f1a4f69eb1213f85b00a818b8c21ad"
@ -1111,6 +1123,13 @@ browserify-zlib@^0.1.4:
dependencies: dependencies:
pako "~0.2.0" 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: bser@1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.npmjs.org/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169" resolved "https://registry.npmjs.org/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169"
@ -1181,6 +1200,10 @@ camelcase@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" 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: case-sensitive-paths-webpack-plugin@2.0.0:
version "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" 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: optionalDependencies:
fsevents "^1.0.0" fsevents "^1.0.0"
chromedriver@2.28.0: chromedriver@2.29.0:
version "2.28.0" version "2.29.0"
resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-2.28.0.tgz#ea0c383621dd27db340c612b85fe39414c16ec79" resolved "https://registry.npmjs.org/chromedriver/-/chromedriver-2.29.0.tgz#e3fd8b3c08dce2562b80ef1b0b846597659d0cc3"
dependencies: dependencies:
adm-zip "^0.4.7" adm-zip "^0.4.7"
kew "^0.7.0" kew "^0.7.0"
@ -1703,6 +1726,10 @@ ee-first@1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 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: elegant-spinner@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" 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" version "2.0.2"
resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" 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" version "1.8.0"
resolved "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz#6f631aef336d6c46362b51764044ce216be3c051" resolved "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz#6f631aef336d6c46362b51764044ce216be3c051"
@ -2066,9 +2093,9 @@ fb-watchman@^2.0.0:
dependencies: dependencies:
bser "^2.0.0" bser "^2.0.0"
fbjs@^0.8.1, fbjs@^0.8.4: fbjs@^0.8.9:
version "0.8.9" version "0.8.12"
resolved "https://registry.npmjs.org/fbjs/-/fbjs-0.8.9.tgz#180247fbd347dcc9004517b904f865400a0c8f14" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.12.tgz#10b5d92f76d45575fd63a217d4ea02bea2f8ed04"
dependencies: dependencies:
core-js "^1.0.0" core-js "^1.0.0"
isomorphic-fetch "^2.1.1" isomorphic-fetch "^2.1.1"
@ -2340,17 +2367,7 @@ glob-promise@3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.npmjs.org/glob-promise/-/glob-promise-3.1.0.tgz#198882a3817be7dc2c55f92623aa9e7b3f82d1eb" resolved "https://registry.npmjs.org/glob-promise/-/glob-promise-3.1.0.tgz#198882a3817be7dc2c55f92623aa9e7b3f82d1eb"
glob@^6.0.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 "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:
version "7.1.1" version "7.1.1"
resolved "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" resolved "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
dependencies: 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" once "^1.3.0"
path-is-absolute "^1.0.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: global@^4.3.0:
version "4.3.1" version "4.3.1"
resolved "https://registry.npmjs.org/global/-/global-4.3.1.tgz#5f757908c7cbabce54f386ae440e11e26b7916df" resolved "https://registry.npmjs.org/global/-/global-4.3.1.tgz#5f757908c7cbabce54f386ae440e11e26b7916df"
@ -2613,7 +2640,7 @@ interpret@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.npmjs.org/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c" 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" version "2.2.2"
resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
dependencies: dependencies:
@ -4042,6 +4069,18 @@ promise@^7.1.1:
dependencies: dependencies:
asap "~2.0.3" 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: prr@~0.0.0:
version "0.0.0" version "0.0.0"
resolved "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" 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" version "2.0.1"
resolved "https://registry.npmjs.org/react-deep-force-update/-/react-deep-force-update-2.0.1.tgz#4f7f6c12c3e7de42f345992a3c518236fa1ecad3" resolved "https://registry.npmjs.org/react-deep-force-update/-/react-deep-force-update-2.0.1.tgz#4f7f6c12c3e7de42f345992a3c518236fa1ecad3"
react-dom@15.4.2: react-dom@15.5.3:
version "15.4.2" version "15.5.3"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-15.4.2.tgz#015363f05b0a1fd52ae9efdd3a0060d90695208f" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.5.3.tgz#2ee127ce942df55da53111ae303316e68072b5c5"
dependencies: dependencies:
fbjs "^0.8.1" fbjs "^0.8.9"
loose-envify "^1.1.0" loose-envify "^1.1.0"
object-assign "^4.1.0" object-assign "^4.1.0"
prop-types "~15.5.0"
react-hot-loader@3.0.0-beta.6: react-hot-loader@3.0.0-beta.6:
version "3.0.0-beta.6" version "3.0.0-beta.6"
@ -4137,13 +4177,14 @@ react-proxy@^3.0.0-alpha.0:
dependencies: dependencies:
lodash "^4.6.1" lodash "^4.6.1"
react@15.4.2: react@15.5.3:
version "15.4.2" version "15.5.3"
resolved "https://registry.npmjs.org/react/-/react-15.4.2.tgz#41f7991b26185392ba9bae96c8889e7e018397ef" resolved "https://registry.yarnpkg.com/react/-/react-15.5.3.tgz#84055382c025dec4e3b902bb61a8697cc79c1258"
dependencies: dependencies:
fbjs "^0.8.4" fbjs "^0.8.9"
loose-envify "^1.1.0" loose-envify "^1.1.0"
object-assign "^4.1.0" object-assign "^4.1.0"
prop-types "^15.5.2"
read-pkg-up@^1.0.1: read-pkg-up@^1.0.1:
version "1.0.1" version "1.0.1"