Skip to content

Commit b0d9087

Browse files
committed
Merge master into use-babel-loader-7.
2 parents ebbcade + b629490 commit b0d9087

File tree

118 files changed

+3182
-1789
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

118 files changed

+3182
-1789
lines changed

.babelrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"presets": [
3-
"latest",
3+
"env",
44
"react"
55
],
66
"plugins": [

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ npm-debug.log
1111
# coverage
1212
.nyc_output
1313
coverage
14+
15+
.DS_Store

bin/next

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#!/usr/bin/env node
22

3-
import { join } from 'path'
3+
import { join, resolve } from 'path'
44
import { spawn } from 'cross-spawn'
55
import { watchFile } from 'fs'
66
import pkg from '../../package.json'
7+
import getConfig from '../server/config'
78

89
if (pkg.peerDependencies) {
910
Object.keys(pkg.peerDependencies).forEach(dependency => {
@@ -65,7 +66,7 @@ const startProcess = () => {
6566
if (signal === 'SIGKILL') {
6667
process.exit(137)
6768
}
68-
console.log(`got signal ${signal}, exitting`)
69+
console.log(`got signal ${signal}, exiting`)
6970
process.exit(1)
7071
}
7172
process.exit(0)
@@ -78,9 +79,10 @@ const startProcess = () => {
7879
}
7980

8081
let proc = startProcess()
82+
const { pagesDirectory = resolve(process.cwd(), 'pages') } = getConfig(process.cwd())
8183

8284
if (cmd === 'dev') {
83-
watchFile(join(process.cwd(), 'next.config.js'), (cur, prev) => {
85+
watchFile(`${resolve(pagesDirectory, '..')}/next.config.js`, (cur, prev) => {
8486
if (cur.size > 0 || prev.size > 0) {
8587
console.log('\n> Found a change in next.config.js, restarting the server...')
8688
// Don't listen to 'close' now since otherwise parent gets killed by listener

bin/next-build

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ if (argv.help) {
2222
Usage
2323
$ next build <dir>
2424
25-
<dir> represents where the compiled .next folder should go.
26-
If no directory is provided, .next will be created in the current directory
25+
<dir> represents where the compiled dist folder should go.
26+
If no directory is provided, the dist folder will be created in the current directory.
27+
You can set a custom folder in config https://github.com/zeit/next.js#custom-configuration, otherwise it will be created inside '.next'
2728
`)
2829
process.exit(0)
2930
}

bin/next-dev

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ if (argv.help) {
2929
Usage
3030
$ next dev <dir> -p <port number>
3131
32-
<dir> represents where the compiled .next folder should go.
33-
If no directory is provided, .next will be created in the current directory
32+
<dir> represents where the compiled folder should go.
33+
If no directory is provided, the folder will be created in the current directory.
34+
You can set a custom folder in config https://github.com/zeit/next.js#custom-configuration.
3435
3536
Options
3637
--port, -p A port number on which to start the application

bin/next-init

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ const basePackage = `{
6363
"name": "my-app",
6464
"description": "",
6565
"dependencies": {
66-
"next": "latest"
66+
"next": "latest",
67+
"react": "^15.4.2",
68+
"react-dom": "^15.4.2"
6769
},
6870
"scripts": {
6971
"dev": "next",
@@ -73,29 +75,28 @@ const basePackage = `{
7375
}`
7476

7577
const basePage = `
76-
7778
import Head from 'next/head'
7879
7980
export default () => (
8081
<div>
8182
<Head>
8283
<meta name='viewport' content='width=device-width, initial-scale=1'/>
83-
<style>{bodyStyles}</style>
8484
</Head>
8585
8686
<img width='112' src='https://cloud.githubusercontent.com/assets/13041/19686250/971bf7f8-9ac0-11e6-975c-188defd82df1.png' alt='next.js' />
87+
88+
<style jsx global>{\`
89+
html, body {
90+
height: 100%
91+
}
92+
93+
body {
94+
display: flex;
95+
align-items: center;
96+
justify-content: center;
97+
margin: 0;
98+
}
99+
\`}</style>
87100
</div>
88101
)
89-
90-
const bodyStyles = \`
91-
html, body {
92-
height: 100%
93-
}
94-
95-
body {
96-
display: flex;
97-
align-items: center;
98-
justify-content: center;
99-
}
100-
\`
101102
`

bin/next-start

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { resolve } from 'path'
44
import parseArgs from 'minimist'
55
import Server from '../server'
66
import { existsSync } from 'fs'
7+
import getConfig from '../server/config'
78

89
process.env.NODE_ENV = process.env.NODE_ENV || 'production'
910

@@ -32,9 +33,10 @@ if (argv.help) {
3233
Usage
3334
$ next start <dir> -p <port>
3435
35-
<dir> is the directory that contains the compiled .next folder
36+
<dir> is the directory that contains the compiled dist folder
3637
created by running \`next build\`.
3738
If no directory is provided, the current directory will be assumed.
39+
You can set a custom dist folder in config https://github.com/zeit/next.js#custom-configuration
3840
3941
Options
4042
--port, -p A port number on which to start the application
@@ -45,11 +47,12 @@ if (argv.help) {
4547
}
4648

4749
const dir = resolve(argv._[0] || '.')
50+
const dist = getConfig(dir).distDir
4851

4952
const srv = new Server({ dir })
5053

51-
if (!existsSync(resolve(dir, '.next', 'BUILD_ID'))) {
52-
console.error(`> Could not find a valid build in the '.next' directory! Try building your app with 'next build' before starting the server.`)
54+
if (!existsSync(resolve(dir, dist, 'BUILD_ID'))) {
55+
console.error(`> Could not find a valid build in the '${dist}' directory! Try building your app with 'next build' before starting the server.`)
5356
process.exit(1)
5457
}
5558

client/index.js

Lines changed: 74 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import mitt from 'mitt'
44
import HeadManager from './head-manager'
55
import { createRouter } from '../lib/router'
66
import App from '../lib/app'
7-
import evalScript from '../lib/eval-script'
87
import { loadGetInitialProps, getURL } from '../lib/utils'
8+
import ErrorDebugComponent from '../lib/error-debug'
9+
import PageLoader from '../lib/page-loader'
910

1011
// Polyfill Promise globally
1112
// This is needed because Webpack2's dynamic loading(common chunks) code
@@ -18,54 +19,100 @@ if (!window.Promise) {
1819

1920
const {
2021
__NEXT_DATA__: {
21-
component,
22-
errorComponent,
2322
props,
2423
err,
2524
pathname,
26-
query
25+
query,
26+
buildId,
27+
assetPrefix
2728
},
2829
location
2930
} = window
3031

31-
const Component = evalScript(component).default
32-
const ErrorComponent = evalScript(errorComponent).default
33-
let lastAppProps
34-
35-
export const router = createRouter(pathname, query, getURL(), {
36-
Component,
37-
ErrorComponent,
38-
err
32+
const pageLoader = new PageLoader(buildId, assetPrefix)
33+
window.__NEXT_LOADED_PAGES__.forEach(({ route, fn }) => {
34+
pageLoader.registerPage(route, fn)
3935
})
36+
delete window.__NEXT_LOADED_PAGES__
37+
38+
window.__NEXT_REGISTER_PAGE = pageLoader.registerPage.bind(pageLoader)
4039

4140
const headManager = new HeadManager()
42-
const container = document.getElementById('__next')
41+
const appContainer = document.getElementById('__next')
42+
const errorContainer = document.getElementById('__next-error')
43+
44+
let lastAppProps
45+
export let router
46+
export let ErrorComponent
47+
let Component
48+
49+
export default async () => {
50+
ErrorComponent = await pageLoader.loadPage('/_error')
51+
52+
try {
53+
Component = await pageLoader.loadPage(pathname)
54+
} catch (err) {
55+
console.error(`${err.message}\n${err.stack}`)
56+
Component = ErrorComponent
57+
}
58+
59+
router = createRouter(pathname, query, getURL(), {
60+
pageLoader,
61+
Component,
62+
ErrorComponent,
63+
err
64+
})
4365

44-
export default (onError) => {
4566
const emitter = mitt()
4667

4768
router.subscribe(({ Component, props, hash, err }) => {
48-
render({ Component, props, err, hash, emitter }, onError)
69+
render({ Component, props, err, hash, emitter })
4970
})
5071

5172
const hash = location.hash.substring(1)
52-
render({ Component, props, hash, err, emitter }, onError)
73+
render({ Component, props, hash, err, emitter })
5374

5475
return emitter
5576
}
5677

57-
export async function render (props, onError = renderErrorComponent) {
78+
export async function render (props) {
79+
// There are some errors we should ignore.
80+
// Next.js rendering logic knows how to handle them.
81+
// These are specially 404 errors
82+
if (props.err && !props.err.ignore) {
83+
await renderError(props.err)
84+
return
85+
}
86+
5887
try {
5988
await doRender(props)
6089
} catch (err) {
61-
await onError(err)
90+
if (err.abort) return
91+
await renderError(err)
6292
}
6393
}
6494

65-
async function renderErrorComponent (err) {
66-
const { pathname, query } = router
67-
const props = await loadGetInitialProps(ErrorComponent, { err, pathname, query })
68-
await doRender({ Component: ErrorComponent, props, err })
95+
// This method handles all runtime and debug errors.
96+
// 404 and 500 errors are special kind of errors
97+
// and they are still handle via the main render method.
98+
export async function renderError (error) {
99+
const prod = process.env.NODE_ENV === 'production'
100+
// We need to unmount the current app component because it's
101+
// in the inconsistant state.
102+
// Otherwise, we need to face issues when the issue is fixed and
103+
// it's get notified via HMR
104+
ReactDOM.unmountComponentAtNode(appContainer)
105+
106+
const errorMessage = `${error.message}\n${error.stack}`
107+
console.error(errorMessage)
108+
109+
if (prod) {
110+
const initProps = { err: error, pathname, query }
111+
const props = await loadGetInitialProps(ErrorComponent, initProps)
112+
ReactDOM.render(createElement(ErrorComponent, props), errorContainer)
113+
} else {
114+
ReactDOM.render(createElement(ErrorDebugComponent, { error }), errorContainer)
115+
}
69116
}
70117

71118
async function doRender ({ Component, props, hash, err, emitter }) {
@@ -78,7 +125,7 @@ async function doRender ({ Component, props, hash, err, emitter }) {
78125
}
79126

80127
if (emitter) {
81-
emitter.emit('before-reactdom-render', { Component })
128+
emitter.emit('before-reactdom-render', { Component, ErrorComponent })
82129
}
83130

84131
Component = Component || lastAppProps.Component
@@ -88,9 +135,11 @@ async function doRender ({ Component, props, hash, err, emitter }) {
88135
// lastAppProps has to be set before ReactDom.render to account for ReactDom throwing an error.
89136
lastAppProps = appProps
90137

91-
ReactDOM.render(createElement(App, appProps), container)
138+
// We need to clear any existing runtime error messages
139+
ReactDOM.unmountComponentAtNode(errorContainer)
140+
ReactDOM.render(createElement(App, appProps), appContainer)
92141

93142
if (emitter) {
94-
emitter.emit('after-reactdom-render', { Component })
143+
emitter.emit('after-reactdom-render', { Component, ErrorComponent })
95144
}
96145
}

client/next-dev.js

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,49 @@
1-
import evalScript from '../lib/eval-script'
2-
3-
const { __NEXT_DATA__: { errorComponent } } = window
4-
const ErrorComponent = evalScript(errorComponent).default
5-
6-
require('react-hot-loader/patch')
1+
import 'react-hot-loader/patch'
2+
import ReactReconciler from 'react-dom/lib/ReactReconciler'
3+
import initOnDemandEntries from './on-demand-entries-client'
4+
import initWebpackHMR from './webpack-hot-middleware-client'
75

86
const next = window.next = require('./')
97

10-
const emitter = next.default(onError)
11-
12-
function onError (err) {
13-
// just show the debug screen but don't render ErrorComponent
14-
// so that the current component doesn't lose props
15-
next.render({ err, emitter })
16-
}
17-
18-
let lastScroll
19-
20-
emitter.on('before-reactdom-render', ({ Component }) => {
21-
// Remember scroll when ErrorComponent is being rendered to later restore it
22-
if (!lastScroll && Component === ErrorComponent) {
23-
const { pageXOffset, pageYOffset } = window
24-
lastScroll = {
25-
x: pageXOffset,
26-
y: pageYOffset
27-
}
28-
}
29-
})
30-
31-
emitter.on('after-reactdom-render', ({ Component }) => {
32-
if (lastScroll && Component !== ErrorComponent) {
33-
// Restore scroll after ErrorComponent was replaced with a page component by HMR
34-
const { x, y } = lastScroll
35-
window.scroll(x, y)
36-
lastScroll = null
8+
next.default()
9+
.then((emitter) => {
10+
initOnDemandEntries()
11+
initWebpackHMR()
12+
13+
let lastScroll
14+
15+
emitter.on('before-reactdom-render', ({ Component, ErrorComponent }) => {
16+
// Remember scroll when ErrorComponent is being rendered to later restore it
17+
if (!lastScroll && Component === ErrorComponent) {
18+
const { pageXOffset, pageYOffset } = window
19+
lastScroll = {
20+
x: pageXOffset,
21+
y: pageYOffset
22+
}
23+
}
24+
})
25+
26+
emitter.on('after-reactdom-render', ({ Component, ErrorComponent }) => {
27+
if (lastScroll && Component !== ErrorComponent) {
28+
// Restore scroll after ErrorComponent was replaced with a page component by HMR
29+
const { x, y } = lastScroll
30+
window.scroll(x, y)
31+
lastScroll = null
32+
}
33+
})
34+
})
35+
.catch((err) => {
36+
console.error(`${err.message}\n${err.stack}`)
37+
})
38+
39+
// This is a patch to catch most of the errors throw inside React components.
40+
const originalMountComponent = ReactReconciler.mountComponent
41+
ReactReconciler.mountComponent = function (...args) {
42+
try {
43+
return originalMountComponent(...args)
44+
} catch (err) {
45+
next.renderError(err)
46+
err.abort = true
47+
throw err
3748
}
38-
})
49+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy