fix(vue-app): handle fallback on generated page (#7718)

* fix(vue-app): handle fallback on generated page

* chore: improvements and small refactor

* fix: lint

Co-authored-by: pooya parsa <pyapar@gmail.com>

* chore: add force-build option to nuxt generate

Co-authored-by: pooya parsa <pyapar@gmail.com>

[release]
This commit is contained in:
Sébastien Chopin 2020-07-16 19:32:09 +02:00 committed by GitHub
parent 361afcb747
commit 6ab65fbf4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 34 additions and 15 deletions

View File

@ -48,6 +48,11 @@ export default {
} }
} }
}, },
'force-build': {
type: 'boolean',
default: false,
description: 'Force to build the application with webpack'
},
'fail-on-error': { 'fail-on-error': {
type: 'boolean', type: 'boolean',
default: false, default: false,

View File

@ -1,5 +1,4 @@
import { TARGETS } from '@nuxt/utils' import { TARGETS } from '@nuxt/utils'
import consola from 'consola'
import { common, server } from '../options' import { common, server } from '../options'
import { showBanner } from '../utils/banner' import { showBanner } from '../utils/banner'
import { serve } from '../utils/serve' import { serve } from '../utils/serve'
@ -16,7 +15,6 @@ export default {
const config = await cmd.getNuxtConfig({ dev: false, _start: true }) const config = await cmd.getNuxtConfig({ dev: false, _start: true })
if (config.target === TARGETS.static) { if (config.target === TARGETS.static) {
consola.info('Serving static dist')
return serve(cmd) return serve(cmd)
} }

View File

@ -1,5 +1,5 @@
import fs from 'fs'
import path, { relative } from 'path' import path, { relative } from 'path'
import fs from 'fs-extra'
import crc32 from 'crc/lib/crc32' import crc32 from 'crc/lib/crc32'
import consola from 'consola' import consola from 'consola'
import globby from 'globby' import globby from 'globby'
@ -19,7 +19,7 @@ export async function ensureBuild (cmd) {
const nuxt = await getNuxt({ _build: true, server: false }, cmd) const nuxt = await getNuxt({ _build: true, server: false }, cmd)
const { options } = nuxt const { options } = nuxt
if (options.generate.cache === false || process.env.NUXT_BUILD) { if (options.generate.cache === false || destr(process.env.NUXT_BUILD) || cmd.argv['force-build']) {
const builder = await cmd.getBuilder(nuxt) const builder = await cmd.getBuilder(nuxt)
await builder.build() await builder.build()
await nuxt.close() await nuxt.close()

View File

@ -1,5 +1,6 @@
import { promises as fs } from 'fs' import { promises as fs } from 'fs'
import { join, extname, basename } from 'path' import { join, extname, sep } from 'path'
import consola from 'consola'
import connect from 'connect' import connect from 'connect'
import serveStatic from 'serve-static' import serveStatic from 'serve-static'
import compression from 'compression' import compression from 'compression'
@ -20,8 +21,9 @@ export async function serve (cmd) {
} catch (err) { } } catch (err) { }
const distStat = await fs.stat(options.generate.dir).catch(err => null) // eslint-disable-line handle-callback-err const distStat = await fs.stat(options.generate.dir).catch(err => null) // eslint-disable-line handle-callback-err
const distPath = join(options.generate.dir.replace(process.cwd() + sep, ''), sep)
if (!distStat || !distStat.isDirectory()) { if (!distStat || !distStat.isDirectory()) {
throw new Error('Output directory `' + basename(options.generate.dir) + '/` does not exists, please use `nuxt generate` before `nuxt start` for static target.') throw new Error('Output directory `' + distPath + '` does not exists, please use `nuxt generate` before `nuxt start` for static target.')
} }
const app = connect() const app = connect()
app.use(compression({ threshold: 0 })) app.use(compression({ threshold: 0 }))
@ -70,4 +72,6 @@ export async function serve (cmd) {
listeners: [listener] listeners: [listener]
} }
}, false) }, false)
consola.info(`Serving static application from \`${distPath}\``)
} }

View File

@ -14,7 +14,8 @@ import {
<% if (features.transitions || features.asyncData || features.fetch) { %>getLocation,<% } %> <% if (features.transitions || features.asyncData || features.fetch) { %>getLocation,<% } %>
compile, compile,
getQueryDiff, getQueryDiff,
globalHandleError globalHandleError,
isSamePath
} from './utils.js' } from './utils.js'
import { createApp<% if (features.layouts) { %>, NuxtError<% } %> } from './index.js' import { createApp<% if (features.layouts) { %>, NuxtError<% } %> } from './index.js'
<% if (features.fetch) { %>import fetchMixin from './mixins/fetch.client'<% } %> <% if (features.fetch) { %>import fetchMixin from './mixins/fetch.client'<% } %>
@ -829,7 +830,7 @@ async function mountApp (__app) {
// Load page chunk // Load page chunk
if (!NUXT.data && NUXT.serverRendered) { if (!NUXT.data && NUXT.serverRendered) {
try { 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) Object.assign(NUXT, payload)
} catch (err) {} } catch (err) {}
} }
@ -887,14 +888,17 @@ async function mountApp (__app) {
router.beforeEach(render.bind(_app)) router.beforeEach(render.bind(_app))
// Fix in static: remove trailing slash to force hydration // 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) === '/') { // Full static, if server-rendered: hydrate, to allow custom redirect to generated page
_app.context.route.path = _app.context.route.path.replace(/\/+$/, '') <% 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 <% } else { %>
if (NUXT.serverRendered && NUXT.routePath === _app.context.route.path) { // Fix in static: remove trailing slash to force hydration
mount() if (NUXT.serverRendered && isSamePath(NUXT.routePath, _app.context.route.path)) {
return return mount()
} }
<% } %>
// First render on client-side // First render on client-side
const clientFirstMount = () => { const clientFirstMount = () => {

View File

@ -648,10 +648,18 @@ export function addLifecycleHook(vm, hook, fn) {
} }
} }
export const urlJoin = function urlJoin () { export function urlJoin () {
return [].slice return [].slice
.call(arguments) .call(arguments)
.join('/') .join('/')
.replace(/\/+/g, '/') .replace(/\/+/g, '/')
.replace(':/', '://') .replace(':/', '://')
} }
export function stripTrailingSlash (path) {
return path.replace(/\/+$/, '') || '/'
}
export function isSamePath (p1, p2) {
return stripTrailingSlash(p1) === stripTrailingSlash(p2)
}