1 | import Vue from 'vue'
|
2 | <% if (store) { %>import Vuex from 'vuex'<% } %>
|
3 | <% if (features.meta) { %>import Meta from 'vue-meta'<% } %>
|
4 | <% if (features.componentClientOnly) { %>import ClientOnly from 'vue-client-only'<% } %>
|
5 | <% if (features.deprecations) { %>import NoSsr from 'vue-no-ssr'<% } %>
|
6 | import { createRouter } from './router.js'
|
7 | import NuxtChild from './components/nuxt-child.js'
|
8 | import NuxtError from '<%= components.ErrorPage ? components.ErrorPage : "./components/nuxt-error.vue" %>'
|
9 | import Nuxt from './components/nuxt.js'
|
10 | import App from '<%= appPath %>'
|
11 | import { setContext, getLocation, getRouteData, normalizeError } from './utils'
|
12 | <% if (store) { %>import { createStore } from './store.js'<% } %>
|
13 |
|
14 |
|
15 | <%= isTest ? '/* eslint-disable camelcase */' : '' %>
|
16 | <% plugins.forEach((plugin) => { %>import <%= plugin.name %> from '<%= plugin.name %>'
|
17 | <% }) %>
|
18 | <%= isTest ? '/* eslint-enable camelcase */' : '' %>
|
19 |
|
20 | <% if (features.componentClientOnly) { %>
|
21 |
|
22 | Vue.component(ClientOnly.name, ClientOnly)
|
23 | <% } %>
|
24 | <% if (features.deprecations) { %>
|
25 |
|
26 | Vue.component(NoSsr.name, {
|
27 | ...NoSsr,
|
28 | render (h, ctx) {
|
29 | if (process.client && !NoSsr._warned) {
|
30 | NoSsr._warned = true
|
31 | <%= isTest ? '// eslint-disable-next-line no-console' : '' %>
|
32 | console.warn('<no-ssr> has been deprecated and will be removed in Nuxt 3, please use <client-only> instead')
|
33 | }
|
34 | return NoSsr.render(h, ctx)
|
35 | }
|
36 | })
|
37 | <% } %>
|
38 |
|
39 | Vue.component(NuxtChild.name, NuxtChild)
|
40 | <% if (features.componentAliases) { %>Vue.component('NChild', NuxtChild)<% } %>
|
41 |
|
42 |
|
43 |
|
44 |
|
45 | Vue.component(Nuxt.name, Nuxt)
|
46 |
|
47 | <% if (features.meta) {
|
48 |
|
49 | const vueMetaOptions = {
|
50 | ...nuxtOptions.vueMeta,
|
51 | keyName: 'head',
|
52 | attribute: 'data-n-head',
|
53 | ssrAttribute: 'data-n-head-ssr',
|
54 | tagIDKeyName: 'hid'
|
55 | }
|
56 | %>
|
57 | Vue.use(Meta, <%= JSON.stringify(vueMetaOptions) %>)<%= isTest ? '// eslint-disable-line' : '' %>
|
58 | <% } %>
|
59 |
|
60 | <% if (features.transitions) { %>
|
61 | const defaultTransition = <%=
|
62 | serialize(pageTransition)
|
63 | .replace('beforeEnter(', 'function(').replace('enter(', 'function(').replace('afterEnter(', 'function(')
|
64 | .replace('enterCancelled(', 'function(').replace('beforeLeave(', 'function(').replace('leave(', 'function(')
|
65 | .replace('afterLeave(', 'function(').replace('leaveCancelled(', 'function(').replace('beforeAppear(', 'function(')
|
66 | .replace('appear(', 'function(').replace('afterAppear(', 'function(').replace('appearCancelled(', 'function(')
|
67 | %><%= isTest ? '// eslint-disable-line' : '' %>
|
68 | <% } %>
|
69 |
|
70 | <% if (store) { %>
|
71 | const originalRegisterModule = Vuex.Store.prototype.registerModule
|
72 | const baseStoreOptions = { preserveState: process.client }
|
73 |
|
74 | function registerModule (path, rawModule, options = {}) {
|
75 | return originalRegisterModule.call(this, path, rawModule, { ...baseStoreOptions, ...options })
|
76 | }
|
77 | <% } %>
|
78 |
|
79 | async function createApp(ssrContext, config = {}) {
|
80 | const router = await createRouter(ssrContext)
|
81 |
|
82 | <% if (store) { %>
|
83 | const store = createStore(ssrContext)
|
84 | // Add this.$router into store actions/mutations
|
85 | store.$router = router
|
86 | <% if (mode === 'universal') { %>
|
87 | // Fix SSR caveat https://github.com/nuxt/nuxt.js/issues/3757#issuecomment-414689141
|
88 | store.registerModule = registerModule
|
89 | <% } %>
|
90 | <% } %>
|
91 |
|
92 | // Create Root instance
|
93 |
|
94 | // here we inject the router and store to all child components,
|
95 | // making them available everywhere as `this.$router` and `this.$store`.
|
96 | const app = {
|
97 | <% if (features.meta) { %>
|
98 | <%= isTest ? '/* eslint-disable array-bracket-spacing, quotes, quote-props, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren, object-shorthand */' : '' %>
|
99 | head: <%= serializeFunction(head) %>,
|
100 | <%= isTest ? '/* eslint-enable array-bracket-spacing, quotes, quote-props, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren, object-shorthand */' : '' %>
|
101 | <% } %>
|
102 | <% if (store) { %>store,<% } %>
|
103 | router,
|
104 | nuxt: {
|
105 | <% if (features.transitions) { %>
|
106 | defaultTransition,
|
107 | transitions: [defaultTransition],
|
108 | setTransitions (transitions) {
|
109 | if (!Array.isArray(transitions)) {
|
110 | transitions = [transitions]
|
111 | }
|
112 | transitions = transitions.map((transition) => {
|
113 | if (!transition) {
|
114 | transition = defaultTransition
|
115 | } else if (typeof transition === 'string') {
|
116 | transition = Object.assign({}, defaultTransition, { name: transition })
|
117 | } else {
|
118 | transition = Object.assign({}, defaultTransition, transition)
|
119 | }
|
120 | return transition
|
121 | })
|
122 | this.$options.nuxt.transitions = transitions
|
123 | return transitions
|
124 | },
|
125 | <% } %>
|
126 | err: null,
|
127 | dateErr: null,
|
128 | error (err) {
|
129 | err = err || null
|
130 | app.context._errored = Boolean(err)
|
131 | err = err ? normalizeError(err) : null
|
132 | let nuxt = app.nuxt // to work with @vue/composition-api, see https://github.com/nuxt/nuxt.js/issues/6517#issuecomment-573280207
|
133 | if (this) {
|
134 | nuxt = this.nuxt || this.$options.nuxt
|
135 | }
|
136 | nuxt.dateErr = Date.now()
|
137 | nuxt.err = err
|
138 | // Used in src/server.js
|
139 | if (ssrContext) {
|
140 | ssrContext.nuxt.error = err
|
141 | }
|
142 | return err
|
143 | }
|
144 | },
|
145 | ...App
|
146 | }
|
147 | <% if (store) { %>
|
148 | // Make app available into store via this.app
|
149 | store.app = app
|
150 | <% } %>
|
151 | const next = ssrContext ? ssrContext.next : location => app.router.push(location)
|
152 | // Resolve route
|
153 | let route
|
154 | if (ssrContext) {
|
155 | route = router.resolve(ssrContext.url).route
|
156 | } else {
|
157 | const path = getLocation(router.options.base, router.options.mode)
|
158 | route = router.resolve(path).route
|
159 | }
|
160 |
|
161 | // Set context to app.context
|
162 | await setContext(app, {
|
163 | <% if (store) { %>store,<% } %>
|
164 | route,
|
165 | next,
|
166 | error: app.nuxt.error.bind(app),
|
167 | payload: ssrContext ? ssrContext.payload : undefined,
|
168 | req: ssrContext ? ssrContext.req : undefined,
|
169 | res: ssrContext ? ssrContext.res : undefined,
|
170 | beforeRenderFns: ssrContext ? ssrContext.beforeRenderFns : undefined,
|
171 | ssrContext
|
172 | })
|
173 |
|
174 | function inject(key, value) {
|
175 | if (!key) {
|
176 | throw new Error('inject(key, value) has no key provided')
|
177 | }
|
178 | if (value === undefined) {
|
179 | throw new Error(`inject('${key}', value) has no value provided`)
|
180 | }
|
181 |
|
182 | key = '$' + key
|
183 | // Add into app
|
184 | app[key] = value
|
185 | // Add into context
|
186 | if (!app.context[key]) {
|
187 | app.context[key] = value
|
188 | }
|
189 | <% if (store) { %>
|
190 | // Add into store
|
191 | store[key] = app[key]
|
192 | <% } %>
|
193 | // Check if plugin not already installed
|
194 | const installKey = '__<%= globals.pluginPrefix %>_' + key + '_installed__'
|
195 | if (Vue[installKey]) {
|
196 | return
|
197 | }
|
198 | Vue[installKey] = true
|
199 | // Call Vue.use() to install the plugin into vm
|
200 | Vue.use(() => {
|
201 | if (!Object.prototype.hasOwnProperty.call(Vue.prototype, key)) {
|
202 | Object.defineProperty(Vue.prototype, key, {
|
203 | get () {
|
204 | return this.$root.$options[key]
|
205 | }
|
206 | })
|
207 | }
|
208 | })
|
209 | }
|
210 |
|
211 | // Inject runtime config as $config
|
212 | inject('config', config)
|
213 |
|
214 | <% if (store) { %>
|
215 | if (process.client) {
|
216 | // Replace store state before plugins execution
|
217 | if (window.<%= globals.context %> && window.<%= globals.context %>.state) {
|
218 | store.replaceState(window.<%= globals.context %>.state)
|
219 | }
|
220 | }
|
221 | <% } %>
|
222 |
|
223 | // Add enablePreview(previewData = {}) in context for plugins
|
224 | if (process.static && process.client) {
|
225 | app.context.enablePreview = function (previewData = {}) {
|
226 | app.previewData = Object.assign({}, previewData)
|
227 | inject('preview', previewData)
|
228 | }
|
229 | }
|
230 | // Plugin execution
|
231 | <%= isTest ? '/* eslint-disable camelcase */' : '' %>
|
232 | <% plugins.forEach((plugin) => { %>
|
233 | <% if (plugin.mode == 'client') { %>
|
234 | if (process.client && typeof <%= plugin.name %> === 'function') {
|
235 | await <%= plugin.name %>(app.context, inject)
|
236 | }
|
237 | <% } else if (plugin.mode == 'server') { %>
|
238 | if (process.server && typeof <%= plugin.name %> === 'function') {
|
239 | await <%= plugin.name %>(app.context, inject)
|
240 | }
|
241 | <% } else { %>
|
242 | if (typeof <%= plugin.name %> === 'function') {
|
243 | await <%= plugin.name %>(app.context, inject)
|
244 | }
|
245 | <% } %>
|
246 | <% }) %>
|
247 | <%= isTest ? '/* eslint-enable camelcase */' : '' %>
|
248 | // Lock enablePreview in context
|
249 | if (process.static && process.client) {
|
250 | app.context.enablePreview = function () {
|
251 | console.warn('You cannot call enablePreview() outside a plugin.')
|
252 | }
|
253 | }
|
254 |
|
255 | // If server-side, wait for async component to be resolved first
|
256 | if (process.server && ssrContext && ssrContext.url) {
|
257 | await new Promise((resolve, reject) => {
|
258 | router.push(ssrContext.url, resolve, (err) => {
|
259 | // https://github.com/vuejs/vue-router/blob/v3.4.3/src/util/errors.js
|
260 | if (!err._isRouter) return reject(err)
|
261 | if (err.type !== 2 /* NavigationFailureType.redirected */) return resolve()
|
262 |
|
263 | // navigated to a different route in router guard
|
264 | const unregister = router.afterEach(async (to, from) => {
|
265 | ssrContext.url = to.fullPath
|
266 | app.context.route = await getRouteData(to)
|
267 | app.context.params = to.params || {}
|
268 | app.context.query = to.query || {}
|
269 | unregister()
|
270 | resolve()
|
271 | })
|
272 | })
|
273 | })
|
274 | }
|
275 |
|
276 | return {
|
277 | <% if(store) { %>store,<% } %>
|
278 | app,
|
279 | router
|
280 | }
|
281 | }
|
282 |
|
283 | export { createApp, NuxtError }
|
284 |
|
\ | No newline at end of file |