mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-30 09:27:13 +00:00
style: format with prettier
This commit is contained in:
parent
b3e9952976
commit
10d1b5974c
@ -11,7 +11,15 @@ const webpackDevMiddleware = require('webpack-dev-middleware')
|
|||||||
const webpackHotMiddleware = require('webpack-hot-middleware')
|
const webpackHotMiddleware = require('webpack-hot-middleware')
|
||||||
const Debug = require('debug')
|
const Debug = require('debug')
|
||||||
const Glob = require('glob')
|
const Glob = require('glob')
|
||||||
const { r, wp, wChunk, createRoutes, sequence, relativeTo, waitFor } = require('../common/utils')
|
const {
|
||||||
|
r,
|
||||||
|
wp,
|
||||||
|
wChunk,
|
||||||
|
createRoutes,
|
||||||
|
sequence,
|
||||||
|
relativeTo,
|
||||||
|
waitFor
|
||||||
|
} = require('../common/utils')
|
||||||
const { Options } = require('../common')
|
const { Options } = require('../common')
|
||||||
const clientWebpackConfig = require('./webpack/client.config.js')
|
const clientWebpackConfig = require('./webpack/client.config.js')
|
||||||
const serverWebpackConfig = require('./webpack/server.config.js')
|
const serverWebpackConfig = require('./webpack/server.config.js')
|
||||||
@ -41,7 +49,8 @@ module.exports = class Builder {
|
|||||||
this.webpackStats = this.options.dev ? false : this.options.build.stats
|
this.webpackStats = this.options.dev ? false : this.options.build.stats
|
||||||
|
|
||||||
// Helper to resolve build paths
|
// Helper to resolve build paths
|
||||||
this.relativeToBuild = (...args) => relativeTo(this.options.buildDir, ...args)
|
this.relativeToBuild = (...args) =>
|
||||||
|
relativeTo(this.options.buildDir, ...args)
|
||||||
|
|
||||||
this._buildStatus = STATUS.INITIAL
|
this._buildStatus = STATUS.INITIAL
|
||||||
|
|
||||||
@ -56,28 +65,34 @@ module.exports = class Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get plugins() {
|
get plugins() {
|
||||||
return _.uniqBy(this.options.plugins.map((p, i) => {
|
return _.uniqBy(
|
||||||
|
this.options.plugins.map((p, i) => {
|
||||||
if (typeof p === 'string') p = { src: p }
|
if (typeof p === 'string') p = { src: p }
|
||||||
const pluginBaseName = basename(p.src, extname(p.src)).replace(/[^a-zA-Z?\d\s:]/g, '')
|
const pluginBaseName = basename(p.src, extname(p.src)).replace(
|
||||||
|
/[^a-zA-Z?\d\s:]/g,
|
||||||
|
''
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
src: this.nuxt.resolveAlias(p.src),
|
src: this.nuxt.resolveAlias(p.src),
|
||||||
ssr: (p.ssr !== false),
|
ssr: p.ssr !== false,
|
||||||
name: 'nuxt_plugin_' + pluginBaseName + '_' + hash(p.src)
|
name: 'nuxt_plugin_' + pluginBaseName + '_' + hash(p.src)
|
||||||
}
|
}
|
||||||
}), p => p.name)
|
}),
|
||||||
|
p => p.name
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
vendor() {
|
vendor() {
|
||||||
return [
|
return ['vue', 'vue-router', 'vue-meta', this.options.store && 'vuex']
|
||||||
'vue',
|
.concat(
|
||||||
'vue-router',
|
this.options.build.extractCSS && [
|
||||||
'vue-meta',
|
|
||||||
this.options.store && 'vuex'
|
|
||||||
].concat(this.options.build.extractCSS && [
|
|
||||||
// https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/456
|
// https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/456
|
||||||
'vue-style-loader/lib/addStylesClient',
|
'vue-style-loader/lib/addStylesClient',
|
||||||
'css-loader/lib/css-base'
|
'css-loader/lib/css-base'
|
||||||
]).concat(this.options.build.vendor).filter(v => v)
|
]
|
||||||
|
)
|
||||||
|
.concat(this.options.build.vendor)
|
||||||
|
.filter(v => v)
|
||||||
}
|
}
|
||||||
|
|
||||||
vendorEntries() {
|
vendorEntries() {
|
||||||
@ -87,7 +102,7 @@ module.exports = class Builder {
|
|||||||
vendor.forEach(v => {
|
vendor.forEach(v => {
|
||||||
try {
|
try {
|
||||||
require.resolve(v)
|
require.resolve(v)
|
||||||
vendorEntries[v] = [ v ]
|
vendorEntries[v] = [v]
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
@ -125,9 +140,13 @@ module.exports = class Builder {
|
|||||||
if (!existsSync(join(this.options.srcDir, 'pages'))) {
|
if (!existsSync(join(this.options.srcDir, 'pages'))) {
|
||||||
let dir = this.options.srcDir
|
let dir = this.options.srcDir
|
||||||
if (existsSync(join(this.options.srcDir, '..', 'pages'))) {
|
if (existsSync(join(this.options.srcDir, '..', 'pages'))) {
|
||||||
throw new Error(`No \`pages\` directory found in ${dir}. Did you mean to run \`nuxt\` in the parent (\`../\`) directory?`)
|
throw new Error(
|
||||||
|
`No \`pages\` directory found in ${dir}. Did you mean to run \`nuxt\` in the parent (\`../\`) directory?`
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Couldn't find a \`pages\` directory in ${dir}. Please create one under the project root`)
|
throw new Error(
|
||||||
|
`Couldn't find a \`pages\` directory in ${dir}. Please create one under the project root`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,10 +177,14 @@ module.exports = class Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getBabelOptions({ isServer }) {
|
getBabelOptions({ isServer }) {
|
||||||
const options = _.defaults({}, {
|
const options = _.defaults(
|
||||||
|
{},
|
||||||
|
{
|
||||||
babelrc: false,
|
babelrc: false,
|
||||||
cacheDirectory: !!this.options.dev
|
cacheDirectory: !!this.options.dev
|
||||||
}, this.options.build.babel)
|
},
|
||||||
|
this.options.build.babel
|
||||||
|
)
|
||||||
|
|
||||||
if (typeof options.presets === 'function') {
|
if (typeof options.presets === 'function') {
|
||||||
options.presets = options.presets({ isServer })
|
options.presets = options.presets({ isServer })
|
||||||
@ -216,7 +239,9 @@ module.exports = class Builder {
|
|||||||
]
|
]
|
||||||
const templateVars = {
|
const templateVars = {
|
||||||
options: this.options,
|
options: this.options,
|
||||||
extensions: this.options.extensions.map((ext) => ext.replace(/^\./, '')).join('|'),
|
extensions: this.options.extensions
|
||||||
|
.map(ext => ext.replace(/^\./, ''))
|
||||||
|
.join('|'),
|
||||||
messages: this.options.messages,
|
messages: this.options.messages,
|
||||||
uniqBy: _.uniqBy,
|
uniqBy: _.uniqBy,
|
||||||
isDev: this.options.dev,
|
isDev: this.options.dev,
|
||||||
@ -232,30 +257,48 @@ module.exports = class Builder {
|
|||||||
appPath: './App.js',
|
appPath: './App.js',
|
||||||
ignorePrefix: this.options.ignorePrefix,
|
ignorePrefix: this.options.ignorePrefix,
|
||||||
layouts: Object.assign({}, this.options.layouts),
|
layouts: Object.assign({}, this.options.layouts),
|
||||||
loading: typeof this.options.loading === 'string' ? this.relativeToBuild(this.options.srcDir, this.options.loading) : this.options.loading,
|
loading:
|
||||||
|
typeof this.options.loading === 'string'
|
||||||
|
? this.relativeToBuild(this.options.srcDir, this.options.loading)
|
||||||
|
: this.options.loading,
|
||||||
transition: this.options.transition,
|
transition: this.options.transition,
|
||||||
layoutTransition: this.options.layoutTransition,
|
layoutTransition: this.options.layoutTransition,
|
||||||
components: {
|
components: {
|
||||||
ErrorPage: this.options.ErrorPage ? this.relativeToBuild(this.options.ErrorPage) : null
|
ErrorPage: this.options.ErrorPage
|
||||||
|
? this.relativeToBuild(this.options.ErrorPage)
|
||||||
|
: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Layouts --
|
// -- Layouts --
|
||||||
if (existsSync(resolve(this.options.srcDir, 'layouts'))) {
|
if (existsSync(resolve(this.options.srcDir, 'layouts'))) {
|
||||||
const layoutsFiles = await glob('layouts/**/*.{vue,js}', { cwd: this.options.srcDir, ignore: [`layouts/**/${this.options.ignorePrefix}*.{vue,js}`] })
|
const layoutsFiles = await glob('layouts/**/*.{vue,js}', {
|
||||||
|
cwd: this.options.srcDir,
|
||||||
|
ignore: [`layouts/**/${this.options.ignorePrefix}*.{vue,js}`]
|
||||||
|
})
|
||||||
let hasErrorLayout = false
|
let hasErrorLayout = false
|
||||||
layoutsFiles.forEach((file) => {
|
layoutsFiles.forEach(file => {
|
||||||
let name = file.split('/').slice(1).join('/').replace(/\.(vue|js)$/, '')
|
let name = file
|
||||||
|
.split('/')
|
||||||
|
.slice(1)
|
||||||
|
.join('/')
|
||||||
|
.replace(/\.(vue|js)$/, '')
|
||||||
if (name === 'error') {
|
if (name === 'error') {
|
||||||
hasErrorLayout = true
|
hasErrorLayout = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!templateVars.layouts[name] || /\.vue$/.test(file)) {
|
if (!templateVars.layouts[name] || /\.vue$/.test(file)) {
|
||||||
templateVars.layouts[name] = this.relativeToBuild(this.options.srcDir, file)
|
templateVars.layouts[name] = this.relativeToBuild(
|
||||||
|
this.options.srcDir,
|
||||||
|
file
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (!templateVars.components.ErrorPage && hasErrorLayout) {
|
if (!templateVars.components.ErrorPage && hasErrorLayout) {
|
||||||
templateVars.components.ErrorPage = this.relativeToBuild(this.options.srcDir, 'layouts/error.vue')
|
templateVars.components.ErrorPage = this.relativeToBuild(
|
||||||
|
this.options.srcDir,
|
||||||
|
'layouts/error.vue'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If no default layout, create its folder and add the default folder
|
// If no default layout, create its folder and add the default folder
|
||||||
@ -270,24 +313,39 @@ module.exports = class Builder {
|
|||||||
// If user defined a custom method to create routes
|
// If user defined a custom method to create routes
|
||||||
if (this._nuxtPages) {
|
if (this._nuxtPages) {
|
||||||
// Use nuxt.js createRoutes bases on pages/
|
// Use nuxt.js createRoutes bases on pages/
|
||||||
const files = {};
|
const files = {}
|
||||||
(await glob('pages/**/*.{vue,js}', { cwd: this.options.srcDir, ignore: [`pages/**/${this.options.ignorePrefix}*.{vue,js}`] })).forEach(f => {
|
;(await glob('pages/**/*.{vue,js}', {
|
||||||
|
cwd: this.options.srcDir,
|
||||||
|
ignore: [`pages/**/${this.options.ignorePrefix}*.{vue,js}`]
|
||||||
|
})).forEach(f => {
|
||||||
const key = f.replace(/\.(js|vue)$/, '')
|
const key = f.replace(/\.(js|vue)$/, '')
|
||||||
if (/\.vue$/.test(f) || !files[key]) {
|
if (/\.vue$/.test(f) || !files[key]) {
|
||||||
files[key] = f
|
files[key] = f
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
templateVars.router.routes = createRoutes(Object.values(files), this.options.srcDir)
|
templateVars.router.routes = createRoutes(
|
||||||
|
Object.values(files),
|
||||||
|
this.options.srcDir
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
templateVars.router.routes = this.options.build.createRoutes(this.options.srcDir)
|
templateVars.router.routes = this.options.build.createRoutes(
|
||||||
|
this.options.srcDir
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.nuxt.callHook('build:extendRoutes', templateVars.router.routes, r)
|
await this.nuxt.callHook(
|
||||||
|
'build:extendRoutes',
|
||||||
|
templateVars.router.routes,
|
||||||
|
r
|
||||||
|
)
|
||||||
|
|
||||||
// router.extendRoutes method
|
// router.extendRoutes method
|
||||||
if (typeof this.options.router.extendRoutes === 'function') {
|
if (typeof this.options.router.extendRoutes === 'function') {
|
||||||
// let the user extend the routes
|
// let the user extend the routes
|
||||||
const extendedRoutes = this.options.router.extendRoutes(templateVars.router.routes, r)
|
const extendedRoutes = this.options.router.extendRoutes(
|
||||||
|
templateVars.router.routes,
|
||||||
|
r
|
||||||
|
)
|
||||||
// Only overwrite routes when something is returned for backwards compatibility
|
// Only overwrite routes when something is returned for backwards compatibility
|
||||||
if (extendedRoutes !== undefined) {
|
if (extendedRoutes !== undefined) {
|
||||||
templateVars.router.routes = extendedRoutes
|
templateVars.router.routes = extendedRoutes
|
||||||
@ -304,9 +362,12 @@ module.exports = class Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve template files
|
// Resolve template files
|
||||||
const customTemplateFiles = this.options.build.templates.map(t => t.dst || basename(t.src || t))
|
const customTemplateFiles = this.options.build.templates.map(
|
||||||
|
t => t.dst || basename(t.src || t)
|
||||||
|
)
|
||||||
|
|
||||||
templatesFiles = templatesFiles.map(file => {
|
templatesFiles = templatesFiles
|
||||||
|
.map(file => {
|
||||||
// Skip if custom file was already provided in build.templates[]
|
// Skip if custom file was already provided in build.templates[]
|
||||||
if (customTemplateFiles.indexOf(file) !== -1) {
|
if (customTemplateFiles.indexOf(file) !== -1) {
|
||||||
return
|
return
|
||||||
@ -316,29 +377,41 @@ module.exports = class Builder {
|
|||||||
const customFileExists = existsSync(customPath)
|
const customFileExists = existsSync(customPath)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
src: customFileExists
|
src: customFileExists ? customPath : r(this.options.nuxtAppDir, file),
|
||||||
? customPath
|
|
||||||
: r(this.options.nuxtAppDir, file),
|
|
||||||
dst: file,
|
dst: file,
|
||||||
custom: customFileExists
|
custom: customFileExists
|
||||||
}
|
}
|
||||||
}).filter(i => !!i)
|
})
|
||||||
|
.filter(i => !!i)
|
||||||
|
|
||||||
// -- Custom templates --
|
// -- Custom templates --
|
||||||
// Add custom template files
|
// Add custom template files
|
||||||
templatesFiles = templatesFiles.concat(this.options.build.templates.map(t => {
|
templatesFiles = templatesFiles.concat(
|
||||||
return Object.assign({
|
this.options.build.templates.map(t => {
|
||||||
|
return Object.assign(
|
||||||
|
{
|
||||||
src: r(this.options.srcDir, t.src || t),
|
src: r(this.options.srcDir, t.src || t),
|
||||||
dst: t.dst || basename(t.src || t),
|
dst: t.dst || basename(t.src || t),
|
||||||
custom: true
|
custom: true
|
||||||
}, t)
|
},
|
||||||
}))
|
t
|
||||||
|
)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
// -- Loading indicator --
|
// -- Loading indicator --
|
||||||
if (this.options.loadingIndicator.name) {
|
if (this.options.loadingIndicator.name) {
|
||||||
const indicatorPath1 = resolve(this.options.nuxtAppDir, 'views/loading', this.options.loadingIndicator.name + '.html')
|
const indicatorPath1 = resolve(
|
||||||
const indicatorPath2 = this.nuxt.resolveAlias(this.options.loadingIndicator.name)
|
this.options.nuxtAppDir,
|
||||||
const indicatorPath = existsSync(indicatorPath1) ? indicatorPath1 : (existsSync(indicatorPath2) ? indicatorPath2 : null)
|
'views/loading',
|
||||||
|
this.options.loadingIndicator.name + '.html'
|
||||||
|
)
|
||||||
|
const indicatorPath2 = this.nuxt.resolveAlias(
|
||||||
|
this.options.loadingIndicator.name
|
||||||
|
)
|
||||||
|
const indicatorPath = existsSync(indicatorPath1)
|
||||||
|
? indicatorPath1
|
||||||
|
: existsSync(indicatorPath2) ? indicatorPath2 : null
|
||||||
if (indicatorPath) {
|
if (indicatorPath) {
|
||||||
templatesFiles.push({
|
templatesFiles.push({
|
||||||
src: indicatorPath,
|
src: indicatorPath,
|
||||||
@ -347,14 +420,24 @@ module.exports = class Builder {
|
|||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
console.error(`Could not fetch loading indicator: ${this.options.loadingIndicator.name}`) // eslint-disable-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(
|
||||||
|
`Could not fetch loading indicator: ${
|
||||||
|
this.options.loadingIndicator.name
|
||||||
|
}`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.nuxt.callHook('build:templates', { templatesFiles, templateVars, resolve: r })
|
await this.nuxt.callHook('build:templates', {
|
||||||
|
templatesFiles,
|
||||||
|
templateVars,
|
||||||
|
resolve: r
|
||||||
|
})
|
||||||
|
|
||||||
// Interpret and move template files to .nuxt/
|
// Interpret and move template files to .nuxt/
|
||||||
await Promise.all(templatesFiles.map(async ({ src, dst, options, custom }) => {
|
await Promise.all(
|
||||||
|
templatesFiles.map(async ({ src, dst, options, custom }) => {
|
||||||
// Add template to watchers
|
// Add template to watchers
|
||||||
this.options.build.watch.push(src)
|
this.options.build.watch.push(src)
|
||||||
// Render template to dst
|
// Render template to dst
|
||||||
@ -373,12 +456,14 @@ module.exports = class Builder {
|
|||||||
relativeToBuild: this.relativeToBuild
|
relativeToBuild: this.relativeToBuild
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
content = template(Object.assign({}, templateVars, {
|
content = template(
|
||||||
|
Object.assign({}, templateVars, {
|
||||||
options: options || {},
|
options: options || {},
|
||||||
custom,
|
custom,
|
||||||
src,
|
src,
|
||||||
dst
|
dst
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
throw new Error(`Could not compile template ${src}: ${err.message}`)
|
throw new Error(`Could not compile template ${src}: ${err.message}`)
|
||||||
@ -388,7 +473,8 @@ module.exports = class Builder {
|
|||||||
await mkdirp(dirname(path))
|
await mkdirp(dirname(path))
|
||||||
// Write file
|
// Write file
|
||||||
await writeFile(path, content, 'utf8')
|
await writeFile(path, content, 'utf8')
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async webpackBuild() {
|
async webpackBuild() {
|
||||||
@ -443,13 +529,20 @@ module.exports = class Builder {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Start Builds
|
// Start Builds
|
||||||
await sequence(this.compilers, (compiler) => new Promise(async (resolve, reject) => {
|
await sequence(
|
||||||
|
this.compilers,
|
||||||
|
compiler =>
|
||||||
|
new Promise(async (resolve, reject) => {
|
||||||
const name = compiler.options.name
|
const name = compiler.options.name
|
||||||
await this.nuxt.callHook('build:compile', { name, compiler })
|
await this.nuxt.callHook('build:compile', { name, compiler })
|
||||||
|
|
||||||
// Resolve only when compiler emit done event
|
// Resolve only when compiler emit done event
|
||||||
compiler.plugin('done', async (stats) => {
|
compiler.plugin('done', async stats => {
|
||||||
await this.nuxt.callHook('build:compiled', { name, compiler, stats })
|
await this.nuxt.callHook('build:compiled', {
|
||||||
|
name,
|
||||||
|
compiler,
|
||||||
|
stats
|
||||||
|
})
|
||||||
// Reload renderer if available
|
// Reload renderer if available
|
||||||
this.nuxt.renderer.loadResources(sharedFS || require('fs'))
|
this.nuxt.renderer.loadResources(sharedFS || require('fs'))
|
||||||
// Resolve on next tick
|
// Resolve on next tick
|
||||||
@ -471,7 +564,7 @@ module.exports = class Builder {
|
|||||||
}
|
}
|
||||||
// Server, build and watch for changes
|
// Server, build and watch for changes
|
||||||
this.compilersWatching.push(
|
this.compilersWatching.push(
|
||||||
compiler.watch(this.options.watchers.webpack, (err) => {
|
compiler.watch(this.options.watchers.webpack, err => {
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
if (err) return reject(err)
|
if (err) return reject(err)
|
||||||
})
|
})
|
||||||
@ -494,26 +587,43 @@ module.exports = class Builder {
|
|||||||
return reject(new Error('Webpack build exited with errors'))
|
return reject(new Error('Webpack build exited with errors'))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
webpackDev(compiler) {
|
webpackDev(compiler) {
|
||||||
debug('Adding webpack middleware...')
|
debug('Adding webpack middleware...')
|
||||||
|
|
||||||
// Create webpack dev middleware
|
// Create webpack dev middleware
|
||||||
this.webpackDevMiddleware = promisify(webpackDevMiddleware(compiler, Object.assign({
|
this.webpackDevMiddleware = promisify(
|
||||||
|
webpackDevMiddleware(
|
||||||
|
compiler,
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
publicPath: this.options.build.publicPath,
|
publicPath: this.options.build.publicPath,
|
||||||
stats: this.webpackStats,
|
stats: this.webpackStats,
|
||||||
logLevel: 'silent',
|
logLevel: 'silent',
|
||||||
watchOptions: this.options.watchers.webpack
|
watchOptions: this.options.watchers.webpack
|
||||||
}, this.options.build.devMiddleware)))
|
},
|
||||||
|
this.options.build.devMiddleware
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
this.webpackDevMiddleware.close = promisify(this.webpackDevMiddleware.close)
|
this.webpackDevMiddleware.close = promisify(this.webpackDevMiddleware.close)
|
||||||
|
|
||||||
this.webpackHotMiddleware = promisify(webpackHotMiddleware(compiler, Object.assign({
|
this.webpackHotMiddleware = promisify(
|
||||||
|
webpackHotMiddleware(
|
||||||
|
compiler,
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
log: false,
|
log: false,
|
||||||
heartbeat: 10000
|
heartbeat: 10000
|
||||||
}, this.options.build.hotMiddleware)))
|
},
|
||||||
|
this.options.build.hotMiddleware
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
// Inject to renderer instance
|
// Inject to renderer instance
|
||||||
if (this.nuxt.renderer) {
|
if (this.nuxt.renderer) {
|
||||||
@ -550,13 +660,17 @@ module.exports = class Builder {
|
|||||||
const refreshFiles = _.debounce(() => this.generateRoutesAndFiles(), 200)
|
const refreshFiles = _.debounce(() => this.generateRoutesAndFiles(), 200)
|
||||||
|
|
||||||
// Watch for src Files
|
// Watch for src Files
|
||||||
this.filesWatcher = chokidar.watch(patterns, options)
|
this.filesWatcher = chokidar
|
||||||
|
.watch(patterns, options)
|
||||||
.on('add', refreshFiles)
|
.on('add', refreshFiles)
|
||||||
.on('unlink', refreshFiles)
|
.on('unlink', refreshFiles)
|
||||||
|
|
||||||
// Watch for custom provided files
|
// Watch for custom provided files
|
||||||
const watchFiles = _.map(_.uniq(this.options.build.watch), p => upath.normalizeSafe(p))
|
const watchFiles = _.map(_.uniq(this.options.build.watch), p =>
|
||||||
this.customFilesWatcher = chokidar.watch(watchFiles, options)
|
upath.normalizeSafe(p)
|
||||||
|
)
|
||||||
|
this.customFilesWatcher = chokidar
|
||||||
|
.watch(watchFiles, options)
|
||||||
.on('change', refreshFiles)
|
.on('change', refreshFiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,7 +692,11 @@ module.exports = class Builder {
|
|||||||
async generateConfig() {
|
async generateConfig() {
|
||||||
const config = resolve(this.options.buildDir, 'build.config.js')
|
const config = resolve(this.options.buildDir, 'build.config.js')
|
||||||
const options = _.omit(this.options, Options.unsafeKeys)
|
const options = _.omit(this.options, Options.unsafeKeys)
|
||||||
await writeFile(config, `module.exports = ${JSON.stringify(options, null, ' ')}`, 'utf8')
|
await writeFile(
|
||||||
|
config,
|
||||||
|
`module.exports = ${JSON.stringify(options, null, ' ')}`,
|
||||||
|
'utf8'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ const { resolve } = require('path')
|
|||||||
const { existsSync } = require('fs')
|
const { existsSync } = require('fs')
|
||||||
const Debug = require('debug')
|
const Debug = require('debug')
|
||||||
const Chalk = require('chalk')
|
const Chalk = require('chalk')
|
||||||
|
const { printWarn } = require('../../common/utils')
|
||||||
const base = require('./base.config.js')
|
const base = require('./base.config.js')
|
||||||
|
|
||||||
const debug = Debug('nuxt:build')
|
const debug = Debug('nuxt:build')
|
||||||
@ -43,7 +44,10 @@ module.exports = function webpackClientConfig() {
|
|||||||
// Env object defined in nuxt.config.js
|
// Env object defined in nuxt.config.js
|
||||||
let env = {}
|
let env = {}
|
||||||
each(this.options.env, (value, key) => {
|
each(this.options.env, (value, key) => {
|
||||||
env['process.env.' + key] = (['boolean', 'number'].indexOf(typeof value) !== -1 ? value : JSON.stringify(value))
|
env['process.env.' + key] =
|
||||||
|
['boolean', 'number'].indexOf(typeof value) !== -1
|
||||||
|
? value
|
||||||
|
: JSON.stringify(value)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Generate output HTML for SPA
|
// Generate output HTML for SPA
|
||||||
@ -85,36 +89,47 @@ module.exports = function webpackClientConfig() {
|
|||||||
|
|
||||||
// Define Env
|
// Define Env
|
||||||
config.plugins.push(
|
config.plugins.push(
|
||||||
new webpack.DefinePlugin(Object.assign(env, {
|
new webpack.DefinePlugin(
|
||||||
'process.env.NODE_ENV': JSON.stringify(env.NODE_ENV || (this.options.dev ? 'development' : 'production')),
|
Object.assign(env, {
|
||||||
|
'process.env.NODE_ENV': JSON.stringify(
|
||||||
|
env.NODE_ENV || (this.options.dev ? 'development' : 'production')
|
||||||
|
),
|
||||||
'process.env.VUE_ENV': JSON.stringify('client'),
|
'process.env.VUE_ENV': JSON.stringify('client'),
|
||||||
'process.mode': JSON.stringify(this.options.mode),
|
'process.mode': JSON.stringify(this.options.mode),
|
||||||
'process.browser': true,
|
'process.browser': true,
|
||||||
'process.client': true,
|
'process.client': true,
|
||||||
'process.server': false,
|
'process.server': false,
|
||||||
'process.static': this.isStatic
|
'process.static': this.isStatic
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Build progress bar
|
// Build progress bar
|
||||||
if (this.options.build.profile) {
|
if (this.options.build.profile) {
|
||||||
config.plugins.push(new ProgressPlugin({
|
config.plugins.push(
|
||||||
|
new ProgressPlugin({
|
||||||
profile: true
|
profile: true
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
config.plugins.push(new ProgressBarPlugin({
|
config.plugins.push(
|
||||||
|
new ProgressBarPlugin({
|
||||||
complete: Chalk.green('█'),
|
complete: Chalk.green('█'),
|
||||||
incomplete: Chalk.white('█'),
|
incomplete: Chalk.white('█'),
|
||||||
format: ' :bar ' + Chalk.green.bold(':percent') + ' :msg',
|
format: ' :bar ' + Chalk.green.bold(':percent') + ' :msg',
|
||||||
clear: false
|
clear: false
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldClearConsole = this.options.build.stats !== false &&
|
const shouldClearConsole =
|
||||||
|
this.options.build.stats !== false &&
|
||||||
this.options.build.stats !== 'errors-only'
|
this.options.build.stats !== 'errors-only'
|
||||||
|
|
||||||
// Add friendly error plugin
|
// Add friendly error plugin
|
||||||
config.plugins.push(new FriendlyErrorsWebpackPlugin({ clearConsole: shouldClearConsole }))
|
config.plugins.push(
|
||||||
|
new FriendlyErrorsWebpackPlugin({ clearConsole: shouldClearConsole })
|
||||||
|
)
|
||||||
|
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
// Dev specific config
|
// Dev specific config
|
||||||
@ -126,7 +141,9 @@ module.exports = function webpackClientConfig() {
|
|||||||
// Add HMR support
|
// Add HMR support
|
||||||
config.entry.app = [
|
config.entry.app = [
|
||||||
// https://github.com/glenjamin/webpack-hot-middleware#config
|
// https://github.com/glenjamin/webpack-hot-middleware#config
|
||||||
`webpack-hot-middleware/client?name=client&reload=true&timeout=30000&path=${this.options.router.base}/__webpack_hmr`.replace(/\/\//g, '/'),
|
`webpack-hot-middleware/client?name=client&reload=true&timeout=30000&path=${
|
||||||
|
this.options.router.base
|
||||||
|
}/__webpack_hmr`.replace(/\/\//g, '/'),
|
||||||
config.entry.app
|
config.entry.app
|
||||||
]
|
]
|
||||||
config.plugins.push(
|
config.plugins.push(
|
||||||
@ -156,7 +173,9 @@ module.exports = function webpackClientConfig() {
|
|||||||
// https://github.com/webpack-contrib/uglifyjs-webpack-plugin
|
// https://github.com/webpack-contrib/uglifyjs-webpack-plugin
|
||||||
if (this.options.build.uglify !== false) {
|
if (this.options.build.uglify !== false) {
|
||||||
config.plugins.push(
|
config.plugins.push(
|
||||||
new UglifyJSPlugin(Object.assign({
|
new UglifyJSPlugin(
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
// cache: true,
|
// cache: true,
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
parallel: true,
|
parallel: true,
|
||||||
@ -168,13 +187,18 @@ module.exports = function webpackClientConfig() {
|
|||||||
comments: /^\**!|@preserve|@license|@cc_on/
|
comments: /^\**!|@preserve|@license|@cc_on/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, this.options.build.uglify))
|
},
|
||||||
|
this.options.build.uglify
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Webpack Bundle Analyzer
|
// Webpack Bundle Analyzer
|
||||||
if (this.options.build.analyze) {
|
if (this.options.build.analyze) {
|
||||||
config.plugins.push(new BundleAnalyzerPlugin(Object.assign({}, this.options.build.analyze)))
|
config.plugins.push(
|
||||||
|
new BundleAnalyzerPlugin(Object.assign({}, this.options.build.analyze))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +207,7 @@ module.exports = function webpackClientConfig() {
|
|||||||
const isDev = this.options.dev
|
const isDev = this.options.dev
|
||||||
const extendedConfig = this.options.build.extend.call(this, config, {
|
const extendedConfig = this.options.build.extend.call(this, config, {
|
||||||
get dev() {
|
get dev() {
|
||||||
console.warn('dev has been deprecated in build.extend(), please use isDev') // eslint-disable-line no-console
|
printWarn('dev has been deprecated in build.extend(), please use isDev')
|
||||||
return isDev
|
return isDev
|
||||||
},
|
},
|
||||||
isDev,
|
isDev,
|
||||||
|
@ -2,9 +2,11 @@ module.exports = class WarnFixPlugin {
|
|||||||
apply(compiler) /* istanbul ignore next */ {
|
apply(compiler) /* istanbul ignore next */ {
|
||||||
compiler.plugin('done', stats => {
|
compiler.plugin('done', stats => {
|
||||||
stats.compilation.warnings = stats.compilation.warnings.filter(warn => {
|
stats.compilation.warnings = stats.compilation.warnings.filter(warn => {
|
||||||
if (warn.name === 'ModuleDependencyWarning' &&
|
if (
|
||||||
|
warn.name === 'ModuleDependencyWarning' &&
|
||||||
warn.message.includes(`export 'default'`) &&
|
warn.message.includes(`export 'default'`) &&
|
||||||
warn.message.includes('nuxt_plugin_')) {
|
warn.message.includes('nuxt_plugin_')
|
||||||
|
) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -14,7 +14,13 @@ module.exports = function postcssConfig() {
|
|||||||
// Search for postCSS config file and use it if exists
|
// Search for postCSS config file and use it if exists
|
||||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
// https://github.com/michael-ciniawsky/postcss-load-config
|
||||||
for (let dir of [this.options.srcDir, this.options.rootDir]) {
|
for (let dir of [this.options.srcDir, this.options.rootDir]) {
|
||||||
for (let file of ['postcss.config.js', '.postcssrc.js', '.postcssrc', '.postcssrc.json', '.postcssrc.yaml']) {
|
for (let file of [
|
||||||
|
'postcss.config.js',
|
||||||
|
'.postcssrc.js',
|
||||||
|
'.postcssrc',
|
||||||
|
'.postcssrc.json',
|
||||||
|
'.postcssrc.yaml'
|
||||||
|
]) {
|
||||||
if (existsSync(resolve(dir, file))) {
|
if (existsSync(resolve(dir, file))) {
|
||||||
const postcssConfigPath = resolve(dir, file)
|
const postcssConfigPath = resolve(dir, file)
|
||||||
return {
|
return {
|
||||||
@ -34,7 +40,8 @@ module.exports = function postcssConfig() {
|
|||||||
|
|
||||||
// Apply default plugins
|
// Apply default plugins
|
||||||
if (isPureObject(config)) {
|
if (isPureObject(config)) {
|
||||||
config = Object.assign({
|
config = Object.assign(
|
||||||
|
{
|
||||||
useConfigFile: false,
|
useConfigFile: false,
|
||||||
sourceMap: this.options.build.cssSourceMap,
|
sourceMap: this.options.build.cssSourceMap,
|
||||||
plugins: {
|
plugins: {
|
||||||
@ -54,7 +61,9 @@ module.exports = function postcssConfig() {
|
|||||||
// http://cssnext.io/postcss
|
// http://cssnext.io/postcss
|
||||||
'postcss-cssnext': {}
|
'postcss-cssnext': {}
|
||||||
}
|
}
|
||||||
}, config)
|
},
|
||||||
|
config
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map postcss plugins into instances on object mode once
|
// Map postcss plugins into instances on object mode once
|
||||||
@ -66,7 +75,8 @@ module.exports = function postcssConfig() {
|
|||||||
if (opts === false) return // Disabled
|
if (opts === false) return // Disabled
|
||||||
const instance = plugin(opts)
|
const instance = plugin(opts)
|
||||||
return instance
|
return instance
|
||||||
}).filter(e => e)
|
})
|
||||||
|
.filter(e => e)
|
||||||
}
|
}
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
@ -4,6 +4,7 @@ const nodeExternals = require('webpack-node-externals')
|
|||||||
const { each } = require('lodash')
|
const { each } = require('lodash')
|
||||||
const { resolve } = require('path')
|
const { resolve } = require('path')
|
||||||
const { existsSync } = require('fs')
|
const { existsSync } = require('fs')
|
||||||
|
const { printWarn } = require('../../common/utils')
|
||||||
const base = require('./base.config.js')
|
const base = require('./base.config.js')
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -17,7 +18,10 @@ module.exports = function webpackServerConfig() {
|
|||||||
// Env object defined in nuxt.config.js
|
// Env object defined in nuxt.config.js
|
||||||
let env = {}
|
let env = {}
|
||||||
each(this.options.env, (value, key) => {
|
each(this.options.env, (value, key) => {
|
||||||
env['process.env.' + key] = (['boolean', 'number'].indexOf(typeof value) !== -1 ? value : JSON.stringify(value))
|
env['process.env.' + key] =
|
||||||
|
['boolean', 'number'].indexOf(typeof value) !== -1
|
||||||
|
? value
|
||||||
|
: JSON.stringify(value)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Config devtool
|
// Config devtool
|
||||||
@ -40,15 +44,19 @@ module.exports = function webpackServerConfig() {
|
|||||||
new VueSSRServerPlugin({
|
new VueSSRServerPlugin({
|
||||||
filename: 'server-bundle.json'
|
filename: 'server-bundle.json'
|
||||||
}),
|
}),
|
||||||
new webpack.DefinePlugin(Object.assign(env, {
|
new webpack.DefinePlugin(
|
||||||
'process.env.NODE_ENV': JSON.stringify(env.NODE_ENV || (this.options.dev ? 'development' : 'production')),
|
Object.assign(env, {
|
||||||
|
'process.env.NODE_ENV': JSON.stringify(
|
||||||
|
env.NODE_ENV || (this.options.dev ? 'development' : 'production')
|
||||||
|
),
|
||||||
'process.env.VUE_ENV': JSON.stringify('server'),
|
'process.env.VUE_ENV': JSON.stringify('server'),
|
||||||
'process.mode': JSON.stringify(this.options.mode),
|
'process.mode': JSON.stringify(this.options.mode),
|
||||||
'process.browser': false,
|
'process.browser': false,
|
||||||
'process.client': false,
|
'process.client': false,
|
||||||
'process.server': true,
|
'process.server': true,
|
||||||
'process.static': this.isStatic
|
'process.static': this.isStatic
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -56,11 +64,13 @@ module.exports = function webpackServerConfig() {
|
|||||||
// https://github.com/liady/webpack-node-externals
|
// https://github.com/liady/webpack-node-externals
|
||||||
this.options.modulesDir.forEach(dir => {
|
this.options.modulesDir.forEach(dir => {
|
||||||
if (existsSync(dir)) {
|
if (existsSync(dir)) {
|
||||||
config.externals.push(nodeExternals({
|
config.externals.push(
|
||||||
|
nodeExternals({
|
||||||
// load non-javascript files with extensions, presumably via loaders
|
// load non-javascript files with extensions, presumably via loaders
|
||||||
whitelist: [/es6-promise|\.(?!(?:js|json)$).{1,5}$/i],
|
whitelist: [/es6-promise|\.(?!(?:js|json)$).{1,5}$/i],
|
||||||
modulesDir: dir
|
modulesDir: dir
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -69,7 +79,7 @@ module.exports = function webpackServerConfig() {
|
|||||||
const isDev = this.options.dev
|
const isDev = this.options.dev
|
||||||
const extendedConfig = this.options.build.extend.call(this, config, {
|
const extendedConfig = this.options.build.extend.call(this, config, {
|
||||||
get dev() {
|
get dev() {
|
||||||
console.warn('dev has been deprecated in build.extend(), please use isDev') // eslint-disable-line no-console
|
printWarn('dev has been deprecated in build.extend(), please use isDev')
|
||||||
return isDev
|
return isDev
|
||||||
},
|
},
|
||||||
isDev,
|
isDev,
|
||||||
|
@ -6,8 +6,12 @@ module.exports = function styleLoader(ext, loaders = [], isVueLoader = false) {
|
|||||||
const sourceMap = Boolean(this.options.build.cssSourceMap)
|
const sourceMap = Boolean(this.options.build.cssSourceMap)
|
||||||
|
|
||||||
// Normalize loaders
|
// Normalize loaders
|
||||||
loaders = (Array.isArray(loaders) ? loaders : [loaders])
|
loaders = (Array.isArray(loaders) ? loaders : [loaders]).map(loader =>
|
||||||
.map(loader => Object.assign({ options: { sourceMap } }, typeof loader === 'string' ? { loader } : loader))
|
Object.assign(
|
||||||
|
{ options: { sourceMap } },
|
||||||
|
typeof loader === 'string' ? { loader } : loader
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
// Prepare vue-style-loader
|
// Prepare vue-style-loader
|
||||||
// https://github.com/vuejs/vue-style-loader
|
// https://github.com/vuejs/vue-style-loader
|
||||||
@ -21,8 +25,14 @@ module.exports = function styleLoader(ext, loaders = [], isVueLoader = false) {
|
|||||||
// style-resources-loader
|
// style-resources-loader
|
||||||
// https://github.com/yenshih/style-resources-loader
|
// https://github.com/yenshih/style-resources-loader
|
||||||
if (this.options.build.styleResources[ext]) {
|
if (this.options.build.styleResources[ext]) {
|
||||||
const patterns = Array.isArray(this.options.build.styleResources[ext]) ? this.options.build.styleResources[ext] : [ this.options.build.styleResources[ext] ]
|
const patterns = Array.isArray(this.options.build.styleResources[ext])
|
||||||
const options = Object.assign({}, (this.options.build.styleResources.options || {}), { patterns })
|
? this.options.build.styleResources[ext]
|
||||||
|
: [this.options.build.styleResources[ext]]
|
||||||
|
const options = Object.assign(
|
||||||
|
{},
|
||||||
|
this.options.build.styleResources.options || {},
|
||||||
|
{ patterns }
|
||||||
|
)
|
||||||
|
|
||||||
loaders.push({
|
loaders.push({
|
||||||
loader: 'style-resources-loader',
|
loader: 'style-resources-loader',
|
||||||
@ -77,9 +87,9 @@ module.exports = function styleLoader(ext, loaders = [], isVueLoader = false) {
|
|||||||
options: { sourceMap }
|
options: { sourceMap }
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.options.dev ? [ hotLoader ].concat(extractLoader) : extractLoader
|
return this.options.dev ? [hotLoader].concat(extractLoader) : extractLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Without extractCSS --
|
// -- Without extractCSS --
|
||||||
return [ vueStyleLoader ].concat(loaders)
|
return [vueStyleLoader].concat(loaders)
|
||||||
}
|
}
|
||||||
|
@ -9,17 +9,22 @@ module.exports = function vueLoader({ isServer }) {
|
|||||||
cssSourceMap: this.options.build.cssSourceMap,
|
cssSourceMap: this.options.build.cssSourceMap,
|
||||||
preserveWhitespace: false,
|
preserveWhitespace: false,
|
||||||
loaders: {
|
loaders: {
|
||||||
'js': {
|
js: {
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
options: this.getBabelOptions({ isServer })
|
options: this.getBabelOptions({ isServer })
|
||||||
},
|
},
|
||||||
// Note: do not nest the `postcss` option under `loaders`
|
// Note: do not nest the `postcss` option under `loaders`
|
||||||
'css': styleLoader.call(this, 'css', [], true),
|
css: styleLoader.call(this, 'css', [], true),
|
||||||
'less': styleLoader.call(this, 'less', 'less-loader', true),
|
less: styleLoader.call(this, 'less', 'less-loader', true),
|
||||||
'scss': styleLoader.call(this, 'scss', 'sass-loader', true),
|
scss: styleLoader.call(this, 'scss', 'sass-loader', true),
|
||||||
'sass': styleLoader.call(this, 'sass', {loader: 'sass-loader', options: { indentedSyntax: true }}, true),
|
sass: styleLoader.call(
|
||||||
'stylus': styleLoader.call(this, 'stylus', 'stylus-loader', true),
|
this,
|
||||||
'styl': styleLoader.call(this, 'stylus', 'stylus-loader', true)
|
'sass',
|
||||||
|
{ loader: 'sass-loader', options: { indentedSyntax: true } },
|
||||||
|
true
|
||||||
|
),
|
||||||
|
stylus: styleLoader.call(this, 'stylus', 'stylus-loader', true),
|
||||||
|
styl: styleLoader.call(this, 'stylus', 'stylus-loader', true)
|
||||||
},
|
},
|
||||||
template: {
|
template: {
|
||||||
doctype: 'html' // For pug, see https://github.com/vuejs/vue-loader/issues/55
|
doctype: 'html' // For pug, see https://github.com/vuejs/vue-loader/issues/55
|
||||||
|
@ -19,7 +19,11 @@ Options.from = function (_options) {
|
|||||||
if (options.loading === true) {
|
if (options.loading === true) {
|
||||||
delete options.loading
|
delete options.loading
|
||||||
}
|
}
|
||||||
if (options.router && options.router.middleware && !Array.isArray(options.router.middleware)) {
|
if (
|
||||||
|
options.router &&
|
||||||
|
options.router.middleware &&
|
||||||
|
!Array.isArray(options.router.middleware)
|
||||||
|
) {
|
||||||
options.router.middleware = [options.router.middleware]
|
options.router.middleware = [options.router.middleware]
|
||||||
}
|
}
|
||||||
if (options.router && typeof options.router.base === 'string') {
|
if (options.router && typeof options.router.base === 'string') {
|
||||||
@ -32,7 +36,7 @@ Options.from = function (_options) {
|
|||||||
options.layoutTransition = { name: options.layoutTransition }
|
options.layoutTransition = { name: options.layoutTransition }
|
||||||
}
|
}
|
||||||
if (typeof options.extensions === 'string') {
|
if (typeof options.extensions === 'string') {
|
||||||
options.extensions = [ options.extensions ]
|
options.extensions = [options.extensions]
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasValue = v => typeof v === 'string' && v
|
const hasValue = v => typeof v === 'string' && v
|
||||||
@ -50,7 +54,9 @@ Options.from = function (_options) {
|
|||||||
_.defaultsDeep(options, Options.defaults)
|
_.defaultsDeep(options, Options.defaults)
|
||||||
|
|
||||||
// Resolve dirs
|
// Resolve dirs
|
||||||
options.srcDir = hasValue(options.srcDir) ? resolve(options.rootDir, options.srcDir) : options.rootDir
|
options.srcDir = hasValue(options.srcDir)
|
||||||
|
? resolve(options.rootDir, options.srcDir)
|
||||||
|
: options.rootDir
|
||||||
options.buildDir = resolve(options.rootDir, options.buildDir)
|
options.buildDir = resolve(options.rootDir, options.buildDir)
|
||||||
options.cacheDir = resolve(options.rootDir, options.cacheDir)
|
options.cacheDir = resolve(options.rootDir, options.cacheDir)
|
||||||
|
|
||||||
@ -94,11 +100,14 @@ Options.from = function (_options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply defaults to loadingIndicator
|
// Apply defaults to loadingIndicator
|
||||||
options.loadingIndicator = Object.assign({
|
options.loadingIndicator = Object.assign(
|
||||||
|
{
|
||||||
name: 'pulse',
|
name: 'pulse',
|
||||||
color: '#dbe1ec',
|
color: '#dbe1ec',
|
||||||
background: 'white'
|
background: 'white'
|
||||||
}, options.loadingIndicator)
|
},
|
||||||
|
options.loadingIndicator
|
||||||
|
)
|
||||||
|
|
||||||
// cssSourceMap
|
// cssSourceMap
|
||||||
if (options.build.cssSourceMap === undefined) {
|
if (options.build.cssSourceMap === undefined) {
|
||||||
@ -111,7 +120,8 @@ Options.from = function (_options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply mode preset
|
// Apply mode preset
|
||||||
let modePreset = Options.modes[options.mode || 'universal'] || Options.modes['universal']
|
let modePreset =
|
||||||
|
Options.modes[options.mode || 'universal'] || Options.modes['universal']
|
||||||
_.defaultsDeep(options, modePreset)
|
_.defaultsDeep(options, modePreset)
|
||||||
|
|
||||||
// If no server-side rendering, add appear true transition
|
// If no server-side rendering, add appear true transition
|
||||||
@ -299,9 +309,11 @@ Options.defaults = {
|
|||||||
server_error: 'Server error',
|
server_error: 'Server error',
|
||||||
nuxtjs: 'Nuxt.js',
|
nuxtjs: 'Nuxt.js',
|
||||||
back_to_home: 'Back to the home page',
|
back_to_home: 'Back to the home page',
|
||||||
server_error_details: 'An error occurred in the application and your page could not be served. If you are the application owner, check your logs for details.',
|
server_error_details:
|
||||||
|
'An error occurred in the application and your page could not be served. If you are the application owner, check your logs for details.',
|
||||||
client_error: 'Error',
|
client_error: 'Error',
|
||||||
client_error_details: 'An error occurred while rendering the page. Check developer tools console for details.',
|
client_error_details:
|
||||||
|
'An error occurred while rendering the page. Check developer tools console for details.',
|
||||||
redirect: 'Redirecting to external page.'
|
redirect: 'Redirecting to external page.'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
const Vue = require('vue')
|
const Vue = require('vue')
|
||||||
const VueMeta = require('vue-meta')
|
const VueMeta = require('vue-meta')
|
||||||
const VueServerRenderer = require('vue-server-renderer')
|
const VueServerRenderer = require('vue-server-renderer')
|
||||||
@ -51,7 +50,13 @@ module.exports = class MetaRenderer {
|
|||||||
// BODY_ATTRS
|
// BODY_ATTRS
|
||||||
meta.BODY_ATTRS = m.bodyAttrs.text()
|
meta.BODY_ATTRS = m.bodyAttrs.text()
|
||||||
// HEAD tags
|
// HEAD tags
|
||||||
meta.HEAD = m.meta.text() + m.title.text() + m.link.text() + m.style.text() + m.script.text() + m.noscript.text()
|
meta.HEAD =
|
||||||
|
m.meta.text() +
|
||||||
|
m.title.text() +
|
||||||
|
m.link.text() +
|
||||||
|
m.style.text() +
|
||||||
|
m.script.text() +
|
||||||
|
m.noscript.text()
|
||||||
// BODY_SCRIPTS
|
// BODY_SCRIPTS
|
||||||
meta.BODY_SCRIPTS = m.script.text({ body: true })
|
meta.BODY_SCRIPTS = m.script.text({ body: true })
|
||||||
// Resources Hints
|
// Resources Hints
|
||||||
@ -62,11 +67,17 @@ module.exports = class MetaRenderer {
|
|||||||
const publicPath = clientManifest.publicPath || '/_nuxt/'
|
const publicPath = clientManifest.publicPath || '/_nuxt/'
|
||||||
// Pre-Load initial resources
|
// Pre-Load initial resources
|
||||||
if (Array.isArray(clientManifest.initial)) {
|
if (Array.isArray(clientManifest.initial)) {
|
||||||
meta.resourceHints += clientManifest.initial.map(r => `<link rel="preload" href="${publicPath}${r}" as="script" />`).join('')
|
meta.resourceHints += clientManifest.initial
|
||||||
|
.map(
|
||||||
|
r => `<link rel="preload" href="${publicPath}${r}" as="script" />`
|
||||||
|
)
|
||||||
|
.join('')
|
||||||
}
|
}
|
||||||
// Pre-Fetch async resources
|
// Pre-Fetch async resources
|
||||||
if (Array.isArray(clientManifest.async)) {
|
if (Array.isArray(clientManifest.async)) {
|
||||||
meta.resourceHints += clientManifest.async.map(r => `<link rel="prefetch" href="${publicPath}${r}" />`).join('')
|
meta.resourceHints += clientManifest.async
|
||||||
|
.map(r => `<link rel="prefetch" href="${publicPath}${r}" />`)
|
||||||
|
.join('')
|
||||||
}
|
}
|
||||||
// Add them to HEAD
|
// Add them to HEAD
|
||||||
if (meta.resourceHints) {
|
if (meta.resourceHints) {
|
||||||
@ -75,7 +86,8 @@ module.exports = class MetaRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emulate getPreloadFiles from vue-server-renderer (works for JS chunks only)
|
// Emulate getPreloadFiles from vue-server-renderer (works for JS chunks only)
|
||||||
meta.getPreloadFiles = () => clientManifest.initial.map(r => ({
|
meta.getPreloadFiles = () =>
|
||||||
|
clientManifest.initial.map(r => ({
|
||||||
file: r,
|
file: r,
|
||||||
fileWithoutQuery: r,
|
fileWithoutQuery: r,
|
||||||
asType: 'script',
|
asType: 'script',
|
||||||
|
@ -6,7 +6,7 @@ module.exports = function errorMiddleware(err, req, res, next) {
|
|||||||
// ensure statusCode, message and name fields
|
// ensure statusCode, message and name fields
|
||||||
err.statusCode = err.statusCode || 500
|
err.statusCode = err.statusCode || 500
|
||||||
err.message = err.message || 'Nuxt Server Error'
|
err.message = err.message || 'Nuxt Server Error'
|
||||||
err.name = (!err.name || err.name === 'Error') ? 'NuxtServerError' : err.name
|
err.name = !err.name || err.name === 'Error' ? 'NuxtServerError' : err.name
|
||||||
|
|
||||||
// We hide actual errors from end users, so show them on server logs
|
// We hide actual errors from end users, so show them on server logs
|
||||||
if (err.statusCode !== 404) {
|
if (err.statusCode !== 404) {
|
||||||
@ -25,8 +25,11 @@ module.exports = function errorMiddleware(err, req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if request accepts JSON
|
// Check if request accepts JSON
|
||||||
const hasReqHeader = (header, includes) => req.headers[header] && req.headers[header].toLowerCase().includes(includes)
|
const hasReqHeader = (header, includes) =>
|
||||||
const isJson = hasReqHeader('accept', 'application/json') || hasReqHeader('user-agent', 'curl/')
|
req.headers[header] && req.headers[header].toLowerCase().includes(includes)
|
||||||
|
const isJson =
|
||||||
|
hasReqHeader('accept', 'application/json') ||
|
||||||
|
hasReqHeader('user-agent', 'curl/')
|
||||||
|
|
||||||
// Use basic errors when debug mode is disabled
|
// Use basic errors when debug mode is disabled
|
||||||
if (!this.options.debug) {
|
if (!this.options.debug) {
|
||||||
@ -46,17 +49,28 @@ module.exports = function errorMiddleware(err, req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show stack trace
|
// Show stack trace
|
||||||
const youch = new Youch(err, req, readSource.bind(this), this.options.router.base, true)
|
const youch = new Youch(
|
||||||
|
err,
|
||||||
|
req,
|
||||||
|
readSource.bind(this),
|
||||||
|
this.options.router.base,
|
||||||
|
true
|
||||||
|
)
|
||||||
if (isJson) {
|
if (isJson) {
|
||||||
youch.toJSON().then(json => { sendResponse(JSON.stringify(json, undefined, 2), 'text/json') })
|
youch.toJSON().then(json => {
|
||||||
|
sendResponse(JSON.stringify(json, undefined, 2), 'text/json')
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
youch.toHTML().then(html => { sendResponse(html) })
|
youch.toHTML().then(html => {
|
||||||
|
sendResponse(html)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function readSource(frame) {
|
async function readSource(frame) {
|
||||||
// Remove webpack:/// & query string from the end
|
// Remove webpack:/// & query string from the end
|
||||||
const sanitizeName = name => name ? name.replace('webpack:///', '').split('?')[0] : null
|
const sanitizeName = name =>
|
||||||
|
name ? name.replace('webpack:///', '').split('?')[0] : null
|
||||||
frame.fileName = sanitizeName(frame.fileName)
|
frame.fileName = sanitizeName(frame.fileName)
|
||||||
|
|
||||||
// Return if fileName is unknown
|
// Return if fileName is unknown
|
||||||
|
@ -11,7 +11,13 @@ module.exports = async function nuxtMiddleware(req, res, next) {
|
|||||||
try {
|
try {
|
||||||
const result = await this.renderRoute(req.url, context)
|
const result = await this.renderRoute(req.url, context)
|
||||||
await this.nuxt.callHook('render:route', req.url, result)
|
await this.nuxt.callHook('render:route', req.url, result)
|
||||||
const { html, cspScriptSrcHashes, error, redirected, getPreloadFiles } = result
|
const {
|
||||||
|
html,
|
||||||
|
cspScriptSrcHashes,
|
||||||
|
error,
|
||||||
|
redirected,
|
||||||
|
getPreloadFiles
|
||||||
|
} = result
|
||||||
|
|
||||||
if (redirected) {
|
if (redirected) {
|
||||||
return html
|
return html
|
||||||
@ -62,7 +68,10 @@ module.exports = async function nuxtMiddleware(req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.render.csp) {
|
if (this.options.render.csp) {
|
||||||
res.setHeader('Content-Security-Policy', `script-src 'self' ${(cspScriptSrcHashes || []).join(' ')}`)
|
res.setHeader(
|
||||||
|
'Content-Security-Policy',
|
||||||
|
`script-src 'self' ${(cspScriptSrcHashes || []).join(' ')}`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send response
|
// Send response
|
||||||
|
@ -94,14 +94,19 @@ module.exports = class Renderer {
|
|||||||
// Reload error template
|
// Reload error template
|
||||||
const errorTemplatePath = resolve(this.options.buildDir, 'views/error.html')
|
const errorTemplatePath = resolve(this.options.buildDir, 'views/error.html')
|
||||||
if (fs.existsSync(errorTemplatePath)) {
|
if (fs.existsSync(errorTemplatePath)) {
|
||||||
this.resources.errorTemplate = parseTemplate(fs.readFileSync(errorTemplatePath, 'utf8'))
|
this.resources.errorTemplate = parseTemplate(
|
||||||
|
fs.readFileSync(errorTemplatePath, 'utf8')
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load loading template
|
// Load loading template
|
||||||
const loadingHTMLPath = resolve(this.options.buildDir, 'loading.html')
|
const loadingHTMLPath = resolve(this.options.buildDir, 'loading.html')
|
||||||
if (fs.existsSync(loadingHTMLPath)) {
|
if (fs.existsSync(loadingHTMLPath)) {
|
||||||
this.resources.loadingHTML = fs.readFileSync(loadingHTMLPath, 'utf8')
|
this.resources.loadingHTML = fs.readFileSync(loadingHTMLPath, 'utf8')
|
||||||
this.resources.loadingHTML = this.resources.loadingHTML.replace(/[\r|\n]/g, '')
|
this.resources.loadingHTML = this.resources.loadingHTML.replace(
|
||||||
|
/[\r|\n]/g,
|
||||||
|
''
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
this.resources.loadingHTML = ''
|
this.resources.loadingHTML = ''
|
||||||
}
|
}
|
||||||
@ -157,11 +162,17 @@ module.exports = class Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create bundle renderer for SSR
|
// Create bundle renderer for SSR
|
||||||
this.bundleRenderer = createBundleRenderer(this.resources.serverBundle, Object.assign({
|
this.bundleRenderer = createBundleRenderer(
|
||||||
|
this.resources.serverBundle,
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
clientManifest: this.resources.clientManifest,
|
clientManifest: this.resources.clientManifest,
|
||||||
runInNewContext: false,
|
runInNewContext: false,
|
||||||
basedir: this.options.rootDir
|
basedir: this.options.rootDir
|
||||||
}, this.options.render.bundleRenderer))
|
},
|
||||||
|
this.options.render.bundleRenderer
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
useMiddleware(m) {
|
useMiddleware(m) {
|
||||||
@ -178,7 +189,10 @@ module.exports = class Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handler = m.handler || m
|
const handler = m.handler || m
|
||||||
const path = (((m.prefix !== false) ? this.options.router.base : '') + (typeof m.path === 'string' ? m.path : '')).replace(/\/\//g, '/')
|
const path = (
|
||||||
|
(m.prefix !== false ? this.options.router.base : '') +
|
||||||
|
(typeof m.path === 'string' ? m.path : '')
|
||||||
|
).replace(/\/\//g, '/')
|
||||||
|
|
||||||
// Inject $src and $m to final handler
|
// Inject $src and $m to final handler
|
||||||
if (src) handler.$src = src
|
if (src) handler.$src = src
|
||||||
@ -189,7 +203,9 @@ module.exports = class Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get publicPath() {
|
get publicPath() {
|
||||||
return isUrl(this.options.build.publicPath) ? Options.defaults.build.publicPath : this.options.build.publicPath
|
return isUrl(this.options.build.publicPath)
|
||||||
|
? Options.defaults.build.publicPath
|
||||||
|
: this.options.build.publicPath
|
||||||
}
|
}
|
||||||
|
|
||||||
async setupMiddleware() {
|
async setupMiddleware() {
|
||||||
@ -233,7 +249,12 @@ module.exports = class Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For serving static/ files to /
|
// For serving static/ files to /
|
||||||
this.useMiddleware(serveStatic(resolve(this.options.srcDir, 'static'), this.options.render.static))
|
this.useMiddleware(
|
||||||
|
serveStatic(
|
||||||
|
resolve(this.options.srcDir, 'static'),
|
||||||
|
this.options.render.static
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
// Serve .nuxt/dist/ files only for production
|
// Serve .nuxt/dist/ files only for production
|
||||||
// For dev they will be served with devMiddleware
|
// For dev they will be served with devMiddleware
|
||||||
@ -280,12 +301,26 @@ module.exports = class Renderer {
|
|||||||
const ENV = this.options.env
|
const ENV = this.options.env
|
||||||
|
|
||||||
if (this.noSSR || spa) {
|
if (this.noSSR || spa) {
|
||||||
const { HTML_ATTRS, BODY_ATTRS, HEAD, BODY_SCRIPTS, getPreloadFiles } = await this.metaRenderer.render(context)
|
const {
|
||||||
const APP = `<div id="__nuxt">${this.resources.loadingHTML}</div>` + BODY_SCRIPTS
|
HTML_ATTRS,
|
||||||
|
BODY_ATTRS,
|
||||||
|
HEAD,
|
||||||
|
BODY_SCRIPTS,
|
||||||
|
getPreloadFiles
|
||||||
|
} = await this.metaRenderer.render(context)
|
||||||
|
const APP =
|
||||||
|
`<div id="__nuxt">${this.resources.loadingHTML}</div>` + BODY_SCRIPTS
|
||||||
|
|
||||||
// Detect 404 errors
|
// Detect 404 errors
|
||||||
if (url.includes(this.options.build.publicPath) || url.includes('__webpack')) {
|
if (
|
||||||
const err = { statusCode: 404, message: this.options.messages.error_404, name: 'ResourceNotFound' }
|
url.includes(this.options.build.publicPath) ||
|
||||||
|
url.includes('__webpack')
|
||||||
|
) {
|
||||||
|
const err = {
|
||||||
|
statusCode: 404,
|
||||||
|
message: this.options.messages.error_404,
|
||||||
|
name: 'ResourceNotFound'
|
||||||
|
}
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +342,13 @@ module.exports = class Renderer {
|
|||||||
APP = '<div id="__nuxt"></div>'
|
APP = '<div id="__nuxt"></div>'
|
||||||
}
|
}
|
||||||
const m = context.meta.inject()
|
const m = context.meta.inject()
|
||||||
let HEAD = m.meta.text() + m.title.text() + m.link.text() + m.style.text() + m.script.text() + m.noscript.text()
|
let HEAD =
|
||||||
|
m.meta.text() +
|
||||||
|
m.title.text() +
|
||||||
|
m.link.text() +
|
||||||
|
m.style.text() +
|
||||||
|
m.script.text() +
|
||||||
|
m.noscript.text()
|
||||||
if (this.options._routerBaseSpecified) {
|
if (this.options._routerBaseSpecified) {
|
||||||
HEAD += `<base href="${this.options.router.base}">`
|
HEAD += `<base href="${this.options.router.base}">`
|
||||||
}
|
}
|
||||||
@ -316,12 +357,16 @@ module.exports = class Renderer {
|
|||||||
HEAD += context.renderResourceHints()
|
HEAD += context.renderResourceHints()
|
||||||
}
|
}
|
||||||
|
|
||||||
let serializedSession = `window.__NUXT__=${serialize(context.nuxt, { isJSON: true })};`
|
let serializedSession = `window.__NUXT__=${serialize(context.nuxt, {
|
||||||
|
isJSON: true
|
||||||
|
})};`
|
||||||
let cspScriptSrcHashes = []
|
let cspScriptSrcHashes = []
|
||||||
if (this.options.render.csp) {
|
if (this.options.render.csp) {
|
||||||
let hash = crypto.createHash(this.options.render.csp.hashAlgorithm)
|
let hash = crypto.createHash(this.options.render.csp.hashAlgorithm)
|
||||||
hash.update(serializedSession)
|
hash.update(serializedSession)
|
||||||
cspScriptSrcHashes.push(`'${this.options.render.csp.hashAlgorithm}-${hash.digest('base64')}'`)
|
cspScriptSrcHashes.push(
|
||||||
|
`'${this.options.render.csp.hashAlgorithm}-${hash.digest('base64')}'`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
APP += `<script type="text/javascript">${serializedSession}</script>`
|
APP += `<script type="text/javascript">${serializedSession}</script>`
|
||||||
@ -375,7 +420,9 @@ module.exports = class Renderer {
|
|||||||
url = url || 'http://localhost:3000'
|
url = url || 'http://localhost:3000'
|
||||||
const { window } = await jsdom.JSDOM.fromURL(url, options)
|
const { window } = await jsdom.JSDOM.fromURL(url, options)
|
||||||
// If Nuxt could not be loaded (error from the server-side)
|
// If Nuxt could not be loaded (error from the server-side)
|
||||||
const nuxtExists = window.document.body.innerHTML.includes(this.options.render.ssr ? 'window.__NUXT__' : '<div id="__nuxt">')
|
const nuxtExists = window.document.body.innerHTML.includes(
|
||||||
|
this.options.render.ssr ? 'window.__NUXT__' : '<div id="__nuxt">'
|
||||||
|
)
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
if (!nuxtExists) {
|
if (!nuxtExists) {
|
||||||
let error = new Error('Could not load the nuxt app')
|
let error = new Error('Could not load the nuxt app')
|
||||||
@ -383,7 +430,7 @@ module.exports = class Renderer {
|
|||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
// Used by nuxt.js to say when the components are loaded and the app ready
|
// Used by nuxt.js to say when the components are loaded and the app ready
|
||||||
await new Promise((resolve) => {
|
await new Promise(resolve => {
|
||||||
window._onNuxtLoaded = () => resolve(window)
|
window._onNuxtLoaded = () => resolve(window)
|
||||||
})
|
})
|
||||||
// Send back window object
|
// Send back window object
|
||||||
@ -391,9 +438,10 @@ module.exports = class Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseTemplate = templateStr => _.template(templateStr, {
|
const parseTemplate = templateStr =>
|
||||||
|
_.template(templateStr, {
|
||||||
interpolate: /{{([\s\S]+?)}}/g
|
interpolate: /{{([\s\S]+?)}}/g
|
||||||
})
|
})
|
||||||
|
|
||||||
const resourceMap = [
|
const resourceMap = [
|
||||||
{
|
{
|
||||||
@ -419,4 +467,7 @@ const resourceMap = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
// Protector utility against request to SSR bundle files
|
// Protector utility against request to SSR bundle files
|
||||||
const ssrResourceRegex = new RegExp(resourceMap.map(resource => resource.fileName).join('|'), 'i')
|
const ssrResourceRegex = new RegExp(
|
||||||
|
resourceMap.map(resource => resource.fileName).join('|'),
|
||||||
|
'i'
|
||||||
|
)
|
||||||
|
@ -20,7 +20,9 @@ const p = JSON.parse(originalPackage)
|
|||||||
p.name = 'nuxt-edge'
|
p.name = 'nuxt-edge'
|
||||||
|
|
||||||
// Get latest git commit id
|
// Get latest git commit id
|
||||||
const gitCommit = String(spawnSync('git', 'rev-parse --short HEAD'.split(' ')).stdout).trim()
|
const gitCommit = String(
|
||||||
|
spawnSync('git', 'rev-parse --short HEAD'.split(' ')).stdout
|
||||||
|
).trim()
|
||||||
|
|
||||||
// Version with latest git commit id
|
// Version with latest git commit id
|
||||||
// Using date.now() so latest push will be always choosen by npm/yarn
|
// Using date.now() so latest push will be always choosen by npm/yarn
|
||||||
@ -32,7 +34,9 @@ p.version = `${baseVersion}-${date}.${gitCommit}`
|
|||||||
writeFileSync(packagePath, JSON.stringify(p, null, 2) + '\r\n')
|
writeFileSync(packagePath, JSON.stringify(p, null, 2) + '\r\n')
|
||||||
|
|
||||||
// Parse git branch to decide npm tag
|
// Parse git branch to decide npm tag
|
||||||
let tag = String(spawnSync('git', 'rev-parse --abbrev-ref HEAD'.split(' ')).stdout).trim()
|
let tag = String(
|
||||||
|
spawnSync('git', 'rev-parse --abbrev-ref HEAD'.split(' ')).stdout
|
||||||
|
).trim()
|
||||||
|
|
||||||
// dev ~> latest
|
// dev ~> latest
|
||||||
if (tag === 'dev') {
|
if (tag === 'dev') {
|
||||||
@ -45,4 +49,6 @@ console.log(`publishing ${p.name}@${p.version} with tag ${tag}`)
|
|||||||
|
|
||||||
// Do publish
|
// Do publish
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(String(spawnSync('npm', `publish --tag ${tag}`.split(' ')).stdout).trim())
|
console.log(
|
||||||
|
String(spawnSync('npm', `publish --tag ${tag}`.split(' ')).stdout).trim()
|
||||||
|
)
|
||||||
|
@ -2,7 +2,13 @@
|
|||||||
|
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
|
|
||||||
const { readFileSync, readJSONSync, writeFileSync, copySync, removeSync } = require('fs-extra')
|
const {
|
||||||
|
readFileSync,
|
||||||
|
readJSONSync,
|
||||||
|
writeFileSync,
|
||||||
|
copySync,
|
||||||
|
removeSync
|
||||||
|
} = require('fs-extra')
|
||||||
const { resolve } = require('path')
|
const { resolve } = require('path')
|
||||||
|
|
||||||
// Dirs
|
// Dirs
|
||||||
@ -13,18 +19,11 @@ const startDir = resolve(rootDir, 'start')
|
|||||||
const packageJSON = readJSONSync(resolve(rootDir, 'package.json'))
|
const packageJSON = readJSONSync(resolve(rootDir, 'package.json'))
|
||||||
|
|
||||||
// Required and Excluded packages for start
|
// Required and Excluded packages for start
|
||||||
let requires = [
|
let requires = ['source-map-support', 'pretty-error', 'minimist']
|
||||||
'source-map-support',
|
|
||||||
'pretty-error',
|
|
||||||
'minimist'
|
|
||||||
]
|
|
||||||
|
|
||||||
const excludes = [
|
const excludes = ['path', 'fs', 'http', 'module'].concat(
|
||||||
'path',
|
Object.keys(packageJSON.devDependencies)
|
||||||
'fs',
|
)
|
||||||
'http',
|
|
||||||
'module'
|
|
||||||
].concat(Object.keys(packageJSON.devDependencies))
|
|
||||||
|
|
||||||
// Parse dist/core.js for all external dependencies
|
// Parse dist/core.js for all external dependencies
|
||||||
const requireRegex = /require\('([-@/\w]+)'\)/g
|
const requireRegex = /require\('([-@/\w]+)'\)/g
|
||||||
@ -66,13 +65,13 @@ packageJSON.bin = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update package.json
|
// Update package.json
|
||||||
writeFileSync(resolve(startDir, 'package.json'), JSON.stringify(packageJSON, null, 2))
|
writeFileSync(
|
||||||
|
resolve(startDir, 'package.json'),
|
||||||
|
JSON.stringify(packageJSON, null, 2)
|
||||||
|
)
|
||||||
|
|
||||||
// Copy required files
|
// Copy required files
|
||||||
const excludeFiles = [
|
const excludeFiles = ['README.md', '.gitignore']
|
||||||
'README.md',
|
|
||||||
'.gitignore'
|
|
||||||
]
|
|
||||||
packageJSON.files.forEach(file => {
|
packageJSON.files.forEach(file => {
|
||||||
if (excludeFiles.indexOf(file) !== -1) {
|
if (excludeFiles.indexOf(file) !== -1) {
|
||||||
return
|
return
|
||||||
@ -99,11 +98,20 @@ extraFiles.forEach(file => {
|
|||||||
|
|
||||||
// Patch index.js
|
// Patch index.js
|
||||||
const startIndexjs = resolve(startDir, 'index.js')
|
const startIndexjs = resolve(startDir, 'index.js')
|
||||||
writeFileSync(startIndexjs, String(readFileSync(startIndexjs)).replace('./dist/nuxt', './dist/core'))
|
writeFileSync(
|
||||||
|
startIndexjs,
|
||||||
|
String(readFileSync(startIndexjs)).replace('./dist/nuxt', './dist/core')
|
||||||
|
)
|
||||||
|
|
||||||
// Patch bin/nuxt-start
|
// Patch bin/nuxt-start
|
||||||
const binStart = resolve(startDir, 'bin/nuxt-start')
|
const binStart = resolve(startDir, 'bin/nuxt-start')
|
||||||
writeFileSync(binStart, String(readFileSync(binStart)).replace(/nuxt start/g, 'nuxt-start'))
|
writeFileSync(
|
||||||
|
binStart,
|
||||||
|
String(readFileSync(binStart)).replace(/nuxt start/g, 'nuxt-start')
|
||||||
|
)
|
||||||
|
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(`Generated ${packageJSON.name}@${packageJSON.version} in ${Date.now() - now}ms`)
|
console.log(
|
||||||
|
`Generated ${packageJSON.name}@${packageJSON.version} in ${Date.now() -
|
||||||
|
now}ms`
|
||||||
|
)
|
||||||
|
@ -5,7 +5,7 @@ import * as browser from './helpers/browser'
|
|||||||
import { interceptLog } from './helpers/console'
|
import { interceptLog } from './helpers/console'
|
||||||
|
|
||||||
const port = 4003
|
const port = 4003
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
|
|
||||||
let nuxt = null
|
let nuxt = null
|
||||||
let page = null
|
let page = null
|
||||||
@ -63,7 +63,10 @@ test.serial('/css', async t => {
|
|||||||
await page.nuxt.navigate('/css')
|
await page.nuxt.navigate('/css')
|
||||||
|
|
||||||
t.is(await page.$text('.red'), 'This is red')
|
t.is(await page.$text('.red'), 'This is red')
|
||||||
t.is(await page.$eval('.red', (red) => window.getComputedStyle(red).color), 'rgb(255, 0, 0)')
|
t.is(
|
||||||
|
await page.$eval('.red', red => window.getComputedStyle(red).color),
|
||||||
|
'rgb(255, 0, 0)'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test.serial('/stateful', async t => {
|
test.serial('/stateful', async t => {
|
||||||
@ -80,7 +83,9 @@ test.serial('/store', async t => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test.serial('/head', async t => {
|
test.serial('/head', async t => {
|
||||||
const msg = new Promise((resolve) => page.on('console', (msg) => resolve(msg.text)))
|
const msg = new Promise(resolve =>
|
||||||
|
page.on('console', msg => resolve(msg.text))
|
||||||
|
)
|
||||||
await page.nuxt.navigate('/head')
|
await page.nuxt.navigate('/head')
|
||||||
const metas = await page.$$attr('meta', 'content')
|
const metas = await page.$$attr('meta', 'content')
|
||||||
|
|
||||||
@ -158,7 +163,9 @@ test.serial('/redirect-external', async t => {
|
|||||||
// New page for redirecting to external link.
|
// New page for redirecting to external link.
|
||||||
const page = await browser.page(url('/'))
|
const page = await browser.page(url('/'))
|
||||||
await page.nuxt.navigate('/redirect-external', false)
|
await page.nuxt.navigate('/redirect-external', false)
|
||||||
await page.waitForFunction(() => window.location.href === 'https://nuxtjs.org/')
|
await page.waitForFunction(
|
||||||
|
() => window.location.href === 'https://nuxtjs.org/'
|
||||||
|
)
|
||||||
page.close()
|
page.close()
|
||||||
t.pass()
|
t.pass()
|
||||||
})
|
})
|
||||||
@ -186,7 +193,10 @@ test.serial('/fn-midd', async t => {
|
|||||||
await page.nuxt.navigate('/fn-midd')
|
await page.nuxt.navigate('/fn-midd')
|
||||||
|
|
||||||
t.is(await page.$text('.title'), 'You need to ask the permission')
|
t.is(await page.$text('.title'), 'You need to ask the permission')
|
||||||
t.deepEqual(await page.nuxt.errorData(), { message: 'You need to ask the permission', statusCode: 403 })
|
t.deepEqual(await page.nuxt.errorData(), {
|
||||||
|
message: 'You need to ask the permission',
|
||||||
|
statusCode: 403
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test.serial('/fn-midd?please=true', async t => {
|
test.serial('/fn-midd?please=true', async t => {
|
||||||
|
@ -4,7 +4,7 @@ import { intercept, release } from './helpers/console'
|
|||||||
import { Nuxt, Builder } from '..'
|
import { Nuxt, Builder } from '..'
|
||||||
|
|
||||||
const port = 4001
|
const port = 4001
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
const rootDir = resolve(__dirname, 'fixtures/basic')
|
const rootDir = resolve(__dirname, 'fixtures/basic')
|
||||||
|
|
||||||
let nuxt = null
|
let nuxt = null
|
||||||
|
@ -22,8 +22,7 @@ test('Fail with routes() which throw an error', async t => {
|
|||||||
const builder = new Builder(nuxt)
|
const builder = new Builder(nuxt)
|
||||||
const generator = new Generator(nuxt, builder)
|
const generator = new Generator(nuxt, builder)
|
||||||
|
|
||||||
return generator.generate()
|
return generator.generate().catch(e => {
|
||||||
.catch((e) => {
|
|
||||||
t.true(e.message === 'Not today!')
|
t.true(e.message === 'Not today!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -10,7 +10,7 @@ import { interceptLog, release } from './helpers/console'
|
|||||||
import { Nuxt, Builder, Generator } from '..'
|
import { Nuxt, Builder, Generator } from '..'
|
||||||
|
|
||||||
const port = 4002
|
const port = 4002
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
const rootDir = resolve(__dirname, 'fixtures/basic')
|
const rootDir = resolve(__dirname, 'fixtures/basic')
|
||||||
|
|
||||||
let nuxt = null
|
let nuxt = null
|
||||||
@ -91,7 +91,9 @@ test.serial('/async-data', async t => {
|
|||||||
test.serial('/users/1/index.html', async t => {
|
test.serial('/users/1/index.html', async t => {
|
||||||
const html = await rp(url('/users/1/index.html'))
|
const html = await rp(url('/users/1/index.html'))
|
||||||
t.true(html.includes('<h1>User: 1</h1>'))
|
t.true(html.includes('<h1>User: 1</h1>'))
|
||||||
t.true(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1/index.html')))
|
t.true(
|
||||||
|
existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1/index.html'))
|
||||||
|
)
|
||||||
t.false(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1.html')))
|
t.false(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1.html')))
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -160,7 +162,9 @@ test.serial('/users/1.html', async t => {
|
|||||||
const html = await rp(url('/users/1.html'))
|
const html = await rp(url('/users/1.html'))
|
||||||
t.true(html.includes('<h1>User: 1</h1>'))
|
t.true(html.includes('<h1>User: 1</h1>'))
|
||||||
t.true(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1.html')))
|
t.true(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1.html')))
|
||||||
t.false(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1/index.html')))
|
t.false(
|
||||||
|
existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1/index.html'))
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test.serial('/-ignored', async t => {
|
test.serial('/-ignored', async t => {
|
||||||
|
@ -5,7 +5,7 @@ import { Nuxt, Builder } from '..'
|
|||||||
import { interceptLog, interceptError, release } from './helpers/console'
|
import { interceptLog, interceptError, release } from './helpers/console'
|
||||||
|
|
||||||
const port = 4004
|
const port = 4004
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
|
|
||||||
let nuxt = null
|
let nuxt = null
|
||||||
|
|
||||||
@ -83,12 +83,16 @@ test('/store', async t => {
|
|||||||
|
|
||||||
test.serial('/head', async t => {
|
test.serial('/head', async t => {
|
||||||
const logSpy = await interceptLog()
|
const logSpy = await interceptLog()
|
||||||
const window = await nuxt.renderAndGetWindow(url('/head'), { virtualConsole: false })
|
const window = await nuxt.renderAndGetWindow(url('/head'), {
|
||||||
|
virtualConsole: false
|
||||||
|
})
|
||||||
t.is(window.document.title, 'My title - Nuxt.js')
|
t.is(window.document.title, 'My title - Nuxt.js')
|
||||||
|
|
||||||
const html = window.document.body.innerHTML
|
const html = window.document.body.innerHTML
|
||||||
t.true(html.includes('<div><h1>I can haz meta tags</h1></div>'))
|
t.true(html.includes('<div><h1>I can haz meta tags</h1></div>'))
|
||||||
t.true(html.includes('<script data-n-head="true" src="/body.js" data-body="true">'))
|
t.true(
|
||||||
|
html.includes('<script data-n-head="true" src="/body.js" data-body="true">')
|
||||||
|
)
|
||||||
|
|
||||||
const metas = window.document.getElementsByTagName('meta')
|
const metas = window.document.getElementsByTagName('meta')
|
||||||
t.is(metas[0].getAttribute('content'), 'my meta')
|
t.is(metas[0].getAttribute('content'), 'my meta')
|
||||||
@ -169,7 +173,11 @@ test.serial('/error status code', async t => {
|
|||||||
const errorSpy = await interceptError()
|
const errorSpy = await interceptError()
|
||||||
const err = await t.throws(rp(url('/error')))
|
const err = await t.throws(rp(url('/error')))
|
||||||
t.true(err.statusCode === 500)
|
t.true(err.statusCode === 500)
|
||||||
t.true(err.response.body.includes('An error occurred in the application and your page could not be served'))
|
t.true(
|
||||||
|
err.response.body.includes(
|
||||||
|
'An error occurred in the application and your page could not be served'
|
||||||
|
)
|
||||||
|
)
|
||||||
release()
|
release()
|
||||||
t.true(errorSpy.calledOnce)
|
t.true(errorSpy.calledOnce)
|
||||||
t.true(errorSpy.args[0][0].message.includes('Error mouahahah'))
|
t.true(errorSpy.args[0][0].message.includes('Error mouahahah'))
|
||||||
@ -215,7 +223,11 @@ test('/redirect-name', async t => {
|
|||||||
|
|
||||||
test('/no-ssr', async t => {
|
test('/no-ssr', async t => {
|
||||||
const { html } = await nuxt.renderRoute('/no-ssr')
|
const { html } = await nuxt.renderRoute('/no-ssr')
|
||||||
t.true(html.includes('<div class="no-ssr-placeholder"><p>Loading...</p></div>'))
|
t.true(
|
||||||
|
html.includes(
|
||||||
|
'<div class="no-ssr-placeholder"><p>Loading...</p></div>'
|
||||||
|
)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('/no-ssr (client-side)', async t => {
|
test('/no-ssr (client-side)', async t => {
|
||||||
@ -225,25 +237,38 @@ test('/no-ssr (client-side)', async t => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('ETag Header', async t => {
|
test('ETag Header', async t => {
|
||||||
const { headers: { etag } } = await rp(url('/stateless'), { resolveWithFullResponse: true })
|
const { headers: { etag } } = await rp(url('/stateless'), {
|
||||||
|
resolveWithFullResponse: true
|
||||||
|
})
|
||||||
// Verify functionality
|
// Verify functionality
|
||||||
const error = await t.throws(rp(url('/stateless'), { headers: { 'If-None-Match': etag } }))
|
const error = await t.throws(
|
||||||
|
rp(url('/stateless'), { headers: { 'If-None-Match': etag } })
|
||||||
|
)
|
||||||
t.is(error.statusCode, 304)
|
t.is(error.statusCode, 304)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Content-Security-Policy Header', async t => {
|
test('Content-Security-Policy Header', async t => {
|
||||||
const { headers } = await rp(url('/stateless'), { resolveWithFullResponse: true })
|
const { headers } = await rp(url('/stateless'), {
|
||||||
|
resolveWithFullResponse: true
|
||||||
|
})
|
||||||
// Verify functionality
|
// Verify functionality
|
||||||
t.is(headers['content-security-policy'], "script-src 'self' 'sha256-BBvfKxDOoRM/gnFwke9u60HBZX3HUss/0lSI1sBRvOU='")
|
t.is(
|
||||||
|
headers['content-security-policy'],
|
||||||
|
"script-src 'self' 'sha256-BBvfKxDOoRM/gnFwke9u60HBZX3HUss/0lSI1sBRvOU='"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('/_nuxt/server-bundle.json should return 404', async t => {
|
test('/_nuxt/server-bundle.json should return 404', async t => {
|
||||||
const err = await t.throws(rp(url('/_nuxt/server-bundle.json'), { resolveWithFullResponse: true }))
|
const err = await t.throws(
|
||||||
|
rp(url('/_nuxt/server-bundle.json'), { resolveWithFullResponse: true })
|
||||||
|
)
|
||||||
t.is(err.statusCode, 404)
|
t.is(err.statusCode, 404)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('/_nuxt/ should return 404', async t => {
|
test('/_nuxt/ should return 404', async t => {
|
||||||
const err = await t.throws(rp(url('/_nuxt/'), { resolveWithFullResponse: true }))
|
const err = await t.throws(
|
||||||
|
rp(url('/_nuxt/'), { resolveWithFullResponse: true })
|
||||||
|
)
|
||||||
t.is(err.statusCode, 404)
|
t.is(err.statusCode, 404)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -253,7 +278,9 @@ test('/meta', async t => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('/fn-midd', async t => {
|
test('/fn-midd', async t => {
|
||||||
const err = await t.throws(rp(url('/fn-midd'), { resolveWithFullResponse: true }))
|
const err = await t.throws(
|
||||||
|
rp(url('/fn-midd'), { resolveWithFullResponse: true })
|
||||||
|
)
|
||||||
t.is(err.statusCode, 403)
|
t.is(err.statusCode, 403)
|
||||||
t.true(err.response.body.includes('You need to ask the permission'))
|
t.true(err.response.body.includes('You need to ask the permission'))
|
||||||
})
|
})
|
||||||
|
@ -5,7 +5,7 @@ import * as browser from './helpers/browser'
|
|||||||
import { interceptLog } from './helpers/console'
|
import { interceptLog } from './helpers/console'
|
||||||
|
|
||||||
const port = 4014
|
const port = 4014
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
|
|
||||||
let nuxt = null
|
let nuxt = null
|
||||||
let page
|
let page
|
||||||
|
@ -5,7 +5,7 @@ import { Nuxt, Builder } from '..'
|
|||||||
import { interceptLog, interceptError, release } from './helpers/console'
|
import { interceptLog, interceptError, release } from './helpers/console'
|
||||||
|
|
||||||
const port = 4009
|
const port = 4009
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
|
|
||||||
let nuxt = null
|
let nuxt = null
|
||||||
|
|
||||||
@ -26,19 +26,32 @@ test.serial('Init Nuxt.js', async t => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test.serial('/test/__open-in-editor (open-in-editor)', async t => {
|
test.serial('/test/__open-in-editor (open-in-editor)', async t => {
|
||||||
const { body } = await rp(url('/test/__open-in-editor?file=pages/index.vue'), { resolveWithFullResponse: true })
|
const { body } = await rp(
|
||||||
|
url('/test/__open-in-editor?file=pages/index.vue'),
|
||||||
|
{ resolveWithFullResponse: true }
|
||||||
|
)
|
||||||
t.is(body, '')
|
t.is(body, '')
|
||||||
})
|
})
|
||||||
|
|
||||||
test.serial('/test/__open-in-editor should return error (open-in-editor)', async t => {
|
test.serial(
|
||||||
const { error, statusCode } = await t.throws(rp(url('/test/__open-in-editor?file='), { resolveWithFullResponse: true }))
|
'/test/__open-in-editor should return error (open-in-editor)',
|
||||||
|
async t => {
|
||||||
|
const { error, statusCode } = await t.throws(
|
||||||
|
rp(url('/test/__open-in-editor?file='), { resolveWithFullResponse: true })
|
||||||
|
)
|
||||||
t.is(statusCode, 500)
|
t.is(statusCode, 500)
|
||||||
t.is(error, 'launch-editor-middleware: required query param "file" is missing.')
|
t.is(
|
||||||
})
|
error,
|
||||||
|
'launch-editor-middleware: required query param "file" is missing.'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
test.serial('/test/error should return error stack trace (Youch)', async t => {
|
test.serial('/test/error should return error stack trace (Youch)', async t => {
|
||||||
const errorSpy = await interceptError()
|
const errorSpy = await interceptError()
|
||||||
const { response, error } = await t.throws(nuxt.renderAndGetWindow(url('/test/error')))
|
const { response, error } = await t.throws(
|
||||||
|
nuxt.renderAndGetWindow(url('/test/error'))
|
||||||
|
)
|
||||||
t.is(response.statusCode, 500)
|
t.is(response.statusCode, 500)
|
||||||
t.is(response.statusMessage, 'NuxtServerError')
|
t.is(response.statusMessage, 'NuxtServerError')
|
||||||
t.true(error.includes('test youch !'))
|
t.true(error.includes('test youch !'))
|
||||||
@ -54,7 +67,9 @@ test.serial('/test/error no source-map (Youch)', async t => {
|
|||||||
nuxt.renderer.resources.serverBundle.maps = {}
|
nuxt.renderer.resources.serverBundle.maps = {}
|
||||||
|
|
||||||
const errorSpy = await interceptError()
|
const errorSpy = await interceptError()
|
||||||
const { response, error } = await t.throws(nuxt.renderAndGetWindow(url('/test/error')))
|
const { response, error } = await t.throws(
|
||||||
|
nuxt.renderAndGetWindow(url('/test/error'))
|
||||||
|
)
|
||||||
t.is(response.statusCode, 500)
|
t.is(response.statusCode, 500)
|
||||||
t.is(response.statusMessage, 'NuxtServerError')
|
t.is(response.statusMessage, 'NuxtServerError')
|
||||||
t.true(error.includes('test youch !'))
|
t.true(error.includes('test youch !'))
|
||||||
@ -70,7 +85,7 @@ test.serial('/test/error no source-map (Youch)', async t => {
|
|||||||
test.serial('/test/error should return json format error (Youch)', async t => {
|
test.serial('/test/error should return json format error (Youch)', async t => {
|
||||||
const opts = {
|
const opts = {
|
||||||
headers: {
|
headers: {
|
||||||
'accept': 'application/json'
|
accept: 'application/json'
|
||||||
},
|
},
|
||||||
resolveWithFullResponse: true
|
resolveWithFullResponse: true
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import { Nuxt, Builder } from '..'
|
|||||||
import { intercept, interceptWarn, release } from './helpers/console'
|
import { intercept, interceptWarn, release } from './helpers/console'
|
||||||
|
|
||||||
const port = 4010
|
const port = 4010
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
|
|
||||||
let nuxt = null
|
let nuxt = null
|
||||||
let builder = null
|
let builder = null
|
||||||
@ -32,14 +32,26 @@ test.serial('Init Nuxt.js', async t => {
|
|||||||
test.serial('Deprecated: context.isServer and context.isClient', async t => {
|
test.serial('Deprecated: context.isServer and context.isClient', async t => {
|
||||||
const warnSpy = await interceptWarn()
|
const warnSpy = await interceptWarn()
|
||||||
await rp(url('/'))
|
await rp(url('/'))
|
||||||
t.true(warnSpy.calledWith('context.isServer has been deprecated, please use process.server instead.'))
|
t.true(
|
||||||
t.true(warnSpy.calledWith('context.isClient has been deprecated, please use process.client instead.'))
|
warnSpy.calledWith(
|
||||||
|
'context.isServer has been deprecated, please use process.server instead.'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
t.true(
|
||||||
|
warnSpy.calledWith(
|
||||||
|
'context.isClient has been deprecated, please use process.client instead.'
|
||||||
|
)
|
||||||
|
)
|
||||||
t.true(warnSpy.calledTwice)
|
t.true(warnSpy.calledTwice)
|
||||||
release()
|
release()
|
||||||
})
|
})
|
||||||
|
|
||||||
test.serial('Deprecated: dev in build.extend()', async t => {
|
test.serial('Deprecated: dev in build.extend()', async t => {
|
||||||
t.true(buildSpies.warn.withArgs('dev has been deprecated in build.extend(), please use isDev').calledTwice)
|
t.true(
|
||||||
|
buildSpies.warn.withArgs(
|
||||||
|
'dev has been deprecated in build.extend(), please use isDev'
|
||||||
|
).calledTwice
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test.serial('Deprecated: nuxt.plugin()', async t => {
|
test.serial('Deprecated: nuxt.plugin()', async t => {
|
||||||
|
@ -9,9 +9,12 @@ const readFile = promisify(fs.readFile)
|
|||||||
const rootDir = resolve(__dirname, 'fixtures/dll')
|
const rootDir = resolve(__dirname, 'fixtures/dll')
|
||||||
const dllDir = resolve(rootDir, '.cache/client-dll')
|
const dllDir = resolve(rootDir, '.cache/client-dll')
|
||||||
|
|
||||||
const checkCache = (lib) => {
|
const checkCache = lib => {
|
||||||
return async (t) => {
|
return async t => {
|
||||||
const manifest = await readFile(resolve(dllDir, `./${lib}-manifest.json`), 'utf-8')
|
const manifest = await readFile(
|
||||||
|
resolve(dllDir, `./${lib}-manifest.json`),
|
||||||
|
'utf-8'
|
||||||
|
)
|
||||||
t.truthy(JSON.parse(manifest).name)
|
t.truthy(JSON.parse(manifest).name)
|
||||||
t.true(fs.existsSync(resolve(dllDir, `./${JSON.parse(manifest).name}.js`)))
|
t.true(fs.existsSync(resolve(dllDir, `./${JSON.parse(manifest).name}.js`)))
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,18 @@ test.serial('Init Nuxt.js', async t => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('Check .nuxt/router.js', t => {
|
test('Check .nuxt/router.js', t => {
|
||||||
return readFile(resolve(__dirname, './fixtures/dynamic-routes/.nuxt/router.js'), 'utf-8')
|
return readFile(
|
||||||
.then((routerFile) => {
|
resolve(__dirname, './fixtures/dynamic-routes/.nuxt/router.js'),
|
||||||
|
'utf-8'
|
||||||
|
).then(routerFile => {
|
||||||
routerFile = routerFile
|
routerFile = routerFile
|
||||||
.slice(routerFile.indexOf('routes: ['))
|
.slice(routerFile.indexOf('routes: ['))
|
||||||
.replace('routes: [', '[')
|
.replace('routes: [', '[')
|
||||||
.replace(/ _[0-9A-z]+,/g, ' "",')
|
.replace(/ _[0-9A-z]+,/g, ' "",')
|
||||||
routerFile = routerFile.substr(routerFile.indexOf('['), routerFile.lastIndexOf(']') + 1)
|
routerFile = routerFile.substr(
|
||||||
|
routerFile.indexOf('['),
|
||||||
|
routerFile.lastIndexOf(']') + 1
|
||||||
|
)
|
||||||
let routes = eval('( ' + routerFile + ')') // eslint-disable-line no-eval
|
let routes = eval('( ' + routerFile + ')') // eslint-disable-line no-eval
|
||||||
// pages/index.vue
|
// pages/index.vue
|
||||||
t.is(routes[0].path, '/')
|
t.is(routes[0].path, '/')
|
||||||
@ -50,8 +55,12 @@ test('Check .nuxt/router.js', t => {
|
|||||||
t.falsy(routes[3].name) // parent route has no name
|
t.falsy(routes[3].name) // parent route has no name
|
||||||
// pages/parent/*.vue
|
// pages/parent/*.vue
|
||||||
t.is(routes[3].children.length, 3) // parent has 3 children
|
t.is(routes[3].children.length, 3) // parent has 3 children
|
||||||
t.deepEqual(routes[3].children.map((r) => r.path), ['', 'teub', 'child'])
|
t.deepEqual(routes[3].children.map(r => r.path), ['', 'teub', 'child'])
|
||||||
t.deepEqual(routes[3].children.map((r) => r.name), ['parent', 'parent-teub', 'parent-child'])
|
t.deepEqual(routes[3].children.map(r => r.name), [
|
||||||
|
'parent',
|
||||||
|
'parent-teub',
|
||||||
|
'parent-child'
|
||||||
|
])
|
||||||
// pages/test/projects/index.vue
|
// pages/test/projects/index.vue
|
||||||
t.is(routes[4].path, '/test/projects')
|
t.is(routes[4].path, '/test/projects')
|
||||||
t.is(routes[4].name, 'test-projects')
|
t.is(routes[4].name, 'test-projects')
|
||||||
@ -60,8 +69,20 @@ test('Check .nuxt/router.js', t => {
|
|||||||
t.falsy(routes[5].name) // parent route has no name
|
t.falsy(routes[5].name) // parent route has no name
|
||||||
// pages/test/users/*.vue
|
// pages/test/users/*.vue
|
||||||
t.is(routes[5].children.length, 5) // parent has 5 children
|
t.is(routes[5].children.length, 5) // parent has 5 children
|
||||||
t.deepEqual(routes[5].children.map((r) => r.path), ['', 'projects', 'projects/:category', ':id', ':index/teub'])
|
t.deepEqual(routes[5].children.map(r => r.path), [
|
||||||
t.deepEqual(routes[5].children.map((r) => r.name), ['test-users', 'test-users-projects', 'test-users-projects-category', 'test-users-id', 'test-users-index-teub'])
|
'',
|
||||||
|
'projects',
|
||||||
|
'projects/:category',
|
||||||
|
':id',
|
||||||
|
':index/teub'
|
||||||
|
])
|
||||||
|
t.deepEqual(routes[5].children.map(r => r.name), [
|
||||||
|
'test-users',
|
||||||
|
'test-users-projects',
|
||||||
|
'test-users-projects-category',
|
||||||
|
'test-users-id',
|
||||||
|
'test-users-index-teub'
|
||||||
|
])
|
||||||
// pages/test/songs/toto.vue
|
// pages/test/songs/toto.vue
|
||||||
t.is(routes[6].path, '/test/songs/toto')
|
t.is(routes[6].path, '/test/songs/toto')
|
||||||
t.is(routes[6].name, 'test-songs-toto')
|
t.is(routes[6].name, 'test-songs-toto')
|
||||||
|
@ -5,7 +5,7 @@ import { Nuxt, Builder } from '..'
|
|||||||
import { interceptLog, interceptError, release } from './helpers/console'
|
import { interceptLog, interceptError, release } from './helpers/console'
|
||||||
|
|
||||||
const port = 4005
|
const port = 4005
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
|
|
||||||
let nuxt = null
|
let nuxt = null
|
||||||
|
|
||||||
@ -46,13 +46,19 @@ test.serial('/ with renderAndGetWindow()', async t => {
|
|||||||
t.is(err.response.statusMessage, 'NuxtServerError')
|
t.is(err.response.statusMessage, 'NuxtServerError')
|
||||||
release()
|
release()
|
||||||
t.true(errorSpy.calledOnce)
|
t.true(errorSpy.calledOnce)
|
||||||
t.true(errorSpy.getCall(0).args[0].message.includes('render function or template not defined in component: anonymous'))
|
t.true(
|
||||||
|
errorSpy
|
||||||
|
.getCall(0)
|
||||||
|
.args[0].message.includes(
|
||||||
|
'render function or template not defined in component: anonymous'
|
||||||
|
)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test.serial('/ with text/json content', async t => {
|
test.serial('/ with text/json content', async t => {
|
||||||
const opts = {
|
const opts = {
|
||||||
headers: {
|
headers: {
|
||||||
'accept': 'application/json'
|
accept: 'application/json'
|
||||||
},
|
},
|
||||||
resolveWithFullResponse: true
|
resolveWithFullResponse: true
|
||||||
}
|
}
|
||||||
@ -61,7 +67,13 @@ test.serial('/ with text/json content', async t => {
|
|||||||
t.is(headers['content-type'], 'text/json; charset=utf-8')
|
t.is(headers['content-type'], 'text/json; charset=utf-8')
|
||||||
release()
|
release()
|
||||||
t.true(errorSpy.calledOnce)
|
t.true(errorSpy.calledOnce)
|
||||||
t.true(errorSpy.getCall(0).args[0].message.includes('render function or template not defined in component: anonymous'))
|
t.true(
|
||||||
|
errorSpy
|
||||||
|
.getCall(0)
|
||||||
|
.args[0].message.includes(
|
||||||
|
'render function or template not defined in component: anonymous'
|
||||||
|
)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Close server and ask nuxt to stop listening to file changes
|
// Close server and ask nuxt to stop listening to file changes
|
||||||
|
@ -6,7 +6,7 @@ import rp from 'request-promise-native'
|
|||||||
import { interceptLog } from './helpers/console'
|
import { interceptLog } from './helpers/console'
|
||||||
|
|
||||||
const port = 4000
|
const port = 4000
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
|
|
||||||
let nuxt
|
let nuxt
|
||||||
let app
|
let app
|
||||||
|
4
test/fixtures/basic/nuxt.config.js
vendored
4
test/fixtures/basic/nuxt.config.js
vendored
@ -21,8 +21,6 @@ module.exports = {
|
|||||||
transition: false,
|
transition: false,
|
||||||
build: {
|
build: {
|
||||||
scopeHoisting: true,
|
scopeHoisting: true,
|
||||||
postcss: [
|
postcss: [require('postcss-cssnext')()]
|
||||||
require('postcss-cssnext')()
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
test/fixtures/deprecate/nuxt.config.js
vendored
4
test/fixtures/deprecate/nuxt.config.js
vendored
@ -1,7 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
modules: [
|
modules: ['~/modules/hooks'],
|
||||||
'~/modules/hooks'
|
|
||||||
],
|
|
||||||
build: {
|
build: {
|
||||||
stats: false,
|
stats: false,
|
||||||
extend(config, options) {
|
extend(config, options) {
|
||||||
|
4
test/fixtures/dll/nuxt.config.js
vendored
4
test/fixtures/dll/nuxt.config.js
vendored
@ -4,7 +4,9 @@ module.exports = {
|
|||||||
dll: true,
|
dll: true,
|
||||||
extend(config, options) {
|
extend(config, options) {
|
||||||
if (options.isClient) {
|
if (options.isClient) {
|
||||||
const dlls = config.plugins.filter(plugin => plugin.constructor.name === 'DllReferencePlugin')
|
const dlls = config.plugins.filter(
|
||||||
|
plugin => plugin.constructor.name === 'DllReferencePlugin'
|
||||||
|
)
|
||||||
console.log('Using dll for ' + dlls.length + ' libs') // eslint-disable-line no-console
|
console.log('Using dll for ' + dlls.length + ' libs') // eslint-disable-line no-console
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
|
8
test/fixtures/module/nuxt.config.js
vendored
8
test/fixtures/module/nuxt.config.js
vendored
@ -9,11 +9,9 @@ module.exports = {
|
|||||||
foo: 'bar'
|
foo: 'bar'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
['./modules/template', {baz: 'ping'}]
|
['./modules/template', { baz: 'ping' }]
|
||||||
],
|
|
||||||
serverMiddleware: [
|
|
||||||
'./modules/middleware/midd2'
|
|
||||||
],
|
],
|
||||||
|
serverMiddleware: ['./modules/middleware/midd2'],
|
||||||
hooks(hook) {
|
hooks(hook) {
|
||||||
hook('ready', nuxt => {
|
hook('ready', nuxt => {
|
||||||
nuxt.__ready_called__ = true
|
nuxt.__ready_called__ = true
|
||||||
@ -22,7 +20,7 @@ module.exports = {
|
|||||||
builder.__build_done__ = true
|
builder.__build_done__ = true
|
||||||
})
|
})
|
||||||
// Add hook for renderer
|
// Add hook for renderer
|
||||||
hook('render:before', (renderer) => {
|
hook('render:before', renderer => {
|
||||||
renderer.useMiddleware({
|
renderer.useMiddleware({
|
||||||
path: '/use-middleware',
|
path: '/use-middleware',
|
||||||
handler: '~/modules/middleware/use-middleware'
|
handler: '~/modules/middleware/use-middleware'
|
||||||
|
8
test/fixtures/with-config/nuxt.config.js
vendored
8
test/fixtures/with-config/nuxt.config.js
vendored
@ -16,9 +16,7 @@ module.exports = {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modulesDir: [
|
modulesDir: [path.join(__dirname, '..', '..', '..', 'node_modules')],
|
||||||
path.join(__dirname, '..', '..', '..', 'node_modules')
|
|
||||||
],
|
|
||||||
transition: 'test',
|
transition: 'test',
|
||||||
layoutTransition: 'test',
|
layoutTransition: 'test',
|
||||||
loadingIndicator: 'circle',
|
loadingIndicator: 'circle',
|
||||||
@ -63,9 +61,7 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
css: [
|
css: [{ src: '~/assets/app.css' }],
|
||||||
{ src: '~/assets/app.css' }
|
|
||||||
],
|
|
||||||
render: {
|
render: {
|
||||||
http2: {
|
http2: {
|
||||||
push: true,
|
push: true,
|
||||||
|
5
test/fixtures/with-config/postcss.config.js
vendored
5
test/fixtures/with-config/postcss.config.js
vendored
@ -6,10 +6,7 @@ module.exports = {
|
|||||||
plugins: {
|
plugins: {
|
||||||
'postcss-import': {
|
'postcss-import': {
|
||||||
root: rootDir,
|
root: rootDir,
|
||||||
path: [
|
path: [rootDir, modulesDir]
|
||||||
rootDir,
|
|
||||||
modulesDir
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
'postcss-url': {},
|
'postcss-url': {},
|
||||||
'postcss-cssnext': {}
|
'postcss-cssnext': {}
|
||||||
|
@ -60,7 +60,7 @@ test('initRoutes with routes (fn(cb, args))', async t => {
|
|||||||
const config = {
|
const config = {
|
||||||
generate: {
|
generate: {
|
||||||
routes(cb, arg1, arg2, arg3, arg4) {
|
routes(cb, arg1, arg2, arg3, arg4) {
|
||||||
cb(null, [ arg1, arg2, arg3, arg4 ])
|
cb(null, [arg1, arg2, arg3, arg4])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,14 @@ let browser = null
|
|||||||
|
|
||||||
export async function start(options = {}) {
|
export async function start(options = {}) {
|
||||||
// https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions
|
// https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions
|
||||||
browser = await puppeteer.launch(Object.assign({
|
browser = await puppeteer.launch(
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
||||||
}, options))
|
},
|
||||||
|
options
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function stop() {
|
export async function stop() {
|
||||||
@ -19,25 +24,38 @@ export async function page(url) {
|
|||||||
const page = await browser.newPage()
|
const page = await browser.newPage()
|
||||||
await page.goto(url)
|
await page.goto(url)
|
||||||
await page.waitForFunction('!!window.$nuxt')
|
await page.waitForFunction('!!window.$nuxt')
|
||||||
page.html = () => page.evaluate(() => window.document.documentElement.outerHTML)
|
page.html = () =>
|
||||||
page.$text = (selector) => page.$eval(selector, (el) => el.textContent)
|
page.evaluate(() => window.document.documentElement.outerHTML)
|
||||||
page.$$text = (selector) => page.$$eval(selector, (els) => els.map((el) => el.textContent))
|
page.$text = selector => page.$eval(selector, el => el.textContent)
|
||||||
page.$attr = (selector, attr) => page.$eval(selector, (el, attr) => el.getAttribute(attr), attr)
|
page.$$text = selector =>
|
||||||
page.$$attr = (selector, attr) => page.$$eval(selector, (els, attr) => els.map((el) => el.getAttribute(attr)), attr)
|
page.$$eval(selector, els => els.map(el => el.textContent))
|
||||||
|
page.$attr = (selector, attr) =>
|
||||||
|
page.$eval(selector, (el, attr) => el.getAttribute(attr), attr)
|
||||||
|
page.$$attr = (selector, attr) =>
|
||||||
|
page.$$eval(
|
||||||
|
selector,
|
||||||
|
(els, attr) => els.map(el => el.getAttribute(attr)),
|
||||||
|
attr
|
||||||
|
)
|
||||||
page.$nuxt = await page.evaluateHandle('window.$nuxt')
|
page.$nuxt = await page.evaluateHandle('window.$nuxt')
|
||||||
|
|
||||||
page.nuxt = {
|
page.nuxt = {
|
||||||
async navigate(path, waitEnd = true) {
|
async navigate(path, waitEnd = true) {
|
||||||
const hook = page.evaluate(() => {
|
const hook = page.evaluate(() => {
|
||||||
return new Promise((resolve) => window.$nuxt.$once('routeChanged', resolve))
|
return new Promise(resolve =>
|
||||||
.then(() => new Promise((resolve) => setTimeout(resolve, 50)))
|
window.$nuxt.$once('routeChanged', resolve)
|
||||||
|
).then(() => new Promise(resolve => setTimeout(resolve, 50)))
|
||||||
})
|
})
|
||||||
await page.evaluate(($nuxt, path) => $nuxt.$router.push(path), page.$nuxt, path)
|
await page.evaluate(
|
||||||
|
($nuxt, path) => $nuxt.$router.push(path),
|
||||||
|
page.$nuxt,
|
||||||
|
path
|
||||||
|
)
|
||||||
if (waitEnd) await hook
|
if (waitEnd) await hook
|
||||||
return { hook }
|
return { hook }
|
||||||
},
|
},
|
||||||
routeData() {
|
routeData() {
|
||||||
return page.evaluate(($nuxt) => {
|
return page.evaluate($nuxt => {
|
||||||
return {
|
return {
|
||||||
path: $nuxt.$route.path,
|
path: $nuxt.$route.path,
|
||||||
query: $nuxt.$route.query
|
query: $nuxt.$route.query
|
||||||
@ -45,13 +63,13 @@ export async function page(url) {
|
|||||||
}, page.$nuxt)
|
}, page.$nuxt)
|
||||||
},
|
},
|
||||||
loadingData() {
|
loadingData() {
|
||||||
return page.evaluate(($nuxt) => $nuxt.$loading.$data, page.$nuxt)
|
return page.evaluate($nuxt => $nuxt.$loading.$data, page.$nuxt)
|
||||||
},
|
},
|
||||||
errorData() {
|
errorData() {
|
||||||
return page.evaluate(($nuxt) => $nuxt.nuxt.err, page.$nuxt)
|
return page.evaluate($nuxt => $nuxt.nuxt.err, page.$nuxt)
|
||||||
},
|
},
|
||||||
storeState() {
|
storeState() {
|
||||||
return page.evaluate(($nuxt) => $nuxt.$store.state, page.$nuxt)
|
return page.evaluate($nuxt => $nuxt.$store.state, page.$nuxt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return page
|
return page
|
||||||
|
@ -4,7 +4,9 @@ let context = null
|
|||||||
|
|
||||||
export function release() {
|
export function release() {
|
||||||
if (context === null) {
|
if (context === null) {
|
||||||
process.stderr.write('Console spy context was empty, did a previous test already release it?\n')
|
process.stderr.write(
|
||||||
|
'Console spy context was empty, did a previous test already release it?\n'
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +34,9 @@ export function release() {
|
|||||||
|
|
||||||
export async function intercept(levels, msg, cb) {
|
export async function intercept(levels, msg, cb) {
|
||||||
if (context !== null) {
|
if (context !== null) {
|
||||||
process.stderr.write('Console spy context was not empty, did a previous test not release it?\n')
|
process.stderr.write(
|
||||||
|
'Console spy context was not empty, did a previous test not release it?\n'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
context = {}
|
context = {}
|
||||||
|
|
||||||
|
@ -25,7 +25,9 @@ test('Fail to build when no pages/ directory but is in the parent', t => {
|
|||||||
return new Builder(nuxt).build().catch(err => {
|
return new Builder(nuxt).build().catch(err => {
|
||||||
let s = String(err)
|
let s = String(err)
|
||||||
t.true(s.includes('No `pages` directory found'))
|
t.true(s.includes('No `pages` directory found'))
|
||||||
t.true(s.includes('Did you mean to run `nuxt` in the parent (`../`) directory?'))
|
t.true(
|
||||||
|
s.includes('Did you mean to run `nuxt` in the parent (`../`) directory?')
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -36,7 +38,7 @@ test('Fail to build when no pages/ directory', t => {
|
|||||||
})
|
})
|
||||||
return new Builder(nuxt).build().catch(err => {
|
return new Builder(nuxt).build().catch(err => {
|
||||||
let s = String(err)
|
let s = String(err)
|
||||||
t.true(s.includes('Couldn\'t find a `pages` directory'))
|
t.true(s.includes("Couldn't find a `pages` directory"))
|
||||||
t.true(s.includes('Please create one under the project root'))
|
t.true(s.includes('Please create one under the project root'))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -5,7 +5,7 @@ import { Nuxt, Builder } from '..'
|
|||||||
import { intercept } from './helpers/console'
|
import { intercept } from './helpers/console'
|
||||||
|
|
||||||
const port = 4006
|
const port = 4006
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
|
|
||||||
let nuxt = null
|
let nuxt = null
|
||||||
let builder = null
|
let builder = null
|
||||||
@ -30,12 +30,19 @@ test.serial('Init Nuxt.js', async t => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test.serial('Vendor', async t => {
|
test.serial('Vendor', async t => {
|
||||||
t.true(nuxt.options.build.vendor.indexOf('lodash') !== -1, 'lodash added to config')
|
t.true(
|
||||||
|
nuxt.options.build.vendor.indexOf('lodash') !== -1,
|
||||||
|
'lodash added to config'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test.serial('Plugin', async t => {
|
test.serial('Plugin', async t => {
|
||||||
t.true(normalize(nuxt.options.plugins[0].src)
|
t.true(
|
||||||
.includes(normalize('fixtures/module/.nuxt/basic.reverse.')), 'plugin added to config')
|
normalize(nuxt.options.plugins[0].src).includes(
|
||||||
|
normalize('fixtures/module/.nuxt/basic.reverse.')
|
||||||
|
),
|
||||||
|
'plugin added to config'
|
||||||
|
)
|
||||||
const { html } = await nuxt.renderRoute('/')
|
const { html } = await nuxt.renderRoute('/')
|
||||||
t.true(html.includes('<h1>TXUN</h1>'), 'plugin works')
|
t.true(html.includes('<h1>TXUN</h1>'), 'plugin works')
|
||||||
})
|
})
|
||||||
|
@ -6,7 +6,7 @@ import { interceptLog, release } from './helpers/console'
|
|||||||
let nuxt = null
|
let nuxt = null
|
||||||
|
|
||||||
const port = 4012
|
const port = 4012
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
|
|
||||||
const renderRoute = async _url => {
|
const renderRoute = async _url => {
|
||||||
const window = await nuxt.renderAndGetWindow(url(_url))
|
const window = await nuxt.renderAndGetWindow(url(_url))
|
||||||
@ -73,7 +73,9 @@ test.serial('/mounted', async t => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('/_nuxt/ (access publicPath in spa mode)', async t => {
|
test('/_nuxt/ (access publicPath in spa mode)', async t => {
|
||||||
const { response: { statusCode, statusMessage } } = await t.throws(renderRoute('/_nuxt/'))
|
const { response: { statusCode, statusMessage } } = await t.throws(
|
||||||
|
renderRoute('/_nuxt/')
|
||||||
|
)
|
||||||
t.is(statusCode, 404)
|
t.is(statusCode, 404)
|
||||||
t.is(statusMessage, 'ResourceNotFound')
|
t.is(statusMessage, 'ResourceNotFound')
|
||||||
})
|
})
|
||||||
|
@ -13,7 +13,7 @@ const range = n => [...Array(n).keys()]
|
|||||||
const FOOBAR_REGEX = /<foobar>([\s\S]*)<\/foobar>/
|
const FOOBAR_REGEX = /<foobar>([\s\S]*)<\/foobar>/
|
||||||
const match = (regex, text) => (regex.exec(text) || [])[1]
|
const match = (regex, text) => (regex.exec(text) || [])[1]
|
||||||
|
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
|
|
||||||
const isWindows = /^win/.test(process.platform)
|
const isWindows = /^win/.test(process.platform)
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ test('unique responses with fetch', async t => {
|
|||||||
// Making 16K requests by default
|
// Making 16K requests by default
|
||||||
// Related issue: https://github.com/nuxt/nuxt.js/issues/1354
|
// Related issue: https://github.com/nuxt/nuxt.js/issues/1354
|
||||||
const stressTest = async (t, _url, concurrency = 64, steps = 256) => {
|
const stressTest = async (t, _url, concurrency = 64, steps = 256) => {
|
||||||
let statusCodes = { }
|
let statusCodes = {}
|
||||||
|
|
||||||
// appveyor memory limit!
|
// appveyor memory limit!
|
||||||
if (isWindows) {
|
if (isWindows) {
|
||||||
|
@ -21,7 +21,7 @@ test('setAnsiColors', t => {
|
|||||||
t.pass()
|
t.pass()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('waitFor', async (t) => {
|
test('waitFor', async t => {
|
||||||
let s = Date.now()
|
let s = Date.now()
|
||||||
await Utils.waitFor(100)
|
await Utils.waitFor(100)
|
||||||
t.true(Date.now() - s >= 100)
|
t.true(Date.now() - s >= 100)
|
||||||
@ -36,8 +36,7 @@ test('promisifyRoute (array)', t => {
|
|||||||
const array = [1]
|
const array = [1]
|
||||||
const promise = Utils.promisifyRoute(array)
|
const promise = Utils.promisifyRoute(array)
|
||||||
t.is(typeof promise, 'object')
|
t.is(typeof promise, 'object')
|
||||||
return promise
|
return promise.then(res => {
|
||||||
.then((res) => {
|
|
||||||
t.is(res, array)
|
t.is(res, array)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -49,8 +48,7 @@ test('promisifyRoute (fn => array)', t => {
|
|||||||
}
|
}
|
||||||
const promise = Utils.promisifyRoute(fn)
|
const promise = Utils.promisifyRoute(fn)
|
||||||
t.is(typeof promise, 'object')
|
t.is(typeof promise, 'object')
|
||||||
return promise
|
return promise.then(res => {
|
||||||
.then((res) => {
|
|
||||||
t.is(res, array)
|
t.is(res, array)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -58,29 +56,27 @@ test('promisifyRoute (fn => array)', t => {
|
|||||||
test('promisifyRoute (fn => promise)', t => {
|
test('promisifyRoute (fn => promise)', t => {
|
||||||
const array = [1, 2, 3]
|
const array = [1, 2, 3]
|
||||||
const fn = function () {
|
const fn = function () {
|
||||||
return new Promise((resolve) => {
|
return new Promise(resolve => {
|
||||||
resolve(array)
|
resolve(array)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const promise = Utils.promisifyRoute(fn)
|
const promise = Utils.promisifyRoute(fn)
|
||||||
t.is(typeof promise, 'object')
|
t.is(typeof promise, 'object')
|
||||||
return promise
|
return promise.then(res => {
|
||||||
.then((res) => {
|
|
||||||
t.is(res, array)
|
t.is(res, array)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('promisifyRoute ((fn(args) => promise))', t => {
|
test('promisifyRoute ((fn(args) => promise))', t => {
|
||||||
const fn = function (array) {
|
const fn = function (array) {
|
||||||
return new Promise((resolve) => {
|
return new Promise(resolve => {
|
||||||
resolve(array)
|
resolve(array)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const array = [1, 2, 3]
|
const array = [1, 2, 3]
|
||||||
const promise = Utils.promisifyRoute(fn, array)
|
const promise = Utils.promisifyRoute(fn, array)
|
||||||
t.is(typeof promise, 'object')
|
t.is(typeof promise, 'object')
|
||||||
return promise
|
return promise.then(res => {
|
||||||
.then((res) => {
|
|
||||||
t.is(res, array)
|
t.is(res, array)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -91,8 +87,7 @@ test('promisifyRoute (fn(cb) with error)', t => {
|
|||||||
}
|
}
|
||||||
const promise = Utils.promisifyRoute(fn)
|
const promise = Utils.promisifyRoute(fn)
|
||||||
t.is(typeof promise, 'object')
|
t.is(typeof promise, 'object')
|
||||||
return promise
|
return promise.catch(e => {
|
||||||
.catch((e) => {
|
|
||||||
t.is(e.message, 'Error here')
|
t.is(e.message, 'Error here')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -104,8 +99,7 @@ test('promisifyRoute (fn(cb, args) with error)', t => {
|
|||||||
const array = [1, 2, 3, 4]
|
const array = [1, 2, 3, 4]
|
||||||
const promise = Utils.promisifyRoute(fn, array)
|
const promise = Utils.promisifyRoute(fn, array)
|
||||||
t.is(typeof promise, 'object')
|
t.is(typeof promise, 'object')
|
||||||
return promise
|
return promise.catch(e => {
|
||||||
.catch((e) => {
|
|
||||||
t.is(e.message, 'Error here: ' + array.join())
|
t.is(e.message, 'Error here: ' + array.join())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -117,8 +111,7 @@ test('promisifyRoute (fn(cb) with result)', t => {
|
|||||||
}
|
}
|
||||||
const promise = Utils.promisifyRoute(fn)
|
const promise = Utils.promisifyRoute(fn)
|
||||||
t.is(typeof promise, 'object')
|
t.is(typeof promise, 'object')
|
||||||
return promise
|
return promise.then(res => {
|
||||||
.then((res) => {
|
|
||||||
t.is(res, array)
|
t.is(res, array)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -131,8 +124,7 @@ test('promisifyRoute (fn(cb, args) with result)', t => {
|
|||||||
const object = { a: 1 }
|
const object = { a: 1 }
|
||||||
const promise = Utils.promisifyRoute(fn, array, object)
|
const promise = Utils.promisifyRoute(fn, array, object)
|
||||||
t.is(typeof promise, 'object')
|
t.is(typeof promise, 'object')
|
||||||
return promise
|
return promise.then(res => {
|
||||||
.then((res) => {
|
|
||||||
t.is(res.array, array)
|
t.is(res.array, array)
|
||||||
t.is(res.object, object)
|
t.is(res.object, object)
|
||||||
})
|
})
|
||||||
|
@ -6,7 +6,7 @@ import styleLoader from '../lib/builder/webpack/style-loader'
|
|||||||
import { interceptLog, release } from './helpers/console'
|
import { interceptLog, release } from './helpers/console'
|
||||||
|
|
||||||
const port = 4007
|
const port = 4007
|
||||||
const url = (route) => 'http://localhost:' + port + route
|
const url = route => 'http://localhost:' + port + route
|
||||||
|
|
||||||
let nuxt = null
|
let nuxt = null
|
||||||
let builder = null
|
let builder = null
|
||||||
@ -45,7 +45,11 @@ test('/ (global styles inlined)', async t => {
|
|||||||
|
|
||||||
test('/ (preload fonts)', async t => {
|
test('/ (preload fonts)', async t => {
|
||||||
const { html } = await nuxt.renderRoute('/')
|
const { html } = await nuxt.renderRoute('/')
|
||||||
t.true(html.includes('<link rel="preload" href="/test/orion/fonts/roboto.7cf5d7c.woff2" as="font" type="font/woff2" crossorigin'))
|
t.true(
|
||||||
|
html.includes(
|
||||||
|
'<link rel="preload" href="/test/orion/fonts/roboto.7cf5d7c.woff2" as="font" type="font/woff2" crossorigin'
|
||||||
|
)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('/ (custom app.html)', async t => {
|
test('/ (custom app.html)', async t => {
|
||||||
@ -168,12 +172,17 @@ test.serial('/test/about-bis (added with extendRoutes)', async t => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('Check stats.json generated by build.analyze', t => {
|
test('Check stats.json generated by build.analyze', t => {
|
||||||
const stats = require(resolve(__dirname, 'fixtures/with-config/.nuxt/dist/stats.json'))
|
const stats = require(resolve(
|
||||||
|
__dirname,
|
||||||
|
'fixtures/with-config/.nuxt/dist/stats.json'
|
||||||
|
))
|
||||||
t.is(stats.assets.length, 35)
|
t.is(stats.assets.length, 35)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Check /test/test.txt with custom serve-static options', async t => {
|
test('Check /test/test.txt with custom serve-static options', async t => {
|
||||||
const { headers } = await rp(url('/test/test.txt'), { resolveWithFullResponse: true })
|
const { headers } = await rp(url('/test/test.txt'), {
|
||||||
|
resolveWithFullResponse: true
|
||||||
|
})
|
||||||
t.is(headers['cache-control'], 'public, max-age=31536000')
|
t.is(headers['cache-control'], 'public, max-age=31536000')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user