@nuxt/vue-app
Advanced tools
Comparing version 2.3.4 to 2.4.0
@@ -6,2 +6,64 @@ # Change Log | ||
# [2.4.0](https://github.com/nuxt/nuxt.js/compare/v2.3.4...v2.4.0) (2019-01-28) | ||
### Bug Fixes | ||
* $nuxt is used instead of globalName ([#4743](https://github.com/nuxt/nuxt.js/issues/4743)) ([fe57a5a](https://github.com/nuxt/nuxt.js/commit/fe57a5a)) | ||
* allow keepAliveProps for nuxt component ([#4610](https://github.com/nuxt/nuxt.js/issues/4610)) ([8dc15d0](https://github.com/nuxt/nuxt.js/commit/8dc15d0)) | ||
* apply store HMR to whole store ([#4589](https://github.com/nuxt/nuxt.js/issues/4589)) ([81cf09c](https://github.com/nuxt/nuxt.js/commit/81cf09c)) | ||
* hotfix for vuex hmr ([#4801](https://github.com/nuxt/nuxt.js/issues/4801)) ([5f0b34f](https://github.com/nuxt/nuxt.js/commit/5f0b34f)) | ||
* keepAliveProps broken in <nuxt-child> ([#4521](https://github.com/nuxt/nuxt.js/issues/4521)) ([431cc15](https://github.com/nuxt/nuxt.js/commit/431cc15)) | ||
* loading.throttle can not be 0 ([2d74804](https://github.com/nuxt/nuxt.js/commit/2d74804)) | ||
* merge route.meta into options.meta ([#4479](https://github.com/nuxt/nuxt.js/issues/4479)) ([5a8e6e4](https://github.com/nuxt/nuxt.js/commit/5a8e6e4)) | ||
* properly serialize head functions ([#4558](https://github.com/nuxt/nuxt.js/issues/4558)) ([7831e57](https://github.com/nuxt/nuxt.js/commit/7831e57)), closes [#4079](https://github.com/nuxt/nuxt.js/issues/4079) | ||
* **vue-app:** Set window. equals to window.{globalName} when defined ([951e745](https://github.com/nuxt/nuxt.js/commit/951e745)) | ||
* remove unnecessary isDev in template/server ([a51ba8d](https://github.com/nuxt/nuxt.js/commit/a51ba8d)) | ||
* **vue-app:** Fix Vuex HMR & refactor for better modules usage ([#4791](https://github.com/nuxt/nuxt.js/issues/4791)) ([deadc48](https://github.com/nuxt/nuxt.js/commit/deadc48)) | ||
* router Expected "0" to be defined ([#4394](https://github.com/nuxt/nuxt.js/issues/4394)) ([39b1b8e](https://github.com/nuxt/nuxt.js/commit/39b1b8e)) | ||
* **vue-app:** Fix route meta to handle order ([45be638](https://github.com/nuxt/nuxt.js/commit/45be638)) | ||
* use triple equals in loading.throttle [release] ([e77c2db](https://github.com/nuxt/nuxt.js/commit/e77c2db)) | ||
* Vue.component(RouterLink) is undefined in vue-router 3.0.0 ([#4668](https://github.com/nuxt/nuxt.js/issues/4668)) ([7ff4058](https://github.com/nuxt/nuxt.js/commit/7ff4058)) | ||
* **ts:** fix missing process type definitions and refactor types tests ([#4798](https://github.com/nuxt/nuxt.js/issues/4798)) ([45afc3f](https://github.com/nuxt/nuxt.js/commit/45afc3f)) | ||
* wrong type checking for loading.duration ([0c15b29](https://github.com/nuxt/nuxt.js/commit/0c15b29)) | ||
* **layout-middleware:** Fix issue [#4724](https://github.com/nuxt/nuxt.js/issues/4724) ([521ac20](https://github.com/nuxt/nuxt.js/commit/521ac20)) | ||
* **progress-bar:** allow 0 for values and remove duplicate defaults ([#4397](https://github.com/nuxt/nuxt.js/issues/4397)) ([ecdc7bc](https://github.com/nuxt/nuxt.js/commit/ecdc7bc)) | ||
* **scrollBehavior:** emit triggerScroll event after changing layer ([#4399](https://github.com/nuxt/nuxt.js/issues/4399)) ([330301c](https://github.com/nuxt/nuxt.js/commit/330301c)), closes [#4080](https://github.com/nuxt/nuxt.js/issues/4080) | ||
* **server, vue-app:** allow unicode page names ([#4402](https://github.com/nuxt/nuxt.js/issues/4402)) ([949785f](https://github.com/nuxt/nuxt.js/commit/949785f)) | ||
* **ts:** Add missing `loading` property to Component options ([#4786](https://github.com/nuxt/nuxt.js/issues/4786)) ([db4001d](https://github.com/nuxt/nuxt.js/commit/db4001d)) | ||
* **ts:** fix `$nuxt.$loading` typedefs ([#4778](https://github.com/nuxt/nuxt.js/issues/4778)) ([6694cf7](https://github.com/nuxt/nuxt.js/commit/6694cf7)) | ||
* **vue-app:** add type definition for `ComponentOptions.middleware` ([#4531](https://github.com/nuxt/nuxt.js/issues/4531)) ([da0a379](https://github.com/nuxt/nuxt.js/commit/da0a379)) | ||
* **vue-app:** allow passing custom props to error function ([#4462](https://github.com/nuxt/nuxt.js/issues/4462)) ([a6fed0a](https://github.com/nuxt/nuxt.js/commit/a6fed0a)), closes [#4460](https://github.com/nuxt/nuxt.js/issues/4460) | ||
* **vue-app:** Call Vue.config.errorHandler instead of simply logging the error ([6c4280f](https://github.com/nuxt/nuxt.js/commit/6c4280f)) | ||
* **vue-app:** Fix default error handler in production ([96892c5](https://github.com/nuxt/nuxt.js/commit/96892c5)) | ||
* **vue-app:** router.meta is null on extendRoutes([#4478](https://github.com/nuxt/nuxt.js/issues/4478)) ([e2ab1b4](https://github.com/nuxt/nuxt.js/commit/e2ab1b4)), closes [#4154](https://github.com/nuxt/nuxt.js/issues/4154) | ||
### Features | ||
* **builder:** validate vue-app dependencies and suggest fix ([#4669](https://github.com/nuxt/nuxt.js/issues/4669)) ([7dd33fe](https://github.com/nuxt/nuxt.js/commit/7dd33fe)) | ||
* **nuxt-link:** Smart prefetching and $nuxt.isOffline ([#4574](https://github.com/nuxt/nuxt.js/issues/4574)) ([f319033](https://github.com/nuxt/nuxt.js/commit/f319033)) | ||
* **ts:** provide type definitions ([#4164](https://github.com/nuxt/nuxt.js/issues/4164)) ([d5716eb](https://github.com/nuxt/nuxt.js/commit/d5716eb)) | ||
* **ts:** typescript examples + improve `vue-app` typings ([#4695](https://github.com/nuxt/nuxt.js/issues/4695)) ([b38e0aa](https://github.com/nuxt/nuxt.js/commit/b38e0aa)) | ||
* **vue-app:** <n-link> and <n-child> component aliases ([#4525](https://github.com/nuxt/nuxt.js/issues/4525)) ([1505197](https://github.com/nuxt/nuxt.js/commit/1505197)) | ||
* **vue-app:** Add deprecating for classic mode and handle mutations/actions HMR to store/index.js ([c8b920a](https://github.com/nuxt/nuxt.js/commit/c8b920a)) | ||
* add store module HMR ([#4582](https://github.com/nuxt/nuxt.js/issues/4582)) ([b2eee17](https://github.com/nuxt/nuxt.js/commit/b2eee17)) | ||
* **vue-app:** add vetur helpers for components auto-complete on VS Code ([#4524](https://github.com/nuxt/nuxt.js/issues/4524)) ([59aee74](https://github.com/nuxt/nuxt.js/commit/59aee74)) | ||
* **vue-app:** support named views ([#4410](https://github.com/nuxt/nuxt.js/issues/4410)) ([b1b9e0b](https://github.com/nuxt/nuxt.js/commit/b1b9e0b)) | ||
* **vue-app, vue-renderer:** support meta `headAttrs` ([#4536](https://github.com/nuxt/nuxt.js/issues/4536)) ([9961453](https://github.com/nuxt/nuxt.js/commit/9961453)) | ||
* add styleExtensions ([#4671](https://github.com/nuxt/nuxt.js/issues/4671)) ([471a32a](https://github.com/nuxt/nuxt.js/commit/471a32a)) | ||
* allow scrollToTop to be explicitly disabled ([#4564](https://github.com/nuxt/nuxt.js/issues/4564)) ([669fecc](https://github.com/nuxt/nuxt.js/commit/669fecc)) | ||
* better stack traces for SSR error, show error with correct URL and use eventsource-polyfill ([#4600](https://github.com/nuxt/nuxt.js/issues/4600)) ([498c4f1](https://github.com/nuxt/nuxt.js/commit/498c4f1)) | ||
* improve SSR bundle ([#4439](https://github.com/nuxt/nuxt.js/issues/4439)) ([0f104aa](https://github.com/nuxt/nuxt.js/commit/0f104aa)), closes [#4225](https://github.com/nuxt/nuxt.js/issues/4225) [#3465](https://github.com/nuxt/nuxt.js/issues/3465) [#1728](https://github.com/nuxt/nuxt.js/issues/1728) [#1601](https://github.com/nuxt/nuxt.js/issues/1601) [#1481](https://github.com/nuxt/nuxt.js/issues/1481) | ||
* mode for plugins ([#4592](https://github.com/nuxt/nuxt.js/issues/4592)) ([e71c455](https://github.com/nuxt/nuxt.js/commit/e71c455)) | ||
### Performance Improvements | ||
* **ssr:** remove extra imprts from server.js ([6178c47](https://github.com/nuxt/nuxt.js/commit/6178c47)) | ||
## [2.3.4](https://github.com/nuxt/nuxt.js/compare/v2.3.2...v2.3.4) (2018-11-26) | ||
@@ -8,0 +70,0 @@ |
/*! | ||
* @nuxt/vue-app v2.3.4 (c) 2016-2018 | ||
* @nuxt/vue-app v2.4.0 (c) 2016-2019 | ||
@@ -16,49 +16,35 @@ * - All the amazing contributors | ||
var name = "@nuxt/vue-app"; | ||
var version = "2.3.4"; | ||
var repository = "nuxt/nuxt.js"; | ||
var license = "MIT"; | ||
var files = [ | ||
"dist", | ||
"template" | ||
]; | ||
var main = "dist/vue-app.js"; | ||
var publishConfig = { | ||
access: "public" | ||
var dependencies = { | ||
vue: "^2.5.22", | ||
"vue-meta": "^1.5.8", | ||
"vue-no-ssr": "^1.1.1", | ||
"vue-router": "^3.0.2", | ||
"vue-template-compiler": "^2.5.22", | ||
vuex: "^3.1.0" | ||
}; | ||
const pkg = { | ||
name: name, | ||
version: version, | ||
repository: repository, | ||
license: license, | ||
files: files, | ||
main: main, | ||
publishConfig: publishConfig | ||
const template = { | ||
dependencies, | ||
dir: path.join(__dirname, '..', 'template'), | ||
files: [ | ||
'App.js', | ||
'client.js', | ||
'index.js', | ||
'middleware.js', | ||
'router.js', | ||
'server.js', | ||
'utils.js', | ||
'empty.js', | ||
'components/nuxt-error.vue', | ||
'components/nuxt-loading.vue', | ||
'components/nuxt-child.js', | ||
'components/nuxt-link.server.js', | ||
'components/nuxt-link.client.js', | ||
'components/nuxt.js', | ||
'components/no-ssr.js', | ||
'views/app.template.html', | ||
'views/error.html' | ||
] | ||
}; | ||
const meta = pkg; | ||
const templatesDir = path.join(__dirname, '..', 'template'); | ||
const templatesFiles = [ | ||
'App.js', | ||
'client.js', | ||
'index.js', | ||
'middleware.js', | ||
'router.js', | ||
'server.js', | ||
'utils.js', | ||
'empty.js', | ||
'components/nuxt-error.vue', | ||
'components/nuxt-loading.vue', | ||
'components/nuxt-child.js', | ||
'components/nuxt-link.js', | ||
'components/nuxt.js', | ||
'components/no-ssr.js', | ||
'views/app.template.html', | ||
'views/error.html' | ||
]; | ||
exports.meta = meta; | ||
exports.templatesDir = templatesDir; | ||
exports.templatesFiles = templatesFiles; | ||
exports.template = template; |
{ | ||
"name": "@nuxt/vue-app", | ||
"version": "2.3.4", | ||
"version": "2.4.0", | ||
"repository": "nuxt/nuxt.js", | ||
@@ -8,5 +8,16 @@ "license": "MIT", | ||
"dist", | ||
"template" | ||
"template", | ||
"types/*.d.ts", | ||
"vetur" | ||
], | ||
"main": "dist/vue-app.js", | ||
"typings": "types/index.d.ts", | ||
"dependencies": { | ||
"vue": "^2.5.22", | ||
"vue-meta": "^1.5.8", | ||
"vue-no-ssr": "^1.1.1", | ||
"vue-router": "^3.0.2", | ||
"vue-template-compiler": "^2.5.22", | ||
"vuex": "^3.1.0" | ||
}, | ||
"publishConfig": { | ||
@@ -13,0 +24,0 @@ "access": "public" |
import Vue from 'vue' | ||
<% if (loading) { %>import NuxtLoading from '<%= (typeof loading === "string" ? loading : "./components/nuxt-loading.vue") %>'<% } %> | ||
<% css.forEach((c) => { %> | ||
import '<%= relativeToBuild(resolvePath(c.src || c)) %>' | ||
import '<%= relativeToBuild(resolvePath(c.src || c, { isStyle: true })) %>' | ||
<% }) %> | ||
@@ -20,7 +20,7 @@ | ||
export default { | ||
<%= isTest ? '/* eslint-disable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, object-property-newline, arrow-parens */' : '' %> | ||
head: <%= serialize(head).replace(/:\w+\(/gm, ':function(').replace('head(', 'function(') %>, | ||
<%= isTest ? '/* eslint-enable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, object-property-newline, arrow-parens */' : '' %> | ||
<%= isTest ? '/* eslint-disable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %> | ||
head: <%= serializeFunction(head) %>, | ||
<%= isTest ? '/* eslint-enable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %> | ||
render(h, props) { | ||
<% if (loading) { %>const loadingEl = h('nuxt-loading', { ref: 'loading' })<% } %> | ||
<% if (loading) { %>const loadingEl = h('NuxtLoading', { ref: 'loading' })<% } %> | ||
const layoutEl = h(this.layout || 'nuxt') | ||
@@ -59,2 +59,3 @@ const templateEl = h('div', { | ||
data: () => ({ | ||
isOnline: true, | ||
layout: null, | ||
@@ -70,7 +71,8 @@ layoutName: '' | ||
// add to window so we can listen when ready | ||
if (typeof window !== 'undefined') { | ||
window.<%= globals.nuxt %> = this | ||
<% if (globals.nuxt !== '$nuxt') { %> | ||
window.$nuxt = { $root: { constructor: this.$root.constructor } } | ||
<% } %> | ||
if (process.client) { | ||
window.<%= globals.nuxt %> = <%= (globals.nuxt !== '$nuxt' ? 'window.$nuxt = ' : '') %>this | ||
this.refreshOnlineStatus() | ||
// Setup the listeners | ||
window.addEventListener('online', this.refreshOnlineStatus) | ||
window.addEventListener('offline', this.refreshOnlineStatus) | ||
} | ||
@@ -88,3 +90,20 @@ // Add $nuxt.error() | ||
<% } %> | ||
computed: { | ||
isOffline() { | ||
return !this.isOnline | ||
} | ||
}, | ||
methods: { | ||
refreshOnlineStatus() { | ||
if (process.client) { | ||
if (typeof window.navigator.onLine === 'undefined') { | ||
// If the browser doesn't support connection status reports | ||
// assume that we are online because most apps' only react | ||
// when they now that the connection has been interrupted | ||
this.isOnline = true | ||
} else { | ||
this.isOnline = window.navigator.onLine | ||
} | ||
} | ||
}, | ||
<% if (loading) { %> | ||
@@ -111,4 +130,4 @@ errorChanged() { | ||
const undef = !layout | ||
const inexisting = !(layouts['_' + layout] || resolvedLayouts['_' + layout]) | ||
let _layout = '_' + ((undef || inexisting) ? 'default' : layout) | ||
const nonexistent = !(layouts['_' + layout] || resolvedLayouts['_' + layout]) | ||
let _layout = '_' + ((undef || nonexistent) ? 'default' : layout) | ||
if (resolvedLayouts[_layout]) { | ||
@@ -115,0 +134,0 @@ return Promise.resolve(resolvedLayouts[_layout]) |
import Vue from 'vue' | ||
import middleware from './middleware' | ||
import middleware from './middleware.js' | ||
import { | ||
@@ -17,7 +17,9 @@ applyAsyncData, | ||
globalHandleError | ||
} from './utils' | ||
import { createApp, NuxtError } from './index' | ||
} 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 | ||
const noopData = () => { return {} } | ||
const noopFetch = () => {} | ||
// Component: <NuxtLink> | ||
Vue.component(NuxtLink.name, NuxtLink) | ||
Vue.component('NLink', NuxtLink) | ||
@@ -28,3 +30,3 @@ // Global shared references | ||
let router | ||
<% if (store) { %>let store<% } %> | ||
<% if (store) { %>let store<%= isTest ? '// eslint-disable-line no-unused-vars' : '' %><% } %> | ||
@@ -36,3 +38,3 @@ // Try to rehydrate SSR data from window | ||
<% if (debug || mode === 'spa') { %> | ||
<% if (debug) { %> | ||
// Setup global Vue error handler | ||
@@ -75,4 +77,4 @@ if (!Vue.config.$nuxt) { | ||
Vue.config.$nuxt.<%= globals.nuxt %> = true | ||
<% } %> | ||
const errorHandler = Vue.config.errorHandler || console.error | ||
@@ -83,3 +85,4 @@ // Create and mount App | ||
.catch((err) => { | ||
console.error('[nuxt] Error while initializing app', err) | ||
err.message = '[nuxt] Error while mounting app: ' + err.message | ||
errorHandler(err) | ||
}) | ||
@@ -152,6 +155,17 @@ | ||
next() | ||
} catch (err) { | ||
this.error(err) | ||
this.<%= globals.nuxt %>.$emit('routeChanged', to, from, error) | ||
next(false) | ||
} catch (error) { | ||
const err = error || {} | ||
const statusCode = err.statusCode || err.status || (err.response && err.response.status) || 500 | ||
const message = err.message || '' | ||
// Handle chunk loading errors | ||
// This may be due to a new deployment or a network problem | ||
if (/^Loading chunk (\d)+ failed\./.test(message)) { | ||
window.location.reload(true /* skip cache */) | ||
return // prevent error page blinking for user | ||
} | ||
this.error({ statusCode, message }) | ||
this.<%= globals.nuxt %>.$emit('routeChanged', to, from, err) | ||
next() | ||
} | ||
@@ -191,4 +205,5 @@ } | ||
midd = [] // Exclude global middleware if layout defined (already called before) | ||
if (layout.middleware) { | ||
midd = midd.concat(layout.middleware) | ||
layout = sanitizeComponent(layout) | ||
if (layout.options.middleware) { | ||
midd = midd.concat(layout.options.middleware) | ||
} | ||
@@ -429,3 +444,3 @@ Components.forEach((Component) => { | ||
this.<%= globals.nuxt %>.$emit('routeChanged', to, from, error) | ||
next(false) | ||
next() | ||
} | ||
@@ -518,2 +533,5 @@ } | ||
<% if (isDev) { %> | ||
const noopData = () => { return {} } | ||
const noopFetch = () => {} | ||
// Special hot reload with asyncData(context) | ||
@@ -686,5 +704,5 @@ function getNuxtChildComponents($parent, $components = []) { | ||
if (!err) return mount() | ||
console.error(err) | ||
errorHandler(err) | ||
}) | ||
}) | ||
} |
@@ -5,3 +5,6 @@ /*<%= isTest ? ' @vue/component' : '' %> | ||
*/ | ||
import NoSSR from 'vue-no-ssr' | ||
export default NoSSR | ||
import NoSsr from 'vue-no-ssr' | ||
export default { | ||
...NoSsr, | ||
name: 'NoSsr' | ||
} |
<%= isTest ? '// @vue/component' : '' %> | ||
export default { | ||
name: 'nuxt-child', | ||
name: 'NuxtChild', | ||
functional: true, | ||
@@ -10,3 +10,7 @@ props: { | ||
}, | ||
keepAlive: Boolean | ||
keepAlive: Boolean, | ||
keepAliveProps: { | ||
type: Object, | ||
default: undefined | ||
} | ||
}, | ||
@@ -13,0 +17,0 @@ render(h, { parent, data, props }) { |
@@ -1,2 +0,1 @@ | ||
<%= isTest ? '// @vue/component' : '' %> | ||
import Vue from 'vue' | ||
@@ -16,26 +15,24 @@ import { compile } from '../utils' | ||
<%= isTest ? '// @vue/component' : '' %> | ||
export default { | ||
name: 'nuxt', | ||
name: 'Nuxt', | ||
components: { | ||
NuxtChild, | ||
NuxtError | ||
}, | ||
props: { | ||
nuxtChildKey: String, | ||
keepAlive: Boolean | ||
}, | ||
render(h) { | ||
// If there is some error | ||
if (this.nuxt.err) { | ||
return h('nuxt-error', { | ||
props: { | ||
error: this.nuxt.err | ||
} | ||
}) | ||
nuxtChildKey: { | ||
type: String, | ||
default: undefined | ||
}, | ||
keepAlive: Boolean, | ||
keepAliveProps: { | ||
type: Object, | ||
default: undefined | ||
}, | ||
name: { | ||
type: String, | ||
default: 'default' | ||
} | ||
// Directly return nuxt child | ||
return h('nuxt-child', { | ||
key: this.routerViewKey, | ||
props: this.$props | ||
}) | ||
}, | ||
beforeCreate() { | ||
Vue.util.defineReactive(this, 'nuxt', this.$root.$options.nuxt) | ||
}, | ||
computed: { | ||
@@ -54,6 +51,20 @@ routerViewKey() { | ||
}, | ||
components: { | ||
NuxtChild, | ||
NuxtError | ||
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 | ||
} | ||
}) | ||
} | ||
// Directly return nuxt child | ||
return h('NuxtChild', { | ||
key: this.routerViewKey, | ||
props: this.$props | ||
}) | ||
} | ||
} |
import Vue from 'vue' | ||
import Meta from 'vue-meta' | ||
import { createRouter } from './router.js' | ||
import NoSSR from './components/no-ssr.js' | ||
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" %>' | ||
@@ -15,16 +14,16 @@ import Nuxt from './components/nuxt.js' | ||
<%= isTest ? '/* eslint-disable camelcase */' : '' %> | ||
<% plugins.forEach((plugin) => { %>import <%= plugin.name %> from '<%= plugin.name %>' // Source: <%= relativeToBuild(plugin.src) %><%= (plugin.ssr===false) ? ' (ssr: false)' : '' %> | ||
<% plugins.forEach((plugin) => { %>import <%= plugin.name %> from '<%= plugin.name %>' // Source: <%= relativeToBuild(plugin.src) %> (mode: '<%= plugin.mode %>') | ||
<% }) %> | ||
<%= isTest ? '/* eslint-enable camelcase */' : '' %> | ||
// Component: <no-ssr> | ||
Vue.component(NoSSR.name, NoSSR) | ||
// Component: <NoSsr> | ||
Vue.component(NoSsr.name, NoSsr) | ||
// Component: <nuxt-child> | ||
// Component: <NuxtChild> | ||
Vue.component(NuxtChild.name, NuxtChild) | ||
Vue.component('NChild', NuxtChild) | ||
// Component: <nuxt-link> | ||
Vue.component(NuxtLink.name, NuxtLink) | ||
// Component NuxtLink is imported in server.js or client.js | ||
// Component: <nuxt>` | ||
// Component: <Nuxt>` | ||
Vue.component(Nuxt.name, Nuxt) | ||
@@ -170,9 +169,16 @@ | ||
<%= isTest ? '/* eslint-disable camelcase */' : '' %> | ||
<% plugins.filter(p => p.ssr).forEach((plugin) => { %> | ||
<% plugins.filter(p => p.mode === 'all').forEach((plugin) => { %> | ||
if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(app.context, inject)<% }) %> | ||
<% if (plugins.filter(p => !p.ssr).length) { %> | ||
<% if (plugins.filter(p => p.mode === 'client').length) { %> | ||
if (process.client) { | ||
<% plugins.filter((p) => !p.ssr).forEach((plugin) => { %> | ||
<% plugins.filter(p => p.mode === 'client').forEach((plugin) => { %> | ||
if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(app.context, inject)<% }) %> | ||
}<% } %> | ||
<% if (plugins.filter(p => p.mode === 'server').length) { %> | ||
if (process.server) { | ||
<% plugins.filter(p => p.mode === 'server').forEach((plugin) => { %> | ||
if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(app.context, inject)<% }) %> | ||
}<% } %> | ||
<%= isTest ? '/* eslint-enable camelcase */' : '' %> | ||
@@ -179,0 +185,0 @@ |
import Vue from 'vue' | ||
import Router from 'vue-router' | ||
import { interopDefault } from './utils' | ||
import { interopDefault } from './utils'<%= isTest ? '// eslint-disable-line no-unused-vars' : '' %> | ||
<% function recursiveRoutes(routes, tab, components, indentCount) { | ||
let res = '' | ||
let res = '', resMap = '' | ||
const baseIndent = tab.repeat(indentCount) | ||
@@ -11,7 +11,41 @@ const firstIndent = '\n' + tab.repeat(indentCount + 1) | ||
routes.forEach((route, i) => { | ||
route._name = '_' + hash(route.component) | ||
components.push({ _name: route._name, component: route.component, name: route.name, chunkName: route.chunkName }) | ||
// If need to handle named views | ||
if (route.components) { | ||
let _name = '_' + hash(route.components.default) | ||
if (splitChunks.pages) { | ||
resMap += `${firstIndent}${tab}default: ${_name}` | ||
} else { | ||
resMap += `${firstIndent}${tab}default: () => ${_name}.default || ${_name}` | ||
} | ||
for (const k in route.components) { | ||
_name = '_' + hash(route.components[k]) | ||
const component = { _name, component: route.components[k] } | ||
if (k === 'default') { | ||
components.push({ | ||
...component, | ||
name: route.name, | ||
chunkName: route.chunkName | ||
}) | ||
} else { | ||
components.push({ | ||
...component, | ||
name: `${route.name}-${k}`, | ||
chunkName: route.chunkNames[k] | ||
}) | ||
if (splitChunks.pages) { | ||
resMap += `${nextIndent}${tab}${k}: ${_name}` | ||
} else { | ||
resMap += `${nextIndent}${tab}${k}: () => ${_name}.default || ${_name}` | ||
} | ||
} | ||
} | ||
route.component = false | ||
} else { | ||
route._name = '_' + hash(route.component) | ||
components.push({ _name: route._name, component: route.component, name: route.name, chunkName: route.chunkName }) | ||
} | ||
// @see: https://router.vuejs.org/api/#router-construction-options | ||
res += '{' | ||
res += firstIndent + 'path: ' + JSON.stringify(route.path) | ||
res += (route.components) ? nextIndent + 'components: {' + resMap + '\n' + baseIndent + tab + '}' : '' | ||
res += (route.component) ? nextIndent + 'component: ' + (splitChunks.pages ? route._name : `() => ${route._name}.default || ${route._name}`) : '' | ||
@@ -53,3 +87,3 @@ res += (route.redirect) ? nextIndent + 'redirect: ' + JSON.stringify(route.redirect) : '' | ||
<% if (router.scrollBehavior) { %> | ||
const scrollBehavior = <%= serialize(router.scrollBehavior).replace(/scrollBehavior\s*\(/, 'function(').replace('function function', 'function') %> | ||
const scrollBehavior = <%= serializeFunction(router.scrollBehavior) %> | ||
<% } else { %> | ||
@@ -64,4 +98,7 @@ if (process.client) { | ||
// if no children detected | ||
if (to.matched.length < 2) { | ||
// if no children detected and scrollToTop is not explicitly disabled | ||
if ( | ||
to.matched.length < 2 && | ||
to.matched.every(r => r.components.default.options.scrollToTop !== false) | ||
) { | ||
// scroll to the top of the page | ||
@@ -112,9 +149,9 @@ position = { x: 0, y: 0 } | ||
scrollBehavior, | ||
<%= isTest ? '/* eslint-disable quotes */' : '' %> | ||
<%= isTest ? '/* eslint-disable quotes, object-curly-spacing, key-spacing */' : '' %> | ||
routes: [<%= _routes %>], | ||
<%= isTest ? '/* eslint-enable quotes */' : '' %> | ||
<% if (router.parseQuery) { %>parseQuery: <%= serialize(router.parseQuery).replace('parseQuery(', 'function(') %>,<% } %> | ||
<% if (router.stringifyQuery) { %>stringifyQuery: <%= serialize(router.stringifyQuery).replace('stringifyQuery(', 'function(') %>,<% } %> | ||
<%= isTest ? '/* eslint-enable quotes, object-curly-spacing, key-spacing */' : '' %> | ||
<% if (router.parseQuery) { %>parseQuery: <%= serializeFunction(router.parseQuery) %>,<% } %> | ||
<% if (router.stringifyQuery) { %>stringifyQuery: <%= serializeFunction(router.stringifyQuery) %>,<% } %> | ||
fallback: <%= router.fallback %> | ||
}) | ||
} |
import { stringify } from 'querystring' | ||
import Vue from 'vue' | ||
import omit from 'lodash/omit' | ||
import middleware from './middleware' | ||
import { applyAsyncData, sanitizeComponent, getMatchedComponents, getContext, middlewareSeries, promisify, urlJoin } from './utils' | ||
import { createApp, NuxtError } from './index' | ||
import middleware from './middleware.js' | ||
import { applyAsyncData, getMatchedComponents, middlewareSeries, promisify, urlJoin, sanitizeComponent } from './utils.js' | ||
import { createApp, NuxtError } from './index.js' | ||
import NuxtLink from './components/nuxt-link.server.js' // should be included after ./index.js | ||
// Component: <NuxtLink> | ||
Vue.component(NuxtLink.name, NuxtLink) | ||
Vue.component('NLink', NuxtLink) | ||
const debug = require('debug')('nuxt:render') | ||
debug.color = 4 // force blue color | ||
const isDev = <%= isDev %> | ||
const noopApp = () => new Vue({ render: h => h('div') }) | ||
@@ -83,3 +85,3 @@ | ||
<% if (isDev) { %>const s = isDev && Date.now()<% } %> | ||
<% if (isDev) { %>const s = Date.now()<% } %> | ||
@@ -136,3 +138,4 @@ // Components are already resolved by setContext -> getRouteData (app/utils.js) | ||
midd = [] | ||
if (layout.middleware) midd = midd.concat(layout.middleware) | ||
layout = sanitizeComponent(layout) | ||
if (layout.options.middleware) midd = midd.concat(layout.options.middleware) | ||
Components.forEach((Component) => { | ||
@@ -139,0 +142,0 @@ if (Component.options.middleware) { |
@@ -6,111 +6,143 @@ import Vue from 'vue' | ||
const files = require.context('@/<%= dir.store %>', true, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/) | ||
const filenames = files.keys() | ||
const log = console // on server-side, consola will catch all console.log | ||
const VUEX_PROPERTIES = ['state', 'getters', 'actions', 'mutations'] | ||
let store = {} | ||
let fileResolver | ||
// Store | ||
let storeData = {} | ||
void (function updateModules() { | ||
fileResolver = require.context('@/<%= dir.store %>', true, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/) | ||
// Check if {dir.store}/index.js exists | ||
const indexFilename = filenames.find(filename => filename.includes('./index.')) | ||
// Paths are sorted from low to high priority (for overwriting properties) | ||
const paths = fileResolver.keys().sort((p1, p2) => { | ||
let res = p1.split('/').length - p2.split('/').length | ||
if (indexFilename) { | ||
storeData = getModule(indexFilename) | ||
} | ||
if (res === 0 && p1.includes('/index.')) { | ||
res = -1 | ||
} else if (res === 0 && p2.includes('/index.')) { | ||
res = 1 | ||
} | ||
return res | ||
}) | ||
// If store is not an exported method = modules store | ||
if (typeof storeData !== 'function') { | ||
// Store modules | ||
if (!storeData.modules) { | ||
storeData.modules = {} | ||
// Check if {dir.store}/index.js exists | ||
const indexPath = paths.find(path => path.includes('./index.')) | ||
if (indexPath) { | ||
store = requireModule(indexPath, { isRoot: true }) | ||
} | ||
for (const filename of filenames) { | ||
let name = filename.replace(/^\.\//, '').replace(/\.(<%= extensions %>)$/, '') | ||
if (name === 'index') continue | ||
// If store is an exported method = classic mode (deprecated) | ||
if (typeof store === 'function') { | ||
return log.warn('Classic mode for store/ is deprecated and will be removed in Nuxt 3.') | ||
} | ||
const namePath = name.split(/\//) | ||
// Enforce store modules | ||
store.modules = store.modules || {} | ||
name = namePath[namePath.length - 1] | ||
if (['state', 'getters', 'actions', 'mutations'].includes(name)) { | ||
const module = getModuleNamespace(storeData, namePath, true) | ||
appendModule(module, filename, name) | ||
for (const path of paths) { | ||
// Remove store path + extension (./foo/index.js -> foo/index) | ||
const namespace = path.replace(/^\.\//, '').replace(/\.(<%= extensions %>)$/, '') | ||
// Ignore indexFile, handled before | ||
if (namespace === 'index') { | ||
continue | ||
} | ||
// If file is foo/index.js, it should be saved as foo | ||
const isIndex = (name === 'index') | ||
if (isIndex) { | ||
namePath.pop() | ||
} | ||
const namespaces = namespace.split('/') | ||
let moduleName = namespaces[namespaces.length - 1] | ||
const moduleData = requireModule(path, { isState: moduleName === 'state' }) | ||
const module = getModuleNamespace(storeData, namePath) | ||
const fileModule = getModule(filename) | ||
// If path is a known Vuex property | ||
if (VUEX_PROPERTIES.includes(moduleName)) { | ||
const property = moduleName | ||
const storeModule = getStoreModule(store, namespaces, { isProperty: true }) | ||
name = namePath.pop() | ||
module[name] = module[name] || {} | ||
// if file is foo.js, existing properties take priority | ||
// because it's the least specific case | ||
if (!isIndex) { | ||
module[name] = Object.assign({}, fileModule, module[name]) | ||
module[name].namespaced = true | ||
// Replace state since it's a function | ||
mergeProperty(storeModule, moduleData, property) | ||
continue | ||
} | ||
// if file is foo/index.js we want to overwrite properties from foo.js | ||
// but not from appended mods like foo/actions.js | ||
const appendedMods = {} | ||
if (module[name].appends) { | ||
appendedMods.appends = module[name].appends | ||
for (const append of module[name].appends) { | ||
appendedMods[append] = module[name][append] | ||
} | ||
// If file is foo/index.js, it should be saved as foo | ||
const isIndexModule = (moduleName === 'index') | ||
if (isIndexModule) { | ||
namespaces.pop() | ||
moduleName = namespaces[namespaces.length - 1] | ||
} | ||
module[name] = Object.assign({}, module[name], fileModule, appendedMods) | ||
module[name].namespaced = true | ||
const storeModule = getStoreModule(store, namespaces) | ||
for (const property of VUEX_PROPERTIES) { | ||
mergeProperty(storeModule, moduleData[property], property) | ||
} | ||
} | ||
} | ||
// If the environment supports hot reloading... | ||
<% if (isDev) { %> | ||
if (process.client && module.hot) { | ||
// Whenever any Vuex module is updated... | ||
module.hot.accept(fileResolver.id, () => { | ||
// Update `root.modules` with the latest definitions. | ||
updateModules() | ||
// Trigger a hot update in the store. | ||
window.<%= globals.nuxt %>.$store.hotUpdate(store) | ||
}) | ||
}<% } %> | ||
})() | ||
// createStore | ||
export const createStore = storeData instanceof Function ? storeData : () => { | ||
export const createStore = store instanceof Function ? store : () => { | ||
return new Vuex.Store(Object.assign({ | ||
strict: (process.env.NODE_ENV !== 'production') | ||
}, storeData, { | ||
state: storeData.state instanceof Function ? storeData.state() : {} | ||
})) | ||
}, store)) | ||
} | ||
// Dynamically require module | ||
function getModule(filename) { | ||
const file = files(filename) | ||
const module = file.default || file | ||
if (module.commit) { | ||
throw new Error('[nuxt] <%= dir.store %>/' + filename.replace('./', '') + ' should export a method which returns a Vuex instance.') | ||
function requireModule(path, { isRoot = false, isState = false } = {}) { | ||
const file = fileResolver(path) | ||
let moduleData = file.default || file | ||
if (isState && typeof moduleData !== 'function') { | ||
log.warn(`${path} should export a method that returns an object`) | ||
const state = Object.assign({}, moduleData) | ||
return () => state | ||
} | ||
if (module.state && typeof module.state !== 'function') { | ||
throw new Error('[nuxt] state should be a function in <%= dir.store %>/' + filename.replace('./', '')) | ||
if (isRoot && moduleData.commit) { | ||
throw new Error('[nuxt] <%= dir.store %>/' + path.replace('./', '') + ' should export a method that returns a Vuex instance.') | ||
} | ||
return module | ||
if (isRoot && typeof moduleData !== 'function') { | ||
// Avoid TypeError: setting a property that has only a getter when overwriting top level keys | ||
moduleData = Object.assign({}, moduleData) | ||
} | ||
if (moduleData.state && typeof moduleData.state !== 'function') { | ||
log.warn(`'state' should be a method that returns an object in ${path}`) | ||
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 getModuleNamespace(storeData, namePath, forAppend = false) { | ||
if (namePath.length === 1) { | ||
if (forAppend) { | ||
return storeData | ||
} | ||
return storeData.modules | ||
function getStoreModule(storeModule, namespaces, { isProperty = false } = {}) { | ||
// If ./mutations.js | ||
if (!namespaces.length || (isProperty && namespaces.length === 1)) { | ||
return storeModule | ||
} | ||
const namespace = namePath.shift() | ||
storeData.modules[namespace] = storeData.modules[namespace] || {} | ||
storeData.modules[namespace].namespaced = true | ||
storeData.modules[namespace].modules = storeData.modules[namespace].modules || {} | ||
return getModuleNamespace(storeData.modules[namespace], namePath, forAppend) | ||
const namespace = namespaces.shift() | ||
storeModule.modules[namespace] = storeModule.modules[namespace] || {} | ||
storeModule.modules[namespace].namespaced = true | ||
storeModule.modules[namespace].modules = storeModule.modules[namespace].modules || {} | ||
return getStoreModule(storeModule.modules[namespace], namespaces, { isProperty }) | ||
} | ||
function appendModule(module, filename, name) { | ||
const file = files(filename) | ||
module.appends = module.appends || [] | ||
module.appends.push(name) | ||
module[name] = file.default || file | ||
function mergeProperty(storeModule, moduleData, property) { | ||
if (!moduleData) return | ||
if (property === 'state') { | ||
storeModule.state = moduleData || storeModule.state | ||
} else { | ||
storeModule[property] = Object.assign({}, storeModule[property], moduleData) | ||
} | ||
} |
@@ -114,4 +114,4 @@ import Vue from 'vue' | ||
...route, | ||
meta: getMatchedComponents(route).map((Component) => { | ||
return Component.options.meta || {} | ||
meta: getMatchedComponents(route).map((Component, index) => { | ||
return { ...Component.options.meta, ...(route.matched[index] || {}).meta } | ||
}) | ||
@@ -289,2 +289,3 @@ } | ||
return { | ||
...err, | ||
message: message, | ||
@@ -570,2 +571,1 @@ statusCode: (err.statusCode || err.status || (err.response && err.response.status) || 500) | ||
} | ||
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
131315
41
2462
0
6
+ Addedvue@^2.5.22
+ Addedvue-meta@^1.5.8
+ Addedvue-no-ssr@^1.1.1
+ Addedvue-router@^3.0.2
+ Addedvuex@^3.1.0
+ Added@babel/helper-string-parser@7.25.7(transitive)
+ Added@babel/helper-validator-identifier@7.25.7(transitive)
+ Added@babel/parser@7.25.8(transitive)
+ Added@babel/types@7.25.8(transitive)
+ Added@vue/compiler-sfc@2.7.16(transitive)
+ Addedcsstype@3.1.3(transitive)
+ Addedde-indent@1.0.2(transitive)
+ Addeddeepmerge@3.3.0(transitive)
+ Addedhe@1.2.0(transitive)
+ Addedlodash.isplainobject@4.0.6(transitive)
+ Addedlodash.uniqueid@4.0.1(transitive)
+ Addednanoid@3.3.7(transitive)
+ Addedobject-assign@4.1.1(transitive)
+ Addedpicocolors@1.1.1(transitive)
+ Addedpostcss@8.4.47(transitive)
+ Addedprettier@2.8.8(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addedsource-map-js@1.2.1(transitive)
+ Addedto-fast-properties@2.0.0(transitive)
+ Addedvue@2.7.16(transitive)
+ Addedvue-meta@1.6.0(transitive)
+ Addedvue-no-ssr@1.1.1(transitive)
+ Addedvue-router@3.6.5(transitive)
+ Addedvue-template-compiler@2.7.16(transitive)
+ Addedvuex@3.6.2(transitive)