Merge branch 'dev' of github.com:nuxt/nuxt.js into dev

This commit is contained in:
Sebastien Chopin 2017-08-01 14:16:19 +02:00
commit 843d21b1ba
18 changed files with 148 additions and 59 deletions

View File

@ -168,12 +168,19 @@ You can start by using one of our starter templates:
## Using nuxt.js programmatically
```js
const Nuxt = require('nuxt')
const { Nuxt, Builder } = require('nuxt')
// Launch nuxt build with given options
// Import and set nuxt.js options
let config = require('./nuxt.config.js')
config.dev = !(process.env.NODE_ENV === 'production')
let nuxt = new Nuxt(config)
// Start build process (only in development)
if (config.dev) {
new Builder(nuxt).build()
}
// You can use nuxt.render(req, res) or nuxt.renderRoute(route, context)
```

View File

@ -1,5 +1,7 @@
#!/usr/bin/env node
const now = Date.now()
const { readFileSync, readJSONSync, writeFileSync, copySync, removeSync } = require('fs-extra')
const { resolve, relative } = require('path')
@ -38,7 +40,7 @@ requires = requires.filter(r => excludes.indexOf(r) === -1)
let dependencies = {}
requires.forEach(r => {
if (!packageJSON.dependencies[r]) {
console.warn('cannot resolve dependency version for ' + r)
console.warn('Cannot resolve dependency version for ' + r)
return
}
dependencies[r] = packageJSON.dependencies[r]
@ -81,6 +83,7 @@ const extraFiles = [
'bin/nuxt-build',
'bin/nuxt-generate',
'bin/nuxt-dev',
'bin/nuxt',
'dist/nuxt.js',
'dist/nuxt.js.map'
]
@ -92,4 +95,9 @@ extraFiles.forEach(file => {
const startIndexjs = resolve(startDir, 'index.js')
writeFileSync(startIndexjs, String(readFileSync(startIndexjs)).replace('./dist/nuxt', './dist/core'))
console.log('generated ' + packageJSON.name + '@' + packageJSON.version)
// Patch bin/nuxt-start
const binStart = resolve(startDir, 'bin/nuxt-start')
writeFileSync(binStart, String(readFileSync(binStart)).replace(/nuxt start/g, 'nuxt-start'))
const ms = Date.now() - now
console.log(`Generated ${packageJSON.name}@${packageJSON.version} in ${ms}ms`)

View File

@ -4,13 +4,13 @@ const { Nuxt, Builder } = require('nuxt')
const host = process.env.HOST || '127.0.0.1'
const port = process.env.PORT || 3000
// Import and Set Nuxt.js options
// Import and set Nuxt.js options
let config = require('./nuxt.config.js')
config.dev = !(process.env.NODE_ENV === 'production')
const nuxt = new Nuxt(config)
// Start build process if
// Start build process in dev mode
if (config.dev) {
const builder = new Builder(nuxt)
builder.build()

View File

@ -372,8 +372,19 @@ export default class Builder extends Tapable {
return reject(err)
}
if (err) return console.error(err) // eslint-disable-line no-console
// Hide internal assets and source maps in stats
const hiddenAssets = [
/.map$/,
/index\..+\.html$/,
/vue-ssr-client-manifest.json/
]
const statsJson = stats.toJson(this.webpackStats, true)
statsJson.assets = statsJson.assets.filter(asset => hiddenAssets.every(e => !e.test(asset.name)))
// Show build stats for production
console.log(stats.toString(this.webpackStats)) // eslint-disable-line no-console
console.log(stats.constructor.jsonToString(statsJson, true))// eslint-disable-line no-console
/* istanbul ignore if */
if (stats.hasErrors()) {
return reject(new Error('Webpack build exited with errors'))

View File

@ -35,7 +35,7 @@ export default class Generator extends Tapable {
await this.builder.build()
}
await this.nuxt.applyPluginsAsync('generate', this)
await this.nuxt.applyPluginsAsync('generator', this)
// Initialize dist directory
if (init) {

View File

@ -5,3 +5,8 @@ export default {
Builder,
Generator
}
export {
Builder,
Generator
}

View File

@ -51,17 +51,19 @@ export default function webpackBaseConfig ({ isClient, isServer }) {
'~~': join(this.options.rootDir),
'@': join(this.options.srcDir),
'@@': join(this.options.rootDir),
'static': join(this.options.srcDir, 'static'), // use in template with <img src="~static/nuxt.png" />
'assets': join(this.options.srcDir, 'assets') // use in template with <img src="~assets/nuxt.png" />
'static': join(this.options.srcDir, 'static'),
'~static': join(this.options.srcDir, 'static'),
'assets': join(this.options.srcDir, 'assets'),
'~assets': join(this.options.srcDir, 'assets')
},
modules: [
join(this.options.rootDir, 'node_modules'),
this.options.modulesDir,
nodeModulesDir
]
},
resolveLoader: {
modules: [
join(this.options.rootDir, 'node_modules'),
this.options.modulesDir,
nodeModulesDir
]
},
@ -78,7 +80,7 @@ export default function webpackBaseConfig ({ isClient, isServer }) {
loader: 'babel-loader',
exclude: /node_modules/,
query: defaults(this.options.build.babel, {
presets: ['vue-app'],
presets: [require.resolve('babel-preset-vue-app')],
babelrc: false,
cacheDirectory: !!this.options.dev
})

View File

@ -3,6 +3,7 @@ import VueSSRServerPlugin from 'vue-server-renderer/server-plugin'
import nodeExternals from 'webpack-node-externals'
import { each } from 'lodash'
import { resolve } from 'path'
import { existsSync } from 'fs'
import base from './base.config.js'
/*
@ -31,16 +32,10 @@ export default function webpackServerConfig () {
libraryTarget: 'commonjs2'
}),
performance: {
hints: false
hints: false,
maxAssetSize: Infinity
},
externals: [
// https://webpack.js.org/configuration/externals/#externals
// https://github.com/liady/webpack-node-externals
nodeExternals({
// load non-javascript files with extensions, presumably via loaders
whitelist: [/\.(?!(?:js|json)$).{1,5}$/i]
})
],
externals: [],
plugins: (config.plugins || []).concat([
new VueSSRServerPlugin({
filename: 'server-bundle.json'
@ -54,6 +49,16 @@ export default function webpackServerConfig () {
])
})
// https://webpack.js.org/configuration/externals/#externals
// https://github.com/liady/webpack-node-externals
if (existsSync(this.options.modulesDir)) {
config.externals.push(nodeExternals({
// load non-javascript files with extensions, presumably via loaders
whitelist: [/\.(?!(?:js|json)$).{1,5}$/i],
modulesDir: this.options.modulesDir
}))
}
// --------------------------------------
// Production specific config
// --------------------------------------

View File

@ -3,7 +3,7 @@ import { extractStyles, styleLoader } from './helpers'
export default function ({ isClient }) {
let babelOptions = JSON.stringify(defaults(this.options.build.babel, {
presets: ['vue-app'],
presets: [require.resolve('babel-preset-vue-app')],
babelrc: false,
cacheDirectory: !!this.options.dev
}))

View File

@ -1,5 +1,12 @@
import * as Utils from './utils'
import Options from './options'
export default {
Utils
Utils,
Options
}
export {
Utils,
Options
}

View File

@ -22,11 +22,13 @@ export default function Options (_options) {
}
// Apply defaults
_.defaultsDeep(options, defaultOptions)
_.defaultsDeep(options, Options.defaults)
// Resolve dirs
options.rootDir = (typeof options.rootDir === 'string' && options.rootDir ? options.rootDir : process.cwd())
options.srcDir = (typeof options.srcDir === 'string' && options.srcDir ? resolve(options.rootDir, options.srcDir) : options.rootDir)
const hasValue = v => typeof v === 'string' && v
options.rootDir = hasValue(options.rootDir) ? options.rootDir : process.cwd()
options.srcDir = hasValue(options.srcDir) ? resolve(options.rootDir, options.srcDir) : options.rootDir
options.modulesDir = resolve(options.rootDir, hasValue(options.modulesDir) ? options.modulesDir : 'node_modules')
options.buildDir = join(options.rootDir, options.buildDir)
// If app.html is defined, set the template path to the user template
@ -38,7 +40,7 @@ export default function Options (_options) {
// Ignore publicPath on dev
/* istanbul ignore if */
if (options.dev && isUrl(options.build.publicPath)) {
options.build.publicPath = defaultOptions.build.publicPath
options.build.publicPath = Options.defaults.build.publicPath
}
// If store defined, update store options to true unless explicitly disabled
@ -52,7 +54,7 @@ export default function Options (_options) {
mode = mode()
}
if (typeof mode === 'string') {
mode = Modes[mode]
mode = Options.modes[mode]
}
// Apply mode
@ -61,7 +63,7 @@ export default function Options (_options) {
return options
}
const Modes = {
Options.modes = {
universal: {
build: {
ssr: true
@ -88,7 +90,7 @@ const Modes = {
}
}
export const defaultOptions = {
Options.defaults = {
mode: 'universal',
dev: process.env.NODE_ENV !== 'production',
buildDir: '.nuxt',

View File

@ -1,13 +1,20 @@
import Options from './options'
import ModuleContainer from './module'
import { Options, Utils } from 'common'
import Module from './module'
import Nuxt from './nuxt'
import Renderer from './renderer'
import * as Utils from 'utils'
export default {
Options,
ModuleContainer,
Nuxt,
Module,
Renderer,
Options,
Utils
}
export {
Nuxt,
Module,
Renderer,
Options,
Utils
}

View File

@ -18,7 +18,7 @@ export default class ModuleContainer extends Tapable {
async _ready () {
await sequence(this.options.modules, this.addModule.bind(this))
await this.nuxt.applyPluginsAsync('module', this)
await this.applyPluginsAsync('ready', this)
}
addVendor (vendor) {

View File

@ -1,8 +1,8 @@
import Tapable from 'tappable'
import chalk from 'chalk'
import { Options } from 'common'
import ModuleContainer from './module'
import Renderer from './renderer'
import Options from './options'
import Debug from 'debug'
import enableDestroy from 'server-destroy'
import Module from 'module'
@ -74,7 +74,7 @@ export default class Nuxt extends Tapable {
})
}))
resolve()
resolve(this.applyPluginsAsync('listen', { server, port, host }))
})
// Add server.destroy(cb) method

View File

@ -11,9 +11,9 @@ import { join, resolve } from 'path'
import fs from 'fs-extra'
import { createBundleRenderer } from 'vue-server-renderer'
import { encodeHtml, getContext, setAnsiColors, isUrl } from 'utils'
import { defaultOptions } from './options'
import Debug from 'debug'
import connect from 'connect'
import { Options } from 'common'
const debug = Debug('nuxt:render')
debug.color = 4 // Force blue color
@ -46,14 +46,12 @@ export default class Renderer extends Tapable {
spaTemplate: null,
errorTemplate: parseTemplate('<pre>{{ stack }}</pre>') // Will be loaded on ready
}
// Bind middleware to this context
this.nuxtMiddleware = this.nuxtMiddleware.bind(this)
this.errorMiddleware = this.errorMiddleware.bind(this)
}
async _ready () {
// Setup all middleWare
await this.nuxt.applyPluginsAsync('renderer', this)
// Setup nuxt middleware
await this.setupMiddleware()
// Load error template
@ -67,12 +65,12 @@ export default class Renderer extends Tapable {
await this.loadResources()
}
await this.nuxt.applyPluginsAsync('renderer', this)
// Call ready plugin
await this.applyPluginsAsync('ready', this)
}
async loadResources (_fs = fs) {
let distPath = resolve(this.options.buildDir, 'dist')
let updated = []
resourceMap.forEach(({ key, fileName, transform }) => {
@ -96,7 +94,6 @@ export default class Renderer extends Tapable {
this.resources[key] = data
updated.push(key)
})
if (updated.length > 0) {
// debug('Updated', updated.join(', '), isServer)
this.createRenderer()
@ -197,7 +194,7 @@ export default class Renderer extends Tapable {
if (!this.options.dev) {
const distDir = resolve(this.options.buildDir, 'dist')
this.useMiddleware({
path: isUrl(this.options.build.publicPath) ? defaultOptions.build.publicPath : this.options.build.publicPath,
path: isUrl(this.options.build.publicPath) ? Options.defaults.build.publicPath : this.options.build.publicPath,
handler: serveStatic(distDir, {
index: false, // Don't serve index.html template
maxAge: (this.options.dev ? 0 : '1y') // 1 year in production
@ -211,10 +208,10 @@ export default class Renderer extends Tapable {
})
// Finally use nuxtMiddleware
this.useMiddleware(this.nuxtMiddleware)
this.useMiddleware(this.nuxtMiddleware.bind(this))
// Error middleware for errors that occurred in middleware that declared above
this.useMiddleware(this.errorMiddleware)
this.useMiddleware(this.errorMiddleware.bind(this))
}
async nuxtMiddleware (req, res, next) {
@ -269,7 +266,7 @@ export default class Renderer extends Tapable {
}
}
async errorMiddleware (err, req, res, next, context) {
errorMiddleware (err, req, res, next, context) {
/* istanbul ignore if */
if (context && context.redirected) {
console.error(err) // eslint-disable-line no-console

View File

@ -1,3 +1,42 @@
# Nuxt-Start
# nuxt-start
WIP - Serve Nuxt.js Application for production
> Start Nuxt.js Application in production mode.
## Installation
```bash
npm install --save nuxt-start
````
Add/Update your "start" script into your `package.json`:
```json
{
"scripts": {
"start": "nuxt-start"
}
}
```
## Usage
```bash
nuxt-start <dir> -p <port number> -H <hostname> -c <config file>
```
## Programmatic Usage
```js
const { Nuxt } = require('nuxt-start')
// Require nuxt config
const config = require('./nuxt.config.js')
// Create a new nuxt instance
const nuxt = new Nuxt(config)
// Start nuxt.js server
nuxt.listen(3000) // nuxt.listen(port, host)
// Or use `nuxt.render` as an express middleware
```

View File

@ -2,7 +2,7 @@ module.exports = function () {
let ctr = 1
// Add hook for module
this.nuxt.plugin('module', moduleContainer => {
this.plugin('ready', moduleContainer => {
this.nuxt.__module_hook = moduleContainer && ctr++
})

View File

@ -62,10 +62,9 @@ test('unique responses with component', async t => {
await uniqueTest(t, '/component')
})
test.todo('unique responses with async components (wait Vue 2.4)')
// test('unique responses with async components', async t => {
// await uniqueTest(t, '/asyncComponent')
// })
test('unique responses with async components', async t => {
await uniqueTest(t, '/asyncComponent')
})
test('unique responses with asyncData()', async t => {
await uniqueTest(t, '/asyncData')