feat: use @nuxt/design (#322)

Co-authored-by: pooya parsa <pyapar@gmail.com>
This commit is contained in:
Daniel Roe 2021-07-15 10:47:15 +01:00 committed by GitHub
parent 6d0bb7c740
commit ea0d2788a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 70 additions and 71 deletions

View File

@ -20,6 +20,7 @@
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
}, },
"devDependencies": { "devDependencies": {
"@nuxt/design": "0.0.4",
"@nuxt/kit": "^0.6.4", "@nuxt/kit": "^0.6.4",
"@types/clear": "^0", "@types/clear": "^0",
"@types/debounce-promise": "^3", "@types/debounce-promise": "^3",

View File

@ -22,7 +22,7 @@ export async function invoke (args) {
const load = async (isRestart) => { const load = async (isRestart) => {
try { try {
const message = `${isRestart ? 'Restarting' : 'Starting'} nuxt...` const message = `${isRestart ? 'Restarting' : 'Starting'} nuxt...`
server.setApp(createLoadingHandler(message, 1)) server.setApp(createLoadingHandler(message))
if (isRestart) { if (isRestart) {
console.log(message) console.log(message)
} }

View File

@ -1,7 +1,8 @@
import type { RequestListener } from 'http' import type { RequestListener } from 'http'
import { loading } from '@nuxt/design'
export function createServer () { export function createServer () {
const listener = createDynamicFunction(createLoadingHandler('Loading...', 1)) const listener = createDynamicFunction(createLoadingHandler('Loading...'))
async function listen (opts) { async function listen (opts) {
const { listen } = await import('listhen') const { listen } = await import('listhen')
@ -14,12 +15,11 @@ export function createServer () {
} }
} }
export function createLoadingHandler (message: string, retryAfter = 60): RequestListener { export function createLoadingHandler (message: string): RequestListener {
return (_req, res) => { return (_req, res) => {
res.setHeader('Content-Type', 'text/html; charset=UTF-8') res.setHeader('Content-Type', 'text/html; charset=UTF-8')
res.statusCode = 503 /* Service Unavailable */ res.statusCode = 503 /* Service Unavailable */
res.setHeader('Retry-After', retryAfter) res.end(loading({ loading: message }))
res.end(`<!DOCTYPE html><html><head><meta http-equiv="refresh" content="${retryAfter || 60}"></head><body>${message}</body>`)
} }
} }

View File

@ -15,6 +15,7 @@
"dependencies": { "dependencies": {
"@cloudflare/kv-asset-handler": "^0.1.3", "@cloudflare/kv-asset-handler": "^0.1.3",
"@netlify/functions": "^0.7.2", "@netlify/functions": "^0.7.2",
"@nuxt/design": "0.0.4",
"@nuxt/devalue": "^2.0.0", "@nuxt/devalue": "^2.0.0",
"@nuxt/kit": "^0.6.4", "@nuxt/kit": "^0.6.4",
"@rollup/plugin-alias": "^3.1.2", "@rollup/plugin-alias": "^3.1.2",

View File

@ -47,6 +47,11 @@ export async function renderMiddleware (req, res) {
const renderer = await loadRenderer() const renderer = await loadRenderer()
const rendered = await renderer.renderToString(ssrContext) const rendered = await renderer.renderToString(ssrContext)
// Handle errors
if (ssrContext.error) {
throw ssrContext.error
}
if (ssrContext.nuxt.hooks) { if (ssrContext.nuxt.hooks) {
await ssrContext.nuxt.hooks.callHook('app:rendered') await ssrContext.nuxt.hooks.callHook('app:rendered')
} }

View File

@ -1,8 +1,15 @@
// import ansiHTML from 'ansi-html' // import ansiHTML from 'ansi-html'
import type { IncomingMessage, ServerResponse } from 'http'
import { error500, error404, errorDev } from '@nuxt/design'
const cwd = process.cwd() const cwd = process.cwd()
// TODO: Handle process.env.DEBUG const hasReqHeader = (req, header, includes) => req.headers[header] && req.headers[header].toLowerCase().includes(includes)
export function handleError (error, req, res) {
const isDev = process.env.NODE_ENV === 'development'
export function handleError (error, req: IncomingMessage, res: ServerResponse) {
const isJsonRequest = hasReqHeader(req, 'accept', 'application/json') || hasReqHeader(req, 'user-agent', 'curl/') || hasReqHeader(req, 'user-agent', 'httpie/')
const stack = (error.stack || '') const stack = (error.stack || '')
.split('\n') .split('\n')
.splice(1) .splice(1)
@ -21,47 +28,35 @@ export function handleError (error, req, res) {
} }
}) })
console.error(error.message + '\n' + stack.map(l => ' ' + l.text).join(' \n')) const is404 = error.statusCode === 404
const html = ` const errorObject = {
<!DOCTYPE html> statusCode: error.statusCode || 500,
<html> statusMessage: is404 ? 'Page Not Found' : 'Internal Server Error',
<head> description: isDev && !is404
<meta charset="utf-8"> ? `
<title>Nuxt Error</title> <h1>${error.message}</h1>
<style> <pre>${stack.map(i => `<span class="stack${i.internal ? ' internal' : ''}">${i.text}</span>`).join('\n')}</pre>
html, body { `
background: white; : ''
color: red; }
font-family: monospace;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 100%;
}
.stack {
padding-left: 2em;
}
.stack.internal {
color: grey;
}
</style>
</head>
<body>
<div>
<div>${req.method} ${req.url}</div><br>
<h1>${error.toString()}</h1>
<pre>${stack.map(i =>
`<span class="stack${i.internal ? ' internal' : ''}">${i.text}</span>`
).join('\n')
}</pre>
</div>
</body>
</html>
`
res.statusCode = error.statusCode || 500 res.statusCode = error.statusCode || 500
res.statusMessage = error.statusMessage || 'Internal Error' res.statusMessage = error.statusMessage || 'Internal Server Error'
// Console output
if (!is404) {
console.error(error.message + '\n' + stack.map(l => ' ' + l.text).join(' \n'))
}
// JSON response
if (isJsonRequest) {
res.setHeader('Content-Type', 'application/json')
return res.end(JSON.stringify(errorObject))
}
// HTML response
const errorTemplate = is404 ? error404 : (isDev ? errorDev : error500)
const html = errorTemplate(errorObject)
res.end(html) res.end(html)
} }

View File

@ -1,5 +1,6 @@
import { Worker } from 'worker_threads' import { Worker } from 'worker_threads'
import { loading as loadingTemplate } from '@nuxt/design'
import chokidar, { FSWatcher } from 'chokidar' import chokidar, { FSWatcher } from 'chokidar'
import debounce from 'debounce' import debounce from 'debounce'
import { stat } from 'fs-extra' import { stat } from 'fs-extra'
@ -74,7 +75,7 @@ export function createDevServer (nitroContext: NitroContext) {
}) })
} else { } else {
res.setHeader('Content-Type', 'text/html; charset=UTF-8') res.setHeader('Content-Type', 'text/html; charset=UTF-8')
res.end('<!DOCTYPE html><html><head><meta http-equiv="refresh" content="1"><head><body>...') res.end(loadingTemplate({}))
} }
}) })

View File

@ -36,17 +36,6 @@ export default defineNuxtModule({
// Resolve routes // Resolve routes
const routes = await resolvePagesRoutes(nuxt) const routes = await resolvePagesRoutes(nuxt)
// Add 404 page is not added
const page404 = routes.find(route => route.name === '404')
if (!page404) {
routes.push({
name: '404',
path: '/:catchAll(.*)*',
file: resolve(runtimeDir, '404.vue'),
children: []
})
}
// Add routes.js // Add routes.js
app.templates.push({ app.templates.push({
path: 'routes.js', path: 'routes.js',

View File

@ -1,5 +0,0 @@
<template>
<div>
404 | Page Not Found
</div>
</template>

View File

@ -1,6 +1,6 @@
<template> <template>
<RouterView v-slot="{ Component }"> <RouterView v-slot="{ Component }">
<NuxtLayout :name="layout || updatedComponentLayout || Component.type.layout"> <NuxtLayout v-if="Component" :name="layout || updatedComponentLayout || Component.type.layout">
<transition name="page" mode="out-in"> <transition name="page" mode="out-in">
<!-- <keep-alive> --> <!-- <keep-alive> -->
<Suspense @pending="() => onSuspensePending(Component)" @resolve="() => onSuspenseResolved(Component)"> <Suspense @pending="() => onSuspensePending(Component)" @resolve="() => onSuspenseResolved(Component)">
@ -9,6 +9,7 @@
<!-- <keep-alive --> <!-- <keep-alive -->
</transition> </transition>
</NuxtLayout> </NuxtLayout>
<!-- TODO: Handle 404 placeholder -->
</RouterView> </RouterView>
</template> </template>

View File

@ -43,13 +43,15 @@ export default defineNuxtPlugin((nuxt) => {
if (process.server) { if (process.server) {
router.push(nuxt.ssrContext.url) router.push(nuxt.ssrContext.url)
} }
try {
await router.isReady() await router.isReady()
if (!router.currentRoute.value.matched.length) {
// TODO const is404 = router.currentRoute.value.matched.length === 0
} if (process.server && is404) {
} catch (err) { const error = new Error(`Page not found: ${nuxt.ssrContext.url}`)
// TODO // @ts-ignore
error.statusCode = 404
nuxt.ssrContext.error = error
} }
}) })
}) })

View File

@ -1305,6 +1305,13 @@ __metadata:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@nuxt/design@npm:0.0.4":
version: 0.0.4
resolution: "@nuxt/design@npm:0.0.4"
checksum: c28506ff41e26721dc1f3a3101d9d2824b3b44e17b4abf1ab246bc2777a49d743fc42b8b1e056460934461892b3af28c4ee96524a1c61d099ad02c23fc22f115
languageName: node
linkType: hard
"@nuxt/devalue@npm:^2.0.0": "@nuxt/devalue@npm:^2.0.0":
version: 2.0.0 version: 2.0.0
resolution: "@nuxt/devalue@npm:2.0.0" resolution: "@nuxt/devalue@npm:2.0.0"
@ -1354,6 +1361,7 @@ __metadata:
dependencies: dependencies:
"@cloudflare/kv-asset-handler": ^0.1.3 "@cloudflare/kv-asset-handler": ^0.1.3
"@netlify/functions": ^0.7.2 "@netlify/functions": ^0.7.2
"@nuxt/design": 0.0.4
"@nuxt/devalue": ^2.0.0 "@nuxt/devalue": ^2.0.0
"@nuxt/kit": ^0.6.4 "@nuxt/kit": ^0.6.4
"@rollup/plugin-alias": ^3.1.2 "@rollup/plugin-alias": ^3.1.2
@ -8531,6 +8539,7 @@ fsevents@~2.3.2:
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "nuxt-cli@workspace:packages/cli" resolution: "nuxt-cli@workspace:packages/cli"
dependencies: dependencies:
"@nuxt/design": 0.0.4
"@nuxt/kit": ^0.6.4 "@nuxt/kit": ^0.6.4
"@types/clear": ^0 "@types/clear": ^0
"@types/debounce-promise": ^3 "@types/debounce-promise": ^3