feat(server): fallback option (#4323)

This commit is contained in:
Pooya Parsa 2018-11-14 23:02:07 +03:30 committed by GitHub
parent 9fbd581557
commit 68523b95bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 101 additions and 24 deletions

View File

@ -1,3 +1,5 @@
// TODO: Refactor @nuxt/server related options into `server.js`
export default () => ({ export default () => ({
bundleRenderer: { bundleRenderer: {
shouldPrefetch: () => false shouldPrefetch: () => false
@ -23,5 +25,16 @@ export default () => ({
index: false, index: false,
// 1 year in production // 1 year in production
maxAge: '1y' maxAge: '1y'
},
// https://github.com/nuxt/serve-placeholder
fallback: {
dist: {},
static: {
skipUnknown: true,
handlers: {
'.htm': false,
'.html': false
}
}
} }
}) })

View File

@ -22,6 +22,7 @@
"ip": "^1.1.5", "ip": "^1.1.5",
"launch-editor-middleware": "^2.2.1", "launch-editor-middleware": "^2.2.1",
"pify": "^4.0.1", "pify": "^4.0.1",
"serve-placeholder": "^1.1.0",
"serve-static": "^1.13.2", "serve-static": "^1.13.2",
"server-destroy": "^1.0.1" "server-destroy": "^1.0.1"
}, },

View File

@ -1,6 +1,7 @@
import path from 'path' import path from 'path'
import launchMiddleware from 'launch-editor-middleware' import launchMiddleware from 'launch-editor-middleware'
import serveStatic from 'serve-static' import serveStatic from 'serve-static'
import servePlaceholder from 'serve-placeholder'
import connect from 'connect' import connect from 'connect'
import { determineGlobals, isUrl } from '@nuxt/common' import { determineGlobals, isUrl } from '@nuxt/common'
@ -125,11 +126,30 @@ export default class Server {
}) })
} }
// Add User provided middleware // Add user provided middleware
this.options.serverMiddleware.forEach((m) => { this.options.serverMiddleware.forEach((m) => {
this.useMiddleware(m) this.useMiddleware(m)
}) })
const { fallback } = this.options.render
if (fallback) {
// Graceful 404 errors for dist files
if (fallback.dist) {
this.useMiddleware({
path: this.publicPath,
handler: servePlaceholder(fallback.dist)
})
}
// Graceful 404 errors for other paths
if (fallback.static) {
this.useMiddleware({
path: '/',
handler: servePlaceholder(fallback.static)
})
}
}
// Finally use nuxtMiddleware // Finally use nuxtMiddleware
this.useMiddleware(nuxtMiddleware({ this.useMiddleware(nuxtMiddleware({
options: this.options, options: this.options,

View File

@ -254,19 +254,6 @@ export default class VueRenderer {
const APP = const APP =
`<div id="${this.context.globals.id}">${this.context.resources.loadingHTML}</div>` + BODY_SCRIPTS `<div id="${this.context.globals.id}">${this.context.resources.loadingHTML}</div>` + BODY_SCRIPTS
// Detect 404 errors
if (
url.includes(this.context.options.build.publicPath) ||
url.includes('__webpack')
) {
const err = {
statusCode: 404,
message: this.context.options.messages.error_404,
name: 'ResourceNotFound'
}
throw err
}
const html = this.renderTemplate(false, { const html = this.renderTemplate(false, {
HTML_ATTRS, HTML_ATTRS,
BODY_ATTRS, BODY_ATTRS,

View File

@ -0,0 +1,44 @@
import { getPort, loadFixture, Nuxt, rp } from '../utils'
let port
const url = route => 'http://localhost:' + port + route
let nuxt = null
describe('fallback', () => {
beforeAll(async () => {
const config = await loadFixture('with-config')
nuxt = new Nuxt(config)
port = await getPort()
await nuxt.server.listen(port, 'localhost')
})
test('robots.txt handled', async () => {
await expect(rp(url('/test/robots.txt')))
.rejects.toMatchObject({
statusCode: 404,
response: { body: '' }
})
})
test('normal html routes should be rendered using SSR', async () => {
await expect(rp(url('/test/index.html')))
.rejects.toMatchObject({
statusCode: 404,
response: { body: expect.stringContaining('data-n-head-ssr') }
})
})
test('uknown assets handled in dist', async () => {
await expect(rp(url('/test/orion/foo.xyz')))
.rejects.toMatchObject({
statusCode: 404,
response: { body: '' }
})
})
// Close server and ask nuxt to stop listening to file changes
afterAll(async () => {
await nuxt.close()
})
})

View File

@ -60,15 +60,6 @@ describe('spa', () => {
expect(html).toMatch('error handler triggered: asyncData error!') expect(html).toMatch('error handler triggered: asyncData error!')
}) })
test('/_nuxt/ (access publicPath in spa mode)', async () => {
await expect(renderRoute('/_nuxt/')).rejects.toMatchObject({
response: {
statusCode: 404,
statusMessage: 'ResourceNotFound'
}
})
})
// Close server and ask nuxt to stop listening to file changes // Close server and ask nuxt to stop listening to file changes
afterAll(async () => { afterAll(async () => {
await nuxt.close() await nuxt.close()

View File

@ -3597,6 +3597,15 @@ default-require-extensions@^1.0.0:
dependencies: dependencies:
strip-bom "^2.0.0" strip-bom "^2.0.0"
defaults-deep@^0.2.4:
version "0.2.4"
resolved "https://registry.npmjs.org/defaults-deep/-/defaults-deep-0.2.4.tgz#a479cfeafce025810fb93aa8d2dde0ee2d677cc6"
integrity sha512-V6BtqzcMvn0EPOy7f+SfMhfmTawq+7UQdt9yZH0EBK89+IHo5f+Hse/qzTorAXOBrQpxpwb6cB/8OgtaMrT+Fg==
dependencies:
for-own "^0.1.3"
is-extendable "^0.1.1"
lazy-cache "^0.2.3"
defaults@^1.0.3: defaults@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
@ -4676,7 +4685,7 @@ for-in@^1.0.1, for-in@^1.0.2:
resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
for-own@^0.1.4: for-own@^0.1.3, for-own@^0.1.4:
version "0.1.5" version "0.1.5"
resolved "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" resolved "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=
@ -6468,6 +6477,11 @@ launch-editor@^2.2.1:
chalk "^2.3.0" chalk "^2.3.0"
shell-quote "^1.6.1" shell-quote "^1.6.1"
lazy-cache@^0.2.3:
version "0.2.7"
resolved "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz#7feddf2dcb6edb77d11ef1d117ab5ffdf0ab1b65"
integrity sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=
lazy-cache@^1.0.3: lazy-cache@^1.0.3:
version "1.0.4" version "1.0.4"
resolved "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" resolved "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
@ -9650,6 +9664,13 @@ serialize-javascript@^1.3.0, serialize-javascript@^1.4.0, serialize-javascript@^
resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz#1aa336162c88a890ddad5384baebc93a655161fe" resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz#1aa336162c88a890ddad5384baebc93a655161fe"
integrity sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ== integrity sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==
serve-placeholder@^1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/serve-placeholder/-/serve-placeholder-1.1.0.tgz#3c0930b311a9896c3d90903bb8ea60fff12101b2"
integrity sha512-kMYOLX8hwcyQ/8nLuyPcOhGhi4c29sJLsfz3i1vOFQnYMtZdPSsJLxxblTU+5wf6CPHh/g3EYo/V/SQ6eVEO5Q==
dependencies:
defaults-deep "^0.2.4"
serve-static@1.13.2, serve-static@^1.13.2: serve-static@1.13.2, serve-static@^1.13.2:
version "1.13.2" version "1.13.2"
resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"