I don't think Quasar offers something similar to server-directory out-of-the-box, but Quasar is a quite flexible framework, and we can easily achieve "SSR full-stack capabilities" by using a Quasar SSR-middleware :-)
The idea is:
SSR-middleware is an additional layer where all browser-requests are supposed to come through. Therefore, all we need to do is to add an additional SSR-middleware to intercept browser-requests when trying to hit a specific route (in this case, /api/*
). Step-by-step:
Disclaimer: it works only when running Quasar in SSR mode, of course.
- Considering that we have already created our Quasar application, and have already added the SSR mode (
npm init quasar && cd my-app && quasar mode add ssr
), let's add an additional SSR-middleware "api" with the command:
quasar new ssrmiddleware api
- After that we need to include our SSR-middleware into
quasar.config.js
:
ssr: {
...
middlewares: [
'api', // <= this is our SSR-middleware (keep this as first one)
'render' // keep this as last one
]
},
...
- And the last step is to implement the browser-requests interception into our SSR-middleware file
src-ssr/middlewares/api.ts
:
export default ssrMiddleware(async ({ app, resolve }) => {
app.all(resolve.urlPath('*'), (req, res, next) => {
if (req.url.substring(0, 4) === '/api') {
// Here we can implement our backend NodeJS/Express related operations.
// See the example below "Real-life example", which provides
// something similar to Next/Nuxt server-directory functionality.
res.status(200).send(`Hi! req.method: ${req.method}, req.url: ${req.url}`);
} else {
next();
}
});
});
Now we can start our Quasar SSR application, and see our API in action by pointing the browser to http://localhost:9100/api/foo/bar/
Response => Hi! req.method: GET, req.url: /api/foo/bar/
Real-life example:
updated according to @David's suggestion. Thanks :-)
- In order to provide something similar to Next/Nuxt server-directory functionality, we need to include some additional lines of code into our SSR-middleware file
src-ssr/middlewares/api.ts
. The example below maps all available API-Handler (see apiHandlers object) and select them to handle browser requests according to the request URL:
import { ssrMiddleware } from 'quasar/wrappers';
const apiHandlers: { [key: string]: any } = {
'req-info': import('../../src/api/req-info'),
version: import('../../src/api/version'),
};
export default ssrMiddleware(async ({ app, resolve }) => {
app.all(resolve.urlPath('*'), (req, res, next) => {
if (req.url.substring(0, 4) === '/api') {
try {
const path = req.url.split('?')[0].substring(5);
const apiHandler = await apiHandlers[path];
if (apiHandler) {
await apiHandler.default(req, res);
} else {
res.sendStatus(404);
}
} catch (error) {
console.error(error);
res.sendStatus(500);
}
} else {
next();
}
});
});
- And after that we just need to create our NodeJS/Express API-Handlers in the folder
/src/api/
.
- Example #1:
/src/api/version.ts
:
import type { Request, Response } from 'express';
export default function (req: Request, res: Response) {
const version = require('../../package.json').version;
res.status(200).send(version);
}
- Example #2:
/src/api/req-info.ts
:
import type { Request, Response } from 'express';
export default function (req: Request, res: Response) {
res.setHeader('Content-Type', 'text/html');
res.status(200).send(`
<ul>
<li>req.url: ${req.url}</li>
<li>req.method: ${req.method}</li>
<li>req.query: ${JSON.stringify(req.query)}</li>
</ul>`);
}
I hope it helps, thanks!
If so, please vote-up :-)
StackBlitz project: https://stackblitz.com/edit/quasarframework-uocha6