Zaklad ssr
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import { ssrMiddleware } from 'quasar/wrappers'
|
||||
|
||||
// This middleware should execute as last one
|
||||
// since it captures everything and tries to
|
||||
// render the page with Vue
|
||||
|
||||
export default ssrMiddleware(({ app, resolve, render, serve }) => {
|
||||
// we capture any other Express route and hand it
|
||||
// over to Vue and Vue Router to render our page
|
||||
app.get(resolve.urlPath('*'), (req, res) => {
|
||||
res.setHeader('Content-Type', 'text/html')
|
||||
|
||||
render(/* the ssrContext: */ { req, res })
|
||||
.then(html => {
|
||||
// now let's send the rendered html to the client
|
||||
res.send(html)
|
||||
})
|
||||
.catch(err => {
|
||||
// oops, we had an error while rendering the page
|
||||
|
||||
// we were told to redirect to another URL
|
||||
if (err.url) {
|
||||
if (err.code) {
|
||||
res.redirect(err.code, err.url)
|
||||
} else {
|
||||
res.redirect(err.url)
|
||||
}
|
||||
} else if (err.code === 404) {
|
||||
// hmm, Vue Router could not find the requested route
|
||||
|
||||
// Should reach here only if no "catch-all" route
|
||||
// is defined in /src/routes
|
||||
res.status(404).send('404 | Page Not Found')
|
||||
} else if (process.env.DEV) {
|
||||
// well, we treat any other code as error;
|
||||
// if we're in dev mode, then we can use Quasar CLI
|
||||
// to display a nice error page that contains the stack
|
||||
// and other useful information
|
||||
|
||||
// serve.error is available on dev only
|
||||
serve.error({ err, req, res })
|
||||
} else {
|
||||
// we're in production, so we should have another method
|
||||
// to display something to the client when we encounter an error
|
||||
// (for security reasons, it's not ok to display the same wealth
|
||||
// of information as we do in development)
|
||||
|
||||
// Render Error Page on production or
|
||||
// create a route (/src/routes) for an error page and redirect to it
|
||||
res.status(500).send('500 | Internal Server Error')
|
||||
// console.error(err.stack)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* More info about this file:
|
||||
* https://v2.quasar.dev/quasar-cli-vite/developing-ssr/ssr-webserver
|
||||
*
|
||||
* Runs in Node context.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Make sure to yarn add / npm install (in your project root)
|
||||
* anything you import here (except for express and compression).
|
||||
*/
|
||||
import express from 'express'
|
||||
import compression from 'compression'
|
||||
import {
|
||||
ssrClose,
|
||||
ssrCreate,
|
||||
ssrListen,
|
||||
ssrRenderPreloadTag,
|
||||
ssrServeStaticContent
|
||||
} from 'quasar/wrappers'
|
||||
|
||||
/**
|
||||
* Create your webserver and return its instance.
|
||||
* If needed, prepare your webserver to receive
|
||||
* connect-like middlewares.
|
||||
*
|
||||
* Should NOT be async!
|
||||
*/
|
||||
export const create = ssrCreate((/* { ... } */) => {
|
||||
const app = express()
|
||||
|
||||
// attackers can use this header to detect apps running Express
|
||||
// and then launch specifically-targeted attacks
|
||||
app.disable('x-powered-by')
|
||||
|
||||
// place here any middlewares that
|
||||
// absolutely need to run before anything else
|
||||
if (process.env.PROD) {
|
||||
app.use(compression())
|
||||
}
|
||||
|
||||
return app
|
||||
})
|
||||
|
||||
/**
|
||||
* You need to make the server listen to the indicated port
|
||||
* and return the listening instance or whatever you need to
|
||||
* close the server with.
|
||||
*
|
||||
* The "listenResult" param for the "close()" definition below
|
||||
* is what you return here.
|
||||
*
|
||||
* For production, you can instead export your
|
||||
* handler for serverless use or whatever else fits your needs.
|
||||
*/
|
||||
export const listen = ssrListen(async ({ app, port, isReady }) => {
|
||||
await isReady()
|
||||
return app.listen(port, () => {
|
||||
if (process.env.PROD) {
|
||||
console.log('Server listening at port ' + port)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Should close the server and free up any resources.
|
||||
* Will be used on development only when the server needs
|
||||
* to be rebooted.
|
||||
*
|
||||
* Should you need the result of the "listen()" call above,
|
||||
* you can use the "listenResult" param.
|
||||
*
|
||||
* Can be async.
|
||||
*/
|
||||
export const close = ssrClose(({ listenResult }) => {
|
||||
return listenResult.close()
|
||||
})
|
||||
|
||||
const maxAge = process.env.DEV
|
||||
? 0
|
||||
: 1000 * 60 * 60 * 24 * 30
|
||||
|
||||
/**
|
||||
* Should return middleware that serves the indicated path
|
||||
* with static content.
|
||||
*/
|
||||
export const serveStaticContent = ssrServeStaticContent((path, opts) => {
|
||||
return express.static(path, {
|
||||
maxAge,
|
||||
...opts
|
||||
})
|
||||
})
|
||||
|
||||
const jsRE = /\.js$/
|
||||
const cssRE = /\.css$/
|
||||
const woffRE = /\.woff$/
|
||||
const woff2RE = /\.woff2$/
|
||||
const gifRE = /\.gif$/
|
||||
const jpgRE = /\.jpe?g$/
|
||||
const pngRE = /\.png$/
|
||||
|
||||
/**
|
||||
* Should return a String with HTML output
|
||||
* (if any) for preloading indicated file
|
||||
*/
|
||||
export const renderPreloadTag = ssrRenderPreloadTag((file) => {
|
||||
if (jsRE.test(file) === true) {
|
||||
return `<link rel="modulepreload" href="${file}" crossorigin>`
|
||||
}
|
||||
|
||||
if (cssRE.test(file) === true) {
|
||||
return `<link rel="stylesheet" href="${file}">`
|
||||
}
|
||||
|
||||
if (woffRE.test(file) === true) {
|
||||
return `<link rel="preload" href="${file}" as="font" type="font/woff" crossorigin>`
|
||||
}
|
||||
|
||||
if (woff2RE.test(file) === true) {
|
||||
return `<link rel="preload" href="${file}" as="font" type="font/woff2" crossorigin>`
|
||||
}
|
||||
|
||||
if (gifRE.test(file) === true) {
|
||||
return `<link rel="preload" href="${file}" as="image" type="image/gif">`
|
||||
}
|
||||
|
||||
if (jpgRE.test(file) === true) {
|
||||
return `<link rel="preload" href="${file}" as="image" type="image/jpeg">`
|
||||
}
|
||||
|
||||
if (pngRE.test(file) === true) {
|
||||
return `<link rel="preload" href="${file}" as="image" type="image/png">`
|
||||
}
|
||||
|
||||
return ''
|
||||
})
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
/* eslint-disable */
|
||||
// THIS FEATURE-FLAG FILE IS AUTOGENERATED,
|
||||
// REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING
|
||||
import "quasar/dist/types/feature-flag";
|
||||
|
||||
declare module "quasar/dist/types/feature-flag" {
|
||||
interface QuasarFeatureFlags {
|
||||
ssr: true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user