refactor server into nuxt

This commit is contained in:
Pooya Parsa 2017-06-20 16:14:47 +04:30
parent bf379fc0fd
commit daa50e4efb
13 changed files with 139 additions and 169 deletions

View File

@ -8,7 +8,7 @@ const debug = require('debug')('nuxt:build')
debug.color = 2 // force green color
const fs = require('fs')
const parseArgs = require('minimist')
const { Nuxt, Server, Builder } = require('../')
const { Nuxt, Builder } = require('../')
const chokidar = require('chokidar')
const resolve = require('path').resolve
@ -50,64 +50,64 @@ if (argv.help) {
const rootDir = resolve(argv._[0] || '.')
const nuxtConfigFile = resolve(rootDir, argv['config-file'])
var options = {}
if (fs.existsSync(nuxtConfigFile)) {
options = require(nuxtConfigFile)
} else if (argv['config-file'] !== 'nuxt.config.js') {
console.error(`> Could not load config file ${argv['config-file']}`)
process.exit(1)
}
if (typeof options.rootDir !== 'string') {
options.rootDir = rootDir
}
// Force development mode: add hot reloading and watching changes
options.dev = true
// Load config once for chokidar
const nuxtConfig = loadNuxtConfig()
_.defaultsDeep(nuxtConfig, { watchers: { chokidar: { ignoreInitial: true } } })
const nuxt = new Nuxt(options)
const builder = new Builder(nuxt)
// Start dev
let dev = startDev()
const port = argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port
const host = argv.hostname || process.env.HOST || process.env.npm_package_config_nuxt_host
const server = new Server(nuxt)
server.listen(port, host)
builder.build().then(() => {
listenOnConfigChanges(nuxt, server)
})
function listenOnConfigChanges (nuxt, server) {
// Listen on nuxt.config.js changes
const build = _.debounce(() => {
// Start watching for nuxt.config.js changes
chokidar
.watch(nuxtConfigFile, nuxtConfig.watchers.chokidar)
.on('all', _.debounce(() => {
debug('[nuxt.config.js] changed')
delete require.cache[nuxtConfigFile]
var options = {}
if (fs.existsSync(nuxtConfigFile)) {
try {
options = require(nuxtConfigFile)
} catch (e) {
return console.error(e) // eslint-disable-line no-console
}
}
debug('Rebuilding the app...')
dev = dev.then(startDev)
}), 2500)
if (typeof options.rootDir !== 'string') {
options.rootDir = rootDir
}
function startDev (oldNuxt) {
// Get latest environment variables
const port = argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port
const host = argv.hostname || process.env.HOST || process.env.npm_package_config_nuxt_host
nuxt.close()
.then(() => {
debug('Rebuilding the app...')
const nuxt = new Nuxt(options)
const builder = new Builder(nuxt)
server.nuxt = nuxt
return builder.build()
})
.catch((error) => {
console.error('Error while rebuild the app:', error) // eslint-disable-line no-console
process.exit(1)
})
}, 200)
chokidar.watch(nuxtConfigFile, Object.assign({}, nuxt.options.watchers.chokidar, { ignoreInitial: true }))
.on('all', build)
// Load options
let options = {}
try {
options = loadNuxtConfig()
} catch (err) {
console.error(err)
return // Wait for next reload
}
// Create nuxt and builder instance
const nuxt = new Nuxt(options)
const builder = new Builder(nuxt)
return Promise.resolve()
.then(() => builder.build()) // 1- Start build
.then(() => oldNuxt ? oldNuxt.close() : Promise.resolve()) // 2- Close old nuxt after successful build
.then(() => nuxt.listen(port, host)) // 3- Start listening
.then(() => nuxt) // 4- Pass new nuxt to watch chain
}
module.exports = nuxt
function loadNuxtConfig () {
let options = {}
if (fs.existsSync(nuxtConfigFile)) {
delete require.cache[nuxtConfigFile]
options = require(nuxtConfigFile)
} else if (argv['config-file'] !== 'nuxt.config.js') {
console.error(`> Could not load config file ${argv['config-file']}`)
process.exit(1)
}
if (typeof options.rootDir !== 'string') {
options.rootDir = rootDir
}
// Force development mode for add hot reloading and watching changes
options.dev = true
return options
}

View File

@ -43,17 +43,21 @@ if (argv.help) {
const rootDir = resolve(argv._[0] || '.')
const nuxtConfigFile = resolve(rootDir, argv['config-file'])
var options = {}
let options = {}
if (fs.existsSync(nuxtConfigFile)) {
options = require(nuxtConfigFile)
} else if (argv['config-file'] !== 'nuxt.config.js') {
console.error(`> Could not load config file ${argv['config-file']}`)
process.exit(1)
}
if (typeof options.rootDir !== 'string') {
options.rootDir = rootDir
}
options.dev = false // Force production mode (no webpack middleware called)
// Force production mode (no webpack middleware called)
options.dev = false
// Check if project is built for production
const distDir = join(options.rootDir, options.buildDir || '.nuxt', 'dist' )
@ -65,6 +69,4 @@ if (!fs.existsSync(join(distDir, 'server-bundle.json'))) {
const nuxt = new Nuxt(options)
const port = argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port
const host = argv.hostname || process.env.HOST || process.env.npm_package_config_nuxt_host
new Server(nuxt).listen(port, host)
module.exports = nuxt
nuxt.listen(port, host)

View File

@ -2,7 +2,6 @@ import Options from './options'
import ModuleContainer from './module'
import Nuxt from './nuxt'
import Renderer from './renderer'
import Server from './server'
import * as Utils from 'utils'
export default {
@ -10,6 +9,5 @@ export default {
ModuleContainer,
Nuxt,
Renderer,
Server,
Utils
}

View File

@ -1,7 +1,12 @@
import Tapable from 'tappable'
import chalk from 'chalk'
import ModuleContainer from './module'
import Renderer from './renderer'
import Options from './options'
import Debug from 'debug'
const debug = Debug('nuxt:')
debug.color = 5
export default class Nuxt extends Tapable {
constructor (_options = {}) {
@ -38,6 +43,34 @@ export default class Nuxt extends Tapable {
return this
}
listen (port = 3000, host = 'localhost') {
return new Promise((resolve, reject) => {
const server = this.renderer.app.listen({ port, host, exclusive: false }, err => {
if (err) {
return reject(err)
}
// Show Open URL
let _host = host === '0.0.0.0' ? 'localhost' : host
// eslint-disable-next-line no-console
console.log('\n' + chalk.bold(chalk.bgBlue.black(' OPEN ') + chalk.blue(` http://${_host}:${port}\n`)))
// Close server on nuxt close
this.plugin('close', () => new Promise((_resolve, _reject) => {
server.close(_err => {
debug('server closed')
if (_err) {
return _reject(err)
}
_resolve()
})
}))
resolve()
})
})
}
errorHandler /* istanbul ignore next */ () {
// Silent
if (this.options.errorHandler === false) {
@ -54,7 +87,6 @@ export default class Nuxt extends Tapable {
}
async close (callback) {
// Call for close
await this.applyPluginsAsync('close')
if (typeof callback === 'function') {

View File

@ -21,31 +21,6 @@ setAnsiColors(ansiHTML)
let jsdom = null
const parseTemplate = templateStr => _.template(templateStr, {
interpolate: /{{([\s\S]+?)}}/g
})
const resourceMap = [
{
key: 'clientManifest',
fileName: 'vue-ssr-client-manifest.json',
transform: JSON.parse
},
{
key: 'serverBundle',
fileName: 'server-bundle.json',
transform: JSON.parse
},
{
key: 'appTemplate',
fileName: 'index.html',
transform: parseTemplate
}
]
// Protector utility against request to SSR bundle files
const ssrResourceRegex = new RegExp(resourceMap.map(resource => resource.fileName).join('|'), 'i')
export default class Renderer extends Tapable {
constructor (nuxt) {
super()
@ -403,3 +378,28 @@ export default class Renderer extends Tapable {
return window
}
}
const parseTemplate = templateStr => _.template(templateStr, {
interpolate: /{{([\s\S]+?)}}/g
})
const resourceMap = [
{
key: 'clientManifest',
fileName: 'vue-ssr-client-manifest.json',
transform: JSON.parse
},
{
key: 'serverBundle',
fileName: 'server-bundle.json',
transform: JSON.parse
},
{
key: 'appTemplate',
fileName: 'index.html',
transform: parseTemplate
}
]
// Protector utility against request to SSR bundle files
const ssrResourceRegex = new RegExp(resourceMap.map(resource => resource.fileName).join('|'), 'i')

View File

@ -1,62 +0,0 @@
import http from 'http'
import chalk from 'chalk'
class Server {
constructor (nuxt) {
this.nuxt = nuxt
this.options = nuxt.options
// Initialize
/* istanbul ignore if */
if (nuxt.initialized) {
// If nuxt already initialized
this._ready = this.ready().catch(this.nuxt.errorHandler)
} else {
// Wait for hook
this.nuxt.plugin('afterInit', () => {
this._ready = this.ready()
return this._ready
})
}
// Stop server on nuxt.close()
this.nuxt.plugin('close', () => this.close())
}
async ready () {
/* istanbul ignore if */
if (this._ready) {
return this._ready
}
this.server = http.createServer(this.nuxt.render)
return this
}
listen (port, host) {
host = host || 'localhost'
port = port || 3000
return this.ready()
.then(() => {
this.server.listen(port, host, () => {
let _host = host === '0.0.0.0' ? 'localhost' : host
// eslint-disable-next-line no-console
console.log('\n' + chalk.bold(chalk.bgBlue.black(' OPEN ') + chalk.blue(` http://${_host}:${port}\n`)))
})
}).catch(this.nuxt.errorHandler)
}
close () {
return new Promise((resolve, reject) => {
this.server.close(err => {
if (err) {
return reject(err)
}
resolve()
})
})
}
}
export default Server

View File

@ -1,7 +1,7 @@
import test from 'ava'
import { resolve } from 'path'
import rp from 'request-promise-native'
import { Nuxt, Server, Builder } from '../index.js'
import { Nuxt, Builder } from '../index.js'
const port = 4001
const url = (route) => 'http://localhost:' + port + route
@ -17,8 +17,8 @@ test.before('Init Nuxt.js', async t => {
}
nuxt = new Nuxt(options)
await new Builder(nuxt).build()
server = new Server(nuxt)
server.listen(port, 'localhost')
await nuxt.listen(port, 'localhost')
})
test('/stateless', async t => {

View File

@ -30,7 +30,7 @@ test.before('Init Nuxt.js', async t => {
server = http.createServer((req, res) => {
serve(req, res, finalhandler(req, res))
})
server.listen(port)
await nuxt.listen(port)
})
test('/stateless', async t => {

View File

@ -2,7 +2,7 @@ import test from 'ava'
import { resolve } from 'path'
import rp from 'request-promise-native'
import stdMocks from 'std-mocks'
import { Nuxt, Server, Builder } from '../index.js'
import { Nuxt, Builder } from '../index.js'
const port = 4003
const url = (route) => 'http://localhost:' + port + route
@ -19,8 +19,8 @@ test.before('Init Nuxt.js', async t => {
}
nuxt = new Nuxt(options)
await new Builder(nuxt).build()
server = new Server(nuxt)
server.listen(port, 'localhost')
await nuxt.listen(port, 'localhost')
})
test('/stateless', async t => {

View File

@ -1,6 +1,6 @@
import test from 'ava'
import { resolve } from 'path'
import { Nuxt, Server, Builder } from '../index.js'
import { Nuxt, Builder } from '../index.js'
const port = 4004
// const url = (route) => 'http://localhost:' + port + route
@ -17,8 +17,8 @@ test.before('Init Nuxt.js', async t => {
}
nuxt = new Nuxt(options)
await new Builder(nuxt).build()
server = new Server(nuxt)
server.listen(port, 'localhost')
await nuxt.listen(port, 'localhost')
})
test('/parent', async t => {

View File

@ -1,6 +1,6 @@
import test from 'ava'
import { resolve } from 'path'
import { Nuxt, Server, Builder } from '../index.js'
import { Nuxt, Builder } from '../index.js'
const port = 4005
const url = (route) => 'http://localhost:' + port + route
@ -17,8 +17,8 @@ test.before('Init Nuxt.js', async t => {
}
nuxt = new Nuxt(options)
await new Builder(nuxt).build()
server = new Server(nuxt)
server.listen(port, 'localhost')
await nuxt.listen(port, 'localhost')
})
test('/ should display an error', async t => {

View File

@ -1,7 +1,7 @@
import test from 'ava'
import { resolve, normalize } from 'path'
import rp from 'request-promise-native'
import { Nuxt, Server, Builder } from '../index.js'
import { Nuxt, Builder } from '../index.js'
const port = 4006
const url = (route) => 'http://localhost:' + port + route
@ -18,8 +18,8 @@ test.before('Init Nuxt.js', async t => {
config.runBuild = true
nuxt = new Nuxt(config)
await new Builder(nuxt).build()
server = new Server(nuxt)
server.listen(port, 'localhost')
await nuxt.listen(port, 'localhost')
})
test('Vendor', async t => {

View File

@ -1,7 +1,7 @@
import test from 'ava'
import { resolve } from 'path'
import rp from 'request-promise-native'
import { Nuxt, Server, Builder } from '../index.js'
import { Nuxt, Builder } from '../index.js'
const port = 4007
const url = (route) => 'http://localhost:' + port + route
@ -18,8 +18,8 @@ test.before('Init Nuxt.js', async t => {
config.runBuild = true
nuxt = new Nuxt(config)
await new Builder(nuxt).build()
server = new Server(nuxt)
server.listen(port, 'localhost')
await nuxt.listen(port, 'localhost')
})
test('/', async t => {