@nuxt/vue-app
Advanced tools
Comparing version 2.9.2 to 2.10.0
/*! | ||
* @nuxt/vue-app v2.9.2 (c) 2016-2019 | ||
* @nuxt/vue-app v2.10.0 (c) 2016-2019 | ||
@@ -21,3 +21,3 @@ * - All the amazing contributors | ||
"vue-client-only": "^2.0.0", | ||
"vue-meta": "^2.2.1", | ||
"vue-meta": "^2.2.2", | ||
"vue-no-ssr": "^1.1.1", | ||
@@ -36,3 +36,2 @@ "vue-router": "~3.0.7", | ||
'index.js', | ||
'middleware.js', | ||
'router.js', | ||
@@ -43,5 +42,3 @@ 'router.scrollBehavior.js', | ||
'empty.js', | ||
'components/nuxt-build-indicator.vue', | ||
'components/nuxt-error.vue', | ||
'components/nuxt-loading.vue', | ||
'components/nuxt-child.js', | ||
@@ -48,0 +45,0 @@ 'components/nuxt-link.server.js', |
// Dummy type definition file to provide backward compatibility | ||
// around Nuxt modules extending `@nuxt/vue-app` for Nuxt < 2.9 | ||
declare module "@nuxt/vue-app" |
{ | ||
"name": "@nuxt/vue-app", | ||
"version": "2.9.2", | ||
"version": "2.10.0", | ||
"repository": "nuxt/nuxt.js", | ||
@@ -19,3 +19,3 @@ "license": "MIT", | ||
"vue-client-only": "^2.0.0", | ||
"vue-meta": "^2.2.1", | ||
"vue-meta": "^2.2.2", | ||
"vue-no-ssr": "^1.1.1", | ||
@@ -22,0 +22,0 @@ "vue-router": "~3.0.7", |
import Vue from 'vue' | ||
import { getMatchedComponentsInstances, promisify, globalHandleError } from './utils' | ||
<% if (features.asyncData || features.fetch) { %> | ||
import { | ||
getMatchedComponentsInstances, | ||
promisify, | ||
globalHandleError | ||
} from './utils' | ||
<% } %> | ||
<% if (features.layouts && components.ErrorPage) { %>import NuxtError from '<%= components.ErrorPage %>'<% } %> | ||
<% if (loading) { %>import NuxtLoading from '<%= (typeof loading === "string" ? loading : "./components/nuxt-loading.vue") %>'<% } %> | ||
<%if (buildIndicator) { %>import NuxtBuildIndicator from './components/nuxt-build-indicator'<% } %> | ||
<% if (buildIndicator) { %>import NuxtBuildIndicator from './components/nuxt-build-indicator'<% } %> | ||
<% css.forEach((c) => { %> | ||
@@ -9,2 +16,3 @@ import '<%= relativeToBuild(resolvePath(c.src || c, { isStyle: true })) %>' | ||
<% if (features.layouts) { %> | ||
<%= Object.keys(layouts).map((key) => { | ||
@@ -21,9 +29,22 @@ if (splitChunks.layouts) { | ||
<% if (splitChunks.layouts) { %>let resolvedLayouts = {}<% } %> | ||
<% } %> | ||
export default { | ||
<%= isTest ? '/* eslint-disable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %> | ||
<% if (features.meta) { %> | ||
<%= isTest ? '/* eslint-disable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren, object-shorthand */' : '' %> | ||
head: <%= serializeFunction(head) %>, | ||
<%= isTest ? '/* eslint-enable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %> | ||
render(h, props) { | ||
<%= isTest ? '/* eslint-enable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren, object-shorthand */' : '' %> | ||
<% } %> | ||
render (h, props) { | ||
<% if (loading) { %>const loadingEl = h('NuxtLoading', { ref: 'loading' })<% } %> | ||
<% if (features.layouts) { %> | ||
<% if (components.ErrorPage) { %> | ||
if (this.nuxt.err && NuxtError.layout) { | ||
this.setLayout( | ||
typeof NuxtError.layout === 'function' | ||
? NuxtError.layout(this.context) | ||
: NuxtError.layout | ||
) | ||
} | ||
<% } %> | ||
const layoutEl = h(this.layout || 'nuxt') | ||
@@ -36,3 +57,7 @@ const templateEl = h('div', { | ||
}, [ layoutEl ]) | ||
<% } else { %> | ||
const templateEl = h('nuxt') | ||
<% } %> | ||
<% if (features.transitions) { %> | ||
const transitionEl = h('transition', { | ||
@@ -44,3 +69,3 @@ props: { | ||
on: { | ||
beforeEnter(el) { | ||
beforeEnter (el) { | ||
// Ensure to trigger scroll event after calling scrollBehavior | ||
@@ -53,2 +78,3 @@ window.<%= globals.nuxt %>.$nextTick(() => { | ||
}, [ templateEl ]) | ||
<% } %> | ||
@@ -59,13 +85,23 @@ return h('div', { | ||
} | ||
}, [<% if (loading) { %>loadingEl, <% } %><%if (buildIndicator) { %>h(NuxtBuildIndicator), <% } %>transitionEl]) | ||
}, [ | ||
<% if (loading) { %>loadingEl, <% } %> | ||
<% if (buildIndicator) { %>h(NuxtBuildIndicator), <% } %> | ||
<% if (features.transitions) { %>transitionEl<% } else { %>templateEl<% } %> | ||
]) | ||
}, | ||
<% if (features.clientOnline || features.layouts) { %> | ||
data: () => ({ | ||
<% if (features.clientOnline) { %> | ||
isOnline: true, | ||
<% } %> | ||
<% if (features.layouts) { %> | ||
layout: null, | ||
layoutName: '' | ||
<% } %> | ||
}), | ||
beforeCreate() { | ||
<% } %> | ||
beforeCreate () { | ||
Vue.util.defineReactive(this, 'nuxt', this.$options.nuxt) | ||
}, | ||
created() { | ||
created () { | ||
// Add this.$nuxt in child instances | ||
@@ -76,2 +112,3 @@ Vue.prototype.<%= globals.nuxt %> = this | ||
window.<%= globals.nuxt %> = <%= (globals.nuxt !== '$nuxt' ? 'window.$nuxt = ' : '') %>this | ||
<% if (features.clientOnline) { %> | ||
this.refreshOnlineStatus() | ||
@@ -81,2 +118,3 @@ // Setup the listeners | ||
window.addEventListener('offline', this.refreshOnlineStatus) | ||
<% } %> | ||
} | ||
@@ -89,3 +127,3 @@ // Add $nuxt.error() | ||
<% if (loading) { %> | ||
mounted() { | ||
mounted () { | ||
this.$loading = this.$refs.loading | ||
@@ -97,9 +135,13 @@ }, | ||
<% } %> | ||
<% if (features.clientOnline) { %> | ||
computed: { | ||
isOffline() { | ||
isOffline () { | ||
return !this.isOnline | ||
} | ||
}, | ||
<% } %> | ||
methods: { | ||
refreshOnlineStatus() { | ||
<%= isTest ? '/* eslint-disable comma-dangle */' : '' %> | ||
<% if (features.clientOnline) { %> | ||
refreshOnlineStatus () { | ||
if (process.client) { | ||
@@ -116,3 +158,5 @@ if (typeof window.navigator.onLine === 'undefined') { | ||
}, | ||
async refresh() { | ||
<% } %> | ||
async refresh () { | ||
<% if (features.asyncData || features.fetch) { %> | ||
const pages = getMatchedComponentsInstances(this.$route) | ||
@@ -124,8 +168,12 @@ | ||
<% if (loading) { %>this.$loading.start()<% } %> | ||
const promises = pages.map(async (page) => { | ||
const promises = pages.map((page) => { | ||
const p = [] | ||
<% if (features.fetch) { %> | ||
if (page.$options.fetch) { | ||
p.push(promisify(page.$options.fetch, this.context)) | ||
} | ||
<% } %> | ||
<% if (features.asyncData) { %> | ||
if (page.$options.asyncData) { | ||
@@ -141,2 +189,3 @@ p.push( | ||
} | ||
<% } %> | ||
return Promise.all(p) | ||
@@ -152,17 +201,27 @@ }) | ||
<% if (loading) { %>this.$loading.finish()<% } %> | ||
<% } %> | ||
}, | ||
<% if (loading) { %> | ||
errorChanged() { | ||
errorChanged () { | ||
if (this.nuxt.err && this.$loading) { | ||
if (this.$loading.fail) this.$loading.fail() | ||
if (this.$loading.finish) this.$loading.finish() | ||
if (this.$loading.fail) { | ||
this.$loading.fail() | ||
} | ||
if (this.$loading.finish) { | ||
this.$loading.finish() | ||
} | ||
} | ||
}, | ||
<% } %> | ||
<% if (features.layouts) { %> | ||
<% if (splitChunks.layouts) { %> | ||
setLayout(layout) { | ||
setLayout (layout) { | ||
<% if (debug) { %> | ||
if(layout && typeof layout !== 'string') throw new Error('[nuxt] Avoid using non-string value as layout property.') | ||
if(layout && typeof layout !== 'string') { | ||
throw new Error('[nuxt] Avoid using non-string value as layout property.') | ||
} | ||
<% } %> | ||
if (!layout || !resolvedLayouts['_' + layout]) layout = 'default' | ||
if (!layout || !resolvedLayouts['_' + layout]) { | ||
layout = 'default' | ||
} | ||
this.layoutName = layout | ||
@@ -173,3 +232,3 @@ let _layout = '_' + layout | ||
}, | ||
loadLayout(layout) { | ||
loadLayout (layout) { | ||
const undef = !layout | ||
@@ -194,5 +253,7 @@ const nonexistent = !(layouts['_' + layout] || resolvedLayouts['_' + layout]) | ||
<% } else { %> | ||
setLayout(layout) { | ||
setLayout (layout) { | ||
<% if (debug) { %> | ||
if(layout && typeof layout !== 'string') throw new Error('[nuxt] Avoid using non-string value as layout property.') | ||
if(layout && typeof layout !== 'string') { | ||
throw new Error('[nuxt] Avoid using non-string value as layout property.') | ||
} | ||
<% } %> | ||
@@ -206,3 +267,3 @@ if (!layout || !layouts['_' + layout]) { | ||
}, | ||
loadLayout(layout) { | ||
loadLayout (layout) { | ||
if (!layout || !layouts['_' + layout]) { | ||
@@ -213,7 +274,11 @@ layout = 'default' | ||
} | ||
<% } %> | ||
<% } /* splitChunks.layouts */ %> | ||
<% } /* features.layouts */ %> | ||
}, | ||
<% if (loading) { %> | ||
components: { | ||
<%= (loading ? 'NuxtLoading' : '') %> | ||
NuxtLoading | ||
} | ||
<% } %> | ||
<%= isTest ? '/* eslint-enable comma-dangle */' : '' %> | ||
} |
import Vue from 'vue' | ||
<% if (fetch.client) { %>import fetch from 'unfetch'<% } %> | ||
import middleware from './middleware.js' | ||
<% if (features.middleware) { %>import middleware from './middleware.js'<% } %> | ||
import { | ||
applyAsyncData, | ||
sanitizeComponent, | ||
resolveRouteComponents, | ||
<% if (features.asyncData) { %>applyAsyncData, | ||
promisify,<% } %> | ||
<% if (features.middleware) { %>middlewareSeries,<% } %> | ||
<% if (features.transitions || (features.middleware && features.layouts)) { %>sanitizeComponent,<% } %> | ||
<% if (loading) { %>resolveRouteComponents,<% } %> | ||
getMatchedComponents, | ||
@@ -12,5 +14,3 @@ getMatchedComponentsInstances, | ||
setContext, | ||
middlewareSeries, | ||
promisify, | ||
getLocation, | ||
<% if (features.transitions || features.asyncData || features.fetch) { %>getLocation,<% } %> | ||
compile, | ||
@@ -20,4 +20,4 @@ getQueryDiff, | ||
} from './utils.js' | ||
import { createApp, NuxtError } from './index.js' | ||
import NuxtLink from './components/nuxt-link.<%= router.prefetchLinks ? "client" : "server" %>.js' // should be included after ./index.js | ||
import { createApp<% if (features.layouts) { %>, NuxtError<% } %> } from './index.js' | ||
import NuxtLink from './components/nuxt-link.<%= features.clientPrefetch ? "client" : "server" %>.js' // should be included after ./index.js | ||
<% if (isDev) { %>import consola from 'consola'<% } %> | ||
@@ -31,3 +31,3 @@ | ||
Vue.component(NuxtLink.name, NuxtLink) | ||
Vue.component('NLink', NuxtLink) | ||
<% if (features.componentAliases) { %>Vue.component('NLink', NuxtLink)<% } %> | ||
@@ -37,3 +37,3 @@ <% if (fetch.client) { %>if (!global.fetch) { global.fetch = fetch }<% } %> | ||
// Global shared references | ||
let _lastPaths = [] | ||
let _lastPaths = []<%= isTest ? '// eslint-disable-line no-unused-vars' : '' %> | ||
let app | ||
@@ -101,3 +101,4 @@ let router | ||
function componentOption(component, key, ...args) { | ||
<% if (features.transitions) { %> | ||
function componentOption (component, key, ...args) { | ||
if (!component || !component.options || !component.options[key]) { | ||
@@ -113,3 +114,3 @@ return {} | ||
function mapTransitions(Components, to, from) { | ||
function mapTransitions (Components, to, from) { | ||
const componentTransitions = (component) => { | ||
@@ -135,4 +136,4 @@ const transition = componentOption(component, 'transition', to, from) || {} | ||
} | ||
async function loadAsyncComponents(to, from, next) { | ||
<% } %> | ||
<% if (loading) { %>async <% } %>function loadAsyncComponents (to, from, next) { | ||
// Check if route path changed (this._pathChanged), only if the page is not an error (for validate()) | ||
@@ -150,16 +151,18 @@ this._pathChanged = Boolean(app.nuxt.err) || from.path !== to.path | ||
try { | ||
const Components = await resolveRouteComponents( | ||
to, | ||
(Component, instance) => ({ Component, instance }) | ||
) | ||
<% if (loading) { %> | ||
if (!this._pathChanged && this._queryChanged) { | ||
const Components = await resolveRouteComponents( | ||
to, | ||
(Component, instance) => ({ Component, instance }) | ||
) | ||
// Add a marker on each component that it needs to refresh or not | ||
const startLoader = Components.some(({Component, instance}) => { | ||
const startLoader = Components.some(({ Component, instance }) => { | ||
const watchQuery = Component.options.watchQuery | ||
if (watchQuery === true) { | ||
return true | ||
} else if (Array.isArray(watchQuery)) { | ||
} | ||
if (Array.isArray(watchQuery)) { | ||
return watchQuery.some(key => this._diffQuery[key]) | ||
} else if (typeof watchQuery === 'function') { | ||
} | ||
if (typeof watchQuery === 'function') { | ||
return watchQuery.apply(instance, [to.query, from.query]) | ||
@@ -194,6 +197,9 @@ } | ||
function applySSRData(Component, ssrData) { | ||
<% if (features.transitions || features.asyncData || features.fetch) { %> | ||
function applySSRData (Component, ssrData) { | ||
<% if (features.asyncData) { %> | ||
if (NUXT.serverRendered && ssrData) { | ||
applyAsyncData(Component, ssrData) | ||
} | ||
<% } %> | ||
Component._Ctor = Component | ||
@@ -204,3 +210,3 @@ return Component | ||
// Get matched components | ||
function resolveComponents(router) { | ||
function resolveComponents (router) { | ||
const path = getLocation(router.options.base, router.options.mode) | ||
@@ -219,7 +225,10 @@ | ||
} | ||
<% } %> | ||
function callMiddleware(Components, context, layout) { | ||
<% if (features.middleware) { %> | ||
function callMiddleware (Components, context, layout) { | ||
let midd = <%= devalue(router.middleware) %><%= isTest ? '// eslint-disable-line' : '' %> | ||
let unknownMiddleware = false | ||
<% if (features.layouts) { %> | ||
// If layout is undefined, only call global middleware | ||
@@ -238,5 +247,8 @@ if (typeof layout !== 'undefined') { | ||
} | ||
<% } %> | ||
midd = midd.map((name) => { | ||
if (typeof name === 'function') return name | ||
if (typeof name === 'function') { | ||
return name | ||
} | ||
if (typeof middleware[name] !== 'function') { | ||
@@ -249,11 +261,23 @@ unknownMiddleware = true | ||
if (unknownMiddleware) return | ||
if (unknownMiddleware) { | ||
return | ||
} | ||
return middlewareSeries(midd, context) | ||
} | ||
async function render(to, from, next) { | ||
if (this._pathChanged === false && this._queryChanged === false) return next() | ||
<% } else if (isDev) { | ||
// This is a placeholder function mainly so we dont have to | ||
// refactor the promise chain in addHotReload() | ||
%> | ||
function callMiddleware () { | ||
return Promise.resolve(true) | ||
} | ||
<% } %> | ||
async function render (to, from, next) { | ||
if (this._pathChanged === false && this._queryChanged === false) { | ||
return next() | ||
} | ||
// Handle first render on SPA mode | ||
if (to === from) _lastPaths = [] | ||
else { | ||
if (to === from) { | ||
_lastPaths = [] | ||
} else { | ||
const fromMatches = [] | ||
@@ -278,3 +302,6 @@ _lastPaths = getMatchedComponents(from, fromMatches).map((Component, i) => { | ||
<% } %> | ||
if (nextCalled) return | ||
if (nextCalled) { | ||
return | ||
} | ||
nextCalled = true | ||
@@ -299,5 +326,11 @@ next(path) | ||
if (!Components.length) { | ||
<% if (features.middleware) { %> | ||
// Default layout | ||
await callMiddleware.call(this, Components, app.context) | ||
if (nextCalled) return | ||
if (nextCalled) { | ||
return | ||
} | ||
<% } %> | ||
<% if (features.layouts) { %> | ||
// Load layout for error page | ||
@@ -309,4 +342,11 @@ const layout = await this.loadLayout( | ||
) | ||
<% } %> | ||
<% if (features.middleware) { %> | ||
await callMiddleware.call(this, Components, app.context, layout) | ||
if (nextCalled) return | ||
if (nextCalled) { | ||
return | ||
} | ||
<% } %> | ||
// Show error page | ||
@@ -317,19 +357,29 @@ app.context.error({ statusCode: 404, message: `<%= messages.error_404 %>` }) | ||
<% if (features.asyncData || features.fetch) { %> | ||
// Update ._data and other properties if hot reloaded | ||
Components.forEach((Component) => { | ||
if (Component._Ctor && Component._Ctor.options) { | ||
Component.options.asyncData = Component._Ctor.options.asyncData | ||
Component.options.fetch = Component._Ctor.options.fetch | ||
<% if (features.asyncData) { %>Component.options.asyncData = Component._Ctor.options.asyncData<% } %> | ||
<% if (features.fetch) { %>Component.options.fetch = Component._Ctor.options.fetch<% } %> | ||
} | ||
}) | ||
<% } %> | ||
<% if (features.transitions) { %> | ||
// Apply transitions | ||
this.setTransitions(mapTransitions(Components, to, from)) | ||
<% } %> | ||
try { | ||
<% if (features.middleware) { %> | ||
// Call middleware | ||
await callMiddleware.call(this, Components, app.context) | ||
if (nextCalled) return | ||
if (app.context._errored) return next() | ||
if (nextCalled) { | ||
return | ||
} | ||
if (app.context._errored) { | ||
return next() | ||
} | ||
<% } %> | ||
<% if (features.layouts) { %> | ||
// Set layout | ||
@@ -341,8 +391,17 @@ let layout = Components[0].options.layout | ||
layout = await this.loadLayout(layout) | ||
<% } %> | ||
<% if (features.middleware) { %> | ||
// Call middleware for layout | ||
await callMiddleware.call(this, Components, app.context, layout) | ||
if (nextCalled) return | ||
if (app.context._errored) return next() | ||
if (nextCalled) { | ||
return | ||
} | ||
if (app.context._errored) { | ||
return next() | ||
} | ||
<% } %> | ||
<% if (features.validate) { %> | ||
// Call .validate() | ||
@@ -376,3 +435,6 @@ let isValid = true | ||
} | ||
<% } %> | ||
<% if (features.asyncData || features.fetch) { %> | ||
let instances | ||
// Call asyncData & fetch hooks on components matched by the route. | ||
@@ -393,6 +455,11 @@ await Promise.all(Components.map((Component, i) => { | ||
Component._dataRefresh = watchQuery.some(key => this._diffQuery[key]) | ||
} else if (typeof watchQuery === 'function') { | ||
if (!instances) { | ||
instances = getMatchedComponentsInstances(to) | ||
} | ||
Component._dataRefresh = watchQuery.apply(instances[i], [to.query, from.query]) | ||
} | ||
} | ||
if (!this._hadError && this._isMounted && !Component._dataRefresh) { | ||
return Promise.resolve() | ||
return | ||
} | ||
@@ -402,2 +469,3 @@ | ||
<% if (features.asyncData) { %> | ||
const hasAsyncData = ( | ||
@@ -407,3 +475,12 @@ Component.options.asyncData && | ||
) | ||
<% } else { %> | ||
const hasAsyncData = false | ||
<% } %> | ||
<% if (features.fetch) { %> | ||
const hasFetch = Boolean(Component.options.fetch) | ||
<% } else { %> | ||
const hasFetch = false | ||
<% } %> | ||
<% if (loading) { %> | ||
@@ -413,2 +490,3 @@ const loadingIncrease = (hasAsyncData && hasFetch) ? 30 : 45 | ||
<% if (features.asyncData) { %> | ||
// Call asyncData(context) | ||
@@ -427,2 +505,3 @@ if (hasAsyncData) { | ||
} | ||
<% } %> | ||
@@ -432,2 +511,3 @@ // Check disabled page loading | ||
<% if (features.fetch) { %> | ||
// Call fetch(context) | ||
@@ -448,5 +528,7 @@ if (hasFetch) { | ||
} | ||
<% } %> | ||
return Promise.all(promises) | ||
})) | ||
<% } %> | ||
@@ -472,2 +554,3 @@ // If not redirected | ||
<% if (features.layouts) { %> | ||
// Load error layout | ||
@@ -479,2 +562,3 @@ let layout = NuxtError.layout | ||
await this.loadLayout(layout) | ||
<% } %> | ||
@@ -488,3 +572,3 @@ this.error(error) | ||
// Fix components format in matched, it's due to code-splitting of vue-router | ||
function normalizeComponents(to, ___) { | ||
function normalizeComponents (to, ___) { | ||
flatMapComponents(to, (Component, _, match, key) => { | ||
@@ -501,3 +585,3 @@ if (typeof Component === 'object' && !Component.options) { | ||
function showNextPage(to) { | ||
function showNextPage (to) { | ||
// Hide error component if no error | ||
@@ -508,2 +592,3 @@ if (this._hadError && this._dateLastError === this.$options.nuxt.dateErr) { | ||
<% if (features.layouts) { %> | ||
// Set layout | ||
@@ -518,2 +603,3 @@ let layout = this.$options.nuxt.err | ||
this.setLayout(layout) | ||
<% } %> | ||
} | ||
@@ -523,17 +609,16 @@ | ||
// Will not update the instance data, so we have to update $data ourselves | ||
function fixPrepatch(to, ___) { | ||
if (this._pathChanged === false && this._queryChanged === false) return | ||
function fixPrepatch (to, ___) { | ||
if (this._pathChanged === false && this._queryChanged === false) { | ||
return | ||
} | ||
const matches = [] | ||
const instances = getMatchedComponentsInstances(to, matches) | ||
const Components = getMatchedComponents(to, matches) | ||
const instances = getMatchedComponentsInstances(to) | ||
const Components = getMatchedComponents(to) | ||
Vue.nextTick(() => { | ||
instances.forEach((instance, i) => { | ||
if (!instance || instance._isDestroyed) return | ||
// if ( | ||
// !this._queryChanged && | ||
// to.matched[matches[i]].path.indexOf(':') === -1 && | ||
// to.matched[matches[i]].path.indexOf('*') === -1 | ||
// ) return // If not a dynamic route, skip | ||
if (!instance || instance._isDestroyed) { | ||
return | ||
} | ||
if ( | ||
@@ -564,3 +649,3 @@ instance.constructor._dataRefresh && | ||
function nuxtReady(_app) { | ||
function nuxtReady (_app) { | ||
window.<%= globals.readyCallback %>Cbs.forEach((cb) => { | ||
@@ -587,3 +672,3 @@ if (typeof cb === 'function') { | ||
// Special hot reload with asyncData(context) | ||
function getNuxtChildComponents($parent, $components = []) { | ||
function getNuxtChildComponents ($parent, $components = []) { | ||
$parent.$children.forEach(($child) => { | ||
@@ -609,3 +694,3 @@ if ($child.$vnode && $child.$vnode.data.nuxtChild && !$components.find(c =>(c.$options.__file === $child.$options.__file))) { | ||
function addHotReload($component, depth) { | ||
function addHotReload ($component, depth) { | ||
if ($component.$vnode.data._hasHotReload) return | ||
@@ -619,3 +704,5 @@ $component.$vnode.data._hasHotReload = true | ||
let Component = Components[depth] | ||
if (!Component) return _forceUpdate() | ||
if (!Component) { | ||
return _forceUpdate() | ||
} | ||
if (typeof Component === 'object' && !Component.options) { | ||
@@ -638,9 +725,17 @@ // Updated via vue-router resolveAsyncComponents() | ||
const context = app.context | ||
<% if (loading) { %> | ||
if (this.$loading.start && !this.$loading.manual) this.$loading.start() | ||
if (this.$loading.start && !this.$loading.manual) { | ||
this.$loading.start() | ||
} | ||
<% } %> | ||
callMiddleware.call(this, Components, context) | ||
.then(() => { | ||
<% if (features.layouts) { %> | ||
// If layout changed | ||
if (depth !== 0) return Promise.resolve() | ||
if (depth !== 0) { | ||
return | ||
} | ||
let layout = Component.options.layout || 'default' | ||
@@ -650,3 +745,5 @@ if (typeof layout === 'function') { | ||
} | ||
if (this.layoutName === layout) return Promise.resolve() | ||
if (this.layoutName === layout) { | ||
return | ||
} | ||
let promise = this.loadLayout(layout) | ||
@@ -658,7 +755,13 @@ promise.then(() => { | ||
return promise | ||
<% } else { %> | ||
return | ||
<% } %> | ||
}) | ||
<% if (features.layouts) { %> | ||
.then(() => { | ||
return callMiddleware.call(this, Components, context, this.layout) | ||
}) | ||
<% } %> | ||
.then(() => { | ||
<% if (features.asyncData) { %> | ||
// Call asyncData(context) | ||
@@ -671,2 +774,5 @@ let pAsyncData = promisify(Component.options.asyncData || noopData, context) | ||
promises.push(pAsyncData) | ||
<% } %> | ||
<% if (features.fetch) { %> | ||
// Call fetch() | ||
@@ -678,2 +784,3 @@ Component.options.fetch = Component.options.fetch || noopFetch | ||
promises.push(pFetch) | ||
<% } %> | ||
return Promise.all(promises) | ||
@@ -690,3 +797,3 @@ }) | ||
async function mountApp(__app) { | ||
<% if (features.layouts || features.transitions) { %>async <% } %>function mountApp (__app) { | ||
// Set global variables | ||
@@ -697,9 +804,6 @@ app = __app.app | ||
// Resolve route components | ||
const Components = await Promise.all(resolveComponents(router)) | ||
// Create Vue instance | ||
const _app = new Vue(app) | ||
<% if (mode !== 'spa') { %> | ||
<% if (features.layouts && mode !== 'spa') { %> | ||
// Load layout | ||
@@ -729,2 +833,5 @@ const layout = NUXT.layout || 'default' | ||
} | ||
<% if (features.transitions) { %> | ||
// Resolve route components | ||
const Components = await Promise.all(resolveComponents(router)) | ||
@@ -737,6 +844,10 @@ // Enable transitions | ||
} | ||
<% } else if (features.asyncData || features.fetch) { %> | ||
await Promise.all(resolveComponents(router)) | ||
<% } %> | ||
// Initialize error handler | ||
_app.$loading = {} // To avoid error while _app.$nuxt does not exist | ||
if (NUXT.error) _app.error(NUXT.error) | ||
if (NUXT.error) { | ||
_app.error(NUXT.error) | ||
} | ||
@@ -777,5 +888,7 @@ // Add beforeEach router hooks | ||
router.push(path, undefined, (err) => { | ||
if (err) errorHandler(err) | ||
if (err) { | ||
errorHandler(err) | ||
} | ||
}) | ||
}) | ||
} |
@@ -16,3 +16,4 @@ <%= isTest ? '// @vue/component' : '' %> | ||
}, | ||
render(h, { parent, data, props }) { | ||
render (h, { parent, data, props }) { | ||
<% if (features.transitions) { %> | ||
data.nuxtChild = true | ||
@@ -73,3 +74,3 @@ const _parent = parent | ||
} | ||
<% } %> | ||
let routerView = h('routerView', data) | ||
@@ -81,2 +82,3 @@ | ||
<% if (features.transitions) { %> | ||
return h('transition', { | ||
@@ -86,5 +88,9 @@ props: transitionProps, | ||
}, [routerView]) | ||
<% } else { %> | ||
return routerView | ||
<% } %> | ||
} | ||
} | ||
<% if (features.transitions) { %> | ||
const transitionsKeys = [ | ||
@@ -123,1 +129,2 @@ 'name', | ||
] | ||
<% } %> |
@@ -9,8 +9,11 @@ import Vue from 'vue' | ||
didTimeout: false, | ||
timeRemaining: function () { | ||
return Math.max(0, 50 - (Date.now() - start)) | ||
} | ||
timeRemaining: () => Math.max(0, 50 - (Date.now() - start)) | ||
}) | ||
}, 1) | ||
} | ||
const cancelIdleCallback = window.cancelIdleCallback || function (id) { | ||
clearTimeout(id) | ||
} | ||
const observer = window.IntersectionObserver && new window.IntersectionObserver((entries) => { | ||
@@ -30,2 +33,6 @@ entries.forEach(({ intersectionRatio, target: link }) => { | ||
props: { | ||
prefetch: { | ||
type: Boolean, | ||
default: <%= router.prefetchLinks ? 'true' : 'false' %> | ||
}, | ||
noPrefetch: { | ||
@@ -40,8 +47,10 @@ type: Boolean, | ||
}, | ||
mounted() { | ||
if (!this.noPrefetch) { | ||
requestIdleCallback(this.observe, { timeout: 2e3 }) | ||
mounted () { | ||
if (this.prefetch && !this.noPrefetch) { | ||
this.handleId = requestIdleCallback(this.observe, { timeout: 2e3 }) | ||
} | ||
}, | ||
beforeDestroy() { | ||
beforeDestroy () { | ||
cancelIdleCallback(this.handleId) | ||
if (this.__observed) { | ||
@@ -53,3 +62,3 @@ observer.unobserve(this.$el) | ||
methods: { | ||
observe() { | ||
observe () { | ||
// If no IntersectionObserver, avoid prefetching | ||
@@ -61,3 +70,3 @@ if (!observer) { | ||
if (this.shouldPrefetch()) { | ||
this.$el.__prefetch = this.prefetch.bind(this) | ||
this.$el.__prefetch = this.prefetchLink.bind(this) | ||
observer.observe(this.$el) | ||
@@ -69,6 +78,6 @@ this.__observed = true | ||
}, | ||
shouldPrefetch() { | ||
shouldPrefetch () { | ||
return this.getPrefetchComponents().length > 0 | ||
}, | ||
canPrefetch() { | ||
canPrefetch () { | ||
const conn = navigator.connection | ||
@@ -79,3 +88,3 @@ const hasBadConnection = this.<%= globals.nuxt %>.isOffline || (conn && ((conn.effectiveType || '').includes('2g') || conn.saveData)) | ||
}, | ||
getPrefetchComponents() { | ||
getPrefetchComponents () { | ||
const ref = this.$router.resolve(this.to, this.$route, this.append) | ||
@@ -86,7 +95,7 @@ const Components = ref.resolved.matched.map(r => r.components.default) | ||
}, | ||
prefetch() { | ||
prefetchLink () { | ||
if (!this.canPrefetch()) { | ||
return | ||
} | ||
// Stop obersing this link (in case of internet connection changes) | ||
// Stop observing this link (in case of internet connection changes) | ||
observer.unobserve(this.$el) | ||
@@ -104,3 +113,3 @@ const Components = this.getPrefetchComponents() | ||
}<% if (router.linkPrefetchedClass) { %>, | ||
addPrefetchedClass() { | ||
addPrefetchedClass () { | ||
if (this.prefetchedClass !== 'false') { | ||
@@ -107,0 +116,0 @@ this.$el.className = (this.$el.className + ' ' + this.prefetchedClass).trim() |
@@ -8,2 +8,6 @@ import Vue from 'vue' | ||
props: { | ||
prefetch: { | ||
type: Boolean, | ||
default: <%= router.prefetchLinks ? 'true' : 'false' %> | ||
}, | ||
noPrefetch: { | ||
@@ -10,0 +14,0 @@ type: Boolean, |
@@ -12,3 +12,3 @@ import Vue from 'vue' | ||
import NuxtError from './nuxt-error.vue' | ||
<% } %> | ||
<% } /* components */ %> | ||
import NuxtChild from './nuxt-child' | ||
@@ -38,4 +38,13 @@ | ||
}, | ||
errorCaptured (error) { | ||
// if we receive and error while showing the NuxtError component | ||
// capture the error and force an immediate update so we re-render | ||
// without the NuxtError component | ||
if (this.displayingNuxtError) { | ||
this.errorFromNuxtError = error | ||
this.$forceUpdate() | ||
} | ||
}, | ||
computed: { | ||
routerViewKey() { | ||
routerViewKey () { | ||
// If nuxtChildKey prop is given or current route has children | ||
@@ -66,20 +75,38 @@ if (typeof this.nuxtChildKey !== 'undefined' || this.$route.matched.length > 1) { | ||
}, | ||
beforeCreate() { | ||
beforeCreate () { | ||
Vue.util.defineReactive(this, 'nuxt', this.$root.$options.nuxt) | ||
}, | ||
render(h) { | ||
// If there is some error | ||
if (this.nuxt.err) { | ||
return h('NuxtError', { | ||
props: { | ||
error: this.nuxt.err | ||
} | ||
render (h) { | ||
// if there is no error | ||
if (!this.nuxt.err) { | ||
// Directly return nuxt child | ||
return h('NuxtChild', { | ||
key: this.routerViewKey, | ||
props: this.$props | ||
}) | ||
} | ||
// Directly return nuxt child | ||
return h('NuxtChild', { | ||
key: this.routerViewKey, | ||
props: this.$props | ||
// if an error occured within NuxtError show a simple | ||
// error message instead to prevent looping | ||
if (this.errorFromNuxtError) { | ||
this.$nextTick(() => (this.errorFromNuxtError = false)) | ||
return h('div', {}, [ | ||
h('h2', 'An error occured while showing the error page'), | ||
h('p', 'Unfortunately an error occured and while showing the error page another error occured'), | ||
h('p', `Error details: ${this.errorFromNuxtError.toString()}`), | ||
h('nuxt-link', { props: { to: '/' } }, 'Go back to home') | ||
]) | ||
} | ||
// track if we are showing the NuxtError component | ||
this.displayingNuxtError = true | ||
this.$nextTick(() => (this.displayingNuxtError = false)) | ||
return h(NuxtError, { | ||
props: { | ||
error: this.nuxt.err | ||
} | ||
}) | ||
} | ||
} |
import Vue from 'vue' | ||
import Meta from 'vue-meta' | ||
import ClientOnly from 'vue-client-only' | ||
import NoSsr from 'vue-no-ssr' | ||
<% if (features.meta) { %>import Meta from 'vue-meta'<% } %> | ||
<% if (features.componentClientOnly) { %>import ClientOnly from 'vue-client-only'<% } %> | ||
<% if (features.deprecations) { %>import NoSsr from 'vue-no-ssr'<% } %> | ||
import { createRouter } from './router.js' | ||
@@ -19,10 +19,14 @@ import NuxtChild from './components/nuxt-child.js' | ||
<% if (features.componentClientOnly) { %> | ||
// Component: <ClientOnly> | ||
Vue.component(ClientOnly.name, ClientOnly) | ||
<% } %> | ||
<% if (features.deprecations) { %> | ||
// TODO: Remove in Nuxt 3: <NoSsr> | ||
Vue.component(NoSsr.name, { | ||
...NoSsr, | ||
render(h, ctx) { | ||
render (h, ctx) { | ||
if (process.client && !NoSsr._warned) { | ||
NoSsr._warned = true | ||
<%= isTest ? '// eslint-disable-next-line no-console' : '' %> | ||
console.warn(`<no-ssr> has been deprecated and will be removed in Nuxt 3, please use <client-only> instead`) | ||
@@ -33,6 +37,6 @@ } | ||
}) | ||
<% } %> | ||
// Component: <NuxtChild> | ||
Vue.component(NuxtChild.name, NuxtChild) | ||
Vue.component('NChild', NuxtChild) | ||
<% if (features.componentAliases) { %>Vue.component('NChild', NuxtChild)<% } %> | ||
@@ -44,4 +48,6 @@ // Component NuxtLink is imported in server.js or client.js | ||
<% if (features.meta) { | ||
// vue-meta configuration | ||
Vue.use(Meta, { | ||
const vueMetaOptions = { | ||
...nuxtOptions.vueMeta, | ||
keyName: 'head', // the component option name that vue-meta looks for meta info on. | ||
@@ -51,4 +57,8 @@ attribute: 'data-n-head', // the attribute name vue-meta adds to the tags it observes | ||
tagIDKeyName: 'hid' // the property name that vue-meta uses to determine whether to overwrite or append a tag | ||
}) | ||
} | ||
%> | ||
Vue.use(Meta, <%= JSON.stringify(vueMetaOptions) %>)<%= isTest ? '// eslint-disable-line' : '' %> | ||
<% } %> | ||
<% if (features.transitions) { %> | ||
const defaultTransition = <%= | ||
@@ -61,4 +71,5 @@ serialize(pageTransition) | ||
%><%= isTest ? '// eslint-disable-line' : '' %> | ||
<% } %> | ||
async function createApp(ssrContext) { | ||
async function createApp (ssrContext) { | ||
const router = await createRouter(ssrContext) | ||
@@ -82,8 +93,9 @@ | ||
const app = { | ||
<% if (store) { %>store,<% } %> | ||
router, | ||
<% if (store) { %>store,<% } %> | ||
nuxt: { | ||
<% if (features.transitions) { %> | ||
defaultTransition, | ||
transitions: [ defaultTransition ], | ||
setTransitions(transitions) { | ||
setTransitions (transitions) { | ||
if (!Array.isArray(transitions)) { | ||
@@ -105,5 +117,6 @@ transitions = [ transitions ] | ||
}, | ||
<% } %> | ||
err: null, | ||
dateErr: null, | ||
error(err) { | ||
error (err) { | ||
err = err || null | ||
@@ -116,3 +129,5 @@ app.context._errored = Boolean(err) | ||
// Used in src/server.js | ||
if (ssrContext) ssrContext.nuxt.error = err | ||
if (ssrContext) { | ||
ssrContext.nuxt.error = err | ||
} | ||
return err | ||
@@ -139,6 +154,6 @@ } | ||
await setContext(app, { | ||
<% if (store) { %>store,<% } %> | ||
route, | ||
next, | ||
error: app.nuxt.error.bind(app), | ||
<% if (store) { %>store,<% } %> | ||
payload: ssrContext ? ssrContext.payload : undefined, | ||
@@ -153,4 +168,9 @@ req: ssrContext ? ssrContext.req : undefined, | ||
const inject = function (key, value) { | ||
if (!key) throw new Error('inject(key, value) has no key provided') | ||
if (typeof value === 'undefined') throw new Error('inject(key, value) has no value provided') | ||
if (!key) { | ||
throw new Error('inject(key, value) has no key provided') | ||
} | ||
if (value === undefined) { | ||
throw new Error('inject(key, value) has no value provided') | ||
} | ||
key = '$' + key | ||
@@ -165,3 +185,5 @@ // Add into app | ||
const installKey = '__<%= globals.pluginPrefix %>_' + key + '_installed__' | ||
if (Vue[installKey]) return | ||
if (Vue[installKey]) { | ||
return | ||
} | ||
Vue[installKey] = true | ||
@@ -172,3 +194,3 @@ // Call Vue.use() to install the plugin into vm | ||
Object.defineProperty(Vue.prototype, key, { | ||
get() { | ||
get () { | ||
return this.$root.$options[key] | ||
@@ -228,4 +250,4 @@ } | ||
return { | ||
<% if(store) { %>store,<% } %> | ||
app, | ||
<% if(store) { %>store,<% } %> | ||
router | ||
@@ -232,0 +254,0 @@ } |
const middleware = {} | ||
<% middleware.forEach(m => { | ||
const name = m.src.replace(new RegExp(`\\.(${extensions})$`), '') | ||
<%= isTest ? '/* eslint-disable dot-notation */' : '' %> | ||
<% for (const m of middleware) { | ||
// TODO: remove duplicate logic in v3 (see builder.resolveMiddleware) | ||
const name = m.name || m.src.replace(new RegExp(`\\.(${extensions})$`), '') | ||
const dst = m.dst || relativeToBuild(srcDir, dir.middleware, m.src) | ||
%> | ||
middleware['<%= name %>'] = require('<%= relativeToBuild(srcDir, dir.middleware, m.src) %>'); | ||
middleware['<%= name %>'] = require('<%= dst %>') | ||
middleware['<%= name %>'] = middleware['<%= name %>'].default || middleware['<%= name %>'] | ||
<% }) %> | ||
<% } %> | ||
<%= isTest ? '/* eslint-enable dot-notation */' : '' %> | ||
export default middleware |
@@ -71,3 +71,3 @@ import Vue from 'vue' | ||
const _components = [] | ||
const _routes = recursiveRoutes(router.routes, ' ', _components, 2) | ||
const _routes = recursiveRoutes(router.routes, ' ', _components, 1) | ||
%><%= uniqBy(_components, '_name').map((route) => { | ||
@@ -102,4 +102,4 @@ if (!route.component) return '' | ||
export function createRouter() { | ||
export function createRouter () { | ||
return new Router(routerOptions) | ||
} |
<% if (router.scrollBehavior) { %> | ||
<%= isTest ? '/* eslint-disable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %> | ||
export default <%= serializeFunction(router.scrollBehavior) %> | ||
<%= isTest ? '/* eslint-enable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %> | ||
<% } else { %>import { getMatchedComponents } from './utils' | ||
@@ -70,2 +72,3 @@ | ||
} catch (e) { | ||
<%= isTest ? '// eslint-disable-next-line no-console' : '' %> | ||
console.warn('Failed to save scroll position. Please add CSS.escape() polyfill (https://github.com/mathiasbynens/CSS.escape).') | ||
@@ -72,0 +75,0 @@ } |
import { stringify } from 'querystring' | ||
import Vue from 'vue' | ||
<% if (fetch.server) { %>import fetch from 'node-fetch'<% } %> | ||
import middleware from './middleware.js' | ||
import { applyAsyncData, getMatchedComponents, middlewareSeries, promisify, urlJoin, sanitizeComponent } from './utils.js' | ||
import { createApp, NuxtError } from './index.js' | ||
<% if (features.middleware) { %>import middleware from './middleware.js'<% } %> | ||
import { | ||
<% if (features.asyncData) { %>applyAsyncData,<% } %> | ||
<% if (features.middleware) { %>middlewareSeries,<% } %> | ||
<% if (features.middleware && features.layouts) { %>sanitizeComponent,<% } %> | ||
getMatchedComponents, | ||
promisify | ||
} from './utils.js' | ||
import { createApp<% if (features.layouts) { %>, NuxtError<% } %> } from './index.js' | ||
import NuxtLink from './components/nuxt-link.server.js' // should be included after ./index.js | ||
@@ -11,3 +17,3 @@ | ||
Vue.component(NuxtLink.name, NuxtLink) | ||
Vue.component('NLink', NuxtLink) | ||
<% if (features.componentAliases) { %>Vue.component('NLink', NuxtLink)<% } %> | ||
@@ -18,2 +24,6 @@ <% if (fetch.server) { %>if (!global.fetch) { global.fetch = fetch }<% } %> | ||
function urlJoin () { | ||
return Array.prototype.slice.call(arguments).join('/').replace(/\/+/g, '/') | ||
} | ||
const createNext = ssrContext => (opts) => { | ||
@@ -55,3 +65,3 @@ ssrContext.redirected = opts | ||
// Nuxt object (window{{globals.context}}, defaults to window.__NUXT__) | ||
ssrContext.nuxt = { layout: 'default', data: [], error: null<%= (store ? ', state: null' : '') %>, serverRendered: true } | ||
ssrContext.nuxt = { <% if (features.layouts) { %>layout: 'default', <% } %>data: [], error: null<%= (store ? ', state: null' : '') %>, serverRendered: true } | ||
// Create the app definition and the instance (created for each request) | ||
@@ -61,6 +71,10 @@ const { app, router<%= (store ? ', store' : '') %> } = await createApp(ssrContext) | ||
<% if (features.meta) { %> | ||
// Add meta infos (used in renderer.js) | ||
ssrContext.meta = _app.$meta() | ||
<% } %> | ||
<% if (features.asyncData) { %> | ||
// Keep asyncData for each matched component in ssrContext (used in app/utils.js via this.$ssrContext) | ||
ssrContext.asyncData = {} | ||
<% } %> | ||
@@ -70,10 +84,12 @@ const beforeRender = async () => { | ||
await Promise.all(ssrContext.beforeRenderFns.map(fn => promisify(fn, { Components, nuxtState: ssrContext.nuxt }))) | ||
<% if (store) { %> | ||
ssrContext.rendered = () => { | ||
<% if (store) { %> | ||
// Add the state from the vuex store | ||
ssrContext.nuxt.state = store.state | ||
} | ||
<% } %> | ||
} | ||
} | ||
const renderErrorPage = async () => { | ||
<% if (features.layouts) { %> | ||
// Load layout for error page | ||
@@ -84,2 +100,3 @@ const errLayout = (typeof NuxtError.layout === 'function' ? NuxtError.layout(app.context) : NuxtError.layout) | ||
_app.setLayout(errLayout) | ||
<% } %> | ||
await beforeRender() | ||
@@ -106,3 +123,3 @@ return _app | ||
} catch (err) { | ||
console.debug('Error occurred when calling nuxtServerInit: ', err.message) | ||
console.debug('Error occurred when calling nuxtServerInit: ', err.message)<%= isTest ? '// eslint-disable-line no-console' : '' %> | ||
throw err | ||
@@ -112,6 +129,11 @@ } | ||
// ...If there is a redirect or an error, stop the process | ||
if (ssrContext.redirected) return noopApp() | ||
if (ssrContext.nuxt.error) return renderErrorPage() | ||
if (ssrContext.redirected) { | ||
return noopApp() | ||
} | ||
if (ssrContext.nuxt.error) { | ||
return renderErrorPage() | ||
} | ||
<% } %> | ||
<% if (features.middleware) { %> | ||
/* | ||
@@ -122,3 +144,5 @@ ** Call global middleware (nuxt.config.js) | ||
midd = midd.map((name) => { | ||
if (typeof name === 'function') return name | ||
if (typeof name === 'function') { | ||
return name | ||
} | ||
if (typeof middleware[name] !== 'function') { | ||
@@ -131,5 +155,11 @@ app.context.error({ statusCode: 500, message: 'Unknown middleware ' + name }) | ||
// ...If there is a redirect or an error, stop the process | ||
if (ssrContext.redirected) return noopApp() | ||
if (ssrContext.nuxt.error) return renderErrorPage() | ||
if (ssrContext.redirected) { | ||
return noopApp() | ||
} | ||
if (ssrContext.nuxt.error) { | ||
return renderErrorPage() | ||
} | ||
<% } %> | ||
<% if (features.layouts) { %> | ||
/* | ||
@@ -139,8 +169,14 @@ ** Set layout | ||
let layout = Components.length ? Components[0].options.layout : NuxtError.layout | ||
if (typeof layout === 'function') layout = layout(app.context) | ||
if (typeof layout === 'function') { | ||
layout = layout(app.context) | ||
} | ||
await _app.loadLayout(layout) | ||
if (ssrContext.nuxt.error) return renderErrorPage() | ||
if (ssrContext.nuxt.error) { | ||
return renderErrorPage() | ||
} | ||
layout = _app.setLayout(layout) | ||
ssrContext.nuxt.layout = _app.layoutName | ||
<% } %> | ||
<% if (features.middleware) { %> | ||
/* | ||
@@ -150,4 +186,8 @@ ** Call middleware (layout + pages) | ||
midd = [] | ||
<% if (features.layouts) { %> | ||
layout = sanitizeComponent(layout) | ||
if (layout.options.middleware) midd = midd.concat(layout.options.middleware) | ||
if (layout.options.middleware) { | ||
midd = midd.concat(layout.options.middleware) | ||
} | ||
<% } %> | ||
Components.forEach((Component) => { | ||
@@ -159,3 +199,5 @@ if (Component.options.middleware) { | ||
midd = midd.map((name) => { | ||
if (typeof name === 'function') return name | ||
if (typeof name === 'function') { | ||
return name | ||
} | ||
if (typeof middleware[name] !== 'function') { | ||
@@ -168,5 +210,11 @@ app.context.error({ statusCode: 500, message: 'Unknown middleware ' + name }) | ||
// ...If there is a redirect or an error, stop the process | ||
if (ssrContext.redirected) return noopApp() | ||
if (ssrContext.nuxt.error) return renderErrorPage() | ||
if (ssrContext.redirected) { | ||
return noopApp() | ||
} | ||
if (ssrContext.nuxt.error) { | ||
return renderErrorPage() | ||
} | ||
<% } %> | ||
<% if (features.validate) { %> | ||
/* | ||
@@ -200,10 +248,16 @@ ** Call .validate() | ||
// Don't server-render the page in generate mode | ||
if (ssrContext._generate) ssrContext.nuxt.serverRendered = false | ||
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() | ||
if (!Components.length) { | ||
return render404Page() | ||
} | ||
<% if (features.asyncData || features.fetch) { %> | ||
// Call asyncData & fetch hooks on components matched by the route. | ||
@@ -213,2 +267,3 @@ const asyncDatas = await Promise.all(Components.map((Component) => { | ||
<% if (features.asyncData) { %> | ||
// Call asyncData(context) | ||
@@ -226,3 +281,5 @@ if (Component.options.asyncData && typeof Component.options.asyncData === 'function') { | ||
} | ||
<% } %> | ||
<% if (features.fetch) { %> | ||
// Call fetch(context) | ||
@@ -234,2 +291,3 @@ if (Component.options.fetch) { | ||
} | ||
<% } %> | ||
@@ -239,10 +297,15 @@ return Promise.all(promises) | ||
<% if (debug) { %>if (process.env.DEBUG && asyncDatas.length)console.debug('Data fetching ' + ssrContext.url + ': ' + (Date.now() - s) + 'ms')<% } %> | ||
<% if (debug) { %>if (process.env.DEBUG && asyncDatas.length) console.debug('Data fetching ' + ssrContext.url + ': ' + (Date.now() - s) + 'ms')<% } %> | ||
// datas are the first row of each | ||
ssrContext.nuxt.data = asyncDatas.map(r => r[0] || {}) | ||
<% } %> | ||
// ...If there is a redirect or an error, stop the process | ||
if (ssrContext.redirected) return noopApp() | ||
if (ssrContext.nuxt.error) return renderErrorPage() | ||
if (ssrContext.redirected) { | ||
return noopApp() | ||
} | ||
if (ssrContext.nuxt.error) { | ||
return renderErrorPage() | ||
} | ||
@@ -249,0 +312,0 @@ // Call beforeNuxtRender methods & add store state |
@@ -6,6 +6,10 @@ import Vue from 'vue' | ||
<% | ||
const willResolveStoreModules = storeModules.some(s => s.src.indexOf('index.') !== 0) | ||
if (willResolveStoreModules) { %> | ||
const VUEX_PROPERTIES = ['state', 'getters', 'actions', 'mutations'] | ||
<% } %> | ||
let store = {} | ||
void (function updateModules() { | ||
void (function updateModules () { | ||
<% storeModules.some(s => { | ||
@@ -19,2 +23,3 @@ if(s.src.indexOf('index.') === 0) { %> | ||
if (typeof store === 'function') { | ||
<%= isTest ? '// eslint-disable-next-line no-console' : '' %> | ||
return console.warn('Classic mode for store/ is deprecated and will be removed in Nuxt 3.') | ||
@@ -52,4 +57,31 @@ }<% } %> | ||
function resolveStoreModules(moduleData, filename) { | ||
function normalizeRoot (moduleData, filePath) { | ||
moduleData = moduleData.default || moduleData | ||
if (moduleData.commit) { | ||
throw new Error(`[nuxt] ${filePath} should export a method that returns a Vuex instance.`) | ||
} | ||
if (typeof moduleData !== 'function') { | ||
// Avoid TypeError: setting a property that has only a getter when overwriting top level keys | ||
moduleData = Object.assign({}, moduleData) | ||
} | ||
return normalizeModule(moduleData, filePath) | ||
} | ||
function normalizeModule (moduleData, filePath) { | ||
if (moduleData.state && typeof moduleData.state !== 'function') { | ||
<%= isTest ? '// eslint-disable-next-line no-console' : '' %> | ||
console.warn(`'state' should be a method that returns an object in ${filePath}`) | ||
const state = Object.assign({}, moduleData.state) | ||
// Avoid TypeError: setting a property that has only a getter when overwriting top level keys | ||
moduleData = Object.assign({}, moduleData, { state: () => state }) | ||
} | ||
return moduleData | ||
} | ||
<% if (willResolveStoreModules) { %> | ||
function resolveStoreModules (moduleData, filename) { | ||
moduleData = moduleData.default || moduleData | ||
// Remove store src + extension (./foo/index.js -> foo/index) | ||
@@ -93,18 +125,5 @@ const namespace = filename.replace(/\.(<%= extensions %>)$/, '') | ||
function normalizeRoot(moduleData, filePath) { | ||
moduleData = moduleData.default || moduleData | ||
if (moduleData.commit) { | ||
throw new Error(`[nuxt] ${filePath} should export a method that returns a Vuex instance.`) | ||
} | ||
function normalizeState (moduleData, filePath) { | ||
if (typeof moduleData !== 'function') { | ||
// Avoid TypeError: setting a property that has only a getter when overwriting top level keys | ||
moduleData = Object.assign({}, moduleData) | ||
} | ||
return normalizeModule(moduleData, filePath) | ||
} | ||
function normalizeState(moduleData, filePath) { | ||
if (typeof moduleData !== 'function') { | ||
<%= isTest ? '// eslint-disable-next-line no-console' : '' %> | ||
console.warn(`${filePath} should export a method that returns an object`) | ||
@@ -117,13 +136,3 @@ const state = Object.assign({}, moduleData) | ||
function normalizeModule(moduleData, filePath) { | ||
if (moduleData.state && typeof moduleData.state !== 'function') { | ||
console.warn(`'state' should be a method that returns an object in ${filePath}`) | ||
const state = Object.assign({}, moduleData.state) | ||
// Avoid TypeError: setting a property that has only a getter when overwriting top level keys | ||
moduleData = Object.assign({}, moduleData, { state: () => state }) | ||
} | ||
return moduleData | ||
} | ||
function getStoreModule(storeModule, namespaces, { isProperty = false } = {}) { | ||
function getStoreModule (storeModule, namespaces, { isProperty = false } = {}) { | ||
// If ./mutations.js | ||
@@ -143,4 +152,6 @@ if (!namespaces.length || (isProperty && namespaces.length === 1)) { | ||
function mergeProperty(storeModule, moduleData, property) { | ||
if (!moduleData) return | ||
function mergeProperty (storeModule, moduleData, property) { | ||
if (!moduleData) { | ||
return | ||
} | ||
@@ -153,1 +164,2 @@ if (property === 'state') { | ||
} | ||
<% } %> |
@@ -12,5 +12,5 @@ import Vue from 'vue' | ||
export function empty() {} | ||
export function empty () {} | ||
export function globalHandleError(error) { | ||
export function globalHandleError (error) { | ||
if (Vue.config.errorHandler) { | ||
@@ -21,7 +21,8 @@ Vue.config.errorHandler(error) | ||
export function interopDefault(promise) { | ||
export function interopDefault (promise) { | ||
return promise.then(m => m.default || m) | ||
} | ||
export function applyAsyncData(Component, asyncData) { | ||
<% if (features.asyncData) { %> | ||
export function applyAsyncData (Component, asyncData) { | ||
if ( | ||
@@ -39,3 +40,3 @@ // For SSR, we once all this function without second param to just apply asyncData | ||
Component.options.data = function () { | ||
const data = ComponentData.call(this) | ||
const data = ComponentData.call(this, this) | ||
if (this.$ssrContext) { | ||
@@ -53,4 +54,5 @@ asyncData = this.$ssrContext.asyncData[Component.cid] | ||
} | ||
<% } %> | ||
export function sanitizeComponent(Component) { | ||
export function sanitizeComponent (Component) { | ||
// If Component already sanitized | ||
@@ -74,7 +76,7 @@ if (Component.options && Component._Ctor === Component) { | ||
export function getMatchedComponents(route, matches = false) { | ||
export function getMatchedComponents (route, matches = false, prop = 'components') { | ||
return Array.prototype.concat.apply([], route.matched.map((m, index) => { | ||
return Object.keys(m.components).map((key) => { | ||
return Object.keys(m[prop]).map((key) => { | ||
matches && matches.push(index) | ||
return m.components[key] | ||
return m[prop][key] | ||
}) | ||
@@ -84,12 +86,7 @@ })) | ||
export function getMatchedComponentsInstances(route, matches = false) { | ||
return Array.prototype.concat.apply([], route.matched.map((m, index) => { | ||
return Object.keys(m.instances).map((key) => { | ||
matches && matches.push(index) | ||
return m.instances[key] | ||
}) | ||
})) | ||
export function getMatchedComponentsInstances (route, matches = false) { | ||
return getMatchedComponents(route, matches, 'instances') | ||
} | ||
export function flatMapComponents(route, fn) { | ||
export function flatMapComponents (route, fn) { | ||
return Array.prototype.concat.apply([], route.matched.map((m, index) => { | ||
@@ -107,3 +104,3 @@ return Object.keys(m.components).reduce((promises, key) => { | ||
export function resolveRouteComponents(route, fn) { | ||
export function resolveRouteComponents (route, fn) { | ||
return Promise.all( | ||
@@ -121,3 +118,3 @@ flatMapComponents(route, async (Component, instance, match, key) => { | ||
export async function getRouteData(route) { | ||
export async function getRouteData (route) { | ||
if (!route) { | ||
@@ -137,3 +134,3 @@ return | ||
export async function setContext(app, context) { | ||
export async function setContext (app, context) { | ||
// If context not defined, create it | ||
@@ -227,8 +224,8 @@ if (!app.context) { | ||
app.context._errored = false | ||
app.context.isHMR = Boolean(context.isHMR) | ||
app.context.isHMR = <% if(isDev) { %>Boolean(context.isHMR)<% } else { %>false<% } %> | ||
app.context.params = app.context.route.params || {} | ||
app.context.query = app.context.route.query || {} | ||
} | ||
export function middlewareSeries(promises, appContext) { | ||
<% if (features.middleware) { %> | ||
export function middlewareSeries (promises, appContext) { | ||
if (!promises.length || appContext._redirected || appContext._errored) { | ||
@@ -242,4 +239,5 @@ return Promise.resolve() | ||
} | ||
export function promisify(fn, context) { | ||
<% } %> | ||
export function promisify (fn, context) { | ||
<% if (features.deprecations) { %> | ||
let promise | ||
@@ -265,10 +263,13 @@ if (fn.length === 2) { | ||
} | ||
if (!promise || (!(promise instanceof Promise) && (typeof promise.then !== 'function'))) { | ||
promise = Promise.resolve(promise) | ||
<% } else { %> | ||
const promise = fn(context) | ||
<% } %> | ||
if (promise && promise instanceof Promise && typeof promise.then === 'function') { | ||
return promise | ||
} | ||
return promise | ||
return Promise.resolve(promise) | ||
} | ||
// Imported from vue-router | ||
export function getLocation(base, mode) { | ||
export function getLocation (base, mode) { | ||
let path = decodeURI(window.location.pathname) | ||
@@ -284,6 +285,2 @@ if (mode === 'hash') { | ||
export function urlJoin() { | ||
return Array.prototype.slice.call(arguments).join('/').replace(/\/+/g, '/') | ||
} | ||
// Imported from path-to-regexp | ||
@@ -298,7 +295,7 @@ | ||
*/ | ||
export function compile(str, options) { | ||
export function compile (str, options) { | ||
return tokensToFunction(parse(str, options)) | ||
} | ||
export function getQueryDiff(toQuery, fromQuery) { | ||
export function getQueryDiff (toQuery, fromQuery) { | ||
const diff = {} | ||
@@ -314,3 +311,3 @@ const queries = { ...toQuery, ...fromQuery } | ||
export function normalizeError(err) { | ||
export function normalizeError (err) { | ||
let message | ||
@@ -358,3 +355,3 @@ if (!(err.message || typeof err === 'string')) { | ||
*/ | ||
function parse(str, options) { | ||
function parse (str, options) { | ||
const tokens = [] | ||
@@ -431,4 +428,5 @@ let key = 0 | ||
*/ | ||
function encodeURIComponentPretty(str) { | ||
return encodeURI(str).replace(/[/?#]/g, (c) => { | ||
function encodeURIComponentPretty (str, slashAllowed) { | ||
const re = slashAllowed ? /[?#]/g : /[/?#]/g | ||
return encodeURI(str).replace(re, (c) => { | ||
return '%' + c.charCodeAt(0).toString(16).toUpperCase() | ||
@@ -444,12 +442,30 @@ }) | ||
*/ | ||
function encodeAsterisk(str) { | ||
return encodeURI(str).replace(/[?#]/g, (c) => { | ||
return '%' + c.charCodeAt(0).toString(16).toUpperCase() | ||
}) | ||
function encodeAsterisk (str) { | ||
return encodeURIComponentPretty(str, true) | ||
} | ||
/** | ||
* Escape a regular expression string. | ||
* | ||
* @param {string} str | ||
* @return {string} | ||
*/ | ||
function escapeString (str) { | ||
return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, '\\$1') | ||
} | ||
/** | ||
* Escape the capturing group by escaping special characters and meaning. | ||
* | ||
* @param {string} group | ||
* @return {string} | ||
*/ | ||
function escapeGroup (group) { | ||
return group.replace(/([=!:$/()])/g, '\\$1') | ||
} | ||
/** | ||
* Expose a method for transforming tokens into the path function. | ||
*/ | ||
function tokensToFunction(tokens) { | ||
function tokensToFunction (tokens) { | ||
// Compile all the tokens into regexps. | ||
@@ -536,22 +552,2 @@ const matches = new Array(tokens.length) | ||
/** | ||
* Escape a regular expression string. | ||
* | ||
* @param {string} str | ||
* @return {string} | ||
*/ | ||
function escapeString(str) { | ||
return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, '\\$1') | ||
} | ||
/** | ||
* Escape the capturing group by escaping special characters and meaning. | ||
* | ||
* @param {string} group | ||
* @return {string} | ||
*/ | ||
function escapeGroup(group) { | ||
return group.replace(/([=!:$/()])/g, '\\$1') | ||
} | ||
/** | ||
* Format given url, append query to url query string | ||
@@ -563,3 +559,21 @@ * | ||
*/ | ||
function formatUrl(url, query) { | ||
function formatUrl (url, query) { | ||
<% if (features.clientUseUrl) { %> | ||
url = new URL(url, top.location.href) | ||
for (const key in query) { | ||
const value = query[key] | ||
if (value == null) { | ||
continue | ||
} | ||
if (Array.isArray(value)) { | ||
for (const arrayValue of value) { | ||
url.searchParams.append(key, arrayValue) | ||
} | ||
continue | ||
} | ||
url.searchParams.append(key, value) | ||
} | ||
url.searchParams.sort() | ||
return url.toString() | ||
<% } else { %> | ||
let protocol | ||
@@ -592,4 +606,5 @@ const index = url.indexOf('://') | ||
return result | ||
<% } %> | ||
} | ||
<% if (!features.clientUseUrl) { %> | ||
/** | ||
@@ -601,3 +616,3 @@ * Transform data object to query string | ||
*/ | ||
function formatQuery(query) { | ||
function formatQuery (query) { | ||
return Object.keys(query).sort().map((key) => { | ||
@@ -614,1 +629,2 @@ const val = query[key] | ||
} | ||
<% } %> |
@@ -8,2 +8,6 @@ { | ||
}, | ||
"prefetch": { | ||
"type": "boolean", | ||
"description": "Prefetch route target (overrides router.prefetchLinks value in nuxt.config.js)." | ||
}, | ||
"no-prefetch": { | ||
@@ -10,0 +14,0 @@ "description": "Avoid prefetching route target." |
@@ -24,2 +24,3 @@ { | ||
"exact-active-class", | ||
"prefetch", | ||
"no-prefetch" | ||
@@ -39,2 +40,3 @@ ], | ||
"exact-active-class", | ||
"prefetch", | ||
"no-prefetch" | ||
@@ -41,0 +43,0 @@ ], |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
138407
2819
39
Updatedvue-meta@^2.2.2