Giter Site home page Giter Site logo

adriaanbalt / boilerplate-react-firebase-graphql Goto Github PK

View Code? Open in Web Editor NEW
4.0 2.0 0.0 1.56 MB

Web App, React, Redux, Apollo, Graphql, Google Cloud Function, GCP Storage and Firebase Authentication. Hosted on Heroku.

JavaScript 81.29% HTML 1.36% SCSS 16.89% Shell 0.46%
frontend heroku firebase firebase-cloud-functions graphql

boilerplate-react-firebase-graphql's Introduction

React, Apollo GraphQL, and Firebase for auth, storage, analytics.

This boilerplate is the foundation for a marketplace application. Users can create accounts, add products they own to their collection.

Technical Structure

  • React + Redux to manager UI state
  • Firebase cloud function hosts GraphQL server
  • Apollo is integrated into React
  • Heroku hosts the frontend & backend
  • Firebase Firestore hosts the database
  • Firebase Auth handles authentication
  • Yarn workspaces divides the app between frontend and backend to help manage dependencies
  • Lunr Search

ToDo

  • i18n helper to make the hard coded copy easier to translate
  • Add analyzer to review bundle sizes
  • Convert to use Typescript

Dependencies

  • NODE 10.18.1 because (at the time) this was the maximum node version allowed by Google Cloud Platform.

Installation steps

  1. Install VS Code IDE (optional, you can use an IDE of choice but we used VSCode while building this app)
  2. Install iTerm2 (optional, convenient way to style your terminal)
  3. Install Oh My Zsh (optional, lets you easily style your terminal)
  4. Install Homebrew
  5. Install NVM
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
  1. Install NVM continued: Update ~/.zshrc (this may happen automatically)
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
  1. Install NODE using NVM
$ nvm install 10.18.1
$ nvm use 10.18.1
  1. Install Yarn using Homebrew $ brew install yarn
  2. Install Firebase CLI $ npm install firebase -g $ npm install -g firebase-tools
  3. Install Heroku CLI using Homebrew $ brew tap heroku/brew && brew install heroku
  4. Install Apollo CLI $ yarn global add apollo
  5. Install VS Code Apollo
  6. Clone the repo $ git clone [email protected]/adriaanbalt/boilerplate-react-firebase-graphql.git
  7. Install dependencies from the app directory (boilerplate-react-firebase-graphql/app) yarn run install

Local Development

  1. Make sure you are using the correct node version $ nvm use 10.18.1
  2. Make sure you are logged into our private Firebase account development account $ firebase login
  3. In another terminal window, start the local backend development server $ yarn run backend-start
  4. In one terminal window, start the local frontend development server $ yarn run frontend-start
  5. Open browser to http://localhost:3000 (this will happen automatically)
  6. API GraphQL "emulator" server will be hosted at http://localhost:5000 Note: Local development is connected to production database and storage on Firebase! (add item local, item is also in prod)

Deployment

To update the production app both the frontend and backend must be on the server. To make this easy, there is one terminal command that updates both: $ yarn deploy

What is this doing under the hood?

  1. Merge to the frontend code to the master branch
$ git add .
$ git commit -m 'YOUR CUSTOM COMMIT MESSAGE HERE'
$ git push origin master
  1. Check that the environments are building Frontend Activity Monitor Frontend Activity Monitor

  2. Deploy the GraphQL Mutation and Query node js files

From the packages/backend folder run this command

$ firebase deploy --only functions

This will deploy the api function which will update the backend requests on the Google Cloud server.

Local setup (this is being worked on)

Setup apollo

$ npx apollo service:push --endpoint=http://localhost:5000

Connect local environment to Firebase (from within project directory)

$ firebase use --add fireplay-app

$ firebase setup:emulators:firestore

$ firebase emulators:start --only firestore // starts firestore local environment

Note: make sure your yarn workspaces are setup correctly (see below)

Environment Setup

  • Note: this has been completed but is here for reference should anything need adjustment

Enable yarn workspaces experimentation mode globally

Note: this may not be necessary but the documenation includes it.

$ yarn config set workspaces-experimental true

Useful links:

Create a yarn workspace folder structure:

root
├── package.json
├── packages
│   ├── backend
│   │   ├── package.json
│   ├── frontend
│   │   ├── package.json
└── yarn.lock

Update root/package.json as follows

  • Note: Node version 8 is specifically so we can use Firebase Cloud Functions. Otherwise this warning will be triggered: 'Warning, FIREBASE_CONFIG and GCLOUD_PROJECT environment variables are missing. Initializing firebase-admin will fail' reference
  • Note: workspace modules package.json files must also be set to the same node version.
  • $ nvm use 10.18.1
{
  "private": true,
  "name": "boilerplate-react-firebase-graphql",
  "workspaces": {
    "packages": [
      "packages/*"
    ]
  },
  "engines": {
    "node": "8.*"
  }
}

Test to make sure it's setup correctly

$ yarn workspaces info

Should see something like this:
{
  "boilerplate-react-firebase-graphql-frontend": {
    "location": "packages/frontend",
    "workspaceDependencies": [],
    "mismatchedWorkspaceDependencies": []
  },
  "boilerplate-react-firebase-graphql-backend": {
    "location": "packages/backend",
    "workspaceDependencies": [
      "boilerplate-react-firebase-graphql-frontend"
    ],
    "mismatchedWorkspaceDependencies": []
  }
}

GraphQL mutation

  1. Update frontend with request
  • open packages/frontend/src/graphql/requests.js
  • Create a new constant variable like below
export const NAME_OF_MUTATION = gql`
    mutation NameOfMutation( $propertyToPass: DataType! ) { // using ! means that this property is required
        NameOfMutation( propertyToPass: $propertyToPass ) {
            propertyToPass,
        }
    }
`;
  • Make sure "NameOfMutation" is the same as the next step
  1. Update resolver and schema in backend
  • open packages/backend/src/resolvers.js
  • inside the "mutation" property create a new function like below
NameOfMutation: async (_, data) => {
    try {
        // update database
        const newDbObjId = await admin
            .firestore()
            .collection('CollectionName')
            .add(data)
            .then( (docRef) => {
                return docRef.id
            })
            .catch( (error) => {
                console.error("[addTransaction] Error adding document: ", error);
            })

        return objectAssignDeep({}, { id: newDbObjId }, data)
    } catch (error) {
        throw new ApolloError(error);
    }
},
  • open packages/backend/src/schema.js

Create 2 Heroku apps (1 for frontend, 1 for backend)

frontend

  1. Create Heroku app using CLI
$ cd packages/frontend
$ heroku create boilerplate-react-firebase-graphql-frontend
$ heroku apps // check if the app installed (you should see a list of apps including one named boilerplate-react-firebase-graphql-frontend
  1. We are using Create React App aka "CRA"
$ cd packages/frontend
$ npx create-react-app .
$ yarn start // check if the app starts (this should open a browser to localhost:3000)
  1. Install buildpacks
$ heroku buildpacks:add -a boilerplate-react-firebase-graphql-frontend https://github.com/heroku/heroku-buildpack-multi-procfile
$ heroku buildpacks --app boilerplate-react-firebase-graphql-frontend // check to make sure the buildpack installed
  1. Setup config variables
$ heroku config:set PROCFILE=/packages/frontend/Procfile --app boilerplate-react-firebase-graphql-frontend
$ heroku config:set BUILD_ENV=frontend --app boilerplate-react-firebase-graphql-backend
  1. Create root/static.json
  • Enables deep linking for the router on Heroku
{
    "root": "packages/frontend/build/",
    "clean_urls": false,
    "routes": {
        "/**": "index.html"
    }
}

backend

  1. Create Heroku app using CLI
$ cd packages/backend
$ heroku create boilerplate-react-firebase-graphql-backend
$ heroku apps // check if the app installed (you should see a list of apps including one named boilerplate-react-firebase-graphql-backend
  1. Create buildpacks for backend
$ heroku buildpacks:add -a boilerplate-react-firebase-graphql-backend https://github.com/heroku/heroku-buildpack-multi-procfile
$ heroku buildpacks --app boilerplate-react-firebase-graphql-backend // check to make sure the buildpack installed
  1. Setup config variables
$ heroku config:set PROCFILE=/packages/backend/Procfile --app boilerplate-react-firebase-graphql-backend
$ heroku config:set BUILD_ENV=backend --app boilerplate-react-firebase-graphql-backend
$ heroku config:set APOLLO_ENGINE_API_KEY={GET FROM APOLLO} --app boilerplate-react-firebase-graphql-backend

Update root/package.json so Heroku build the code

  • Note: this runs both the frontend and backend build scripts within the heroku server
  • Note: bash may not be required
  • Note: ./scripts/ is required to run this command because of how permissions are setup globally on Heroku
"scripts": {
    "heroku-postbuild": "bash ./scripts/heroku.build",
}

Setup Sub domain

  1. Add domain to heroku project, reference
$ cd packages/frontend
$ heroku domains:add -a boilerplate-react-firebase-graphql-frontend app.{your-domain}.com --remote prod
  1. Copy generated DNS target
$ heroku domains --app boilerplate-react-firebase-graphql-frontend
  1. Login to GoDaddy
  2. Go to DNS Management
  3. Create CNAME record in DNS manager with desired subdomain (in our case 'app' or 'api' in the case of the backend)
  4. Paste generated DNS target in the GoDaddy's CNAME record created in the previous step, reference

Final Folder Structure

root
├── package.json
├── static.json // used by CRA
├── packages
│   ├── frontend
│   │   ├── package.json
│   │   ├── Procfile
│   ├── backend
│   │   ├── package.json
│   │   ├── Procfile
├── scripts // must be within this folder otherwise heroku will not give permission to run it
│   ├── heroku.build // used by heroku-postbuild step (see ${root}/package.json)
└── yarn.lock // you need this for Heroku to run YARN otherwise it will run NPM by default

Cloud Functions

  • Deployment

From the packages/backend folder run this command

$ firebase deploy --only functions
  • List of Cloud Functions

1. api

This is where the GraphQL server is hosted.

2. processSignUp

When a new user is created, we need to update the Firestore database with user credentials. This appears to be the only way to store the uid from the "authentication" tab in Firebase console.

3. storageOnChange

This function only logs a statement that an object on storage has changed. The callback includes a reference to the object.

Debugging

  • See what is happening on the server
$ heroku logs --tail --app boilerplate-react-firebase-graphql-frontend // or boilerplate-react-firebase-graphql-backend
$ git push heroku-frontend master
  • Graph QL errors can happen. When they do, look at the Network tab in your Browser's Dev Inspector to find the broken request. You will find more information about the error there.

How to run the app

In the project directory, you can run:

yarn start

Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.

The page will reload if you make edits.
You will also see any lint errors in the console.

yarn test

Launches the test runner in the interactive watch mode.
See the section about running tests for more information.

yarn run build

Builds the app for production to the build folder.
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.
Your app is ready to be deployed!

See the section about deployment for more information.

Learn More

You can learn more in the Create React App documentation.

To learn React, check out the React documentation.

Code Splitting

This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting

Analyzing the Bundle Size

This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size

Making a Progressive Web App

This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app

Advanced Configuration

This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration

Deployment

This section has moved here: https://facebook.github.io/create-react-app/docs/deployment

npm run build fails to minify

This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify

Files and Folders explanation

  • /globalStyles is where universal files are located. They are loaded into /index.scss which does not include module in its name so it does not act like a css module.
  • React directives can be found in the /components folder, including the screens themselves as their helper directives like Search or DropDown
  • There is an analytics middleware that is able to catch each action that is performed. As you can see in that file, some actions have been chosen to dispatch analytics events to the server (there is no server but this is where that functionality would exist)
  • Using HOC to have inheritance between the screens, which helps with the animations as well as the responsiveness of the app. If I had more time I would further flesh out the animations.
  • The data is stored within the reducers folder and is combined together in the Store.js file.
  • Selectors are used to memoize and quickly retrieve state.
  • Actions are available across the app located in the actions folder.

Strange things

  • There is a warning from router but the creators of React Router haven't fixed it yet, not sure why that is the case. See more here

boilerplate-react-firebase-graphql's People

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.