diff --git a/packages/next-server/package.json b/packages/next-server/package.json
index 62dc836c..081f527e 100644
--- a/packages/next-server/package.json
+++ b/packages/next-server/package.json
@@ -24,10 +24,12 @@
]
},
"dependencies": {
+ "@babel/runtime-corejs2": "^7.1.2",
"ansi-html": "0.0.7",
"etag": "1.8.1",
"find-up": "3.0.0",
"fresh": "0.5.2",
+ "hoist-non-react-statics": "^3.0.1",
"htmlescape": "1.1.1",
"http-errors": "1.6.2",
"path-to-regexp": "2.1.0",
diff --git a/packages/next/app.js b/packages/next/app.js
index 0bcca764..5437bb67 100644
--- a/packages/next/app.js
+++ b/packages/next/app.js
@@ -1 +1 @@
-module.exports = require('./dist/lib/app')
+module.exports = require('./dist/pages/_app')
diff --git a/packages/next/build/webpack.js b/packages/next/build/webpack.js
index fb871e55..1881e942 100644
--- a/packages/next/build/webpack.js
+++ b/packages/next/build/webpack.js
@@ -32,14 +32,20 @@ function externalsConfig (dir, isServer) {
return externals
}
+ const notExternalModules = ['next/app', 'next/document', 'next/error']
+
externals.push((context, request, callback) => {
- resolve(request, { basedir: dir, preserveSymlinks: true }, (err, res) => {
+ if (notExternalModules.indexOf(request) !== -1) {
+ return callback()
+ }
+
+ resolve(request, { basedir: context, preserveSymlinks: true }, (err, res) => {
if (err) {
return callback()
}
// Default pages have to be transpiled
- if (res.match(/node_modules[/\\]next[/\\]dist[/\\]pages/)) {
+ if (res.match(/next[/\\]dist[/\\]pages/)) {
return callback()
}
diff --git a/packages/next/document.js b/packages/next/document.js
index 18bc2528..5741035f 100644
--- a/packages/next/document.js
+++ b/packages/next/document.js
@@ -1 +1 @@
-module.exports = require('./dist/server/document')
+module.exports = require('./dist/pages/_document')
diff --git a/packages/next/error.js b/packages/next/error.js
index 1dd94bb4..899cd046 100644
--- a/packages/next/error.js
+++ b/packages/next/error.js
@@ -1 +1 @@
-module.exports = require('./dist/lib/error')
+module.exports = require('./dist/pages/_error')
diff --git a/packages/next/lib/app.js b/packages/next/lib/app.js
deleted file mode 100644
index d0e558bd..00000000
--- a/packages/next/lib/app.js
+++ /dev/null
@@ -1,116 +0,0 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-import { execOnce, loadGetInitialProps } from 'next-server/dist/lib/utils'
-import { makePublicRouterInstance } from 'next-server/router'
-
-export default class App extends Component {
- static childContextTypes = {
- headManager: PropTypes.object,
- router: PropTypes.object
- }
-
- static async getInitialProps ({ Component, router, ctx }) {
- const pageProps = await loadGetInitialProps(Component, ctx)
- return {pageProps}
- }
-
- getChildContext () {
- const { headManager } = this.props
- return {
- headManager,
- router: makePublicRouterInstance(this.props.router)
- }
- }
-
- // Kept here for backwards compatibility.
- // When someone ended App they could call `super.componentDidCatch`. This is now deprecated.
- componentDidCatch (err) {
- throw err
- }
-
- render () {
- const {router, Component, pageProps} = this.props
- const url = createUrl(router)
- return
-
-
- }
-}
-
-export class Container extends Component {
- componentDidMount () {
- this.scrollToHash()
- }
-
- componentDidUpdate () {
- this.scrollToHash()
- }
-
- scrollToHash () {
- let { hash } = window.location
- hash = hash ? hash.substring(1) : false
- if (!hash) return
-
- const el = document.getElementById(hash)
- if (!el) return
-
- // If we call scrollIntoView() in here without a setTimeout
- // it won't scroll properly.
- setTimeout(() => el.scrollIntoView(), 0)
- }
-
- render () {
- return this.props.children
- }
-}
-
-const warnUrl = execOnce(() => {
- if (process.env.NODE_ENV !== 'production') {
- console.error(`Warning: the 'url' property is deprecated. https://err.sh/zeit/next.js/url-deprecated`)
- }
-})
-
-export function createUrl (router) {
- // This is to make sure we don't references the router object at call time
- const {pathname, asPath, query} = router
- return {
- get query () {
- warnUrl()
- return query
- },
- get pathname () {
- warnUrl()
- return pathname
- },
- get asPath () {
- warnUrl()
- return asPath
- },
- back: () => {
- warnUrl()
- router.back()
- },
- push: (url, as) => {
- warnUrl()
- return router.push(url, as)
- },
- pushTo: (href, as) => {
- warnUrl()
- const pushRoute = as ? href : null
- const pushUrl = as || href
-
- return router.push(pushRoute, pushUrl)
- },
- replace: (url, as) => {
- warnUrl()
- return router.replace(url, as)
- },
- replaceTo: (href, as) => {
- warnUrl()
- const replaceRoute = as ? href : null
- const replaceUrl = as || href
-
- return router.replace(replaceRoute, replaceUrl)
- }
- }
-}
diff --git a/packages/next/lib/error.js b/packages/next/lib/error.js
deleted file mode 100644
index cef92cf7..00000000
--- a/packages/next/lib/error.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import HTTPStatus from 'http-status'
-import Head from 'next-server/head'
-
-export default class Error extends React.Component {
- static getInitialProps ({ res, err }) {
- const statusCode = res ? res.statusCode : (err ? err.statusCode : null)
- return { statusCode }
- }
-
- render () {
- const { statusCode } = this.props
- const title = statusCode === 404
- ? 'This page could not be found'
- : HTTPStatus[statusCode] || 'An unexpected error has occurred'
-
- return
-
-
-
{statusCode}: {title}
-
-
-
- {statusCode ?
{statusCode}
: null}
-
-
{title}.
-
-
-
- }
-}
-
-if (process.env.NODE_ENV !== 'production') {
- Error.propTypes = {
- statusCode: PropTypes.number
- }
-}
-
-const styles = {
- error: {
- color: '#000',
- background: '#fff',
- fontFamily: '-apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir, "Helvetica Neue", "Lucida Grande", sans-serif',
- height: '100vh',
- textAlign: 'center',
- display: 'flex',
- flexDirection: 'column',
- alignItems: 'center',
- justifyContent: 'center'
- },
-
- desc: {
- display: 'inline-block',
- textAlign: 'left',
- lineHeight: '49px',
- height: '49px',
- verticalAlign: 'middle'
- },
-
- h1: {
- display: 'inline-block',
- borderRight: '1px solid rgba(0, 0, 0,.3)',
- margin: 0,
- marginRight: '20px',
- padding: '10px 23px 10px 0',
- fontSize: '24px',
- fontWeight: 500,
- verticalAlign: 'top'
- },
-
- h2: {
- fontSize: '14px',
- fontWeight: 'normal',
- lineHeight: 'inherit',
- margin: 0,
- padding: 0
- }
-}
diff --git a/packages/next/pages/_app.js b/packages/next/pages/_app.js
index c96c4b94..d0e558bd 100644
--- a/packages/next/pages/_app.js
+++ b/packages/next/pages/_app.js
@@ -1 +1,116 @@
-module.exports = require('next/app')
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { execOnce, loadGetInitialProps } from 'next-server/dist/lib/utils'
+import { makePublicRouterInstance } from 'next-server/router'
+
+export default class App extends Component {
+ static childContextTypes = {
+ headManager: PropTypes.object,
+ router: PropTypes.object
+ }
+
+ static async getInitialProps ({ Component, router, ctx }) {
+ const pageProps = await loadGetInitialProps(Component, ctx)
+ return {pageProps}
+ }
+
+ getChildContext () {
+ const { headManager } = this.props
+ return {
+ headManager,
+ router: makePublicRouterInstance(this.props.router)
+ }
+ }
+
+ // Kept here for backwards compatibility.
+ // When someone ended App they could call `super.componentDidCatch`. This is now deprecated.
+ componentDidCatch (err) {
+ throw err
+ }
+
+ render () {
+ const {router, Component, pageProps} = this.props
+ const url = createUrl(router)
+ return
+
+
+ }
+}
+
+export class Container extends Component {
+ componentDidMount () {
+ this.scrollToHash()
+ }
+
+ componentDidUpdate () {
+ this.scrollToHash()
+ }
+
+ scrollToHash () {
+ let { hash } = window.location
+ hash = hash ? hash.substring(1) : false
+ if (!hash) return
+
+ const el = document.getElementById(hash)
+ if (!el) return
+
+ // If we call scrollIntoView() in here without a setTimeout
+ // it won't scroll properly.
+ setTimeout(() => el.scrollIntoView(), 0)
+ }
+
+ render () {
+ return this.props.children
+ }
+}
+
+const warnUrl = execOnce(() => {
+ if (process.env.NODE_ENV !== 'production') {
+ console.error(`Warning: the 'url' property is deprecated. https://err.sh/zeit/next.js/url-deprecated`)
+ }
+})
+
+export function createUrl (router) {
+ // This is to make sure we don't references the router object at call time
+ const {pathname, asPath, query} = router
+ return {
+ get query () {
+ warnUrl()
+ return query
+ },
+ get pathname () {
+ warnUrl()
+ return pathname
+ },
+ get asPath () {
+ warnUrl()
+ return asPath
+ },
+ back: () => {
+ warnUrl()
+ router.back()
+ },
+ push: (url, as) => {
+ warnUrl()
+ return router.push(url, as)
+ },
+ pushTo: (href, as) => {
+ warnUrl()
+ const pushRoute = as ? href : null
+ const pushUrl = as || href
+
+ return router.push(pushRoute, pushUrl)
+ },
+ replace: (url, as) => {
+ warnUrl()
+ return router.replace(url, as)
+ },
+ replaceTo: (href, as) => {
+ warnUrl()
+ const replaceRoute = as ? href : null
+ const replaceUrl = as || href
+
+ return router.replace(replaceRoute, replaceUrl)
+ }
+ }
+}
diff --git a/packages/next/pages/_document.js b/packages/next/pages/_document.js
index 37050c9a..cfb38f36 100644
--- a/packages/next/pages/_document.js
+++ b/packages/next/pages/_document.js
@@ -1 +1,218 @@
-module.exports = require('next/document')
+/* eslint-disable */
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import htmlescape from 'htmlescape'
+import flush from 'styled-jsx/server'
+
+const Fragment = React.Fragment || function Fragment ({ children }) {
+ return {children}
+}
+
+export default class Document extends Component {
+ static childContextTypes = {
+ _documentProps: PropTypes.any
+ }
+
+ static getInitialProps ({ renderPage }) {
+ const { html, head, buildManifest } = renderPage()
+ const styles = flush()
+ return { html, head, styles, buildManifest }
+ }
+
+ getChildContext () {
+ return { _documentProps: this.props }
+ }
+
+ render () {
+ return
+
+
+
+
+
+ }
+}
+
+export class Head extends Component {
+ static contextTypes = {
+ _documentProps: PropTypes.any
+ }
+
+ static propTypes = {
+ nonce: PropTypes.string
+ }
+
+ getCssLinks () {
+ const { assetPrefix, files } = this.context._documentProps
+ if(!files || files.length === 0) {
+ return null
+ }
+
+ return files.map((file) => {
+ // Only render .css files here
+ if(!/\.css$/.exec(file)) {
+ return null
+ }
+
+ return
+ })
+ }
+
+ getPreloadDynamicChunks () {
+ const { dynamicImports, assetPrefix } = this.context._documentProps
+ return dynamicImports.map((bundle) => {
+ return
+ })
+ }
+
+ getPreloadMainLinks () {
+ const { assetPrefix, files } = this.context._documentProps
+ if(!files || files.length === 0) {
+ return null
+ }
+
+ return files.map((file) => {
+ // Only render .js files here
+ if(!/\.js$/.exec(file)) {
+ return null
+ }
+
+ return
+ })
+ }
+
+ render () {
+ const { head, styles, assetPrefix, __NEXT_DATA__ } = this.context._documentProps
+ const { page, pathname, buildId } = __NEXT_DATA__
+ const pagePathname = getPagePathname(pathname)
+
+ let children = this.props.children
+ // show a warning if Head contains (only in development)
+ if (process.env.NODE_ENV !== 'production') {
+ children = React.Children.map(children, (child) => {
+ if (child && child.type === 'title') {
+ console.warn("Warning: should not be used in _document.js's . https://err.sh/next.js/no-document-title")
+ }
+ return child
+ })
+ }
+
+ return
+ {head}
+ {page !== '/_error' && }
+
+
+ {this.getPreloadDynamicChunks()}
+ {this.getPreloadMainLinks()}
+ {this.getCssLinks()}
+ {styles || null}
+ {children}
+
+ }
+}
+
+export class Main extends Component {
+ static contextTypes = {
+ _documentProps: PropTypes.any
+ }
+
+ render () {
+ const { html } = this.context._documentProps
+ return (
+
+ )
+ }
+}
+
+export class NextScript extends Component {
+ static contextTypes = {
+ _documentProps: PropTypes.any
+ }
+
+ static propTypes = {
+ nonce: PropTypes.string
+ }
+
+ getDynamicChunks () {
+ const { dynamicImports, assetPrefix } = this.context._documentProps
+ return dynamicImports.map((bundle) => {
+ return
+ })
+ }
+
+ getScripts () {
+ const { assetPrefix, files } = this.context._documentProps
+ if(!files || files.length === 0) {
+ return null
+ }
+
+ return files.map((file) => {
+ // Only render .js files here
+ if(!/\.js$/.exec(file)) {
+ return null
+ }
+
+ return
+ })
+ }
+
+ static getInlineScriptSource (documentProps) {
+ const { __NEXT_DATA__ } = documentProps
+ const { page, pathname } = __NEXT_DATA__
+ return `__NEXT_DATA__ = ${htmlescape(__NEXT_DATA__)};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}${page === '/_error' ? `;__NEXT_REGISTER_PAGE(${htmlescape(pathname)},function(){var e = new Error('Page does not exist: ${htmlescape(pathname)}');e.statusCode=404;return {error:e}})`:''}`
+ }
+
+ render () {
+ const { staticMarkup, assetPrefix, devFiles, __NEXT_DATA__ } = this.context._documentProps
+ const { page, pathname, buildId } = __NEXT_DATA__
+ const pagePathname = getPagePathname(pathname)
+
+ return
+ {devFiles ? devFiles.map((file) => ) : null}
+ {staticMarkup ? null : }
+ {page !== '/_error' && }
+
+
+ {staticMarkup ? null : this.getDynamicChunks()}
+ {staticMarkup ? null : this.getScripts()}
+
+ }
+}
+
+function getPagePathname (pathname) {
+ if (pathname === '/') {
+ return '/index.js'
+ }
+
+ return `${pathname}.js`
+}
diff --git a/packages/next/pages/_error.js b/packages/next/pages/_error.js
index b60f10cf..cef92cf7 100644
--- a/packages/next/pages/_error.js
+++ b/packages/next/pages/_error.js
@@ -1 +1,79 @@
-module.exports = require('next/error')
+import React from 'react'
+import PropTypes from 'prop-types'
+import HTTPStatus from 'http-status'
+import Head from 'next-server/head'
+
+export default class Error extends React.Component {
+ static getInitialProps ({ res, err }) {
+ const statusCode = res ? res.statusCode : (err ? err.statusCode : null)
+ return { statusCode }
+ }
+
+ render () {
+ const { statusCode } = this.props
+ const title = statusCode === 404
+ ? 'This page could not be found'
+ : HTTPStatus[statusCode] || 'An unexpected error has occurred'
+
+ return
+
+
+
{statusCode}: {title}
+
+
+
+ {statusCode ?
{statusCode}
: null}
+
+
{title}.
+
+
+
+ }
+}
+
+if (process.env.NODE_ENV !== 'production') {
+ Error.propTypes = {
+ statusCode: PropTypes.number
+ }
+}
+
+const styles = {
+ error: {
+ color: '#000',
+ background: '#fff',
+ fontFamily: '-apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir, "Helvetica Neue", "Lucida Grande", sans-serif',
+ height: '100vh',
+ textAlign: 'center',
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ justifyContent: 'center'
+ },
+
+ desc: {
+ display: 'inline-block',
+ textAlign: 'left',
+ lineHeight: '49px',
+ height: '49px',
+ verticalAlign: 'middle'
+ },
+
+ h1: {
+ display: 'inline-block',
+ borderRight: '1px solid rgba(0, 0, 0,.3)',
+ margin: 0,
+ marginRight: '20px',
+ padding: '10px 23px 10px 0',
+ fontSize: '24px',
+ fontWeight: 500,
+ verticalAlign: 'top'
+ },
+
+ h2: {
+ fontSize: '14px',
+ fontWeight: 'normal',
+ lineHeight: 'inherit',
+ margin: 0,
+ padding: 0
+ }
+}
diff --git a/packages/next/server/document.js b/packages/next/server/document.js
deleted file mode 100644
index cfb38f36..00000000
--- a/packages/next/server/document.js
+++ /dev/null
@@ -1,218 +0,0 @@
-/* eslint-disable */
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-import htmlescape from 'htmlescape'
-import flush from 'styled-jsx/server'
-
-const Fragment = React.Fragment || function Fragment ({ children }) {
- return {children}
-}
-
-export default class Document extends Component {
- static childContextTypes = {
- _documentProps: PropTypes.any
- }
-
- static getInitialProps ({ renderPage }) {
- const { html, head, buildManifest } = renderPage()
- const styles = flush()
- return { html, head, styles, buildManifest }
- }
-
- getChildContext () {
- return { _documentProps: this.props }
- }
-
- render () {
- return
-
-
-
-
-
-
- }
-}
-
-export class Head extends Component {
- static contextTypes = {
- _documentProps: PropTypes.any
- }
-
- static propTypes = {
- nonce: PropTypes.string
- }
-
- getCssLinks () {
- const { assetPrefix, files } = this.context._documentProps
- if(!files || files.length === 0) {
- return null
- }
-
- return files.map((file) => {
- // Only render .css files here
- if(!/\.css$/.exec(file)) {
- return null
- }
-
- return
- })
- }
-
- getPreloadDynamicChunks () {
- const { dynamicImports, assetPrefix } = this.context._documentProps
- return dynamicImports.map((bundle) => {
- return
- })
- }
-
- getPreloadMainLinks () {
- const { assetPrefix, files } = this.context._documentProps
- if(!files || files.length === 0) {
- return null
- }
-
- return files.map((file) => {
- // Only render .js files here
- if(!/\.js$/.exec(file)) {
- return null
- }
-
- return
- })
- }
-
- render () {
- const { head, styles, assetPrefix, __NEXT_DATA__ } = this.context._documentProps
- const { page, pathname, buildId } = __NEXT_DATA__
- const pagePathname = getPagePathname(pathname)
-
- let children = this.props.children
- // show a warning if Head contains (only in development)
- if (process.env.NODE_ENV !== 'production') {
- children = React.Children.map(children, (child) => {
- if (child && child.type === 'title') {
- console.warn("Warning: should not be used in _document.js's . https://err.sh/next.js/no-document-title")
- }
- return child
- })
- }
-
- return
- {head}
- {page !== '/_error' && }
-
-
- {this.getPreloadDynamicChunks()}
- {this.getPreloadMainLinks()}
- {this.getCssLinks()}
- {styles || null}
- {children}
-
- }
-}
-
-export class Main extends Component {
- static contextTypes = {
- _documentProps: PropTypes.any
- }
-
- render () {
- const { html } = this.context._documentProps
- return (
-
- )
- }
-}
-
-export class NextScript extends Component {
- static contextTypes = {
- _documentProps: PropTypes.any
- }
-
- static propTypes = {
- nonce: PropTypes.string
- }
-
- getDynamicChunks () {
- const { dynamicImports, assetPrefix } = this.context._documentProps
- return dynamicImports.map((bundle) => {
- return
- })
- }
-
- getScripts () {
- const { assetPrefix, files } = this.context._documentProps
- if(!files || files.length === 0) {
- return null
- }
-
- return files.map((file) => {
- // Only render .js files here
- if(!/\.js$/.exec(file)) {
- return null
- }
-
- return
- })
- }
-
- static getInlineScriptSource (documentProps) {
- const { __NEXT_DATA__ } = documentProps
- const { page, pathname } = __NEXT_DATA__
- return `__NEXT_DATA__ = ${htmlescape(__NEXT_DATA__)};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}${page === '/_error' ? `;__NEXT_REGISTER_PAGE(${htmlescape(pathname)},function(){var e = new Error('Page does not exist: ${htmlescape(pathname)}');e.statusCode=404;return {error:e}})`:''}`
- }
-
- render () {
- const { staticMarkup, assetPrefix, devFiles, __NEXT_DATA__ } = this.context._documentProps
- const { page, pathname, buildId } = __NEXT_DATA__
- const pagePathname = getPagePathname(pathname)
-
- return
- {devFiles ? devFiles.map((file) => ) : null}
- {staticMarkup ? null : }
- {page !== '/_error' && }
-
-
- {staticMarkup ? null : this.getDynamicChunks()}
- {staticMarkup ? null : this.getScripts()}
-
- }
-}
-
-function getPagePathname (pathname) {
- if (pathname === '/') {
- return '/index.js'
- }
-
- return `${pathname}.js`
-}
diff --git a/packages/next/taskfile.js b/packages/next/taskfile.js
index c97c4b5d..3e598bae 100644
--- a/packages/next/taskfile.js
+++ b/packages/next/taskfile.js
@@ -1,7 +1,7 @@
const notifier = require('node-notifier')
export async function compile (task) {
- await task.parallel(['bin', 'server', 'nextbuild', 'nextbuildstatic', 'lib', 'client'])
+ await task.parallel(['bin', 'server', 'nextbuild', 'nextbuildstatic', 'pages', 'lib', 'client'])
}
export async function bin (task, opts) {
@@ -35,18 +35,18 @@ export async function nextbuildstatic (task, opts) {
notify('Compiled export files')
}
-export async function copy (task) {
- await task.source('pages/**/*.js').target('dist/pages')
+export async function pages (task, opts) {
+ await task.source(opts.src || 'pages/**/*.js').babel().target('dist/pages')
}
export async function build (task) {
- await task.serial(['copy', 'compile'])
+ await task.serial(['compile'])
}
export default async function (task) {
await task.start('build')
await task.watch('bin/*', 'bin')
- await task.watch('pages/**/*.js', 'copy')
+ await task.watch('pages/**/*.js', 'pages')
await task.watch('server/**/*.js', 'server')
await task.watch('build/**/*.js', 'nextbuild')
await task.watch('export/**/*.js', 'nextexport')