Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save keanulee/8f29a24533453928b7d9ef5d21d158a6 to your computer and use it in GitHub Desktop.
Save keanulee/8f29a24533453928b7d9ef5d21d158a6 to your computer and use it in GitHub Desktop.
A simple guide that explains how to deploy PWA Starter Kit to Firebase

Deploying prpl-server to Firebase

Firebase Hosting alone is not sufficient for hosting the prpl-server build since it requires some server-side processing of the user agent string. Instead, you will have to use Firebase Functions for that.

  1. Sign up for a Firebase account

  2. Head over the Firebase Console and create your project. Make note of the project ID associated with your app

  3. Install Firebase Command Line Tools:

    $ npm i -g firebase-tools
  4. Log into your Firebase account from the CLI by running:

    $ firebase login
  5. Set the default Firebase project for your PWA. You can do that by either running this command:

    $ firebase use --add <project-id>

    Or by creating a file named .firebaserc in the root of your application, containing:

    {
      "projects": {
        "default": "<project-id>"
      }
    }
  6. Create a file named firebase.json in the root of you PWA and paste this JSON in it:

    {
      "hosting": {
        "public": "build",
        "ignore": [
          "firebase.json",
          "**/.*"
        ],
        "rewrites": [
          {
            "source": "**",
            "function": "app"
          }
        ],
        "headers": [
          {
            "source" : "**/service-worker.js",
            "headers" : [
              {
                "key" : "Service-Worker-Allowed",
                "value" : "/"
              }
            ]
          }
        ]
      }
    }

    The public field tells Firebase that the build folder should be statically served through its CDN. The rewrites field tells Firebase to send each request to the app function - we will create it later. The headers field tells Firebase to add the Service-Worker-Allowed header when the user requests a service-worker.js file

  7. Create a functions folder. This folder will contain the code executed by Firebase Functions. You will need to create two files in it:

    1. package.json
      {
        "name": "functions",
        "description": "Cloud Functions for Firebase",
        "scripts": {
          "serve": "firebase serve --only functions",
          "shell": "firebase functions:shell",
          "start": "npm run shell",
          "deploy": "firebase deploy --only functions",
          "logs": "firebase functions:log"
        },
        "dependencies": {
          "express": "^4.16.3",
          "firebase-admin": "~5.12.1",
          "firebase-functions": "^1.0.3",
          "prpl-server": "^1.2.0",
          "rendertron-middleware": "^0.1.2"
        },
        "private": true
      }
    2. index.js
      const functions = require('firebase-functions');
      const prpl = require('prpl-server');
      const express = require('express');
      const rendertron = require('rendertron-middleware');
      
      const app = express();
      
      app.use(rendertron.makeMiddleware({
        proxyUrl: 'https://render-tron.appspot.com/render',
        injectShadyDom: true,
      }));
      
      app.get('/*', prpl.makeHandler('./build', require('./build/polymer.json')));
      
      exports.app = functions.https.onRequest(app);
      This is the main file for our Firebase Functions. First, we create an Express app. Then, we add a rendertron middleware, that will server side render our PWA for crawler bots, and we give to PRPL Server the responsability to answer to any other GET request. Last but not least, we tell Firebase to make our Express app handle each request to the app function.
  8. Install the npm dependencies inside the functions directory:

    $ cd functions && npm i
  9. Now that the Firebase Functions part is ready, we have to setup our build to make it work correctly with it. Since Firebase Functions cannot require files that are not inside the functions directory, we need to build the PWA and make Gulp move the files needed by PRPL Server to the functions directory, while leaving the static assets in the build directory. To do that, we are going to add a new task to gulpfile.js:

    /**
     * Builds the Firebase-ready version of the PWA, auto setting the base path
     * and moving the necessary files to the functions folder to be used by PRPL Server
     */
    gulp.task('build:firebase', (cb) => {
      // Build the PWA, auto setting the base path for each build
      exec('polymer build --auto-base-path', (err) => {
        if (err) {
          cb(err);
        }
        // These are the files needed by PRPL Server, that are going to be moved to the functions folder
        const filesToMove = [ 'build/polymer.json', 'build/**/index.html' ];
        // Delete the build folder inside the functions folder
        del([ 'functions/build' ])
          .then(() =>
            // Copy the files needed by PRPL Server
            new Promise((resolve) =>
              gulp
                .src(filesToMove, { base: '.' })
                .pipe(gulp.dest('functions'))
                .on('end', resolve)))
          // Delete them from the original build
          .then(() => del(filesToMove))
          .then(() => cb());
      });
    });
  10. Add a script named build:firebase in your project root's package.json:

    "build:firebase": "gulp build:firebase"
    
  11. Now that you have everything set up, just run the build:firebase script to build the PWA for Firebase:

    $ npm run build:firebase
  12. Finally, deploy your PWA to Firebase:

    $ firebase deploy --only functions,hosting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment