Skip to content

Commit

Permalink
Move out start method from server (#5315)
Browse files Browse the repository at this point in the history
- This makes sure the Next.js renderer / server doesn't have a dependency on the `http` module.
- Splits out util functions for SSR only
- Removes obsolete methods / methods that weren't being tree-shaken
  • Loading branch information
timneutkens committed Sep 27, 2018
1 parent 20f3b6b commit fb0b485
Show file tree
Hide file tree
Showing 13 changed files with 51 additions and 131 deletions.
2 changes: 1 addition & 1 deletion bin/next-build
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { resolve, join } from 'path'
import { existsSync } from 'fs'
import parseArgs from 'minimist'
import build from '../build'
import { printAndExit } from '../lib/utils'
import { printAndExit } from '../server/lib/utils'

const argv = parseArgs(process.argv.slice(2), {
alias: {
Expand Down
11 changes: 4 additions & 7 deletions bin/next-dev
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import { resolve, join } from 'path'
import parseArgs from 'minimist'
import { existsSync } from 'fs'
import Server from '../server'
import { printAndExit } from '../lib/utils'
import startServer from '../server/lib/start-server'
import { printAndExit } from '../server/lib/utils'

const argv = parseArgs(process.argv.slice(2), {
alias: {
Expand Down Expand Up @@ -52,12 +52,9 @@ if (!existsSync(join(dir, 'pages'))) {
printAndExit('> Couldn\'t find a `pages` directory. Please create one under the project root')
}

const srv = new Server({ dir, dev: true })
srv.start(argv.port, argv.hostname)
startServer({dir, dev: true}, argv.port, argv.hostname)
.then(async () => {
if (!process.env.NOW) {
console.log(`> Ready on http://${argv.hostname ? argv.hostname : 'localhost'}:${argv.port}`)
}
console.log(`> Ready on http://${argv.hostname ? argv.hostname : 'localhost'}:${argv.port}`)
})
.catch((err) => {
if (err.code === 'EADDRINUSE') {
Expand Down
2 changes: 1 addition & 1 deletion bin/next-export
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { resolve, join } from 'path'
import { existsSync } from 'fs'
import parseArgs from 'minimist'
import exportApp from '../export'
import { printAndExit } from '../lib/utils'
import { printAndExit } from '../server/lib/utils'

const argv = parseArgs(process.argv.slice(2), {
alias: {
Expand Down
9 changes: 3 additions & 6 deletions bin/next-start
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { resolve } from 'path'
import parseArgs from 'minimist'
import Server from '../server'
import startServer from '../server/lib/start-server'

const argv = parseArgs(process.argv.slice(2), {
alias: {
Expand Down Expand Up @@ -44,12 +44,9 @@ if (argv.help) {

const dir = resolve(argv._[0] || '.')

const srv = new Server({ dir })
srv.start(argv.port, argv.hostname)
startServer({dir}, argv.port, argv.hostname)
.then(() => {
if (!process.env.NOW) {
console.log(`> Ready on http://${argv.hostname ? argv.hostname : 'localhost'}:${argv.port}`)
}
console.log(`> Ready on http://${argv.hostname ? argv.hostname : 'localhost'}:${argv.port}`)
})
.catch((err) => {
console.error(err)
Expand Down
4 changes: 2 additions & 2 deletions lib/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import shallowEquals from './shallow-equals'
import { execOnce, warn, loadGetInitialProps } from './utils'
import { execOnce, loadGetInitialProps } from './utils'
import { makePublicRouterInstance } from './router'

export default class App extends Component {
Expand Down Expand Up @@ -79,7 +79,7 @@ export class Container extends Component {

const warnUrl = execOnce(() => {
if (process.env.NODE_ENV !== 'production') {
warn(`Warning: the 'url' property is deprecated. https://err.sh/zeit/next.js/url-deprecated`)
console.error(`Warning: the 'url' property is deprecated. https://err.sh/zeit/next.js/url-deprecated`)
}
})

Expand Down
8 changes: 4 additions & 4 deletions lib/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { resolve, format, parse } from 'url'
import React, { Component, Children } from 'react'
import PropTypes from 'prop-types'
import Router, { _rewriteUrlForNextExport } from './router'
import { warn, execOnce, getLocationOrigin } from './utils'
import { execOnce, getLocationOrigin } from './utils'

function isLocal (href) {
const url = parse(href, false, true)
Expand All @@ -14,8 +14,6 @@ function isLocal (href) {
(url.protocol === origin.protocol && url.host === origin.host)
}

const warnLink = execOnce(warn)

function memoizedFormatUrl (formatUrl) {
let lastHref = null
let lastAs = null
Expand Down Expand Up @@ -155,6 +153,8 @@ class Link extends Component {
}

if (process.env.NODE_ENV === 'development') {
const warn = execOnce(console.error)

// This module gets removed by webpack.IgnorePlugin
const exact = require('prop-types-exact')
Link.propTypes = exact({
Expand All @@ -171,7 +171,7 @@ if (process.env.NODE_ENV === 'development') {
const value = props[propName]

if (typeof value === 'string') {
warnLink(`Warning: You're using a string directly inside <Link>. This usage has been deprecated. Please add an <a> tag as child of <Link>`)
warn(`Warning: You're using a string directly inside <Link>. This usage has been deprecated. Please add an <a> tag as child of <Link>`)
}

return null
Expand Down
33 changes: 0 additions & 33 deletions lib/prefetch.js

This file was deleted.

26 changes: 10 additions & 16 deletions lib/router/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,9 @@ import { parse, format } from 'url'
import EventEmitter from '../EventEmitter'
import shallowEquals from '../shallow-equals'
import PQueue from '../p-queue'
import { loadGetInitialProps, getURL, warn, execOnce } from '../utils'
import { loadGetInitialProps, getURL } from '../utils'
import { _rewriteUrlForNextExport } from './'

const historyUnavailableWarning = execOnce(() => {
warn(`Warning: window.history is not available.`)
})
const historyMethodWarning = execOnce((method) => {
warn(`Warning: window.history.${method} is not available`)
})

export default class Router {
static events = new EventEmitter()

Expand Down Expand Up @@ -219,14 +212,15 @@ export default class Router {
}

changeState (method, url, as, options = {}) {
if (typeof window.history === 'undefined') {
historyUnavailableWarning()
return
}

if (typeof window.history[method] === 'undefined') {
historyMethodWarning(method)
return
if (process.env.NODE_ENV !== 'production') {
if (typeof window.history === 'undefined') {
console.error(`Warning: window.history is not available.`)
return
}
if (typeof window.history[method] === 'undefined') {
console.error(`Warning: window.history.${method} is not available`)
return
}
}

if (method !== 'pushState' || getURL() !== as) {
Expand Down
37 changes: 0 additions & 37 deletions lib/utils.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
export function warn (message) {
if (process.env.NODE_ENV !== 'production') {
console.error(message)
}
}

export function execOnce (fn) {
let used = false
return (...args) => {
Expand All @@ -14,37 +8,6 @@ export function execOnce (fn) {
}
}

export function deprecated (fn, message) {
// else is used here so that webpack/uglify will remove the code block depending on the build environment
if (process.env.NODE_ENV === 'production') {
return fn
} else {
let warned = false
const newFn = function (...args) {
if (!warned) {
warned = true
console.error(message)
}
return fn.apply(this, args)
}

// copy all properties
Object.assign(newFn, fn)

return newFn
}
}

export function printAndExit (message, code = 1) {
if (code === 0) {
console.log(message)
} else {
console.error(message)
}

process.exit(code)
}

export function getDisplayName (Component) {
if (typeof Component === 'string') {
return Component
Expand Down
26 changes: 2 additions & 24 deletions server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { resolve, join, sep } from 'path'
import { parse as parseUrl } from 'url'
import { parse as parseQs } from 'querystring'
import fs from 'fs'
import http, { STATUS_CODES } from 'http'
import {
renderToHTML,
renderErrorToHTML,
Expand All @@ -27,7 +26,6 @@ export default class Server {
this.dev = dev
this.quiet = quiet
this.router = new Router()
this.http = null
const phase = dev ? PHASE_DEVELOPMENT_SERVER : PHASE_PRODUCTION_SERVER
this.nextConfig = loadConfig(phase, this.dir, conf)
this.distDir = join(this.dir, this.nextConfig.distDir)
Expand Down Expand Up @@ -87,7 +85,7 @@ export default class Server {
.catch((err) => {
if (!this.quiet) console.error(err)
res.statusCode = 500
res.end(STATUS_CODES[500])
res.end('Internal Server Error')
})
}

Expand All @@ -111,15 +109,6 @@ export default class Server {
if (this.hotReloader) {
await this.hotReloader.stop()
}

if (this.http) {
await new Promise((resolve, reject) => {
this.http.close((err) => {
if (err) return reject(err)
return resolve()
})
})
}
}

async defineRoutes () {
Expand Down Expand Up @@ -203,17 +192,6 @@ export default class Server {
}
}

async start (port, hostname) {
await this.prepare()
this.http = http.createServer(this.getRequestHandler())
await new Promise((resolve, reject) => {
// This code catches EADDRINUSE error if the port is already in use
this.http.on('error', reject)
this.http.on('listening', () => resolve())
this.http.listen(port, hostname)
})
}

async run (req, res, parsedUrl) {
if (this.hotReloader) {
const {finished} = await this.hotReloader.run(req, res, parsedUrl)
Expand All @@ -232,7 +210,7 @@ export default class Server {
await this.render404(req, res, parsedUrl)
} else {
res.statusCode = 501
res.end(STATUS_CODES[501])
res.end('Not Implemented')
}
}

Expand Down
14 changes: 14 additions & 0 deletions server/lib/start-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import http from 'http'
import Server from '../index'

export default async function start (serverOptions, port, hostname) {
const app = new Server(serverOptions)
await app.prepare()
const srv = http.createServer(app.getRequestHandler())
await new Promise((resolve, reject) => {
// This code catches EADDRINUSE error if the port is already in use
srv.on('error', reject)
srv.on('listening', () => resolve())
srv.listen(port, hostname)
})
}
9 changes: 9 additions & 0 deletions server/lib/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function printAndExit (message, code = 1) {
if (code === 0) {
console.log(message)
} else {
console.error(message)
}

process.exit(code)
}
1 change: 1 addition & 0 deletions server/next.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Server from './'

// This file is used for when users run `require('next')`
module.exports = (opts) => {
return new Server(opts)
}

0 comments on commit fb0b485

Please sign in to comment.