feat(builder): validate vue-app dependencies and suggest fix (#4669)

This commit is contained in:
Pooya Parsa 2019-01-02 17:47:19 +03:30 committed by Xin Du (Clark)
parent 7ff4058318
commit 7dd33fedd2
5 changed files with 75 additions and 43 deletions

View File

@ -18,6 +18,7 @@
"hash-sum": "^1.0.2", "hash-sum": "^1.0.2",
"lodash": "^4.17.11", "lodash": "^4.17.11",
"pify": "^4.0.1", "pify": "^4.0.1",
"semver": "^5.6.0",
"serialize-javascript": "^1.6.1", "serialize-javascript": "^1.6.1",
"upath": "^1.1.0" "upath": "^1.1.0"
}, },

View File

@ -7,6 +7,7 @@ import hash from 'hash-sum'
import pify from 'pify' import pify from 'pify'
import serialize from 'serialize-javascript' import serialize from 'serialize-javascript'
import upath from 'upath' import upath from 'upath'
import semver from 'semver'
import debounce from 'lodash/debounce' import debounce from 'lodash/debounce'
import omit from 'lodash/omit' import omit from 'lodash/omit'
@ -75,7 +76,7 @@ export default class Builder {
// Resolve template // Resolve template
this.template = this.options.build.template || '@nuxt/vue-app' this.template = this.options.build.template || '@nuxt/vue-app'
if (typeof this.template === 'string') { if (typeof this.template === 'string') {
this.template = this.nuxt.resolver.requireModule(this.template) this.template = this.nuxt.resolver.requireModule(this.template).template
} }
// if(!this.options.dev) { // if(!this.options.dev) {
@ -205,6 +206,13 @@ export default class Builder {
} }
} }
// Validate template
try {
this.validateTemplate()
} catch (err) {
consola.fatal(err)
}
consola.success('Builder initialized') consola.success('Builder initialized')
consola.debug(`App root: ${this.options.srcDir}`) consola.debug(`App root: ${this.options.srcDir}`)
@ -237,6 +245,43 @@ export default class Builder {
return this return this
} }
validateTemplate() {
// Validate template dependencies
const templateDependencies = this.template.dependencies
const dpendencyFixes = []
for (const depName in templateDependencies) {
const depVersion = templateDependencies[depName]
const requiredVersion = `${depName}@${depVersion}`
// Load installed version
const pkg = this.nuxt.resolver.requireModule(path.join(depName, 'package.json'))
if (pkg) {
const validVersion = semver.satisfies(pkg.version, depVersion)
if (!validVersion) {
consola.warn(`${requiredVersion} is required but ${depName}@${pkg.version} is installed!`)
dpendencyFixes.push(requiredVersion)
}
} else {
consola.warn(`${depName}@${depVersion} is required but not installed!`)
dpendencyFixes.push(requiredVersion)
}
}
// Suggest dependency fixes (TODO: automate me)
if (dpendencyFixes.length) {
consola.error(
`Please install missing dependencies:\n`,
'\n',
`Using yarn:\n`,
`yarn add ${dpendencyFixes.join(' ')}\n`,
'\n',
`Using npm:\n`,
`npm i ${dpendencyFixes.join(' ')}\n`
)
throw new Error('Missing Template Dependencies')
}
}
async generateRoutesAndFiles() { async generateRoutesAndFiles() {
consola.debug(`Generating nuxt files`) consola.debug(`Generating nuxt files`)
@ -244,7 +289,7 @@ export default class Builder {
this.plugins = Array.from(this.normalizePlugins()) this.plugins = Array.from(this.normalizePlugins())
// -- Templates -- // -- Templates --
let templatesFiles = Array.from(this.template.templatesFiles) let templatesFiles = Array.from(this.template.files)
const templateVars = { const templateVars = {
options: this.options, options: this.options,
@ -325,7 +370,7 @@ export default class Builder {
if (this._defaultPage) { if (this._defaultPage) {
templateVars.router.routes = createRoutes( templateVars.router.routes = createRoutes(
['index.vue'], ['index.vue'],
this.template.templatesDir + '/pages', this.template.dir + '/pages',
'', '',
this.options.router.routeNameSplitter this.options.router.routeNameSplitter
) )
@ -396,7 +441,7 @@ export default class Builder {
const customFileExists = fsExtra.existsSync(customPath) const customFileExists = fsExtra.existsSync(customPath)
return { return {
src: customFileExists ? customPath : r(this.template.templatesDir, file), src: customFileExists ? customPath : r(this.template.dir, file),
dst: file, dst: file,
custom: customFileExists custom: customFileExists
} }
@ -421,7 +466,7 @@ export default class Builder {
// -- Loading indicator -- // -- Loading indicator --
if (this.options.loadingIndicator.name) { if (this.options.loadingIndicator.name) {
const indicatorPath1 = path.resolve( const indicatorPath1 = path.resolve(
this.template.templatesDir, this.template.dir,
'views/loading', 'views/loading',
this.options.loadingIndicator.name + '.html' this.options.loadingIndicator.name + '.html'
) )

View File

@ -253,14 +253,6 @@ export function getNuxtConfig(_options) {
delete options.render.gzip delete options.render.gzip
} }
if (options.nuxtAppDir) {
consola.warn('nuxtAppDir is deprecated and will be removed in a future version! Please switch to build.template')
options.build.template = {
templatesDir: options.nuxtAppDir
}
delete options.nuxtAppDir
}
// Apply mode preset // Apply mode preset
const modePreset = options.modes[options.mode || 'universal'] const modePreset = options.modes[options.mode || 'universal']

View File

@ -1,26 +1,26 @@
import path from 'path' import path from 'path'
import pkg from '../package.json' import { dependencies } from '../package.json'
export const meta = pkg export const template = {
dependencies,
export const templatesDir = path.join(__dirname, '..', 'template') dir: path.join(__dirname, '..', 'template'),
files: [
export const templatesFiles = [ 'App.js',
'App.js', 'client.js',
'client.js', 'index.js',
'index.js', 'middleware.js',
'middleware.js', 'router.js',
'router.js', 'server.js',
'server.js', 'utils.js',
'utils.js', 'empty.js',
'empty.js', 'components/nuxt-error.vue',
'components/nuxt-error.vue', 'components/nuxt-loading.vue',
'components/nuxt-loading.vue', 'components/nuxt-child.js',
'components/nuxt-child.js', 'components/nuxt-link.server.js',
'components/nuxt-link.server.js', 'components/nuxt-link.client.js',
'components/nuxt-link.client.js', 'components/nuxt.js',
'components/nuxt.js', 'components/no-ssr.js',
'components/no-ssr.js', 'views/app.template.html',
'views/app.template.html', 'views/error.html'
'views/error.html' ]
] }

View File

@ -81,12 +81,6 @@ const _routes = recursiveRoutes(router.routes, ' ', _components, 2)
}).join('\n')%> }).join('\n')%>
Vue.use(Router) Vue.use(Router)
// router-view was changed to RouterView in vue-router 3.0.2
// Fix: Vue.component('RouterLink') is undefined in vue-router 3.0.0
if (!Vue.component('RouterLink')) {
Vue.options.components['RouterView'] = Vue.component('router-view')
Vue.options.components['RouterLink'] = Vue.component('router-link')
}
<% if (router.scrollBehavior) { %> <% if (router.scrollBehavior) { %>
const scrollBehavior = <%= serializeFunction(router.scrollBehavior) %> const scrollBehavior = <%= serializeFunction(router.scrollBehavior) %>