diff --git a/lib/app/App.vue b/lib/app/App.js similarity index 97% rename from lib/app/App.vue rename to lib/app/App.js index 54b5251da8..37e81a2af4 100644 --- a/lib/app/App.vue +++ b/lib/app/App.js @@ -1,4 +1,3 @@ - diff --git a/lib/app/components/nuxt-link.js b/lib/app/components/nuxt-link.js index c23fdd7ac3..fea5f308ce 100644 --- a/lib/app/components/nuxt-link.js +++ b/lib/app/components/nuxt-link.js @@ -1,5 +1,3 @@ -import Vue from 'vue' - export default { name: 'nuxt-link', functional: true, diff --git a/lib/app/components/nuxt.vue b/lib/app/components/nuxt.js similarity index 92% rename from lib/app/components/nuxt.vue rename to lib/app/components/nuxt.js index c392f882bf..068b1b16e5 100644 --- a/lib/app/components/nuxt.vue +++ b/lib/app/components/nuxt.js @@ -1,4 +1,3 @@ - diff --git a/lib/app/index.js b/lib/app/index.js index 05cf531221..ce1763aec2 100644 --- a/lib/app/index.js +++ b/lib/app/index.js @@ -6,9 +6,9 @@ import NoSSR from './components/no-ssr.js' import NuxtChild from './components/nuxt-child.js' import NuxtLink from './components/nuxt-link.js' import NuxtError from '<%= components.ErrorPage ? components.ErrorPage : "./components/nuxt-error.vue" %>' -import Nuxt from './components/nuxt.vue' +import Nuxt from './components/nuxt.js' import App from '<%= appPath %>' -import { getContext, getLocation } from './utils' +import { setContext, getLocation } from './utils' <% if (store) { %>import { createStore } from './store.js'<% } %> <% plugins.forEach(plugin => { %>import <%= plugin.name %> from '<%= plugin.name %>' <% }) %> @@ -37,7 +37,8 @@ const defaultTransition = <%= serialize(transition) .replace('beforeEnter(', 'function(').replace('enter(', 'function(').replace('afterEnter(', 'function(') .replace('enterCancelled(', 'function(').replace('beforeLeave(', 'function(').replace('leave(', 'function(') - .replace('afterLeave(', 'function(').replace('leaveCancelled(', 'function(') + .replace('afterLeave(', 'function(').replace('leaveCancelled(', 'function(').replace('beforeAppear(', 'function(') + .replace('appear(', 'function(').replace('afterAppear(', 'function(').replace('appearCancelled(', 'function(') %> async function createApp (ssrContext) { @@ -55,7 +56,7 @@ async function createApp (ssrContext) { const app = { router, <% if (store) { %>store,<% } %> - _nuxt: { + nuxt: { defaultTransition, transitions: [ defaultTransition ], setTransitions (transitions) { @@ -72,29 +73,30 @@ async function createApp (ssrContext) { } return transition }) - this.$options._nuxt.transitions = transitions + this.$options.nuxt.transitions = transitions return transitions }, err: null, dateErr: null, error (err) { err = err || null - if (typeof err === 'string') { - err = { statusCode: 500, message: err } - } - const _nuxt = this._nuxt || this.$options._nuxt - _nuxt.dateErr = Date.now() - _nuxt.err = err + if (typeof err === 'string') err = { statusCode: 500, message: err } + const nuxt = this.nuxt || this.$options.nuxt + nuxt.dateErr = Date.now() + nuxt.err = err + // Used in lib/server.js + if (ssrContext) ssrContext.nuxt.error = err return err } }, ...App } <% if (store) { %> - // Make app available in store + // Make app available into store via this.app store.app = app <% } %> const next = ssrContext ? ssrContext.next : location => app.router.push(location) + // Resolve route let route if (ssrContext) { route = router.resolve(ssrContext.url).route @@ -102,17 +104,19 @@ async function createApp (ssrContext) { const path = getLocation(router.options.base) route = router.resolve(path).route } - const ctx = getContext({ + + // Set context to app.context + await setContext(app, { isServer: !!ssrContext, isClient: !ssrContext, route, next, - error: app._nuxt.error.bind(app), - <% if (store) { %>store,<% } %> + error: app.nuxt.error.bind(app), + <% if (store) { %>store,<% } %> req: ssrContext ? ssrContext.req : undefined, res: ssrContext ? ssrContext.res : undefined, beforeRenderFns: ssrContext ? ssrContext.beforeRenderFns : undefined - }, app) + }) const inject = function (key, value) { if (!key) throw new Error('inject(key, value) has no key provided') @@ -120,11 +124,12 @@ async function createApp (ssrContext) { key = '$' + key // Add into app app[key] = value - // Add into vm + // Check if plugin not already installed + const installKey = '__nuxt_' + key + '_installed__' + if (Vue[installKey]) return + Vue[installKey] = true + // Call Vue.use() to install the plugin into vm Vue.use(() => { - const installKey = '__nuxt_' + key + '_installed__' - if (Vue[installKey]) return - Vue[installKey] = true if (!Vue.prototype.hasOwnProperty(key)) { Object.defineProperty(Vue.prototype, key, { get () { @@ -148,16 +153,15 @@ async function createApp (ssrContext) { } <% } %> + // Plugin execution <% plugins.filter(p => p.ssr).forEach(plugin => { %> - if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(ctx, inject)<% }) %> + if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(app.context, inject)<% }) %> <% if (plugins.filter(p => !p.ssr).length) { %> if (process.browser) { <% plugins.filter(p => !p.ssr).forEach(plugin => { %> - if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(ctx, inject)<% }) %> + if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(app.context, inject)<% }) %> }<% } %> - // Inject context - inject('ctx', ctx) - + // If server-side, wait for async component to be resolved first if (process.server && ssrContext && ssrContext.url) { await new Promise((resolve, reject) => { router.push(ssrContext.url, resolve, reject) diff --git a/lib/app/server.js b/lib/app/server.js index 01c62be7e6..427633defc 100644 --- a/lib/app/server.js +++ b/lib/app/server.js @@ -13,11 +13,11 @@ const isDev = <%= isDev %> const noopApp = () => new Vue({ render: (h) => h('div') }) -const createNext = context => opts => { - context.redirected = opts +const createNext = ssrContext => opts => { + ssrContext.redirected = opts // If nuxt generate - if (!context.res) { - context.nuxt.serverRendered = false + if (!ssrContext.res) { + ssrContext.nuxt.serverRendered = false return } opts.query = stringify(opts.query) @@ -26,14 +26,14 @@ const createNext = context => opts => { opts.path = urlJoin('<%= router.base %>', opts.path) } // Avoid loop redirect - if (opts.path === context.url) { - context.redirected = false + if (opts.path === ssrContext.url) { + ssrContext.redirected = false return } - context.res.writeHead(opts.status, { + ssrContext.res.writeHead(opts.status, { 'Location': opts.path }) - context.res.end() + ssrContext.res.end() } // This exported function will be called by `bundleRenderer`. @@ -41,137 +41,142 @@ const createNext = context => opts => { // state of our application before actually rendering it. // Since data fetching is async, this function is expected to // return a Promise that resolves to the app instance. -export default async context => { - // Create context.next for simulate next() of beforeEach() when wanted to redirect - context.redirected = false - context.next = createNext(context) - context.beforeRenderFns = [] +export default async ssrContext => { + // Create ssrContext.next for simulate next() of beforeEach() when wanted to redirect + ssrContext.redirected = false + ssrContext.next = createNext(ssrContext) + // Used for beforeNuxtRender({ Components, nuxtState }) + ssrContext.beforeRenderFns = [] - const { app, router<%= (store ? ', store' : '') %> } = await createApp(context) + // Create the app definition and the instance (created for each request) + const { app, router<%= (store ? ', store' : '') %> } = await createApp(ssrContext) const _app = new Vue(app) - <% if (store) { %> - // Add store to the context - context.store = store - <% } %> + // Nuxt object (window.__NUXT__) + ssrContext.nuxt = { layout: 'default', data: [], error: null<%= (store ? ', state: null' : '') %>, serverRendered: true } + // Add meta infos (used in renderer.js) + ssrContext.meta = _app.$meta() + // Keep asyncData for each matched component in ssrContext (used in app/utils.js via this.$ssrContext) + ssrContext.asyncData = {} - // Add route to the context - context.route = router.currentRoute - - // Nuxt object - context.nuxt = { layout: 'default', data: [], error: null<%= (store ? ', state: null' : '') %>, serverRendered: true } - - // Add meta infos - context.meta = _app.$meta() - - // Error function - context.error = _app.$options._nuxt.error.bind(_app) - - // Keep asyncData for each matched component in context - context.asyncData = {} - - // Create shared ctx - const ctx = getContext(context, app) + const beforeRender = async () => { + // Call beforeNuxtRender() methods + await Promise.all(ssrContext.beforeRenderFns.map((fn) => promisify(fn, { Components, nuxtState: ssrContext.nuxt }))) + <% if (store) { %> + // Add the state from the vuex store + ssrContext.nuxt.state = store.state + <% } %> + } + const renderErrorPage = async () => { + // Load layout for error page + let errLayout = (typeof NuxtError.layout === 'function' ? NuxtError.layout(app.context) : NuxtError.layout) + ssrContext.nuxt.layout = errLayout || '' + await _app.loadLayout(errLayout) + _app.setLayout(errLayout) + await beforeRender() + return _app + } + const render404Page = async () => { + app.context.error({ statusCode: 404, message: '<%= messages.error_404 %>' }) + return await renderErrorPage() + } <% if (isDev) { %>const s = isDev && Date.now()<% } %> - // Resolve components - let Components = [] - try { - Components = await Promise.all(getMatchedComponents(router.match(context.url)).map(Component => { - if (typeof Component !== 'function' || Component.cid) { - return sanitizeComponent(Component) - } - return Component().then(Component => sanitizeComponent(Component)) - })) - } catch (err) { - // Throw back error to renderRoute() - throw err - } + // Components are already resolved by setContext -> getRouteData (app/utils.js) + const Components = getMatchedComponents(router.match(ssrContext.url)) <% if (store) { %> - // Dispatch store nuxtServerInit + /* + ** Dispatch store nuxtServerInit + */ if (store._actions && store._actions.nuxtServerInit) { - await store.dispatch('nuxtServerInit', ctx) + await store.dispatch('nuxtServerInit', app.context) } - // ...If there is a redirect - if (context.redirected) return noopApp() + // ...If there is a redirect or an error, stop the process + if (ssrContext.redirected) return noopApp() + if (ssrContext.nuxt.error) return await renderErrorPage() <% } %> - // Call global middleware (nuxt.config.js) + /* + ** Call global middleware (nuxt.config.js) + */ let midd = <%= serialize(router.middleware, { isJSON: true }) %> midd = midd.map((name) => { if (typeof middleware[name] !== 'function') { - context.nuxt.error = context.error({ statusCode: 500, message: 'Unknown middleware ' + name }) + ssrContext.error({ statusCode: 500, message: 'Unknown middleware ' + name }) } return middleware[name] }) - if (!context.nuxt.error) { - await middlewareSeries(midd, ctx) - } - // ...If there is a redirect - if (context.redirected) return noopApp() + await middlewareSeries(midd, app.context) + // ...If there is a redirect or an error, stop the process + if (ssrContext.redirected) return noopApp() + if (ssrContext.nuxt.error) return await renderErrorPage() - // Set layout + /* + ** Set layout + */ let layout = Components.length ? Components[0].options.layout : NuxtError.layout - if (typeof layout === 'function') layout = layout(ctx) + if (typeof layout === 'function') layout = layout(app.context) await _app.loadLayout(layout) layout = _app.setLayout(layout) // ...Set layout to __NUXT__ - context.nuxt.layout = _app.layoutName + ssrContext.nuxt.layout = _app.layoutName - // Call middleware (layout + pages) - if (!context.nuxt.error) { - midd = [] - if (layout.middleware) midd = midd.concat(layout.middleware) - Components.forEach((Component) => { - if (Component.options.middleware) { - midd = midd.concat(Component.options.middleware) - } - }) - midd = midd.map((name) => { - if (typeof middleware[name] !== 'function') { - context.nuxt.error = context.error({ statusCode: 500, message: 'Unknown middleware ' + name }) - } - return middleware[name] - }) + /* + ** Call middleware (layout + pages) + */ + midd = [] + if (layout.middleware) midd = midd.concat(layout.middleware) + Components.forEach((Component) => { + if (Component.options.middleware) { + midd = midd.concat(Component.options.middleware) + } + }) + midd = midd.map((name) => { + if (typeof middleware[name] !== 'function') { + app.context.error({ statusCode: 500, message: 'Unknown middleware ' + name }) + } + return middleware[name] + }) + await middlewareSeries(midd, app.context) + // ...If there is a redirect or an error, stop the process + if (ssrContext.redirected) return noopApp() + if (ssrContext.nuxt.error) return await renderErrorPage() - await middlewareSeries(midd, ctx) - - // If there is a redirect - if (context.redirected) return noopApp() - } - - // Call .validate() + /* + ** Call .validate() + */ let isValid = true Components.forEach((Component) => { if (!isValid) return if (typeof Component.options.validate !== 'function') return isValid = Component.options.validate({ - params: context.route.params || {}, - query: context.route.query || {}, - <%= (store ? 'store: ctx.store' : '') %> + params: app.context.route.params || {}, + query: app.context.route.query || {}, + <%= (store ? 'store' : '') %> }) }) // ...If .validate() returned false if (!isValid) { // Don't server-render the page in generate mode - if (context._generate) { - context.nuxt.serverRendered = false - } - // Call the 404 error by making the Components array empty - Components = [] + if (ssrContext._generate) ssrContext.nuxt.serverRendered = false + // Render a 404 error page + return render404Page() } + // If no Components found, returns 404 + if (!Components.length) return render404Page() + // Call asyncData & fetch hooks on components matched by the route. let asyncDatas = await Promise.all(Components.map(Component => { let promises = [] // Call asyncData(context) if (Component.options.asyncData && typeof Component.options.asyncData === 'function') { - let promise = promisify(Component.options.asyncData, ctx) + let promise = promisify(Component.options.asyncData, app.context) promise.then(asyncDataResult => { - context.asyncData[Component.cid] = asyncDataResult + ssrContext.asyncData[Component.cid] = asyncDataResult applyAsyncData(Component) return asyncDataResult }) @@ -182,7 +187,7 @@ export default async context => { // Call fetch(context) if (Component.options.fetch) { - promises.push(Component.options.fetch(ctx)) + promises.push(Component.options.fetch(app.context)) } else { promises.push(null) @@ -191,38 +196,17 @@ export default async context => { return Promise.all(promises) })) - // If no Components found, returns 404 - if (!Components.length) { - context.nuxt.error = context.error({ statusCode: 404, message: '<%= messages.error_404 %>' }) - } - - <% if (isDev) { %>if (asyncDatas.length) debug('Data fetching ' + context.url + ': ' + (Date.now() - s) + 'ms')<% } %> + <% if (isDev) { %>if (asyncDatas.length) debug('Data fetching ' + ssrContext.url + ': ' + (Date.now() - s) + 'ms')<% } %> // datas are the first row of each - context.nuxt.data = asyncDatas.map(r => r[0] || {}) + ssrContext.nuxt.data = asyncDatas.map(r => r[0] || {}) - // If an error occured in the execution - if (_app.$options._nuxt.err) { - context.nuxt.error = _app.$options._nuxt.err - } - - <% if (store) { %> - // Add the state from the vuex store - context.nuxt.state = store.state - <% } %> - - await Promise.all(context.beforeRenderFns.map((fn) => promisify(fn, { Components, nuxtState: context.nuxt }))) - - // If no error, return main app - if (!context.nuxt.error) { - return _app - } - - // Load layout for error page - layout = (typeof NuxtError.layout === 'function' ? NuxtError.layout(ctx) : NuxtError.layout) - context.nuxt.layout = layout || '' - await _app.loadLayout(layout) - _app.setLayout(layout) + // ...If there is a redirect or an error, stop the process + if (ssrContext.redirected) return noopApp() + if (ssrContext.nuxt.error) return await renderErrorPage() + // Call beforeNuxtRender methods & add store state + await beforeRender() + return _app } diff --git a/lib/app/utils.js b/lib/app/utils.js index d98304dd73..bffc4fba74 100644 --- a/lib/app/utils.js +++ b/lib/app/utils.js @@ -11,7 +11,7 @@ if (process.browser) { } } -export function applyAsyncData (Component, asyncData) { +export function applyAsyncData(Component, asyncData) { const ComponentData = Component.options.data || noopData // Prevent calling this method for each request on SSR context if (!asyncData && Component.options.hasAsyncData) { @@ -30,7 +30,11 @@ export function applyAsyncData (Component, asyncData) { } } -export function sanitizeComponent (Component) { +export function sanitizeComponent(Component) { + // If Component already sanitized + if (Component.options && Component._Ctor === Component) { + return Component + } if (!Component.options) { Component = Vue.extend(Component) // fix issue #6 Component._Ctor = Component @@ -45,7 +49,7 @@ export function sanitizeComponent (Component) { return Component } -export function getMatchedComponents (route) { +export function getMatchedComponents(route) { return [].concat.apply([], route.matched.map(function (m) { return Object.keys(m.components).map(function (key) { return m.components[key] @@ -53,7 +57,7 @@ export function getMatchedComponents (route) { })) } -export function getMatchedComponentsInstances (route) { +export function getMatchedComponentsInstances(route) { return [].concat.apply([], route.matched.map(function (m) { return Object.keys(m.instances).map(function (key) { return m.instances[key] @@ -61,7 +65,7 @@ export function getMatchedComponentsInstances (route) { })) } -export function flatMapComponents (route, fn) { +export function flatMapComponents(route, fn) { return Array.prototype.concat.apply([], route.matched.map(function (m, index) { return Object.keys(m.components).map(function (key) { return fn(m.components[key], m.instances[key], m, key, index) @@ -69,53 +73,79 @@ export function flatMapComponents (route, fn) { })) } -export function getContext (context, app) { - let ctx = { - isServer: !!context.isServer, - isClient: !!context.isClient, - isStatic: process.static, - isDev: <%= isDev %>, - isHMR: context.isHMR || false, - app: app, - <%= (store ? 'store: context.store,' : '') %> - route: (context.to ? context.to : context.route), - payload: context.payload, - error: context.error, - base: '<%= router.base %>', - env: <%= JSON.stringify(env) %> - } - const next = context.next - ctx.params = ctx.route.params || {} - ctx.query = ctx.route.query || {} - ctx.redirect = function (status, path, query) { - if (!status) return - ctx._redirected = true // Used in middleware - // if only 1 or 2 arguments: redirect('/') or redirect('/', { foo: 'bar' }) - if (typeof status === 'string' && (typeof path === 'undefined' || typeof path === 'object')) { - query = path || {} - path = status - status = 302 - } - next({ - path: path, - query: query, - status: status +export async function resolveRouteComponents(route) { + await Promise.all( + flatMapComponents(route, async (Component, _, match, key) => { + // If component is a function, resolve it + if (typeof Component === 'function' && !Component.options) { + Component = await Component() + } + return match.components[key] = sanitizeComponent(Component) }) - } - if (context.req) ctx.req = context.req - if (context.res) ctx.res = context.res - if (context.from) ctx.from = context.from - if (ctx.isServer && context.beforeRenderFns) { - ctx.beforeNuxtRender = (fn) => context.beforeRenderFns.push(fn) - } - if (ctx.isClient && window.__NUXT__) { - ctx.nuxtState = window.__NUXT__ - } - return ctx + ) } -export function middlewareSeries (promises, context) { - if (!promises.length || context._redirected) { +async function getRouteData(route) { + // Make sure the components are resolved (code-splitting) + await resolveRouteComponents(route) + // Send back a copy of route with meta based on Component definition + return { + ...route, + meta: getMatchedComponents(route).map((Component) => { + return Component.options.meta || {} + }) + } +} + +export async function setContext(app, context) { + const route = (context.to ? context.to : context.route) + // If context not defined, create it + if (!app.context) { + app.context = { + isServer: !!context.isServer, + isClient: !!context.isClient, + isStatic: process.static, + isDev: <%= isDev %>, + isHMR: false, + app, + <%= (store ? 'store: app.store,' : '') %> + payload: context.payload, + error: context.error, + base: '<%= router.base %>', + env: <%= JSON.stringify(env) %> + } + // Only set once + if (context.req) app.context.req = context.req + if (context.res) app.context.res = context.res + app.context.redirect = function (status, path, query) { + if (!status) return + ctx._redirected = true // Used in middleware + // if only 1 or 2 arguments: redirect('/') or redirect('/', { foo: 'bar' }) + if (typeof status === 'string' && (typeof path === 'undefined' || typeof path === 'object')) { + query = path || {} + path = status + status = 302 + } + app.context.next({ + path: path, + query: query, + status: status + }) + } + if (app.context.isServer) app.context.beforeNuxtRender = (fn) => context.beforeRenderFns.push(fn) + if (app.context.isClient) app.context.nuxtState = window.__NUXT__ + } + // Dynamic keys + app.context.next = context.next + app.context.isHMR = !!context.isHMR + if (context.route) app.context.route = await getRouteData(context.route) + app.context.params = app.context.route.params || {} + app.context.query = app.context.route.query || {} + if (context.from) app.context.from = await getRouteData(context.from) +} + +export function middlewareSeries(promises, appContext) { + if (!promises.length || appContext._redirected || appContext.app.nuxt.err) { return Promise.resolve() } return promisify(promises[0], context) @@ -124,7 +154,7 @@ export function middlewareSeries (promises, context) { }) } -export function promisify (fn, context) { +export function promisify(fn, context) { let promise if (fn.length === 2) { // fn(context, callback) @@ -147,7 +177,7 @@ export function promisify (fn, context) { } // Imported from vue-router -export function getLocation (base, mode) { +export function getLocation(base, mode) { var path = window.location.pathname if (mode === 'hash') { return window.location.hash.replace(/^#\//, '') @@ -158,7 +188,7 @@ export function getLocation (base, mode) { return (path || '/') + window.location.search + window.location.hash } -export function urlJoin () { +export function urlJoin() { return [].slice.call(arguments).join('/').replace(/\/+/g, '/') } @@ -171,7 +201,7 @@ export function urlJoin () { * @param {Object=} options * @return {!function(Object=, Object=)} */ -export function compile (str, options) { +export function compile(str, options) { return tokensToFunction(parse(str, options)) } @@ -200,7 +230,7 @@ const PATH_REGEXP = new RegExp([ * @param {Object=} options * @return {!Array} */ -function parse (str, options) { +function parse(str, options) { var tokens = [] var key = 0 var index = 0 @@ -272,7 +302,7 @@ function parse (str, options) { * @param {string} * @return {string} */ -function encodeURIComponentPretty (str) { +function encodeURIComponentPretty(str) { return encodeURI(str).replace(/[\/?#]/g, function (c) { return '%' + c.charCodeAt(0).toString(16).toUpperCase() }) @@ -284,7 +314,7 @@ function encodeURIComponentPretty (str) { * @param {string} * @return {string} */ -function encodeAsterisk (str) { +function encodeAsterisk(str) { return encodeURI(str).replace(/[?#]/g, function (c) { return '%' + c.charCodeAt(0).toString(16).toUpperCase() }) @@ -293,7 +323,7 @@ function encodeAsterisk (str) { /** * Expose a method for transforming tokens into the path function. */ -function tokensToFunction (tokens) { +function tokensToFunction(tokens) { // Compile all the tokens into regexps. var matches = new Array(tokens.length) @@ -304,7 +334,7 @@ function tokensToFunction (tokens) { } } - return function (obj, opts) { + return function(obj, opts) { var path = '' var data = obj || {} var options = opts || {} @@ -380,7 +410,7 @@ function tokensToFunction (tokens) { * @param {string} str * @return {string} */ -function escapeString (str) { +function escapeString(str) { return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1') } @@ -390,6 +420,6 @@ function escapeString (str) { * @param {string} group * @return {string} */ -function escapeGroup (group) { +function escapeGroup(group) { return group.replace(/([=!:$\/()])/g, '\\$1') } diff --git a/lib/builder/builder.js b/lib/builder/builder.js index acffbfe671..fb543a95e6 100644 --- a/lib/builder/builder.js +++ b/lib/builder/builder.js @@ -184,7 +184,7 @@ export default class Builder extends Tapable { debug('Generating files...') // -- Templates -- let templatesFiles = [ - 'App.vue', + 'App.js', 'client.js', 'index.js', 'middleware.js', @@ -196,7 +196,7 @@ export default class Builder extends Tapable { 'components/nuxt-loading.vue', 'components/nuxt-child.js', 'components/nuxt-link.js', - 'components/nuxt.vue', + 'components/nuxt.js', 'components/no-ssr.js', 'views/app.template.html', 'views/error.html' @@ -215,7 +215,7 @@ export default class Builder extends Tapable { store: this.options.store, css: this.options.css, plugins: this.plugins, - appPath: './App.vue', + appPath: './App.js', layouts: Object.assign({}, this.options.layouts), loading: typeof this.options.loading === 'string' ? this.relativeToBuild(this.options.srcDir, this.options.loading) : this.options.loading, transition: this.options.transition,