Brinta
Brinta

Reputation: 1

Deploy quasar v2 ssr app into firebase functions

How can deploy quasar v2 ssr application into firebase-functions?

In v1, it can be done by following step:

First, I insert code at bottom in src-ssr/index.js file:

const functions=require("firebase-functions"); exports.samplefun=functions.https.onRequest(app);

But in new version, there are no file "index.js" in src-ssr directory.

Please help me to resolve the problem.

Upvotes: 0

Views: 587

Answers (2)

Joh
Joh

Reputation: 21

The solution above doesn't work for me with the new version of quasar V2.

Here my src-ssr/server.ts file :

    import { RenderError } from '@quasar/app-vite';
    import { ssrMiddleware } from 'quasar/wrappers';
    
    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: RenderError) => {
            // 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)
            }
          });
      });
    });

Here my src-ssr/middlewares/render.ts file :

/**
 * 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';
// const functions = require('firebase-functions')
// import functions from 'firebase-functions'

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 '';
});

My question is : 1- How to configure the rewrites object in firebase.json 2- how to configure firebase to use the ssr from quasar js

I'm really surprised that it's such a misery to do ssr at a time when google referencing is the norm.

Upvotes: 0

l1qu1d
l1qu1d

Reputation: 456

Quasar v2 has replaced the index.js file with file(s) called "middleware." Here's the URL where they talk about it: Quasar v2 SSR Upgrade Guide.

I made a full working repo and explanation that will get you going: https://github.com/l1qu1d/quasar-v2-ssr-firebase

Upvotes: 1

Related Questions