mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-27 08:02:01 +00:00
commit
3b7f23afb6
3
bin/nuxt
3
bin/nuxt
@ -1,8 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Show logs
|
||||
process.env.DEBUG = process.env.DEBUG || 'nuxt:*'
|
||||
|
||||
const { join } = require('path')
|
||||
const semver = require('semver')
|
||||
|
||||
|
@ -69,7 +69,6 @@ if (options.mode !== 'spa') {
|
||||
// -- Build for SSR app --
|
||||
builder
|
||||
.build()
|
||||
.then(() => debug('Building done'))
|
||||
.then(() => close())
|
||||
.catch(Utils.fatalError)
|
||||
} else {
|
||||
|
@ -1,7 +1,4 @@
|
||||
module.exports = {
|
||||
build: {
|
||||
vendor: ['axios'] // Add axios in the vendor.bundle.js
|
||||
},
|
||||
loading: {
|
||||
color: '#4FC08D',
|
||||
failedColor: '#bf5050',
|
||||
|
@ -10,9 +10,6 @@ module.exports = {
|
||||
{ hid: 'description', content: 'Auth Routes example' }
|
||||
]
|
||||
},
|
||||
build: {
|
||||
vendor: ['axios']
|
||||
},
|
||||
/*
|
||||
** Add server middleware
|
||||
** Nuxt.js uses `connect` module as server
|
||||
|
@ -3,10 +3,8 @@ module.exports = {
|
||||
filenames: {
|
||||
css: 'styles.[chunkhash].css', // default: common.[chunkhash].css
|
||||
manifest: 'manifest.[hash].js', // default: manifest.[hash].js
|
||||
vendor: 'vendor.[hash].js', // default: vendor.bundle.[hash].js
|
||||
app: 'app.[chunkhash].js' // default: nuxt.bundle.[chunkhash].js
|
||||
},
|
||||
vendor: ['lodash'],
|
||||
extend(config, { isDev }) {
|
||||
if (isDev) {
|
||||
config.devtool = 'eval-source-map'
|
||||
|
@ -3,7 +3,6 @@
|
||||
<p><img src="~/assets/nuxt.png" /></p>
|
||||
<p>This image is included as data:image/png;base64...</p>
|
||||
<p>In the source code, the files generated are based on the build.filenames data.</p>
|
||||
<p>If you look at the <a href="/_nuxt/vendor.js">vendor.js</a>, lodash has been included (cmd/ctrl + F "lodash").</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -1,5 +1,2 @@
|
||||
module.exports = {
|
||||
build: {
|
||||
vendor: ['axios']
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,5 @@
|
||||
module.exports = {
|
||||
loading: { color: 'cyan' },
|
||||
build: {
|
||||
vendor: ['vue-i18n']
|
||||
},
|
||||
router: {
|
||||
middleware: 'i18n'
|
||||
},
|
||||
|
@ -1,7 +1,4 @@
|
||||
module.exports = {
|
||||
build: {
|
||||
vendor: ['axios']
|
||||
},
|
||||
css: ['~/assets/main.css'],
|
||||
layoutTransition: {
|
||||
name: 'layout',
|
||||
|
@ -1,7 +1,4 @@
|
||||
module.exports = {
|
||||
build: {
|
||||
vendor: ['axios', 'mini-toastr', 'vue-notifications']
|
||||
},
|
||||
plugins: [
|
||||
// ssr: false to only include it on client-side
|
||||
{ src: '~/plugins/vue-notifications.js', ssr: false }
|
||||
|
@ -1,6 +1,3 @@
|
||||
module.exports = {
|
||||
build: {
|
||||
vendor: ['axios']
|
||||
},
|
||||
css: ['~/assets/main.css']
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
module.exports = {
|
||||
build: {
|
||||
vendor: ['axios']
|
||||
},
|
||||
css: ['~/assets/main.css']
|
||||
}
|
||||
|
@ -19,8 +19,5 @@ module.exports = {
|
||||
** Build configuration
|
||||
*/
|
||||
css: ['tachyons/css/tachyons.min.css', '~/assets/css/main.css'],
|
||||
build: {
|
||||
vendor: ['axios', 'vuex-class', 'nuxt-class-component']
|
||||
},
|
||||
modules: ['~/modules/typescript']
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ module.exports = {
|
||||
]
|
||||
},
|
||||
build: {
|
||||
vendor: ['axios', 'moment', 'chart.js', 'vue-chartjs'],
|
||||
maxChunkSize: 300000
|
||||
},
|
||||
env: {
|
||||
|
@ -7,8 +7,5 @@ module.exports = {
|
||||
link: [
|
||||
{ rel: 'stylesheet', href: 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css' }
|
||||
]
|
||||
},
|
||||
build: {
|
||||
vendor: ['axios']
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,6 @@ module.exports = function () {
|
||||
// close this server on 'close' event
|
||||
this.nuxt.plugin('close', () => new Promise((resolve) => server.close(resolve)))
|
||||
|
||||
// Add `socket.io-client` in vendor
|
||||
this.addVendor('socket.io-client')
|
||||
|
||||
// Add socket.io events
|
||||
let messages = []
|
||||
io.on('connection', (socket) => {
|
||||
|
@ -10,11 +10,8 @@ module.exports = {
|
||||
{ rel: 'stylesheet', type: 'text/css', href: 'https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' }
|
||||
]
|
||||
},
|
||||
/*
|
||||
** Add Vuetify into vendor.bundle.js
|
||||
*/
|
||||
|
||||
build: {
|
||||
vendor: ['vuetify'],
|
||||
extractCSS: true,
|
||||
extend(config, ctx) {
|
||||
if (ctx.isServer) {
|
||||
|
@ -4,15 +4,17 @@ import Vue from 'vue'
|
||||
import '<%= relativeToBuild(resolvePath(c.src || c)) %>'
|
||||
<% }) %>
|
||||
|
||||
let layouts = {
|
||||
<%
|
||||
var layoutsKeys = Object.keys(layouts);
|
||||
layoutsKeys.forEach(function (key, i) { %>
|
||||
"_<%= key %>": () => import('<%= layouts[key] %>' /* webpackChunkName: "<%= wChunk('layouts/'+key) %>" */).then(m => m.default || m)<%= (i + 1) < layoutsKeys.length ? ',' : '' %>
|
||||
<% }) %>
|
||||
}
|
||||
<%= Object.keys(layouts).map(key => {
|
||||
if (splitPages) {
|
||||
return `const _${hash(key)} = () => import('${layouts[key]}' /* webpackChunkName: "${wChunk('layouts/' + key)}" */).then(m => m.default || m)`
|
||||
} else {
|
||||
return `import _${hash(key)} from '${layouts[key]}'`
|
||||
}
|
||||
}).join('\n') %>
|
||||
|
||||
let resolvedLayouts = {}
|
||||
const layouts = { <%= Object.keys(layouts).map(key => `"_${key}": _${hash(key)}`).join(',') %> }
|
||||
|
||||
<% if (splitPages) { %>let resolvedLayouts = {}<% } %>
|
||||
|
||||
export default {
|
||||
head: <%= serialize(head).replace('head(', 'function(').replace('titleTemplate(', 'function(') %>,
|
||||
@ -76,6 +78,7 @@ export default {
|
||||
}
|
||||
},
|
||||
<% } %>
|
||||
<% if (splitPages) { %>
|
||||
setLayout (layout) {
|
||||
if (!layout || !resolvedLayouts['_' + layout]) layout = 'default'
|
||||
this.layoutName = layout
|
||||
@ -101,6 +104,17 @@ export default {
|
||||
}
|
||||
})
|
||||
}
|
||||
<% } else { %>
|
||||
setLayout(layout) {
|
||||
if (!layout || !layouts['_' + layout]) layout = 'default'
|
||||
this.layoutName = layout
|
||||
this.layout = layouts['_' + layout]
|
||||
return this.layout
|
||||
},
|
||||
loadLayout(layout) {
|
||||
return Promise.resolve(layouts['_' + layout])
|
||||
}
|
||||
<% } %>
|
||||
},
|
||||
components: {
|
||||
<%= (loading ? 'NuxtLoading' : '') %>
|
||||
|
@ -1,17 +1,14 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
<%
|
||||
function recursiveRoutes(routes, tab, components) {
|
||||
<% function recursiveRoutes(routes, tab, components) {
|
||||
let res = ''
|
||||
routes.forEach((route, i) => {
|
||||
route._name = '_' + hash(route.component)
|
||||
components.push({ _name: route._name, component: route.component, name: route.name, chunkName: route.chunkName })
|
||||
res += tab + '{\n'
|
||||
res += tab + '\tpath: ' + JSON.stringify(route.path) + ',\n'
|
||||
res += tab + '\tcomponent: ' + route._name
|
||||
res += tab + '\tcomponent: ' + (splitPages ? route._name : `() => ${route._name}.default || ${route._name}`)
|
||||
res += (route.name) ? ',\n\t' + tab + 'name: ' + JSON.stringify(route.name) : ''
|
||||
res += (route.children) ? ',\n\t' + tab + 'children: [\n' + recursiveRoutes(routes[i].children, tab + '\t\t', components) + '\n\t' + tab + ']' : ''
|
||||
res += '\n' + tab + '}' + (i + 1 === routes.length ? '' : ',\n')
|
||||
@ -20,8 +17,19 @@ function recursiveRoutes(routes, tab, components) {
|
||||
}
|
||||
const _components = []
|
||||
const _routes = recursiveRoutes(router.routes, '\t\t', _components)
|
||||
uniqBy(_components, '_name').forEach((route) => { %>const <%= route._name %> = () => import('<%= relativeToBuild(route.component) %>' /* webpackChunkName: "<%= wChunk(route.chunkName) %>" */).then(m => m.default || m)
|
||||
<% }) %>
|
||||
%><%= uniqBy(_components, '_name').map((route) => {
|
||||
const path = relativeToBuild(route.component)
|
||||
const chunkName = wChunk(route.chunkName)
|
||||
const name = route._name
|
||||
|
||||
if (splitPages) {
|
||||
return `const ${name} = () => import('${path}' /* webpackChunkName: "${chunkName}" */).then(m => m.default || m)`
|
||||
} else {
|
||||
return `import ${name} from '${path}'`
|
||||
}
|
||||
}).join('\n')%>
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
<% if (router.scrollBehavior) { %>
|
||||
const scrollBehavior = <%= serialize(router.scrollBehavior).replace('scrollBehavior(', 'function(').replace('function function', 'function') %>
|
||||
|
@ -1,5 +1,4 @@
|
||||
import Vue from 'vue'
|
||||
import clone from 'clone'
|
||||
import { stringify } from 'querystring'
|
||||
import { omit } from 'lodash'
|
||||
import middleware from './middleware'
|
||||
|
@ -2,6 +2,7 @@ const { promisify } = require('util')
|
||||
const _ = require('lodash')
|
||||
const chokidar = require('chokidar')
|
||||
const { remove, readFile, writeFile, mkdirp, existsSync } = require('fs-extra')
|
||||
const fs = require('fs')
|
||||
const hash = require('hash-sum')
|
||||
const webpack = require('webpack')
|
||||
const serialize = require('serialize-javascript')
|
||||
@ -11,20 +12,12 @@ const webpackDevMiddleware = require('webpack-dev-middleware')
|
||||
const webpackHotMiddleware = require('webpack-hot-middleware')
|
||||
const Debug = require('debug')
|
||||
const Glob = require('glob')
|
||||
const {
|
||||
r,
|
||||
wp,
|
||||
wChunk,
|
||||
createRoutes,
|
||||
sequence,
|
||||
relativeTo,
|
||||
waitFor
|
||||
} = require('../common/utils')
|
||||
const { r, wp, wChunk, createRoutes, parallel, relativeTo, waitFor } = require('../common/utils')
|
||||
const { Options } = require('../common')
|
||||
const clientWebpackConfig = require('./webpack/client.config.js')
|
||||
const serverWebpackConfig = require('./webpack/server.config.js')
|
||||
const dllWebpackConfig = require('./webpack/dll.config.js')
|
||||
const upath = require('upath')
|
||||
const ORA = require('ora')
|
||||
|
||||
const debug = Debug('nuxt:build')
|
||||
debug.color = 2 // Force green color
|
||||
@ -44,6 +37,8 @@ module.exports = class Builder {
|
||||
this.webpackHotMiddleware = null
|
||||
this.filesWatcher = null
|
||||
this.customFilesWatcher = null
|
||||
this.spinner = new ORA()
|
||||
this.spinner.color = 'green'
|
||||
|
||||
// Mute stats on dev
|
||||
this.webpackStats = this.options.dev ? false : this.options.build.stats
|
||||
@ -82,34 +77,6 @@ module.exports = class Builder {
|
||||
)
|
||||
}
|
||||
|
||||
vendor() {
|
||||
return ['vue', 'vue-router', 'vue-meta', this.options.store && 'vuex']
|
||||
.concat(
|
||||
this.options.build.extractCSS && [
|
||||
// https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/456
|
||||
'vue-style-loader/lib/addStylesClient',
|
||||
'css-loader/lib/css-base'
|
||||
]
|
||||
)
|
||||
.concat(this.options.build.vendor)
|
||||
.filter(v => v)
|
||||
}
|
||||
|
||||
vendorEntries() {
|
||||
// Used for dll
|
||||
const vendor = this.vendor()
|
||||
const vendorEntries = {}
|
||||
vendor.forEach(v => {
|
||||
try {
|
||||
require.resolve(v)
|
||||
vendorEntries[v] = [v]
|
||||
} catch (e) {
|
||||
// Ignore
|
||||
}
|
||||
})
|
||||
return vendorEntries
|
||||
}
|
||||
|
||||
forGenerate() {
|
||||
this.isStatic = true
|
||||
}
|
||||
@ -128,6 +95,8 @@ module.exports = class Builder {
|
||||
}
|
||||
this._buildStatus = STATUS.BUILDING
|
||||
|
||||
this.spinner.start('Initializing builder')
|
||||
|
||||
// Wait for nuxt ready
|
||||
await this.nuxt.ready()
|
||||
|
||||
@ -151,8 +120,9 @@ module.exports = class Builder {
|
||||
}
|
||||
}
|
||||
|
||||
this.spinner.start(`Generating nuxt files...`)
|
||||
|
||||
debug(`App root: ${this.options.srcDir}`)
|
||||
debug(`Generating ${this.options.buildDir} files...`)
|
||||
|
||||
// Create .nuxt/, .nuxt/components and .nuxt/dist folders
|
||||
await remove(r(this.options.buildDir))
|
||||
@ -164,6 +134,8 @@ module.exports = class Builder {
|
||||
// Generate routes and interpret the template files
|
||||
await this.generateRoutesAndFiles()
|
||||
|
||||
this.spinner.start('Compiling...')
|
||||
|
||||
// Start webpack build
|
||||
await this.webpackBuild()
|
||||
|
||||
@ -236,6 +208,7 @@ module.exports = class Builder {
|
||||
.map(ext => ext.replace(/^\./, ''))
|
||||
.join('|'),
|
||||
messages: this.options.messages,
|
||||
splitPages: this.options.build.splitPages,
|
||||
uniqBy: _.uniqBy,
|
||||
isDev: this.options.dev,
|
||||
debug: this.options.debug,
|
||||
@ -503,28 +476,22 @@ module.exports = class Builder {
|
||||
}
|
||||
})
|
||||
|
||||
// Make a dll plugin after compile to make nuxt dev builds faster
|
||||
if (this.options.build.dll && this.options.dev) {
|
||||
compilersOptions.push(dllWebpackConfig.call(this, clientConfig))
|
||||
}
|
||||
|
||||
// Initialize shared FS and Cache
|
||||
const sharedFS = this.options.dev && new MFS()
|
||||
const sharedCache = {}
|
||||
|
||||
// Initialize compilers
|
||||
this.compilers = compilersOptions.map(compilersOption => {
|
||||
const compiler = webpack(compilersOption)
|
||||
// In dev, write files in memory FS (except for DLL)
|
||||
if (sharedFS && !compiler.name.includes('-dll')) {
|
||||
// In dev, write files in memory FS
|
||||
if (sharedFS) {
|
||||
compiler.outputFileSystem = sharedFS
|
||||
}
|
||||
compiler.cache = sharedCache
|
||||
|
||||
return compiler
|
||||
})
|
||||
|
||||
// Start Builds
|
||||
await sequence(
|
||||
await parallel(
|
||||
this.compilers,
|
||||
compiler =>
|
||||
new Promise(async (resolve, reject) => {
|
||||
@ -532,14 +499,14 @@ module.exports = class Builder {
|
||||
await this.nuxt.callHook('build:compile', { name, compiler })
|
||||
|
||||
// Resolve only when compiler emit done event
|
||||
compiler.plugin('done', async stats => {
|
||||
compiler.hooks.done.tap('load-resources', async stats => {
|
||||
await this.nuxt.callHook('build:compiled', {
|
||||
name,
|
||||
compiler,
|
||||
stats
|
||||
})
|
||||
// Reload renderer if available
|
||||
this.nuxt.renderer.loadResources(sharedFS || require('fs'))
|
||||
this.nuxt.renderer.loadResources(sharedFS || fs)
|
||||
// Resolve on next tick
|
||||
process.nextTick(resolve)
|
||||
})
|
||||
@ -549,14 +516,6 @@ module.exports = class Builder {
|
||||
if (compiler.options.name === 'client') {
|
||||
return this.webpackDev(compiler)
|
||||
}
|
||||
// DLL build, should run only once
|
||||
if (compiler.options.name.includes('-dll')) {
|
||||
compiler.run((err, stats) => {
|
||||
if (err) return reject(err)
|
||||
debug('[DLL] updated')
|
||||
})
|
||||
return
|
||||
}
|
||||
// Server, build and watch for changes
|
||||
this.compilersWatching.push(
|
||||
compiler.watch(this.options.watchers.webpack, err => {
|
||||
@ -574,13 +533,7 @@ module.exports = class Builder {
|
||||
return reject(err)
|
||||
}
|
||||
|
||||
// Show build stats for production
|
||||
console.log(stats.toString(this.webpackStats)) // eslint-disable-line no-console
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (stats.hasErrors()) {
|
||||
return reject(new Error('Webpack build exited with errors'))
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
)
|
||||
|
@ -10,6 +10,7 @@ const _ = require('lodash')
|
||||
const { resolve, join, dirname, sep } = require('path')
|
||||
const { minify } = require('html-minifier')
|
||||
const Chalk = require('chalk')
|
||||
const ORA = require('ora')
|
||||
const { printWarn } = require('../common/utils')
|
||||
|
||||
const {
|
||||
@ -34,14 +35,23 @@ module.exports = class Generator {
|
||||
this.distPath,
|
||||
isUrl(this.options.build.publicPath) ? '' : this.options.build.publicPath
|
||||
)
|
||||
|
||||
this.spinner = new ORA()
|
||||
}
|
||||
|
||||
async generate({ build = true, init = true } = {}) {
|
||||
this.spinner.start('Initializing generator...')
|
||||
|
||||
await this.initiate({ build, init })
|
||||
|
||||
this.spinner.start('Preparing routes for generate...')
|
||||
|
||||
const routes = await this.initRoutes()
|
||||
|
||||
this.spinner.start('Generating pages...')
|
||||
|
||||
const errors = await this.generateRoutes(routes)
|
||||
|
||||
await this.afterGenerate()
|
||||
|
||||
// Done hook
|
||||
@ -128,7 +138,7 @@ module.exports = class Generator {
|
||||
const color = isHandled ? 'yellow' : 'red'
|
||||
|
||||
let line =
|
||||
Chalk.black[bgColor](' ROUTE ') + Chalk[color](` ${route}\n\n`)
|
||||
Chalk.black[bgColor](' GENERATE ERR ') + Chalk[color](` ${route}\n\n`)
|
||||
|
||||
if (isHandled) {
|
||||
line += Chalk.grey(JSON.stringify(error, undefined, 2) + '\n')
|
||||
@ -280,7 +290,10 @@ module.exports = class Generator {
|
||||
})
|
||||
|
||||
if (pageErrors.length) {
|
||||
this.spinner.fail('Error generating ' + route)
|
||||
Array.prototype.push.apply(errors, pageErrors)
|
||||
} else {
|
||||
this.spinner.succeed('Generated ' + route)
|
||||
}
|
||||
|
||||
return true
|
||||
|
@ -1,11 +1,16 @@
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
const TimeFixPlugin = require('time-fix-plugin')
|
||||
const WarnFixPlugin = require('./plugins/warnfix')
|
||||
const ProgressPlugin = require('./plugins/progress')
|
||||
|
||||
const webpack = require('webpack')
|
||||
const { cloneDeep } = require('lodash')
|
||||
const { join, resolve } = require('path')
|
||||
|
||||
const { isUrl, urlJoin } = require('../../common/utils')
|
||||
|
||||
const vueLoader = require('./vue-loader')
|
||||
const styleLoader = require('./style-loader')
|
||||
const TimeFixPlugin = require('./plugins/timefix')
|
||||
const WarnFixPlugin = require('./plugins/warnfix')
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -23,14 +28,22 @@ module.exports = function webpackBaseConfig({ name, isServer }) {
|
||||
|
||||
// Used by vue-loader so we can use in templates
|
||||
// with <img src="~/assets/nuxt.png"/>
|
||||
configAlias[this.options.dir.assets] = join(this.options.srcDir, this.options.dir.assets)
|
||||
configAlias[this.options.dir.static] = join(this.options.srcDir, this.options.dir.static)
|
||||
configAlias[this.options.dir.assets] = join(
|
||||
this.options.srcDir,
|
||||
this.options.dir.assets
|
||||
)
|
||||
configAlias[this.options.dir.static] = join(
|
||||
this.options.srcDir,
|
||||
this.options.dir.static
|
||||
)
|
||||
|
||||
const config = {
|
||||
name,
|
||||
mode: this.options.dev ? 'development' : 'production',
|
||||
entry: {
|
||||
app: null
|
||||
},
|
||||
optimization: {},
|
||||
output: {
|
||||
path: resolve(this.options.buildDir, 'dist'),
|
||||
filename: this.getFileName('app'),
|
||||
@ -46,12 +59,15 @@ module.exports = function webpackBaseConfig({ name, isServer }) {
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.json', '.vue', '.jsx'],
|
||||
alias: Object.assign({
|
||||
alias: Object.assign(
|
||||
{
|
||||
'~': join(this.options.srcDir),
|
||||
'~~': join(this.options.rootDir),
|
||||
'@': join(this.options.srcDir),
|
||||
'@@': join(this.options.rootDir)
|
||||
}, configAlias),
|
||||
},
|
||||
configAlias
|
||||
),
|
||||
modules: webpackModulesDir
|
||||
},
|
||||
resolveLoader: {
|
||||
@ -113,6 +129,17 @@ module.exports = function webpackBaseConfig({ name, isServer }) {
|
||||
plugins: this.options.build.plugins
|
||||
}
|
||||
|
||||
// Build progress indicator
|
||||
if (this.options.build.profile) {
|
||||
config.plugins.push(new webpack.ProgressPlugin({ profile: true }))
|
||||
} else {
|
||||
config.plugins.push(new ProgressPlugin({
|
||||
spinner: this.spinner,
|
||||
name: isServer ? 'server' : 'client',
|
||||
color: isServer ? 'orange' : 'green'
|
||||
}))
|
||||
}
|
||||
|
||||
// Add timefix-plugin before others plugins
|
||||
if (this.options.dev) {
|
||||
config.plugins.unshift(new TimeFixPlugin())
|
||||
|
@ -3,43 +3,21 @@ const webpack = require('webpack')
|
||||
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
|
||||
const HTMLPlugin = require('html-webpack-plugin')
|
||||
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin')
|
||||
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
|
||||
const ProgressBarPlugin = require('progress-bar-webpack-plugin')
|
||||
const ProgressPlugin = require('webpack/lib/ProgressPlugin')
|
||||
const StylishPlugin = require('webpack-stylish')
|
||||
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
|
||||
const { resolve } = require('path')
|
||||
const { existsSync } = require('fs')
|
||||
const Debug = require('debug')
|
||||
const Chalk = require('chalk')
|
||||
const { printWarn } = require('../../common/utils')
|
||||
const base = require('./base.config.js')
|
||||
|
||||
const debug = Debug('nuxt:build')
|
||||
debug.color = 2 // Force green color
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Webpack Client Config
|
||||
|
|
||||
| Generate public/dist/client-vendor-bundle.js
|
||||
| Generate public/dist/client-bundle.js
|
||||
|
|
||||
| In production, will generate public/dist/style.css
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
module.exports = function webpackClientConfig() {
|
||||
let config = base.call(this, { name: 'client', isServer: false })
|
||||
|
||||
// Entry points
|
||||
config.entry.app = resolve(this.options.buildDir, 'client.js')
|
||||
config.entry.vendor = this.vendor()
|
||||
|
||||
// Config devtool
|
||||
config.devtool = this.options.dev ? 'cheap-source-map' : false
|
||||
config.output.devtoolModuleFilenameTemplate = '[absolute-resource-path]'
|
||||
|
||||
// Add CommonChunks plugin
|
||||
commonChunksPlugin.call(this, config)
|
||||
|
||||
// Env object defined in nuxt.config.js
|
||||
let env = {}
|
||||
@ -78,22 +56,10 @@ module.exports = function webpackClientConfig() {
|
||||
})
|
||||
)
|
||||
|
||||
// Extract webpack runtime & manifest
|
||||
config.plugins.push(
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'manifest',
|
||||
minChunks: Infinity,
|
||||
filename: this.getFileName('manifest')
|
||||
})
|
||||
)
|
||||
|
||||
// Define Env
|
||||
config.plugins.push(
|
||||
new webpack.DefinePlugin(
|
||||
Object.assign(env, {
|
||||
'process.env.NODE_ENV': JSON.stringify(
|
||||
this.options.env.NODE_ENV || (this.options.dev ? 'development' : 'production')
|
||||
),
|
||||
'process.env.VUE_ENV': JSON.stringify('client'),
|
||||
'process.mode': JSON.stringify(this.options.mode),
|
||||
'process.browser': true,
|
||||
@ -104,24 +70,6 @@ module.exports = function webpackClientConfig() {
|
||||
)
|
||||
)
|
||||
|
||||
// Build progress bar
|
||||
if (this.options.build.profile) {
|
||||
config.plugins.push(
|
||||
new ProgressPlugin({
|
||||
profile: true
|
||||
})
|
||||
)
|
||||
} else {
|
||||
config.plugins.push(
|
||||
new ProgressBarPlugin({
|
||||
complete: Chalk.green('█'),
|
||||
incomplete: Chalk.white('█'),
|
||||
format: ' :bar ' + Chalk.green.bold(':percent') + ' :msg',
|
||||
clear: false
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const shouldClearConsole =
|
||||
this.options.build.stats !== false &&
|
||||
this.options.build.stats !== 'errors-only'
|
||||
@ -131,13 +79,19 @@ module.exports = function webpackClientConfig() {
|
||||
new FriendlyErrorsWebpackPlugin({ clearConsole: shouldClearConsole })
|
||||
)
|
||||
|
||||
// Optimization
|
||||
config.optimization = {
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
// TODO: remove spa after https://github.com/jantimon/html-webpack-plugin/issues/878 solved
|
||||
name: this.options.dev || this.options.mode === 'spa'
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------
|
||||
// Dev specific config
|
||||
// --------------------------------------
|
||||
if (this.options.dev) {
|
||||
// https://webpack.js.org/plugins/named-modules-plugin
|
||||
config.plugins.push(new webpack.NamedModulesPlugin())
|
||||
|
||||
// Add HMR support
|
||||
config.entry.app = [
|
||||
// https://github.com/glenjamin/webpack-hot-middleware#config
|
||||
@ -146,26 +100,15 @@ module.exports = function webpackClientConfig() {
|
||||
}/__webpack_hmr`.replace(/\/\//g, '/'),
|
||||
config.entry.app
|
||||
]
|
||||
config.plugins.push(
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.NoEmitOnErrorsPlugin()
|
||||
)
|
||||
|
||||
// DllReferencePlugin
|
||||
if (this.options.build.dll) {
|
||||
dllPlugin.call(this, config)
|
||||
}
|
||||
// HMR
|
||||
config.plugins.push(new webpack.HotModuleReplacementPlugin())
|
||||
}
|
||||
|
||||
// --------------------------------------
|
||||
// Production specific config
|
||||
// --------------------------------------
|
||||
if (!this.options.dev) {
|
||||
// Scope Hoisting
|
||||
if (this.options.build.scopeHoisting === true) {
|
||||
config.plugins.push(new webpack.optimize.ModuleConcatenationPlugin())
|
||||
}
|
||||
|
||||
// Chunks size limit
|
||||
// https://webpack.js.org/plugins/aggressive-splitting-plugin/
|
||||
if (this.options.build.maxChunkSize) {
|
||||
@ -177,32 +120,9 @@ module.exports = function webpackClientConfig() {
|
||||
)
|
||||
}
|
||||
|
||||
// https://webpack.js.org/plugins/hashed-module-ids-plugin
|
||||
config.plugins.push(new webpack.HashedModuleIdsPlugin())
|
||||
|
||||
// Minify JS
|
||||
// https://github.com/webpack-contrib/uglifyjs-webpack-plugin
|
||||
if (this.options.build.uglify !== false) {
|
||||
config.plugins.push(
|
||||
new UglifyJSPlugin(
|
||||
Object.assign(
|
||||
{
|
||||
// cache: true,
|
||||
sourceMap: true,
|
||||
parallel: true,
|
||||
extractComments: {
|
||||
filename: 'LICENSES'
|
||||
},
|
||||
uglifyOptions: {
|
||||
output: {
|
||||
comments: /^\**!|@preserve|@license|@cc_on/
|
||||
}
|
||||
}
|
||||
},
|
||||
this.options.build.uglify
|
||||
)
|
||||
)
|
||||
)
|
||||
// https://github.com/webpack-contrib/webpack-stylish
|
||||
if (!this.options.dev) {
|
||||
config.plugins.push(new StylishPlugin())
|
||||
}
|
||||
|
||||
// Webpack Bundle Analyzer
|
||||
@ -224,6 +144,7 @@ module.exports = function webpackClientConfig() {
|
||||
isDev,
|
||||
isClient: true
|
||||
})
|
||||
|
||||
// Only overwrite config when something is returned for backwards compatibility
|
||||
if (extendedConfig !== undefined) {
|
||||
config = extendedConfig
|
||||
@ -232,50 +153,3 @@ module.exports = function webpackClientConfig() {
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Adds Common Chunks Plugin
|
||||
// --------------------------------------------------------------------------
|
||||
function commonChunksPlugin(config) {
|
||||
// Create explicit vendor chunk
|
||||
config.plugins.unshift(
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'vendor',
|
||||
filename: this.getFileName('vendor'),
|
||||
minChunks(module, count) {
|
||||
// A module is extracted into the vendor chunk when...
|
||||
return (
|
||||
// If it's inside node_modules
|
||||
/node_modules/.test(module.context) &&
|
||||
// Do not externalize if the request is a CSS file or a Vue file which can potentially emit CSS assets!
|
||||
!/\.(css|less|scss|sass|styl|stylus|vue)$/.test(module.request)
|
||||
)
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Adds DLL plugin
|
||||
// https://github.com/webpack/webpack/tree/master/examples/dll-user
|
||||
// --------------------------------------------------------------------------
|
||||
function dllPlugin(config) {
|
||||
const _dlls = []
|
||||
const vendorEntries = this.vendorEntries()
|
||||
const dllDir = resolve(this.options.cacheDir, config.name + '-dll')
|
||||
Object.keys(vendorEntries).forEach(v => {
|
||||
const dllManifestFile = resolve(dllDir, v + '-manifest.json')
|
||||
if (existsSync(dllManifestFile)) {
|
||||
_dlls.push(v)
|
||||
config.plugins.push(
|
||||
new webpack.DllReferencePlugin({
|
||||
// context: this.options.rootDir,
|
||||
manifest: dllManifestFile // Using full path to allow finding .js dll file
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
if (_dlls.length) {
|
||||
debug('Using dll for ' + _dlls.join(','))
|
||||
}
|
||||
}
|
||||
|
@ -1,46 +0,0 @@
|
||||
const webpack = require('webpack')
|
||||
const { resolve } = require('path')
|
||||
const ClientConfig = require('./client.config')
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Webpack Dll Config
|
||||
| https://github.com/webpack/webpack/tree/master/examples/dll
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
module.exports = function webpackDllConfig(_refConfig) {
|
||||
const refConfig = _refConfig || new ClientConfig()
|
||||
|
||||
const name = refConfig.name + '-dll'
|
||||
const dllDir = resolve(this.options.cacheDir, name)
|
||||
|
||||
let config = {
|
||||
name,
|
||||
entry: this.vendorEntries(),
|
||||
// context: this.options.rootDir,
|
||||
resolve: refConfig.resolve,
|
||||
target: refConfig.target,
|
||||
resolveLoader: refConfig.resolveLoader,
|
||||
module: refConfig.module,
|
||||
plugins: []
|
||||
}
|
||||
|
||||
config.output = {
|
||||
path: dllDir,
|
||||
filename: '[name]_[hash].js',
|
||||
library: '[name]_[hash]'
|
||||
}
|
||||
|
||||
config.plugins.push(
|
||||
new webpack.DllPlugin({
|
||||
// The path to the manifest file which maps between
|
||||
// modules included in a bundle and the internal IDs
|
||||
// within that bundle
|
||||
path: resolve(dllDir, '[name]-manifest.json'),
|
||||
|
||||
name: '[name]_[hash]'
|
||||
})
|
||||
)
|
||||
|
||||
return config
|
||||
}
|
83
lib/builder/webpack/plugins/progress.js
Normal file
83
lib/builder/webpack/plugins/progress.js
Normal file
@ -0,0 +1,83 @@
|
||||
const webpack = require('webpack')
|
||||
const chalk = require('chalk')
|
||||
const _ = require('lodash')
|
||||
|
||||
const sharedState = {}
|
||||
|
||||
const BLOCK_CHAR = '█'
|
||||
|
||||
module.exports = class ProgressPlugin extends webpack.ProgressPlugin {
|
||||
constructor(options) {
|
||||
super(options)
|
||||
|
||||
this.handler = (percent, msg) => this.updateProgress(percent, msg)
|
||||
|
||||
this.options = options
|
||||
|
||||
if (!sharedState[options.name]) {
|
||||
sharedState[options.name] = {
|
||||
color: options.color
|
||||
}
|
||||
}
|
||||
|
||||
this.spinner = options.spinner
|
||||
}
|
||||
|
||||
get state() {
|
||||
return sharedState[this.options.name]
|
||||
}
|
||||
|
||||
updateProgress(percent, msg) {
|
||||
const progress = Math.floor(percent * 100)
|
||||
|
||||
this.state.progress = progress
|
||||
this.state.msg = msg
|
||||
|
||||
// Process all states
|
||||
let inProgress = false
|
||||
|
||||
const additional = []
|
||||
|
||||
const bars = Object.keys(sharedState).map(name => {
|
||||
const state = sharedState[name]
|
||||
|
||||
if (state.progress < 100) {
|
||||
inProgress = true
|
||||
}
|
||||
|
||||
const blockChar = chalk.keyword(state.color)(BLOCK_CHAR)
|
||||
|
||||
additional.push(`${blockChar} ${name} (${state.progress}%) `)
|
||||
|
||||
return {
|
||||
name,
|
||||
color: state.color,
|
||||
progress: state.progress,
|
||||
blockChar: chalk.keyword(state.color)(BLOCK_CHAR)
|
||||
}
|
||||
})
|
||||
|
||||
if (!inProgress) {
|
||||
this.spinner.succeed('Compiled ' + this.options.name)
|
||||
return
|
||||
}
|
||||
|
||||
// Generate progressbars
|
||||
|
||||
const width = 25
|
||||
const progressbars = _.range(width).fill(chalk.white(BLOCK_CHAR))
|
||||
|
||||
_.sortBy(bars, 'progress').reverse().forEach(bar => {
|
||||
const w = bar.progress * (width / 100)
|
||||
|
||||
for (let i = 0; i < w; i++) {
|
||||
progressbars[i] = bar.blockChar
|
||||
}
|
||||
})
|
||||
|
||||
// Update spinner
|
||||
|
||||
this.spinner.start()
|
||||
this.spinner.text = 'Compiling ' + progressbars.join('') + ' ' + additional.join(' ')
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
// Taken from https://github.com/egoist/poi/blob/3e93c88c520db2d20c25647415e6ae0d3de61145/packages/poi/lib/webpack/timefix-plugin.js#L1-L16
|
||||
// Thanks to @egoist
|
||||
module.exports = class TimeFixPlugin {
|
||||
constructor(timefix = 11000) {
|
||||
this.timefix = timefix
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
compiler.plugin('watch-run', (watching, callback) => {
|
||||
watching.startTime += this.timefix
|
||||
callback()
|
||||
})
|
||||
|
||||
compiler.plugin('done', stats => {
|
||||
stats.startTime -= this.timefix
|
||||
})
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
module.exports = class WarnFixPlugin {
|
||||
apply(compiler) /* istanbul ignore next */ {
|
||||
compiler.plugin('done', stats => {
|
||||
compiler.hooks.done.tap('warnfix-plugin', stats => {
|
||||
stats.compilation.warnings = stats.compilation.warnings.filter(warn => {
|
||||
if (
|
||||
warn.name === 'ModuleDependencyWarning' &&
|
||||
|
@ -46,9 +46,6 @@ module.exports = function webpackServerConfig() {
|
||||
}),
|
||||
new webpack.DefinePlugin(
|
||||
Object.assign(env, {
|
||||
'process.env.NODE_ENV': JSON.stringify(
|
||||
this.options.env.NODE_ENV || (this.options.dev ? 'development' : 'production')
|
||||
),
|
||||
'process.env.VUE_ENV': JSON.stringify('server'),
|
||||
'process.mode': JSON.stringify(this.options.mode),
|
||||
'process.browser': false,
|
||||
|
@ -197,8 +197,7 @@ Options.defaults = {
|
||||
build: {
|
||||
analyze: false,
|
||||
profile: process.argv.includes('--profile'),
|
||||
dll: false,
|
||||
scopeHoisting: false,
|
||||
splitPages: true,
|
||||
maxChunkSize: false,
|
||||
extractCSS: false,
|
||||
cssSourceMap: undefined,
|
||||
@ -208,12 +207,10 @@ Options.defaults = {
|
||||
filenames: {
|
||||
css: '[name].[contenthash].css',
|
||||
manifest: 'manifest.[hash].js',
|
||||
vendor: 'vendor.[chunkhash].js',
|
||||
app: '[name].[chunkhash].js',
|
||||
chunk: '[name].[chunkhash].js'
|
||||
},
|
||||
styleResources: {},
|
||||
vendor: [],
|
||||
plugins: [],
|
||||
babel: {
|
||||
babelrc: false
|
||||
@ -342,9 +339,7 @@ Options.defaults = {
|
||||
}
|
||||
},
|
||||
watchers: {
|
||||
webpack: {
|
||||
ignored: /-dll/
|
||||
},
|
||||
webpack: {},
|
||||
chokidar: {}
|
||||
},
|
||||
editor: undefined,
|
||||
|
@ -53,6 +53,31 @@ exports.waitFor = function waitFor(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms || 0))
|
||||
}
|
||||
|
||||
async function promiseFinally(fn, finalFn) {
|
||||
let result
|
||||
try {
|
||||
if (typeof fn === 'function') {
|
||||
result = await fn()
|
||||
} else {
|
||||
result = await fn
|
||||
}
|
||||
} finally {
|
||||
finalFn()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
exports.promiseFinally = promiseFinally
|
||||
|
||||
exports.timeout = function timeout(fn, ms, msg) {
|
||||
let timerId
|
||||
const warpPromise = promiseFinally(fn, () => clearTimeout(timerId))
|
||||
const timerPromise = new Promise((resolve, reject) => {
|
||||
timerId = setTimeout(() => reject(new Error(msg)), ms)
|
||||
})
|
||||
return Promise.race([warpPromise, timerPromise])
|
||||
}
|
||||
|
||||
exports.urlJoin = function urlJoin() {
|
||||
return [].slice
|
||||
.call(arguments)
|
||||
|
@ -1,6 +1,5 @@
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const { uniq } = require('lodash')
|
||||
const hash = require('hash-sum')
|
||||
const { chainFn, sequence, printWarn } = require('../common/utils')
|
||||
|
||||
@ -23,12 +22,7 @@ module.exports = class ModuleContainer {
|
||||
}
|
||||
|
||||
addVendor(vendor) {
|
||||
/* istanbul ignore if */
|
||||
if (typeof vendor !== 'string' && !Array.isArray(vendor)) {
|
||||
throw new Error('Invalid vendor: ' + vendor)
|
||||
}
|
||||
|
||||
this.options.build.vendor = uniq(this.options.build.vendor.concat(vendor))
|
||||
printWarn('module: addVendor is no longer necessary')
|
||||
}
|
||||
|
||||
addTemplate(template) {
|
||||
|
@ -11,7 +11,7 @@ const connect = require('connect')
|
||||
const launchMiddleware = require('launch-editor-middleware')
|
||||
const crypto = require('crypto')
|
||||
|
||||
const { setAnsiColors, isUrl, waitFor } = require('../common/utils')
|
||||
const { setAnsiColors, isUrl, waitFor, timeout } = require('../common/utils')
|
||||
const { Options } = require('../common')
|
||||
|
||||
const MetaRenderer = require('./meta')
|
||||
@ -440,9 +440,9 @@ module.exports = class Renderer {
|
||||
throw error
|
||||
}
|
||||
// Used by nuxt.js to say when the components are loaded and the app ready
|
||||
await new Promise(resolve => {
|
||||
await timeout(new Promise(resolve => {
|
||||
window._onNuxtLoaded = () => resolve(window)
|
||||
})
|
||||
}), 20000, 'Components loading in renderAndGetWindow was not completed in 20s')
|
||||
if (opts.virtualConsole !== false) {
|
||||
// after window initialized successfully
|
||||
options.virtualConsole.removeListener('jsdomError', jsdomErrHandler)
|
||||
|
72
package.json
72
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nuxt",
|
||||
"version": "1.4.0",
|
||||
"version": "2.0.0",
|
||||
"description": "A minimalistic framework for server-rendered Vue.js applications (inspired by Next.js)",
|
||||
"contributors": [
|
||||
{
|
||||
@ -59,37 +59,37 @@
|
||||
"dependencies": {
|
||||
"@nuxtjs/youch": "^4.2.3",
|
||||
"ansi-html": "^0.0.7",
|
||||
"autoprefixer": "^7.2.5",
|
||||
"autoprefixer": "^8.1.0",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-loader": "^7.1.4",
|
||||
"babel-preset-vue-app": "^2.0.0",
|
||||
"caniuse-lite": "^1.0.30000808",
|
||||
"chalk": "^2.3.1",
|
||||
"caniuse-lite": "^1.0.30000813",
|
||||
"chalk": "^2.3.2",
|
||||
"chokidar": "^2.0.1",
|
||||
"clone": "^2.1.1",
|
||||
"compression": "^1.7.1",
|
||||
"connect": "^3.6.5",
|
||||
"css-hot-loader": "^1.3.7",
|
||||
"css-hot-loader": "^1.3.8",
|
||||
"css-loader": "^0.28.9",
|
||||
"debug": "^3.1.0",
|
||||
"es6-promise": "^4.2.4",
|
||||
"etag": "^1.8.1",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^1.1.6",
|
||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||
"file-loader": "^1.1.11",
|
||||
"fresh": "^0.5.2",
|
||||
"friendly-errors-webpack-plugin": "^1.6.1",
|
||||
"fs-extra": "^5.0.0",
|
||||
"glob": "^7.1.2",
|
||||
"hash-sum": "^1.0.2",
|
||||
"html-minifier": "^3.5.9",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"html-minifier": "^3.5.10",
|
||||
"html-webpack-plugin": "^3.0.6",
|
||||
"launch-editor": "^2.2.1",
|
||||
"launch-editor-middleware": "^2.2.1",
|
||||
"lodash": "^4.17.5",
|
||||
"lru-cache": "^4.1.1",
|
||||
"lru-cache": "^4.1.2",
|
||||
"memory-fs": "^0.4.1",
|
||||
"minimist": "^1.2.0",
|
||||
"opencollective": "^1.0.3",
|
||||
"ora": "^2.0.0",
|
||||
"postcss": "^6.0.17",
|
||||
"postcss-cssnext": "^3.1.0",
|
||||
"postcss-import": "^11.1.0",
|
||||
@ -97,41 +97,37 @@
|
||||
"postcss-loader": "^2.1.0",
|
||||
"postcss-url": "^7.3.0",
|
||||
"pretty-error": "^2.1.1",
|
||||
"progress-bar-webpack-plugin": "^1.10.0",
|
||||
"semver": "^5.5.0",
|
||||
"serialize-javascript": "^1.4.0",
|
||||
"serve-static": "^1.13.2",
|
||||
"server-destroy": "^1.0.1",
|
||||
"source-map": "^0.7.0",
|
||||
"style-resources-loader": "^1.0.0",
|
||||
"uglifyjs-webpack-plugin": "^1.1.8",
|
||||
"source-map": "^0.7.2",
|
||||
"style-resources-loader": "^1.1.0",
|
||||
"time-fix-plugin": "^2.0.0",
|
||||
"upath": "^1.0.2",
|
||||
"url-loader": "^0.6.2",
|
||||
"vue": "^2.5.13",
|
||||
"vue-loader": "13.7.0",
|
||||
"vue-meta": "^1.4.3",
|
||||
"url-loader": "^1.0.1",
|
||||
"vue": "^2.5.15",
|
||||
"vue-loader": "^14.2.1",
|
||||
"vue-meta": "^1.4.1",
|
||||
"vue-router": "^3.0.1",
|
||||
"vue-server-renderer": "^2.5.13",
|
||||
"vue-template-compiler": "^2.5.13",
|
||||
"vue-server-renderer": "^2.5.15",
|
||||
"vue-template-compiler": "^2.5.15",
|
||||
"vuex": "^3.0.1",
|
||||
"webpack": "^3.11.0",
|
||||
"webpack-bundle-analyzer": "^2.10.0",
|
||||
"webpack-dev-middleware": "^2.0.5",
|
||||
"webpack-hot-middleware": "^2.21.0",
|
||||
"webpack-node-externals": "^1.6.0"
|
||||
"webpack": "^4.1.1",
|
||||
"webpack-bundle-analyzer": "^2.11.1",
|
||||
"webpack-dev-middleware": "^3.0.1",
|
||||
"webpack-hot-middleware": "^2.21.2",
|
||||
"webpack-node-externals": "^1.6.0",
|
||||
"webpack-stylish": "^0.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^0.25.0",
|
||||
"babel-eslint": "^8.2.1",
|
||||
"babel-plugin-array-includes": "^2.0.3",
|
||||
"babel-plugin-external-helpers": "^6.22.0",
|
||||
"babel-plugin-istanbul": "^4.1.5",
|
||||
"codecov": "^3.0.0",
|
||||
"copy-webpack-plugin": "^4.4.1",
|
||||
"cross-env": "^5.1.3",
|
||||
"eslint": "^4.17.0",
|
||||
"eslint-config-standard": "^11.0.0-beta.0",
|
||||
"eslint-config-standard-jsx": "^4.0.2",
|
||||
"eslint": "^4.18.2",
|
||||
"eslint-config-standard": "^11.0.0",
|
||||
"eslint-config-standard-jsx": "^5.0.0",
|
||||
"eslint-plugin-html": "^4.0.2",
|
||||
"eslint-plugin-import": "^2.8.0",
|
||||
"eslint-plugin-node": "^6.0.0",
|
||||
@ -139,15 +135,13 @@
|
||||
"eslint-plugin-react": "^7.6.1",
|
||||
"eslint-plugin-standard": "^3.0.1",
|
||||
"express": "^4.16.2",
|
||||
"finalhandler": "^1.1.0",
|
||||
"finalhandler": "^1.1.1",
|
||||
"jsdom": "^11.6.2",
|
||||
"json-loader": "^0.5.7",
|
||||
"nyc": "^11.4.1",
|
||||
"nyc": "^11.6.0",
|
||||
"puppeteer": "^1.0.0",
|
||||
"request": "^2.83.0",
|
||||
"request-promise-native": "^1.0.5",
|
||||
"sinon": "^4.3.0",
|
||||
"uglify-js": "^3.3.10"
|
||||
"sinon": "^4.3.0"
|
||||
},
|
||||
"collective": {
|
||||
"type": "opencollective",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { promisify } from 'util'
|
||||
import test from 'ava'
|
||||
import { resolve, sep } from 'path'
|
||||
import { resolve } from 'path'
|
||||
import rp from 'request-promise-native'
|
||||
import { exec, spawn } from 'child_process'
|
||||
import { Utils } from '..'
|
||||
@ -14,10 +14,9 @@ const url = route => 'http://localhost:' + port + route
|
||||
const nuxtBin = resolve(__dirname, '..', 'bin', 'nuxt')
|
||||
|
||||
test.serial('nuxt build', async t => {
|
||||
const { stdout, stderr } = await execify(`node ${nuxtBin} build ${rootDir}`)
|
||||
const { stdout } = await execify(`node ${nuxtBin} build ${rootDir}`)
|
||||
|
||||
t.true(stdout.includes('server-bundle.json'))
|
||||
t.true(stderr.includes('Building done'))
|
||||
t.true(stdout.includes('Compiled successfully'))
|
||||
})
|
||||
|
||||
test.serial('nuxt build -> error config', async t => {
|
||||
@ -91,12 +90,7 @@ test.serial('nuxt start', async t => {
|
||||
})
|
||||
|
||||
test.serial('nuxt generate', async t => {
|
||||
const { stdout, stderr } = await execify(`node ${nuxtBin} generate ${rootDir}`)
|
||||
const { stdout } = await execify(`node ${nuxtBin} generate ${rootDir}`)
|
||||
|
||||
t.true(stdout.includes('server-bundle.json'))
|
||||
t.true(stderr.includes('Destination folder cleaned'))
|
||||
t.true(stderr.includes('Static & build files copied'))
|
||||
t.true(stderr.includes(`Generate file: ${sep}users${sep}1${sep}index.html`))
|
||||
t.true(stdout.includes('Generate errors summary:'))
|
||||
t.true(stderr.includes('Generate done'))
|
||||
t.true(stdout.includes('vue-ssr-client-manifest.json'))
|
||||
})
|
||||
|
@ -1,53 +0,0 @@
|
||||
import { promisify } from 'util'
|
||||
import test from 'ava'
|
||||
import { resolve } from 'path'
|
||||
import fs from 'fs'
|
||||
import { Nuxt, Builder } from '..'
|
||||
import { interceptLog, release } from './helpers/console'
|
||||
|
||||
const readFile = promisify(fs.readFile)
|
||||
const rootDir = resolve(__dirname, 'fixtures/dll')
|
||||
const dllDir = resolve(rootDir, '.cache/client-dll')
|
||||
|
||||
const checkCache = lib => {
|
||||
return async t => {
|
||||
const manifest = await readFile(
|
||||
resolve(dllDir, `./${lib}-manifest.json`),
|
||||
'utf-8'
|
||||
)
|
||||
t.truthy(JSON.parse(manifest).name)
|
||||
t.true(fs.existsSync(resolve(dllDir, `./${JSON.parse(manifest).name}.js`)))
|
||||
}
|
||||
}
|
||||
|
||||
let nuxt
|
||||
|
||||
test.serial('Init Nuxt.js', async t => {
|
||||
let config = require(resolve(rootDir, 'nuxt.config.js'))
|
||||
config.rootDir = rootDir
|
||||
config.dev = true
|
||||
|
||||
const logSpy = await interceptLog(async () => {
|
||||
nuxt = new Nuxt(config)
|
||||
await new Builder(nuxt).build()
|
||||
})
|
||||
t.true(logSpy.calledWithMatch('DONE'))
|
||||
})
|
||||
|
||||
test('Check vue cache', checkCache('vue'))
|
||||
|
||||
test('Check vue-meta cache', checkCache('vue-meta'))
|
||||
|
||||
test('Check vue-router cache', checkCache('vue-router'))
|
||||
|
||||
test('Build with DllReferencePlugin', async t => {
|
||||
const logSpy = await interceptLog()
|
||||
await new Builder(nuxt).build()
|
||||
release()
|
||||
t.true(logSpy.withArgs('Using dll for 3 libs').calledOnce)
|
||||
})
|
||||
|
||||
// Close server and ask nuxt to stop listening to file changes
|
||||
test.after.always('Closing nuxt.js', t => {
|
||||
nuxt.close()
|
||||
})
|
15
test/fixtures/dll/nuxt.config.js
vendored
15
test/fixtures/dll/nuxt.config.js
vendored
@ -1,15 +0,0 @@
|
||||
module.exports = {
|
||||
build: {
|
||||
stats: false,
|
||||
dll: true,
|
||||
extend(config, options) {
|
||||
if (options.isClient) {
|
||||
const dlls = config.plugins.filter(
|
||||
plugin => plugin.constructor.name === 'DllReferencePlugin'
|
||||
)
|
||||
console.log('Using dll for ' + dlls.length + ' libs') // eslint-disable-line no-console
|
||||
}
|
||||
return config
|
||||
}
|
||||
}
|
||||
}
|
0
test/fixtures/dll/pages/index.vue
vendored
0
test/fixtures/dll/pages/index.vue
vendored
3
test/fixtures/module/modules/basic/index.js
vendored
3
test/fixtures/module/modules/basic/index.js
vendored
@ -1,9 +1,8 @@
|
||||
const path = require('path')
|
||||
|
||||
module.exports = function basicModule(options, resolve) {
|
||||
// Add vendor
|
||||
// Add vendor (deprecated)
|
||||
this.addVendor('lodash')
|
||||
this.addVendor(['lodash', 'lodash'])
|
||||
|
||||
// Add a plugin
|
||||
this.addPlugin(path.resolve(__dirname, 'reverse.js'))
|
||||
|
@ -30,6 +30,7 @@ export function release() {
|
||||
}
|
||||
|
||||
context = null
|
||||
delete console.spiedInTest // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
export async function intercept(levels, msg, cb) {
|
||||
@ -39,6 +40,7 @@ export async function intercept(levels, msg, cb) {
|
||||
)
|
||||
}
|
||||
context = {}
|
||||
console.spiedInTest = true // eslint-disable-line no-console
|
||||
|
||||
if (cb === undefined && typeof msg === 'function') {
|
||||
cb = msg
|
||||
|
@ -29,13 +29,6 @@ test.serial('Init Nuxt.js', async t => {
|
||||
t.true(buildSpies.log.calledWithMatch('OPEN'))
|
||||
})
|
||||
|
||||
test.serial('Vendor', async t => {
|
||||
t.true(
|
||||
nuxt.options.build.vendor.indexOf('lodash') !== -1,
|
||||
'lodash added to config'
|
||||
)
|
||||
})
|
||||
|
||||
test.serial('Plugin', async t => {
|
||||
t.true(
|
||||
normalize(nuxt.options.plugins[0].src).includes(
|
||||
|
@ -28,6 +28,33 @@ test('waitFor', async t => {
|
||||
await Utils.waitFor()
|
||||
})
|
||||
|
||||
test('timeout (promise)', async t => {
|
||||
const result = await Utils.timeout(Promise.resolve('time not run out'), 100)
|
||||
t.is(result, 'time not run out')
|
||||
})
|
||||
|
||||
test('timeout (async function)', async t => {
|
||||
const result = await Utils.timeout(async () => {
|
||||
await Utils.waitFor(10)
|
||||
return 'time not run out'
|
||||
}, 100)
|
||||
t.is(result, 'time not run out')
|
||||
})
|
||||
|
||||
test('timeout (timeout in 100ms)', async t => {
|
||||
const timeout = Utils.timeout(Utils.waitFor(200), 100, 'timeout test 100ms')
|
||||
const { message } = await t.throws(timeout)
|
||||
t.is(message, 'timeout test 100ms')
|
||||
})
|
||||
|
||||
test('timeout (async timeout in 100ms)', async t => {
|
||||
const timeout = Utils.timeout(async () => {
|
||||
await Utils.waitFor(500)
|
||||
}, 100, 'timeout test 100ms')
|
||||
const { message } = await t.throws(timeout)
|
||||
t.is(message, 'timeout test 100ms')
|
||||
})
|
||||
|
||||
test('urlJoin', t => {
|
||||
t.is(Utils.urlJoin('test', '/about'), 'test/about')
|
||||
})
|
||||
|
@ -43,7 +43,7 @@ test('/ (global styles inlined)', async t => {
|
||||
t.true(html.includes('.global-css-selector'))
|
||||
})
|
||||
|
||||
test('/ (preload fonts)', async t => {
|
||||
test.skip('/ (preload fonts)', async t => {
|
||||
const { html } = await nuxt.renderRoute('/')
|
||||
t.true(
|
||||
html.includes(
|
||||
@ -59,7 +59,7 @@ test('/ (custom app.html)', async t => {
|
||||
|
||||
test('/ (custom build.publicPath)', async t => {
|
||||
const { html } = await nuxt.renderRoute('/')
|
||||
t.true(html.includes('src="/test/orion/vendor.'))
|
||||
t.true(html.includes('<script src="/test/orion/'))
|
||||
})
|
||||
|
||||
test('/ (custom postcss.config.js)', async t => {
|
||||
@ -176,7 +176,7 @@ test('Check stats.json generated by build.analyze', t => {
|
||||
__dirname,
|
||||
'fixtures/with-config/.nuxt/dist/stats.json'
|
||||
))
|
||||
t.is(stats.assets.length, 37)
|
||||
t.is(stats.assets.length, 34)
|
||||
})
|
||||
|
||||
test('Check /test/test.txt with custom serve-static options', async t => {
|
||||
|
Loading…
Reference in New Issue
Block a user