forked from daren.hsu/line_push
update
This commit is contained in:
+17
@@ -0,0 +1,17 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [2.15.0](https://github.com/nuxt/nuxt.js/compare/v2.14.12...v2.15.0) (2020-12-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **vue-app:** do not preserve state when registering client-side dynamic module ([#8486](https://github.com/nuxt/nuxt.js/issues/8486)) ([1269773](https://github.com/nuxt/nuxt.js/commit/1269773d9d3ebc2e28df1efae9d15f6322ba3882))
|
||||
* **vue-app, vue-renderer, utils:** respect `trailingSlash` setting for payloads ([#8489](https://github.com/nuxt/nuxt.js/issues/8489)) ([fb191d2](https://github.com/nuxt/nuxt.js/commit/fb191d2fbd86a2ddeb5d83ee48f822139cc603c4)), closes [#8488](https://github.com/nuxt/nuxt.js/issues/8488)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **vue-app:** support custom `fetchKey` for full static generation ([#8466](https://github.com/nuxt/nuxt.js/issues/8466)) ([92018e5](https://github.com/nuxt/nuxt.js/commit/92018e586b766b6e2728925c9a324d9863bd5e77))
|
||||
+15
-14
@@ -1,35 +1,36 @@
|
||||
/*!
|
||||
* @nuxt/vue-app v2.13.3 (c) 2016-2020
|
||||
|
||||
* - All the amazing contributors
|
||||
* Released under the MIT License.
|
||||
* @nuxt/vue-app v2.15.8 (c) 2016-2021
|
||||
* Released under the MIT License
|
||||
* Repository: https://github.com/nuxt/nuxt.js
|
||||
* Website: https://nuxtjs.org
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
||||
const path = require('path');
|
||||
|
||||
const path = _interopDefault(require('path'));
|
||||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
||||
|
||||
const path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
||||
|
||||
var dependencies = {
|
||||
"node-fetch": "^2.6.0",
|
||||
unfetch: "^4.1.0",
|
||||
vue: "^2.6.11",
|
||||
"node-fetch": "^2.6.1",
|
||||
ufo: "^0.7.4",
|
||||
unfetch: "^4.2.0",
|
||||
vue: "^2.6.12",
|
||||
"vue-client-only": "^2.0.0",
|
||||
"vue-meta": "^2.4.0",
|
||||
"vue-no-ssr": "^1.1.1",
|
||||
"vue-router": "^3.3.4",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
vuex: "^3.5.1"
|
||||
"vue-router": "^3.5.1",
|
||||
"vue-template-compiler": "^2.6.12",
|
||||
vuex: "^3.6.2"
|
||||
};
|
||||
|
||||
const template = {
|
||||
dependencies,
|
||||
dir: path.join(__dirname, '..', 'template'),
|
||||
dir: path__default['default'].join(__dirname, '..', 'template'),
|
||||
files: [
|
||||
'nuxt/config.json',
|
||||
'App.js',
|
||||
'client.js',
|
||||
'index.js',
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
// Dummy type definition file to provide backward compatibility
|
||||
// around Nuxt modules extending `@nuxt/vue-app` for Nuxt < 2.9
|
||||
declare module "@nuxt/vue-app"
|
||||
declare module '@nuxt/vue-app'
|
||||
|
||||
+23
-19
@@ -1,51 +1,54 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"@nuxt/vue-app@2.13.3",
|
||||
"/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series"
|
||||
"@nuxt/vue-app@2.15.8",
|
||||
"/home/node/nuxt"
|
||||
]
|
||||
],
|
||||
"_from": "@nuxt/vue-app@2.13.3",
|
||||
"_id": "@nuxt/vue-app@2.13.3",
|
||||
"_from": "@nuxt/vue-app@2.15.8",
|
||||
"_id": "@nuxt/vue-app@2.15.8",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-C/KBGsm5x4W1aCffLLdcXnO1spQpjsqxXTyHGFlhfaMuShWYkb5n1HQcG2Nla7AY4QzOHbr6YPvJL1sF1CdyWw==",
|
||||
"_integrity": "sha512-FJf9FSMPsWT3BqkS37zEuPTxLKzSg2EIwp1sP8Eou25eE08qxRfe2PwTVA8HnXUPNdpz2uk/T9DlNw+JraiFRQ==",
|
||||
"_location": "/@nuxt/vue-app",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "@nuxt/vue-app@2.13.3",
|
||||
"raw": "@nuxt/vue-app@2.15.8",
|
||||
"name": "@nuxt/vue-app",
|
||||
"escapedName": "@nuxt%2fvue-app",
|
||||
"scope": "@nuxt",
|
||||
"rawSpec": "2.13.3",
|
||||
"rawSpec": "2.15.8",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "2.13.3"
|
||||
"fetchSpec": "2.15.8"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/@nuxt/builder"
|
||||
"/@nuxt/builder",
|
||||
"/nuxt"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/@nuxt/vue-app/-/vue-app-2.13.3.tgz",
|
||||
"_spec": "2.13.3",
|
||||
"_where": "/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series",
|
||||
"_resolved": "https://registry.npmjs.org/@nuxt/vue-app/-/vue-app-2.15.8.tgz",
|
||||
"_spec": "2.15.8",
|
||||
"_where": "/home/node/nuxt",
|
||||
"bugs": {
|
||||
"url": "https://github.com/nuxt/nuxt.js/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.0",
|
||||
"unfetch": "^4.1.0",
|
||||
"vue": "^2.6.11",
|
||||
"node-fetch": "^2.6.1",
|
||||
"ufo": "^0.7.4",
|
||||
"unfetch": "^4.2.0",
|
||||
"vue": "^2.6.12",
|
||||
"vue-client-only": "^2.0.0",
|
||||
"vue-meta": "^2.4.0",
|
||||
"vue-no-ssr": "^1.1.1",
|
||||
"vue-router": "^3.3.4",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"vuex": "^3.5.1"
|
||||
"vue-router": "^3.5.1",
|
||||
"vue-template-compiler": "^2.6.12",
|
||||
"vuex": "^3.6.2"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"template",
|
||||
"vetur",
|
||||
"web-types",
|
||||
"index.d.ts"
|
||||
],
|
||||
"homepage": "https://github.com/nuxt/nuxt.js#readme",
|
||||
@@ -60,5 +63,6 @@
|
||||
"url": "git+https://github.com/nuxt/nuxt.js.git"
|
||||
},
|
||||
"typings": "index.d.ts",
|
||||
"version": "2.13.3"
|
||||
"version": "2.15.8",
|
||||
"web-types": "web-types/web-types.json"
|
||||
}
|
||||
|
||||
+53
-23
@@ -1,4 +1,5 @@
|
||||
import Vue from 'vue'
|
||||
import { decode, parsePath, withoutBase, withoutTrailingSlash, normalizeURL } from 'ufo'
|
||||
<% utilsImports = [
|
||||
...(features.asyncData || features.fetch) ? [
|
||||
'getMatchedComponentsInstances',
|
||||
@@ -12,7 +13,7 @@ import Vue from 'vue'
|
||||
]: []
|
||||
] %>
|
||||
<% if (utilsImports.length) { %>import { <%= utilsImports.join(', ') %> } from './utils'<% } %>
|
||||
<% if (features.layouts && components.ErrorPage) { %>import NuxtError from '<%= components.ErrorPage %>'<% } %>
|
||||
import NuxtError from '<%= components.ErrorPage ? components.ErrorPage : "./components/nuxt-error.vue" %>'
|
||||
<% if (loading) { %>import NuxtLoading from '<%= (typeof loading === "string" ? loading : "./components/nuxt-loading.vue") %>'<% } %>
|
||||
<% if (buildIndicator) { %>import NuxtBuildIndicator from './components/nuxt-build-indicator'<% } %>
|
||||
<% css.forEach((c) => { %>
|
||||
@@ -98,7 +99,8 @@ export default {
|
||||
},
|
||||
created () {
|
||||
// Add this.$nuxt in child instances
|
||||
Vue.prototype.<%= globals.nuxt %> = this
|
||||
this.$root.$options.<%= globals.nuxt %> = this
|
||||
|
||||
if (process.client) {
|
||||
// add to window so we can listen when ready
|
||||
window.<%= globals.nuxt %> = <%= (globals.nuxt !== '$nuxt' ? 'window.$nuxt = ' : '') %>this
|
||||
@@ -129,11 +131,9 @@ export default {
|
||||
<% } %>
|
||||
},
|
||||
<% } %>
|
||||
<% if (loading) { %>
|
||||
watch: {
|
||||
'nuxt.err': 'errorChanged'
|
||||
},
|
||||
<% } %>
|
||||
<% if (features.clientOnline) { %>
|
||||
computed: {
|
||||
isOffline () {
|
||||
@@ -215,18 +215,29 @@ export default {
|
||||
<% if (loading) { %>this.$loading.finish()<% } %>
|
||||
<% } %>
|
||||
},
|
||||
<% if (loading) { %>
|
||||
errorChanged () {
|
||||
if (this.nuxt.err && this.$loading) {
|
||||
if (this.$loading.fail) {
|
||||
this.$loading.fail(this.nuxt.err)
|
||||
<% if (splitChunks.layouts) { %>async <% } %>errorChanged () {
|
||||
if (this.nuxt.err) {
|
||||
<% if (loading) { %>
|
||||
if (this.$loading) {
|
||||
if (this.$loading.fail) {
|
||||
this.$loading.fail(this.nuxt.err)
|
||||
}
|
||||
if (this.$loading.finish) {
|
||||
this.$loading.finish()
|
||||
}
|
||||
}
|
||||
if (this.$loading.finish) {
|
||||
this.$loading.finish()
|
||||
<% } %>
|
||||
let errorLayout = (NuxtError.options || NuxtError).layout;
|
||||
|
||||
if (typeof errorLayout === 'function') {
|
||||
errorLayout = errorLayout(this.context)
|
||||
}
|
||||
<% if (splitChunks.layouts) { %>
|
||||
await this.loadLayout(errorLayout)
|
||||
<% } %>
|
||||
this.setLayout(errorLayout)
|
||||
}
|
||||
},
|
||||
<% } %>
|
||||
<% if (features.layouts) { %>
|
||||
<% if (splitChunks.layouts) { %>
|
||||
setLayout (layout) {
|
||||
@@ -285,24 +296,43 @@ export default {
|
||||
<% } /* splitChunks.layouts */ %>
|
||||
<% } /* features.layouts */ %>
|
||||
<% if (isFullStatic) { %>
|
||||
getRouterBase() {
|
||||
return withoutTrailingSlash(this.$router.options.base)
|
||||
},
|
||||
getRoutePath(route = '/') {
|
||||
const base = this.getRouterBase()
|
||||
return withoutTrailingSlash(withoutBase(parsePath(route).pathname, base))
|
||||
},
|
||||
getStaticAssetsPath(route = '/') {
|
||||
const { staticAssetsBase } = window.<%= globals.context %>
|
||||
|
||||
return urlJoin(staticAssetsBase, this.getRoutePath(route))
|
||||
},
|
||||
<% if (nuxtOptions.generate.manifest) { %>
|
||||
async fetchStaticManifest() {
|
||||
return window.__NUXT_IMPORT__('manifest.js', normalizeURL(urlJoin(this.getStaticAssetsPath(), 'manifest.js')))
|
||||
},
|
||||
<% } %>
|
||||
setPagePayload(payload) {
|
||||
this._pagePayload = payload
|
||||
this._payloadFetchIndex = 0
|
||||
this._fetchCounters = {}
|
||||
},
|
||||
async fetchPayload(route) {
|
||||
const { staticAssetsBase } = window.<%= globals.context %>
|
||||
const base = (this.$router.options.base || '').replace(/\/+$/, '')
|
||||
if (base && route.startsWith(base)) {
|
||||
route = route.substr(base.length)
|
||||
async fetchPayload(route, prefetch) {
|
||||
const path = decode(this.getRoutePath(route))
|
||||
<% if (nuxtOptions.generate.manifest) { %>
|
||||
const manifest = await this.fetchStaticManifest()
|
||||
if (!manifest.routes.includes(path)) {
|
||||
if (!prefetch) { this.setPagePayload(false) }
|
||||
throw new Error(`Route ${path} is not pre-rendered`)
|
||||
}
|
||||
route = (route.replace(/\/+$/, '') || '/').split('?')[0].split('#')[0]
|
||||
const src = urlJoin(base, staticAssetsBase, route, 'payload.js')
|
||||
<% } %>
|
||||
const src = urlJoin(this.getStaticAssetsPath(route), 'payload.js')
|
||||
try {
|
||||
const payload = await window.__NUXT_IMPORT__(decodeURI(route), encodeURI(src))
|
||||
this.setPagePayload(payload)
|
||||
const payload = await window.__NUXT_IMPORT__(path, normalizeURL(src))
|
||||
if (!prefetch) { this.setPagePayload(payload) }
|
||||
return payload
|
||||
} catch (err) {
|
||||
this.setPagePayload(false)
|
||||
if (!prefetch) { this.setPagePayload(false) }
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
+46
-24
@@ -14,12 +14,16 @@ import {
|
||||
<% if (features.transitions || features.asyncData || features.fetch) { %>getLocation,<% } %>
|
||||
compile,
|
||||
getQueryDiff,
|
||||
globalHandleError
|
||||
globalHandleError,
|
||||
isSamePath,
|
||||
urlJoin
|
||||
} from './utils.js'
|
||||
import { createApp<% if (features.layouts) { %>, NuxtError<% } %> } from './index.js'
|
||||
<% if (features.fetch) { %>import fetchMixin from './mixins/fetch.client'<% } %>
|
||||
import NuxtLink from './components/nuxt-link.<%= features.clientPrefetch ? "client" : "server" %>.js' // should be included after ./index.js
|
||||
<% if (isFullStatic) { %>import './jsonp'<% } %>
|
||||
<% if (isFullStatic) { %>import { installJsonp } from './jsonp'<% } %>
|
||||
|
||||
<% if (isFullStatic) { %>installJsonp()<% } %>
|
||||
|
||||
<% if (features.fetch) { %>
|
||||
// Fetch mixin
|
||||
@@ -44,6 +48,11 @@ let router
|
||||
// Try to rehydrate SSR data from window
|
||||
const NUXT = window.<%= globals.context %> || {}
|
||||
|
||||
const $config = NUXT.config || {}
|
||||
if ($config._app) {
|
||||
__webpack_public_path__ = urlJoin($config._app.cdnURL, $config._app.assetsPath)
|
||||
}
|
||||
|
||||
Object.assign(Vue.config, <%= serialize(vue.config) %>)<%= isTest ? '// eslint-disable-line' : '' %>
|
||||
|
||||
<% if (nuxtOptions.render.ssrLog) { %>
|
||||
@@ -220,10 +229,8 @@ function applySSRData (Component, ssrData) {
|
||||
}
|
||||
|
||||
// Get matched components
|
||||
function resolveComponents (router) {
|
||||
const path = getLocation(router.options.base, router.options.mode)
|
||||
|
||||
return flatMapComponents(router.match(path), async (Component, _, match, key, index) => {
|
||||
function resolveComponents (route) {
|
||||
return flatMapComponents(route, async (Component, _, match, key, index) => {
|
||||
// If component is not resolved yet, resolve it
|
||||
if (typeof Component === 'function' && !Component.options) {
|
||||
Component = await Component()
|
||||
@@ -525,10 +532,12 @@ async function render (to, from, next) {
|
||||
<% } %>
|
||||
|
||||
<% if (isFullStatic && store) { %>
|
||||
// Replay store mutations, catching to avoid error page on SPA fallback
|
||||
promises.push(this.fetchPayload(to.path).then(payload => {
|
||||
payload.mutations.forEach(m => { this.$store.commit(m[0], m[1]) })
|
||||
}).catch(err => null))
|
||||
if (!this.isPreview && !spaFallback) {
|
||||
// Replay store mutations, catching to avoid error page on SPA fallback
|
||||
promises.push(this.fetchPayload(to.path).then(payload => {
|
||||
payload.mutations.forEach(m => { this.$store.commit(m[0], m[1]) })
|
||||
}).catch(err => null))
|
||||
}
|
||||
<% } %>
|
||||
|
||||
// Check disabled page loading
|
||||
@@ -610,7 +619,7 @@ function normalizeComponents (to, ___) {
|
||||
}
|
||||
|
||||
<% if (features.layouts) { %>
|
||||
function setLayoutForNextPage (to) {
|
||||
<% if (splitChunks.layouts) { %>async <% } %>function setLayoutForNextPage (to) {
|
||||
// Set layout
|
||||
let hasError = Boolean(this.$options.nuxt.err)
|
||||
if (this._hadError && this._dateLastError === this.$options.nuxt.dateErr) {
|
||||
@@ -623,6 +632,9 @@ function setLayoutForNextPage (to) {
|
||||
if (typeof layout === 'function') {
|
||||
layout = layout(app.context)
|
||||
}
|
||||
<% if (splitChunks.layouts) { %>
|
||||
await this.loadLayout(layout)
|
||||
<% } %>
|
||||
this.setLayout(layout)
|
||||
}
|
||||
<% } %>
|
||||
@@ -644,6 +656,8 @@ function fixPrepatch (to, ___) {
|
||||
const instances = getMatchedComponentsInstances(to)
|
||||
const Components = getMatchedComponents(to)
|
||||
|
||||
let triggerScroll = <%= features.transitions ? 'false' : 'true' %>
|
||||
|
||||
Vue.nextTick(() => {
|
||||
instances.forEach((instance, i) => {
|
||||
if (!instance || instance._isDestroyed) {
|
||||
@@ -661,12 +675,17 @@ function fixPrepatch (to, ___) {
|
||||
Vue.set(instance.$data, key, newData[key])
|
||||
}
|
||||
|
||||
// Ensure to trigger scroll event after calling scrollBehavior
|
||||
window.<%= globals.nuxt %>.$nextTick(() => {
|
||||
window.<%= globals.nuxt %>.$emit('triggerScroll')
|
||||
})
|
||||
triggerScroll = true
|
||||
}
|
||||
})
|
||||
|
||||
if (triggerScroll) {
|
||||
// Ensure to trigger scroll event after calling scrollBehavior
|
||||
window.<%= globals.nuxt %>.$nextTick(() => {
|
||||
window.<%= globals.nuxt %>.$emit('triggerScroll')
|
||||
})
|
||||
}
|
||||
|
||||
checkForErrors(this)
|
||||
<% if (isDev) { %>
|
||||
// Hot reloading
|
||||
@@ -827,7 +846,7 @@ async function mountApp (__app) {
|
||||
// Load page chunk
|
||||
if (!NUXT.data && NUXT.serverRendered) {
|
||||
try {
|
||||
const payload = await _app.fetchPayload(_app.context.route.path)
|
||||
const payload = await _app.fetchPayload(NUXT.routePath || _app.context.route.path)
|
||||
Object.assign(NUXT, payload)
|
||||
} catch (err) {}
|
||||
}
|
||||
@@ -863,7 +882,7 @@ async function mountApp (__app) {
|
||||
}
|
||||
<% if (features.transitions) { %>
|
||||
// Resolve route components
|
||||
const Components = await Promise.all(resolveComponents(router))
|
||||
const Components = await Promise.all(resolveComponents(app.context.route))
|
||||
|
||||
// Enable transitions
|
||||
_app.setTransitions = _app.$options.nuxt.setTransitions.bind(_app)
|
||||
@@ -872,7 +891,7 @@ async function mountApp (__app) {
|
||||
_lastPaths = router.currentRoute.matched.map(route => compile(route.path)(router.currentRoute.params))
|
||||
}
|
||||
<% } else if (features.asyncData || features.fetch) { %>
|
||||
await Promise.all(resolveComponents(router))
|
||||
await Promise.all(resolveComponents(app.context.route))
|
||||
<% } %>
|
||||
// Initialize error handler
|
||||
_app.$loading = {} // To avoid error while _app.$nuxt does not exist
|
||||
@@ -885,14 +904,17 @@ async function mountApp (__app) {
|
||||
router.beforeEach(render.bind(_app))
|
||||
|
||||
// Fix in static: remove trailing slash to force hydration
|
||||
if (process.static && NUXT.serverRendered && NUXT.routePath !== '/' && NUXT.routePath.slice(-1) !== '/' && _app.context.route.path.slice(-1) === '/') {
|
||||
_app.context.route.path = _app.context.route.path.replace(/\/+$/, '')
|
||||
// Full static, if server-rendered: hydrate, to allow custom redirect to generated page
|
||||
<% if (isFullStatic) { %>
|
||||
if (NUXT.serverRendered) {
|
||||
return mount()
|
||||
}
|
||||
// If page already is server rendered and it was done on the same route path as client side render
|
||||
if (NUXT.serverRendered && NUXT.routePath === _app.context.route.path) {
|
||||
mount()
|
||||
return
|
||||
<% } else { %>
|
||||
// Fix in static: remove trailing slash to force hydration
|
||||
if (NUXT.serverRendered && isSamePath(NUXT.routePath, _app.context.route.path)) {
|
||||
return mount()
|
||||
}
|
||||
<% } %>
|
||||
|
||||
// First render on client-side
|
||||
const clientFirstMount = () => {
|
||||
|
||||
+2
-1
@@ -7,7 +7,8 @@
|
||||
|
||||
<div class="title">{{ message }}</div>
|
||||
<p v-if="statusCode === 404" class="description">
|
||||
<NuxtLink class="error-link" to="/"><%= messages.back_to_home %></NuxtLink>
|
||||
<a v-if="typeof $route === 'undefined'" class="error-link" href="/"><% messages.back_to_home %></a>
|
||||
<NuxtLink v-else class="error-link" to="/"><%= messages.back_to_home %></NuxtLink>
|
||||
</p>
|
||||
<% if(debug) { %>
|
||||
<p class="description" v-else><%= messages.client_error_details %></p>
|
||||
|
||||
+3
-2
@@ -17,7 +17,7 @@ const cancelIdleCallback = window.cancelIdleCallback || function (id) {
|
||||
|
||||
const observer = window.IntersectionObserver && new window.IntersectionObserver((entries) => {
|
||||
entries.forEach(({ intersectionRatio, target: link }) => {
|
||||
if (intersectionRatio <= 0) {
|
||||
if (intersectionRatio <= 0 || !link.__prefetch) {
|
||||
return
|
||||
}
|
||||
link.__prefetch()
|
||||
@@ -111,7 +111,8 @@ export default {
|
||||
// Preload the data only if not in preview mode
|
||||
if (!this.$root.isPreview) {
|
||||
const { href } = this.$router.resolve(this.to, this.$route, this.append)
|
||||
this.$nuxt.fetchPayload(href).catch(() => {})
|
||||
if (this.<%= globals.nuxt %>)
|
||||
this.<%= globals.nuxt %>.fetchPayload(href, true).catch(() => {})
|
||||
}
|
||||
<% } %>
|
||||
<% if (router.linkPrefetchedClass) { %>
|
||||
|
||||
+51
-16
@@ -1,4 +1,5 @@
|
||||
import Vue from 'vue'
|
||||
<% if (store) { %>import Vuex from 'vuex'<% } %>
|
||||
<% 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'<% } %>
|
||||
@@ -43,6 +44,17 @@ Vue.component(NuxtChild.name, NuxtChild)
|
||||
// Component: <Nuxt>
|
||||
Vue.component(Nuxt.name, Nuxt)
|
||||
|
||||
Object.defineProperty(Vue.prototype, '<%= globals.nuxt %>', {
|
||||
get() {
|
||||
const globalNuxt = this.$root.$options.<%= globals.nuxt %>
|
||||
if (process.client && !globalNuxt && typeof window !== 'undefined') {
|
||||
return window.<%= globals.nuxt %>
|
||||
}
|
||||
return globalNuxt
|
||||
},
|
||||
configurable: true
|
||||
})
|
||||
|
||||
<% if (features.meta) {
|
||||
// vue-meta configuration
|
||||
const vueMetaOptions = {
|
||||
@@ -66,8 +78,21 @@ const defaultTransition = <%=
|
||||
%><%= isTest ? '// eslint-disable-line' : '' %>
|
||||
<% } %>
|
||||
|
||||
<% if (store) { %>
|
||||
const originalRegisterModule = Vuex.Store.prototype.registerModule
|
||||
|
||||
function registerModule (path, rawModule, options = {}) {
|
||||
const preserveState = process.client && (
|
||||
Array.isArray(path)
|
||||
? !!path.reduce((namespacedState, path) => namespacedState && namespacedState[path], this.state)
|
||||
: path in this.state
|
||||
)
|
||||
return originalRegisterModule.call(this, path, rawModule, { preserveState, ...options })
|
||||
}
|
||||
<% } %>
|
||||
|
||||
async function createApp(ssrContext, config = {}) {
|
||||
const router = await createRouter(ssrContext)
|
||||
const router = await createRouter(ssrContext, config)
|
||||
|
||||
<% if (store) { %>
|
||||
const store = createStore(ssrContext)
|
||||
@@ -75,8 +100,7 @@ async function createApp(ssrContext, config = {}) {
|
||||
store.$router = router
|
||||
<% if (mode === 'universal') { %>
|
||||
// Fix SSR caveat https://github.com/nuxt/nuxt.js/issues/3757#issuecomment-414689141
|
||||
const registerModule = store.registerModule
|
||||
store.registerModule = (path, rawModule, options) => registerModule.call(store, path, rawModule, Object.assign({ preserveState: process.client }, options))
|
||||
store.registerModule = registerModule
|
||||
<% } %>
|
||||
<% } %>
|
||||
|
||||
@@ -243,22 +267,33 @@ async function createApp(ssrContext, config = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
// If server-side, wait for async component to be resolved first
|
||||
if (process.server && ssrContext && ssrContext.url) {
|
||||
await new Promise((resolve, reject) => {
|
||||
router.push(ssrContext.url, resolve, () => {
|
||||
// navigated to a different route in router guard
|
||||
const unregister = router.afterEach(async (to, from, next) => {
|
||||
// Wait for async component to be resolved first
|
||||
await new Promise((resolve, reject) => {
|
||||
// Ignore 404s rather than blindly replacing URL in browser
|
||||
if (process.client) {
|
||||
const { route } = router.resolve(app.context.route.fullPath)
|
||||
if (!route.matched.length) {
|
||||
return resolve()
|
||||
}
|
||||
}
|
||||
router.replace(app.context.route.fullPath, resolve, (err) => {
|
||||
// https://github.com/vuejs/vue-router/blob/v3.4.3/src/util/errors.js
|
||||
if (!err._isRouter) return reject(err)
|
||||
if (err.type !== 2 /* NavigationFailureType.redirected */) return resolve()
|
||||
|
||||
// navigated to a different route in router guard
|
||||
const unregister = router.afterEach(async (to, from) => {
|
||||
if (process.server && ssrContext && ssrContext.url) {
|
||||
ssrContext.url = to.fullPath
|
||||
app.context.route = await getRouteData(to)
|
||||
app.context.params = to.params || {}
|
||||
app.context.query = to.query || {}
|
||||
unregister()
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
app.context.route = await getRouteData(to)
|
||||
app.context.params = to.params || {}
|
||||
app.context.query = to.query || {}
|
||||
unregister()
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
<% if(store) { %>store,<% } %>
|
||||
|
||||
+6
-3
@@ -75,6 +75,9 @@ function importChunk(chunkId, src) {
|
||||
return promise
|
||||
}
|
||||
|
||||
window.__NUXT_JSONP__ = function (chunkId, exports) { chunks[chunkId] = exports }
|
||||
window.__NUXT_JSONP_CACHE__ = chunks
|
||||
window.__NUXT_IMPORT__ = importChunk
|
||||
export function installJsonp() {
|
||||
window.__NUXT_JSONP__ = function (chunkId, exports) { chunks[chunkId] = exports }
|
||||
window.__NUXT_JSONP_CACHE__ = chunks
|
||||
window.__NUXT_IMPORT__ = importChunk
|
||||
}
|
||||
|
||||
|
||||
+21
-5
@@ -1,5 +1,5 @@
|
||||
import Vue from 'vue'
|
||||
import { hasFetch, normalizeError, addLifecycleHook } from '../utils'
|
||||
import { hasFetch, normalizeError, addLifecycleHook, createGetCounter } from '../utils'
|
||||
|
||||
const isSsrHydration = (vm) => vm.$vnode && vm.$vnode.elm && vm.$vnode.elm.dataset && vm.$vnode.elm.dataset.fetchKey
|
||||
const nuxtState = window.<%= globals.context %>
|
||||
@@ -38,7 +38,7 @@ function created() {
|
||||
|
||||
// Hydrate component
|
||||
this._hydrated = true
|
||||
this._fetchKey = +this.$vnode.elm.dataset.fetchKey
|
||||
this._fetchKey = this.$vnode.elm.dataset.fetchKey
|
||||
const data = nuxtState.fetch[this._fetchKey]
|
||||
|
||||
// If fetch error
|
||||
@@ -60,12 +60,22 @@ function createdFullStatic() {
|
||||
if (typeof this.$options.fetchOnServer === 'function') {
|
||||
fetchedOnServer = this.$options.fetchOnServer.call(this) !== false
|
||||
}
|
||||
if (!fetchedOnServer || this.$nuxt.isPreview || !this.$nuxt._pagePayload) {
|
||||
if (!fetchedOnServer || this.<%= globals.nuxt %>.isPreview || !this.<%= globals.nuxt %>._pagePayload) {
|
||||
return
|
||||
}
|
||||
this._hydrated = true
|
||||
this._fetchKey = this.$nuxt._payloadFetchIndex++
|
||||
const data = this.$nuxt._pagePayload.fetch[this._fetchKey]
|
||||
|
||||
const defaultKey = this.$options._scopeId || this.$options.name || ''
|
||||
const getCounter = createGetCounter(this.<%= globals.nuxt %>._fetchCounters, defaultKey)
|
||||
|
||||
if (typeof this.$options.fetchKey === 'function') {
|
||||
this._fetchKey = this.$options.fetchKey.call(this, getCounter)
|
||||
} else {
|
||||
const key = 'string' === typeof this.$options.fetchKey ? this.$options.fetchKey : defaultKey
|
||||
this._fetchKey = key ? key + ':' + getCounter(key) : String(getCounter(key))
|
||||
}
|
||||
|
||||
const data = this.<%= globals.nuxt %>._pagePayload.fetch[this._fetchKey]
|
||||
|
||||
// If fetch error
|
||||
if (data && data._error) {
|
||||
@@ -73,6 +83,12 @@ function createdFullStatic() {
|
||||
return
|
||||
}
|
||||
|
||||
// If there is a missing payload
|
||||
if (!data) {
|
||||
this.$fetch()
|
||||
return
|
||||
}
|
||||
|
||||
// Merge data
|
||||
for (const key in data) {
|
||||
Vue.set(this.$data, key, data[key])
|
||||
|
||||
+21
-3
@@ -1,5 +1,5 @@
|
||||
import Vue from 'vue'
|
||||
import { hasFetch, normalizeError, addLifecycleHook } from '../utils'
|
||||
import { hasFetch, normalizeError, addLifecycleHook, purifyData, createGetCounter } from '../utils'
|
||||
|
||||
async function serverPrefetch() {
|
||||
if (!this._fetchOnServer) {
|
||||
@@ -19,14 +19,20 @@ async function serverPrefetch() {
|
||||
|
||||
|
||||
// Define an ssrKey for hydration
|
||||
this._fetchKey = this.$ssrContext.nuxt.fetch.length
|
||||
this._fetchKey = this._fetchKey || this.$ssrContext.fetchCounters['']++
|
||||
|
||||
// Add data-fetch-key on parent element of Component
|
||||
const attrs = this.$vnode.data.attrs = this.$vnode.data.attrs || {}
|
||||
attrs['data-fetch-key'] = this._fetchKey
|
||||
|
||||
// Add to ssrContext for window.__NUXT__.fetch
|
||||
this.$ssrContext.nuxt.fetch.push(this.$fetchState.error ? { _error: this.$fetchState.error } : this._data)
|
||||
<% if (debug) { %>
|
||||
if (this.$ssrContext.nuxt.fetch[this._fetchKey] !== undefined) {
|
||||
console.warn(`Duplicate fetch key detected (${this._fetchKey}). This may lead to unexpected results.`)
|
||||
}
|
||||
<% } %>
|
||||
this.$ssrContext.nuxt.fetch[this._fetchKey] =
|
||||
this.$fetchState.error ? { _error: this.$fetchState.error } : purifyData(this._data)
|
||||
}
|
||||
|
||||
export default {
|
||||
@@ -41,6 +47,18 @@ export default {
|
||||
this._fetchOnServer = this.$options.fetchOnServer !== false
|
||||
}
|
||||
|
||||
const defaultKey = this.$options._scopeId || this.$options.name || ''
|
||||
const getCounter = createGetCounter(this.$ssrContext.fetchCounters, defaultKey)
|
||||
|
||||
if (typeof this.$options.fetchKey === 'function') {
|
||||
this._fetchKey = this.$options.fetchKey.call(this, getCounter)
|
||||
} else {
|
||||
const key = 'string' === typeof this.$options.fetchKey ? this.$options.fetchKey : defaultKey
|
||||
this._fetchKey = key ? key + ':' + getCounter(key) : String(getCounter(key))
|
||||
}
|
||||
|
||||
// Added for remove vue undefined warning while ssr
|
||||
this.$fetch = () => {} // issue #8043
|
||||
Vue.util.defineReactive(this, '$fetchState', {
|
||||
pending: true,
|
||||
error: null,
|
||||
|
||||
+22
-9
@@ -1,5 +1,6 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import { normalizeURL, decode } from 'ufo'
|
||||
import { interopDefault } from './utils'<%= isTest ? '// eslint-disable-line no-unused-vars' : '' %>
|
||||
import scrollBehavior from './router.scrollBehavior.js'
|
||||
|
||||
@@ -50,7 +51,7 @@ import scrollBehavior from './router.scrollBehavior.js'
|
||||
res += firstIndent + 'path: ' + JSON.stringify(route.path)
|
||||
res += (route.components) ? nextIndent + 'components: {' + resMap + '\n' + baseIndent + tab + '}' : ''
|
||||
res += (route.component) ? nextIndent + 'component: ' + route._name : ''
|
||||
res += (route.redirect) ? nextIndent + 'redirect: ' + JSON.stringify(route.redirect) : ''
|
||||
res += (route.redirect) ? nextIndent + 'redirect: ' + (typeof route.redirect === 'function' ? serialize(route.redirect) : JSON.stringify(route.redirect)) : ''
|
||||
res += (route.meta) ? nextIndent + 'meta: ' + JSON.stringify(route.meta) : ''
|
||||
res += (typeof route.props !== 'undefined') ? nextIndent + 'props: ' + (typeof route.props === 'function' ? serialize(route.props) : JSON.stringify(route.props)) : ''
|
||||
res += (typeof route.caseSensitive !== 'undefined') ? nextIndent + 'caseSensitive: ' + JSON.stringify(route.caseSensitive) : ''
|
||||
@@ -82,18 +83,13 @@ const _routes = recursiveRoutes(router.routes, ' ', _components, 1)
|
||||
}
|
||||
}).join('\n')%>
|
||||
|
||||
// TODO: remove in Nuxt 3
|
||||
const emptyFn = () => {}
|
||||
const originalPush = Router.prototype.push
|
||||
Router.prototype.push = function push (location, onComplete = emptyFn, onAbort) {
|
||||
return originalPush.call(this, location, onComplete, onAbort)
|
||||
}
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export const routerOptions = {
|
||||
mode: '<%= router.mode %>',
|
||||
base: decodeURI('<%= router.base %>'),
|
||||
base: '<%= router.base %>',
|
||||
linkActiveClass: '<%= router.linkActiveClass %>',
|
||||
linkExactActiveClass: '<%= router.linkExactActiveClass %>',
|
||||
scrollBehavior,
|
||||
@@ -105,6 +101,23 @@ export const routerOptions = {
|
||||
fallback: <%= router.fallback %>
|
||||
}
|
||||
|
||||
export function createRouter () {
|
||||
return new Router(routerOptions)
|
||||
export function createRouter (ssrContext, config) {
|
||||
const base = (config._app && config._app.basePath) || routerOptions.base
|
||||
const router = new Router({ ...routerOptions, base })
|
||||
|
||||
// TODO: remove in Nuxt 3
|
||||
const originalPush = router.push
|
||||
router.push = function push (location, onComplete = emptyFn, onAbort) {
|
||||
return originalPush.call(this, location, onComplete, onAbort)
|
||||
}
|
||||
|
||||
const resolve = router.resolve.bind(router)
|
||||
router.resolve = (to, current, append) => {
|
||||
if (typeof to === 'string') {
|
||||
to = normalizeURL(to)
|
||||
}
|
||||
return resolve(to, current, append)
|
||||
}
|
||||
|
||||
return router
|
||||
}
|
||||
|
||||
+24
-22
@@ -2,53 +2,55 @@
|
||||
<%= 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'
|
||||
<% } else { %>import { getMatchedComponents, setScrollRestoration } from './utils'
|
||||
|
||||
if (process.client) {
|
||||
if ('scrollRestoration' in window.history) {
|
||||
window.history.scrollRestoration = 'manual'
|
||||
setScrollRestoration('manual')
|
||||
|
||||
// reset scrollRestoration to auto when leaving page, allowing page reload
|
||||
// and back-navigation from other pages to use the browser to restore the
|
||||
// scrolling position.
|
||||
window.addEventListener('beforeunload', () => {
|
||||
window.history.scrollRestoration = 'auto'
|
||||
setScrollRestoration('auto')
|
||||
})
|
||||
|
||||
// Setting scrollRestoration to manual again when returning to this page.
|
||||
window.addEventListener('load', () => {
|
||||
window.history.scrollRestoration = 'manual'
|
||||
setScrollRestoration('manual')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default function (to, from, savedPosition) {
|
||||
// if the returned position is falsy or an empty object,
|
||||
// will retain current scroll position.
|
||||
let position = false
|
||||
function shouldScrollToTop(route) {
|
||||
const Pages = getMatchedComponents(route)
|
||||
if (Pages.length === 1) {
|
||||
const { options = {} } = Pages[0]
|
||||
return options.scrollToTop !== false
|
||||
}
|
||||
return Pages.some(({ options }) => options && options.scrollToTop)
|
||||
}
|
||||
|
||||
// if no children detected and scrollToTop is not explicitly disabled
|
||||
const Pages = getMatchedComponents(to)
|
||||
if (
|
||||
Pages.length < 2 &&
|
||||
Pages.every(Page => Page.options.scrollToTop !== false)
|
||||
) {
|
||||
// scroll to the top of the page
|
||||
position = { x: 0, y: 0 }
|
||||
} else if (Pages.some(Page => Page.options.scrollToTop)) {
|
||||
// if one of the children has scrollToTop option set to true
|
||||
position = { x: 0, y: 0 }
|
||||
}
|
||||
export default function (to, from, savedPosition) {
|
||||
// If the returned position is falsy or an empty object, will retain current scroll position
|
||||
let position = false
|
||||
const isRouteChanged = to !== from
|
||||
|
||||
// savedPosition is only available for popstate navigations (back button)
|
||||
if (savedPosition) {
|
||||
position = savedPosition
|
||||
} else if (isRouteChanged && shouldScrollToTop(to)) {
|
||||
position = { x: 0, y: 0 }
|
||||
}
|
||||
|
||||
const nuxt = window.<%= globals.nuxt %>
|
||||
|
||||
// triggerScroll is only fired when a new component is loaded
|
||||
if (to.path === from.path && to.hash !== from.hash) {
|
||||
if (
|
||||
// Initial load (vuejs/vue-router#3199)
|
||||
!isRouteChanged ||
|
||||
// Route hash changes
|
||||
(to.path === from.path && to.hash !== from.hash)
|
||||
) {
|
||||
nuxt.$nextTick(() => nuxt.$emit('triggerScroll'))
|
||||
}
|
||||
|
||||
|
||||
+40
-17
@@ -1,5 +1,5 @@
|
||||
import { stringify } from 'querystring'
|
||||
import Vue from 'vue'
|
||||
import { joinURL, normalizeURL, withQuery } from 'ufo'
|
||||
<% if (fetch.server) { %>import fetch from 'node-fetch'<% } %>
|
||||
<% if (features.middleware) { %>import middleware from './middleware.js'<% } %>
|
||||
import {
|
||||
@@ -24,17 +24,31 @@ if (!Vue.__nuxt__fetch__mixin__) {
|
||||
}
|
||||
<% } %>
|
||||
|
||||
<% if (isDev) { %>
|
||||
if (!Vue.__original_use__) {
|
||||
Vue.__original_use__ = Vue.use
|
||||
Vue.__install_times__ = 0
|
||||
Vue.use = function (plugin, ...args) {
|
||||
plugin.__nuxt_external_installed__ = Vue._installedPlugins.includes(plugin)
|
||||
return Vue.__original_use__(plugin, ...args)
|
||||
}
|
||||
}
|
||||
if (Vue.__install_times__ === 2) {
|
||||
Vue.__install_times__ = 0
|
||||
Vue._installedPlugins = Vue._installedPlugins.filter(plugin => {
|
||||
return plugin.__nuxt_external_installed__ === true
|
||||
})
|
||||
}
|
||||
Vue.__install_times__++
|
||||
<% } %>
|
||||
|
||||
// Component: <NuxtLink>
|
||||
Vue.component(NuxtLink.name, NuxtLink)
|
||||
<% if (features.componentAliases) { %>Vue.component('NLink', NuxtLink)<% } %>
|
||||
|
||||
<% if (fetch.server) { %>if (!global.fetch) { global.fetch = fetch }<% } %>
|
||||
|
||||
const noopApp = () => new Vue({ render: h => h('div') })
|
||||
|
||||
function urlJoin () {
|
||||
return Array.prototype.slice.call(arguments).join('/').replace(/\/+/g, '/')
|
||||
}
|
||||
const noopApp = () => new Vue({ render: h => h('div', { domProps: { id: '<%= globals.id %>' } }) })
|
||||
|
||||
const createNext = ssrContext => (opts) => {
|
||||
// If static target, render on client-side
|
||||
@@ -43,19 +57,19 @@ const createNext = ssrContext => (opts) => {
|
||||
ssrContext.nuxt.serverRendered = false
|
||||
return
|
||||
}
|
||||
opts.query = stringify(opts.query)
|
||||
opts.path = opts.path + (opts.query ? '?' + opts.query : '')
|
||||
const routerBase = '<%= router.base %>'
|
||||
if (!opts.path.startsWith('http') && (routerBase !== '/' && !opts.path.startsWith(routerBase))) {
|
||||
opts.path = urlJoin(routerBase, opts.path)
|
||||
let fullPath = withQuery(opts.path, opts.query)
|
||||
const $config = ssrContext.runtimeConfig || {}
|
||||
const routerBase = ($config._app && $config._app.basePath) || '<%= router.base %>'
|
||||
if (!fullPath.startsWith('http') && (routerBase !== '/' && !fullPath.startsWith(routerBase))) {
|
||||
fullPath = joinURL(routerBase, fullPath)
|
||||
}
|
||||
// Avoid loop redirect
|
||||
if (opts.path === ssrContext.url) {
|
||||
if (decodeURI(fullPath) === decodeURI(ssrContext.url)) {
|
||||
ssrContext.redirected = false
|
||||
return
|
||||
}
|
||||
ssrContext.res.writeHead(opts.status, {
|
||||
Location: opts.path
|
||||
Location: normalizeURL(fullPath)
|
||||
})
|
||||
ssrContext.res.end()
|
||||
}
|
||||
@@ -72,15 +86,24 @@ export default async (ssrContext) => {
|
||||
// Used for beforeNuxtRender({ Components, nuxtState })
|
||||
ssrContext.beforeRenderFns = []
|
||||
// Nuxt object (window.{{globals.context}}, defaults to window.__NUXT__)
|
||||
ssrContext.nuxt = { <% if (features.layouts) { %>layout: 'default', <% } %>data: [], <% if (features.fetch) { %>fetch: [], <% } %>error: null<%= (store ? ', state: null' : '') %>, serverRendered: true, routePath: '' }
|
||||
ssrContext.nuxt = { <% if (features.layouts) { %>layout: 'default', <% } %>data: [], <% if (features.fetch) { %>fetch: {}, <% } %>error: null<%= (store ? ', state: null' : '') %>, serverRendered: true, routePath: '' }
|
||||
<% if (features.fetch) { %>
|
||||
ssrContext.fetchCounters = {}
|
||||
<% } %>
|
||||
|
||||
// Remove query from url is static target
|
||||
if (process.static && ssrContext.url) {
|
||||
<% if (isFullStatic) { %>
|
||||
if (ssrContext.url) {
|
||||
ssrContext.url = ssrContext.url.split('?')[0]
|
||||
}
|
||||
<% } %>
|
||||
// Public runtime config
|
||||
ssrContext.nuxt.config = ssrContext.runtimeConfig.public
|
||||
if (ssrContext.nuxt.config._app) {
|
||||
__webpack_public_path__ = joinURL(ssrContext.nuxt.config._app.cdnURL, ssrContext.nuxt.config._app.assetsPath)
|
||||
}
|
||||
// Create the app definition and the instance (created for each request)
|
||||
const { app, router<%= (store ? ', store' : '') %> } = await createApp(ssrContext, { ...ssrContext.runtimeConfig.public, ...ssrContext.runtimeConfig.private })
|
||||
const { app, router<%= (store ? ', store' : '') %> } = await createApp(ssrContext, ssrContext.runtimeConfig.private)
|
||||
const _app = new Vue(app)
|
||||
// Add ssr route path to nuxt context so we can account for page navigation between ssr and csr
|
||||
ssrContext.nuxt.routePath = app.context.route.path
|
||||
@@ -133,7 +156,7 @@ export default async (ssrContext) => {
|
||||
<% if (debug) { %>const s = Date.now()<% } %>
|
||||
|
||||
// Components are already resolved by setContext -> getRouteData (app/utils.js)
|
||||
const Components = getMatchedComponents(router.match(ssrContext.url))
|
||||
const Components = getMatchedComponents(app.context.route)
|
||||
|
||||
<% if (store) { %>
|
||||
/*
|
||||
|
||||
+2
-2
@@ -94,10 +94,10 @@ function resolveStoreModules (moduleData, filename) {
|
||||
// If src is a known Vuex property
|
||||
if (VUEX_PROPERTIES.includes(moduleName)) {
|
||||
const property = moduleName
|
||||
const storeModule = getStoreModule(store, namespaces, { isProperty: true })
|
||||
const propertyStoreModule = getStoreModule(store, namespaces, { isProperty: true })
|
||||
|
||||
// Replace state since it's a function
|
||||
mergeProperty(storeModule, moduleData, property)
|
||||
mergeProperty(propertyStoreModule, moduleData, property)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+77
-95
@@ -1,4 +1,5 @@
|
||||
import Vue from 'vue'
|
||||
import { isSamePath as _isSamePath, joinURL, normalizeURL, withQuery, withoutTrailingSlash } from 'ufo'
|
||||
|
||||
// window.{{globals.loadedCallback}} hook
|
||||
// Useful for jsdom testing or plugins (https://github.com/tmpvar/jsdom#dealing-with-asynchronous-script-loading)
|
||||
@@ -9,6 +10,15 @@ if (process.client) {
|
||||
}
|
||||
}
|
||||
|
||||
export function createGetCounter (counterObject, defaultKey = '') {
|
||||
return function getCounter (id = defaultKey) {
|
||||
if (counterObject[id] === undefined) {
|
||||
counterObject[id] = 0
|
||||
}
|
||||
return counterObject[id]++
|
||||
}
|
||||
}
|
||||
|
||||
export function empty () {}
|
||||
|
||||
export function globalHandleError (error) {
|
||||
@@ -25,6 +35,24 @@ export function interopDefault (promise) {
|
||||
export function hasFetch(vm) {
|
||||
return vm.$options && typeof vm.$options.fetch === 'function' && !vm.$options.fetch.length
|
||||
}
|
||||
export function purifyData(data) {
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
return data
|
||||
}
|
||||
|
||||
return Object.entries(data).filter(
|
||||
([key, value]) => {
|
||||
const valid = !(value instanceof Function) && !(value instanceof Promise)
|
||||
if (!valid) {
|
||||
console.warn(`${key} is not able to be stringified. This will break in a production environment.`)
|
||||
}
|
||||
return valid
|
||||
}
|
||||
).reduce((obj, [key, value]) => {
|
||||
obj[key] = value
|
||||
return obj
|
||||
}, {})
|
||||
}
|
||||
export function getChildrenComponentInstancesUsingFetch(vm, instances = []) {
|
||||
const children = vm.$children || []
|
||||
for (const child of children) {
|
||||
@@ -118,7 +146,29 @@ export function resolveRouteComponents (route, fn) {
|
||||
flatMapComponents(route, async (Component, instance, match, key) => {
|
||||
// If component is a function, resolve it
|
||||
if (typeof Component === 'function' && !Component.options) {
|
||||
Component = await Component()
|
||||
try {
|
||||
Component = await Component()
|
||||
} catch (error) {
|
||||
// Handle webpack chunk loading errors
|
||||
// This may be due to a new deployment or a network problem
|
||||
if (
|
||||
error &&
|
||||
error.name === 'ChunkLoadError' &&
|
||||
typeof window !== 'undefined' &&
|
||||
window.sessionStorage
|
||||
) {
|
||||
const timeNow = Date.now()
|
||||
const previousReloadTime = parseInt(window.sessionStorage.getItem('nuxt-reload'))
|
||||
|
||||
// check for previous reload time not to reload infinitely
|
||||
if (!previousReloadTime || previousReloadTime + 60000 < timeNow) {
|
||||
window.sessionStorage.setItem('nuxt-reload', timeNow)
|
||||
window.location.reload(true /* skip cache */)
|
||||
}
|
||||
}
|
||||
|
||||
throw error
|
||||
}
|
||||
}
|
||||
match.components[key] = Component = sanitizeComponent(Component)
|
||||
return typeof fn === 'function' ? fn(Component, instance, match, key) : Component
|
||||
@@ -152,16 +202,18 @@ export async function setContext (app, context) {
|
||||
<%= (store ? 'store: app.store,' : '') %>
|
||||
payload: context.payload,
|
||||
error: context.error,
|
||||
base: '<%= router.base %>',
|
||||
base: app.router.options.base,
|
||||
env: <%= JSON.stringify(env) %><%= isTest ? '// eslint-disable-line' : '' %>
|
||||
}
|
||||
// Only set once
|
||||
if (!process.static && context.req) {
|
||||
<% if (!isFullStatic) { %>
|
||||
if (context.req) {
|
||||
app.context.req = context.req
|
||||
}
|
||||
if (!process.static && context.res) {
|
||||
if (context.res) {
|
||||
app.context.res = context.res
|
||||
}
|
||||
<% } %>
|
||||
if (context.ssrContext) {
|
||||
app.context.ssrContext = context.ssrContext
|
||||
}
|
||||
@@ -189,7 +241,7 @@ export async function setContext (app, context) {
|
||||
status
|
||||
})
|
||||
} else {
|
||||
path = formatUrl(path, query)
|
||||
path = withQuery(path, query)
|
||||
if (process.server) {
|
||||
app.context.next({
|
||||
path,
|
||||
@@ -278,15 +330,20 @@ export function promisify (fn, context) {
|
||||
|
||||
// Imported from vue-router
|
||||
export function getLocation (base, mode) {
|
||||
let path = decodeURI(window.location.pathname)
|
||||
if (mode === 'hash') {
|
||||
return window.location.hash.replace(/^#\//, '')
|
||||
}
|
||||
// To get matched with sanitized router.base add trailing slash
|
||||
if (base && (path.endsWith('/') ? path : path + '/').startsWith(base)) {
|
||||
|
||||
base = decodeURI(base).slice(0, -1) // consideration is base is normalized with trailing slash
|
||||
let path = decodeURI(window.location.pathname)
|
||||
|
||||
if (base && path.startsWith(base)) {
|
||||
path = path.slice(base.length)
|
||||
}
|
||||
return (path || '/') + window.location.search + window.location.hash
|
||||
|
||||
const fullPath = (path || '/') + window.location.search + window.location.hash
|
||||
|
||||
return normalizeURL(fullPath)
|
||||
}
|
||||
|
||||
// Imported from path-to-regexp
|
||||
@@ -559,86 +616,6 @@ function flags (options) {
|
||||
return options && options.sensitive ? '' : 'i'
|
||||
}
|
||||
|
||||
/**
|
||||
* Format given url, append query to url query string
|
||||
*
|
||||
* @param {string} url
|
||||
* @param {string} query
|
||||
* @return {string}
|
||||
*/
|
||||
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
|
||||
const index = url.indexOf('://')
|
||||
if (index !== -1) {
|
||||
protocol = url.substring(0, index)
|
||||
url = url.substring(index + 3)
|
||||
} else if (url.startsWith('//')) {
|
||||
url = url.substring(2)
|
||||
}
|
||||
|
||||
let parts = url.split('/')
|
||||
let result = (protocol ? protocol + '://' : '//') + parts.shift()
|
||||
|
||||
let path = parts.join('/')
|
||||
if (path === '' && parts.length === 1) {
|
||||
result += '/'
|
||||
}
|
||||
|
||||
let hash
|
||||
parts = path.split('#')
|
||||
if (parts.length === 2) {
|
||||
[path, hash] = parts
|
||||
}
|
||||
|
||||
result += path ? '/' + path : ''
|
||||
|
||||
if (query && JSON.stringify(query) !== '{}') {
|
||||
result += (url.split('?').length === 2 ? '&' : '?') + formatQuery(query)
|
||||
}
|
||||
result += hash ? '#' + hash : ''
|
||||
|
||||
return result
|
||||
<% } %>
|
||||
}
|
||||
<% if (!features.clientUseUrl) { %>
|
||||
/**
|
||||
* Transform data object to query string
|
||||
*
|
||||
* @param {object} query
|
||||
* @return {string}
|
||||
*/
|
||||
function formatQuery (query) {
|
||||
return Object.keys(query).sort().map((key) => {
|
||||
const val = query[key]
|
||||
if (val == null) {
|
||||
return ''
|
||||
}
|
||||
if (Array.isArray(val)) {
|
||||
return val.slice().map(val2 => [key, '=', val2].join('')).join('&')
|
||||
}
|
||||
return key + '=' + val
|
||||
}).filter(Boolean).join('&')
|
||||
}
|
||||
<% } %>
|
||||
|
||||
export function addLifecycleHook(vm, hook, fn) {
|
||||
if (!vm.$options[hook]) {
|
||||
vm.$options[hook] = []
|
||||
@@ -648,10 +625,15 @@ export function addLifecycleHook(vm, hook, fn) {
|
||||
}
|
||||
}
|
||||
|
||||
export const urlJoin = function urlJoin () {
|
||||
return [].slice
|
||||
.call(arguments)
|
||||
.join('/')
|
||||
.replace(/\/+/g, '/')
|
||||
.replace(':/', '://')
|
||||
export const urlJoin = joinURL
|
||||
|
||||
export const stripTrailingSlash = withoutTrailingSlash
|
||||
|
||||
export const isSamePath = _isSamePath
|
||||
|
||||
export function setScrollRestoration (newVal) {
|
||||
try {
|
||||
window.history.scrollRestoration = newVal;
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/web-types",
|
||||
"name": "@nuxt/vue-app",
|
||||
"framework": "vue",
|
||||
"version": "2.13.1",
|
||||
"contributions": {
|
||||
"html": {
|
||||
"description-markup": "markdown",
|
||||
"types-syntax": "typescript",
|
||||
"tags": [
|
||||
{
|
||||
"name": "Nuxt",
|
||||
"description": "This component is used only in layouts to display the page components.",
|
||||
"doc-url": "https://nuxtjs.org/api/components-nuxt",
|
||||
"attributes": [
|
||||
{
|
||||
"name": "next-child-key",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "string"
|
||||
},
|
||||
"default": "$route.path",
|
||||
"description": "This prop will be set to `<router-view/>`, useful to make transitions inside a dynamic page and different route."
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "string"
|
||||
},
|
||||
"default": "default",
|
||||
"description": "This prop will be set to `<router-view/>`, used to render `named-view` of page component."
|
||||
},
|
||||
{
|
||||
"name": "keep-alive",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "keep-alive-props",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "NuxtChild",
|
||||
"aliases": [
|
||||
"NChild"
|
||||
],
|
||||
"description": "This component is used for displaying the children components in a nested route.",
|
||||
"doc-url": "https://nuxtjs.org/api/components-nuxt-child",
|
||||
"attributes": [
|
||||
{
|
||||
"name": "nuxt-child-key",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "string"
|
||||
},
|
||||
"description": "This prop will be set to `<router-view/>`, used to render named-view of page component."
|
||||
},
|
||||
{
|
||||
"name": "keep-alive",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "keep-alive-props",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "NuxtLink",
|
||||
"aliases": [
|
||||
"NLink"
|
||||
],
|
||||
"doc-url": "https://nuxtjs.org/api/components-nuxt-link",
|
||||
"description": "This component is used to provide navigations between page components and enhance performances with smart prefetching.",
|
||||
"attributes": [
|
||||
{
|
||||
"name": "no-prefetch",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "prefetch",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "prefetched-class",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "to",
|
||||
"required": true,
|
||||
"doc-url": "https://router.vuejs.org/api/#to",
|
||||
"description": "Denotes the target route of the link. When clicked, the value of the `to` prop will be passed to `router.push()` internally, so the value can be either a string or a location descriptor object.",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": [
|
||||
"string",
|
||||
"object"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tag",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "string"
|
||||
},
|
||||
"default": "'a'",
|
||||
"doc-url": "https://router.vuejs.org/api/#tag",
|
||||
"description": "Sometimes we want `<router-link>` to render as another tag, e.g `<li>`. Then we can use `tag` prop to specify which tag to render to, and it will still listen to click events for navigation."
|
||||
},
|
||||
{
|
||||
"name": "exact",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": "false",
|
||||
"doc-url": "https://router.vuejs.org/api/#exact",
|
||||
"description": "The default active class matching behavior is **inclusive match**. For example, `<router-link to=\"/a\">` will get this class applied as long as the current path starts with `/a/` or is `/a`.\n\nOne consequence of this is that `<router-link to=\"/\">` will be active for every route! To force the link into \"exact match mode\", use the `exact` prop"
|
||||
},
|
||||
{
|
||||
"name": "append",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": "false",
|
||||
"doc-url": "https://router.vuejs.org/api/#append",
|
||||
"description": "Setting `append` prop always appends the relative path to the current path. "
|
||||
},
|
||||
{
|
||||
"name": "replace",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "boolean"
|
||||
},
|
||||
"default": "false",
|
||||
"doc-url": "https://router.vuejs.org/api/#replace",
|
||||
"description": "Setting `replace` prop will call `router.replace()` instead of `router.push()` when clicked, so the navigation will not leave a history record."
|
||||
},
|
||||
{
|
||||
"name": "activeClass",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "string"
|
||||
},
|
||||
"default": "'router-link-active'",
|
||||
"doc-url": "https://router.vuejs.org/api/#active-class",
|
||||
"description": "Configure the active CSS class applied when the link is active. Note the default value can also be configured globally via the `linkActiveClass` router constructor option."
|
||||
},
|
||||
{
|
||||
"name": "exactActiveClass",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "string"
|
||||
},
|
||||
"default": "'router-link-exact-active'",
|
||||
"doc-url": "https://router.vuejs.org/api/#exact-active-class",
|
||||
"description": "Configure the active CSS class applied when the link is active with exact match. Note the default value can also be configured globally via the `linkExactActiveClass` router constructor option."
|
||||
},
|
||||
{
|
||||
"name": "ariaCurrentValue",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": "'page' | 'step' | 'location' | 'date' | 'time'"
|
||||
},
|
||||
"default": "'page'",
|
||||
"doc-url": "https://router.vuejs.org/api/#aria-current-value",
|
||||
"description": "Configure the value of `aria-current` when the link is active with exact match. It must be one of the allowed values for aria-current in the ARIA spec. In most cases, the default of `page` should be the best fit."
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"value": {
|
||||
"kind": "expression",
|
||||
"type": [
|
||||
"string",
|
||||
"string[]"
|
||||
]
|
||||
},
|
||||
"default": "'click'",
|
||||
"doc-url": "https://router.vuejs.org/api/#event",
|
||||
"description": "Specify the event(s) that can trigger the link navigation."
|
||||
}
|
||||
],
|
||||
"slots": [
|
||||
{
|
||||
"name": "default",
|
||||
"vue-properties": [
|
||||
{
|
||||
"name": "href",
|
||||
"description": "Resolved url. This would be the `href` attribute of an `a` element",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "route",
|
||||
"description": "Resolved normalized location",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"name": "navigate",
|
||||
"description": "Function to trigger the navigation. **It will automatically prevent events when necessary**, the same way `router-link` does",
|
||||
"type": "() => any"
|
||||
},
|
||||
{
|
||||
"name": "isActive",
|
||||
"description": "`true` if the active class should be applied. Allows to apply an arbitrary class",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "isExactActive",
|
||||
"description": "`true` if the exact active class should be applied. Allows to apply an arbitrary class",
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user