Top 100 Firebase Pro Tips 🔥💯. Optimize your app for performance, costs, and developer happiness - and avoid common mistakes https://fireship.io/lessons/firebase-tips-and-tricks/

🍍 Firebase https://firebase.google.com/
🚀 Firebase PRO courses https://fireship.io/courses/

Leave a comment below with your best Firebase Tip for a chance to win a free T-shirt. 

#top100 #firebase

Take the Firebase quiz 🤓

iOS https://itunes.apple.com/us/app/fireship/id1462592372?mt=8
Android https://play.google.com/store/apps/details?id=io.fireship.quizapp

Upgrade to Fireship PRO at https://fireship.io/pro
Use code lORhwXd2 for 25% off your first payment.
2024-02-04T06:32:17.567Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
f7252b6f-a346-4303-b3fe-a87cb3d8b70d
5b9966d51b62353d14c57c96a45a55936414c58360a1829ce658ddacb973e337
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
Welcome to my top 10 Firebase tips.
Welcome to my top 25 Firebase tips.
Nope.
Welcome to my top 100 Firebase tips.
I've been working with Firebase for several years now.
I've made plenty of mistakes along the way, but I've also uncovered some secrets that you may not know about.
So hopefully this video makes your experience with Firebase 100 times easier.
If you're new here, like and subscribe.
And if you're serious about building an app of Firebase, consider becoming a pro member at Fireship I tip.
You'll get access to full project courses and a free t shirt if you sign up for life.
Or you can get a free t shirt by leaving the best Firebase tip in the comments below.
The first thing you'll need is a Firebase project.
If you're building a serious app, create 2 Firebase projects, one for development and one for production.
This gives you a sandbox for testing and Experimenting, and you can keep your customer data pristine in the production project.
In your production project, link Google Analytics.
Firebase can automatically set up analytics for iOS, Android, and the web.
If you're working with a team, head over to the settings tab and then go to users and permissions.
Assign roles based on the principle of least privilege, so team members only have access to the resources that they actually need.
From there, head over to the data privacy tab and update your contact information to ensure you're in compliance with GDPR.
Now click the button to add a new app to your Firebase project.
When you do that, it will give you an object with a bunch of credentials.
Don't worry.
These are perfectly safe in your front end code as long as you set up security rules, which we'll look at later.
Upgrade your Firebase plan to Blaze.
It's pay as you go, but you still get all of the free stuff that you would on the Spark tier.
But you still want to stay on top of cost, so head over to the GCP console and set up a budget alert for your project.
Then monitor your monthly usage from the reports panel.
This will tell you Exactly which services are costing you the most money.
Make sure to install the Firebase command line tools globally on your system and also the Google Cloud SDK.
A Firebase project is actually just a layer on top of a Google Cloud Platform project.
Once you've done this, you should have access to the Firebase command and the gcloud command on your local system.
So now that we have a project set up, let's look at how we can actually deploy our code to this project.
If you're building an iOS or Android app, use Firebase app distribution to distribute your app to testers.
This will bypass TestFlight and the Google Play Store, making your life much easier.
Now if you're building a web application, you're likely using a package manager like npm.
Install Firebase tools into the development environment for that project.
And now you can write npm scripts that use the Firebase CLI tools.
Now if you followed my earlier advice to set up different projects for development and production, you can use the project flag to set up different commands that specify the project.
So here we have a command to deploy to our development project and another for our production project.
Now after you've deployed your site, head over to the Firebase console, and you can see it's deployed at a cool domain called your project dot web dot app, or you can just connect your own custom domain.
And you're not limited to a single domain.
For example, you might have an admin site and a customer facing site.
They can both share the same Firebase project with multisite hosting.
Then go into your Firebase JSON file, change the hosting value to an array, and set up different targets that represent the different sites you want to deploy.
Now you're not just limited to static files when deploying to hosting.
You can actually rewrite traffic to a Cloud Function or to a Cloud Run instance.
And that means you can do SSR with something like Angular Universal or Next.
Js.
You can also set up Firebase hosting rewrites for dynamic links.
This allows you to dynamically send the user to the app with the best possible experience.
So if the user goes to a link on their iPhone, it will take them to a specific screen in the iPhone app.
You can also specify headers on the static files in your hosting account.
For example, if we wanted to change the core settings for all of the font files, we could do it like this.
And Firebase Hosting will also cache our static files for better performance, but we can change the caching behavior by setting different cache headers here as well.
And one cool thing you might do to extend Firebase Hosting is to set it up with Google Cloud Build.
So every git commit you make to your project, it will deploy a new version of your site to your hosting account.
That's exactly what I do for Fireship IO.
Firebase provides 2 different fully managed NoSQL databases.
So how do you know which one to choose?
I default to Cloud Firestore because it has more powerful query capabilities.
It also costs less per gigabyte stored.
However, real time database does not charge for rights, So it can be a great option if you have data that's updated frequently like an IoT sensor or something along those lines.
But when it comes to pricing, you really shouldn't worry about it too much.
Don't even trip, dawg.
Firebase overall is very inexpensive, and it will take a decent number of monthly active users before you even break out of the free tier.
Unless you make a silly mistake, you'll be paying much less than you would be with other cloud solutions.
A more important thing to worry about is that you back up your data on a regular basis.
Set up a dedicated cloud storage bucket for backups, and then you can back up your entire database with a single command.
When you create your based for the first time, set it in locked mode.
It's safer to start with a locked down database than incrementally allow operations as they become necessary.
After you've created a Firestore collection, go ahead and click the filter icon, and you'll see that you can make queries directly from the Firebase console.
And it even provides some code for your query that you can copy and paste to using your app source code.
In fact, let's go ahead and switch gears and jump into the source code for a JavaScript application.
Now the way you import Firebase depends on the flavor of JavaScript you're using.
You can see the import syntax here for CommonJS, ES 6, and TypeScript.
But all of these are actually wrong because they're importing from Firebase directly.
Your code will work, but it will create a huge JavaScript bundle that will slow down your app.
The correct way to use Firebase is to import from the Firebase app namespace and then import these services that you plan on using, aka progressive enhancement.
In any case, Firebase is a pretty big dependency.
So if you're loading it with a script tag, You'll wanna use the defer keyword on that script to ensure it loads after the actual DOM or HTML has been parsed.
But if you're using a framework, then you shouldn't have to worry about this.
Angular app should use AngularFire, which integrates with change detection and the Angular router.
If you use React on the front end, the ReactFire library was just undeprecated, and it provides support for hooks and suspense.
You have RXFire to integrate with RxJS, which works great in frameworks like Svelte.
Then outside of the web, you have support for all kinds of different other frameworks in Firebase extended like Flutter, Arduino, and many others.
When you first add Firebase to a project, there's a couple of no brainer services that you'll definitely wanna use, such as performance monitoring.
With a single line of code, we can see how well our app performs out in the wild, giving us metrics like first contentful paint across all devices using our app.
The next one is Crashlytics, which is only relevant to native mobile apps.
It's very easy to set up, and it will give you error reporting and crash reporting throughout your entire application and automatically open issues so you can address those problems.
And lastly, we have Firebase Analytics.
With a single line of code, we'll get the default reporting from Google Analytics, giving us insight about the behavior of our users.
Now in your source code, one of the first things you'll likely wanna do is determine if a user is logged in or not.
There are 2 main ways to do this.
You can pull the current user at any time by calling auth current user.
This is usually best for handling events, like when the user clicks a button and then you want to grab their auth record and do something afterwards.
The other way to get the current user is to always be listening to the current auth state.
In this case, you provide a callback function to listen to changes to the auth state, like when the user signs in or signs out.
In either case, I recommend getting good at asynchronous JavaScript to be test with Firebase.
Understanding async await is very useful for the first approach, then understanding callbacks and functional programming is very useful for the second approach.
When a user attempts to log in, something might go wrong.
It might be your fault as the developer or the user's fault.
In any case, you'll want to make sure that you catch these and then create a default handler that routes them to a visual UI element like a dialogue.
A cool trick you can do with Firebase auth is to register a user lazily.
For example, you might first have a user sign in anonymously, which will give you a user ID that you can tie to the database.
Then later in the onboarding process, you can collect their email or link social accounts like Twitter, Facebook, Google, etcetera.
Now certain authentication methods like email password may need to send emails to your users for things like email verification and resetting passwords.
Sometimes you might want to control this process on your own, which you can do with custom email action handlers, And you can even bring your own custom SMTP email server.
Now one of the most important aspects of any application is managing relational data.
Let's check out a few common techniques for connecting our users to the Firestore database.
We can create a one to one relationship where the user has one document in Fire store by first retrieving their user ID, then we'll make a reference to a collection and set the document ID as the user ID.
Every user ID is unique, So it guarantees that that user can only have one document in that collection.
Now if it's possible that data already exists there, you might want to use the merge true option.
This will ensure that any data that already exists there won't be overwritten.
The merge true option just makes it a nondestructive update.
Another common relationship is one to many.
A user might have many orders, but an order belongs to one user.
The best way to handle this type of relationship is to use a subcollection.
In the last example, we created a document with a user ID, and we know that every subcollection under that document is owned by that user.
But sometimes you might run into a situation where you want to query orders across all the users in your database.
Firebase provides a special method that allows you to group subcollections and query them together.
Collection group will find all of the collections that share the name orders, group them together, allowing you to make a single query against all of them.
And another very common relationship is many to many.
In this case, we have a single collection called chats, and each chat document can be associated with multiple users.
We can associate multiple users to multiple chats by embedding their user IDs on the chat document using a map of key value pairs.
The key is the user ID, and then I'm going to duplicate the display name in case we want to show that in the UI.
Data duplication is perfectly okay in NoSQL.
It can optimize for performance and costs, but it works best with values that are immutable or that don't need to be updated very often.
And now that we have a map object on this document where each key in that map is a user ID.
We can query it by using dot notation in our queries, like order by members dot user ID.
Now that we've modeled some data and made some queries, we need to decide if we want our data in real time format or not.
If you're trying to optimize pricing and don't think you'll need real time updates For your data, you can just call query git to retrieve the data once and then not listen to any future updates.
But if you are building a feature where the UI should react To change this in real time, you'll want to use query on snapshot, then run a callback function anytime the underlying data changes.
On a collection query, when you listen to docs, You'll get a new array anytime there's a change to the underlying data, but you might want to know exactly which documents were added, modified, or removed.
Doc changes provides an array of all the documents that changed, their old index, new index, and the change type.
Another awesome thing about Firestore is that it's able to work offline.
If the Internet goes out and the user's still trying to send rights to the database, Firestore will still update the UI and then send those rights to the actual database and commit them after the Internet comes back online.
And you can even make this work across multiple browser tabs by setting the synchronized tabs option to true.
Now one question I get a lot is how do I use emoji characters in my code?
Well, they're actually just u t f eight characters, which means you can use them in a regular string.
And that also means that you can use them in your Firestore documents and make queries against them.
Another trick you might wanna use is to match a wildcard string.
For example, if we wanted to query all of the Fast and the Furious movie titles.
Create a starting point and then make your ending point a tilde character.
This will match all the documents that start with the Fast and the Furious title.
And with that, we have reached the halfway mark.
Let's take a quick break.
Welcome back.
Sometimes you might have a compound query where you chain together multiple query conditions.
This query won't work by default because it requires an index, but don't create the index manually.
Let your app throw an error, then click the link to the Firestore console to create the index automatically.
One of the most powerful data types in Firestore is a list.
We can add a list to a document by simply setting it with a JavaScript array.
But we might decide later that any good Firebase recipe needs to include a pineapple.
We can use the Firestore array union method to ensure that the array includes exactly 1 pineapple.
Or we might decide later on that maybe squid wasn't such a good idea in this recipe, so we can remove it by using the array remove method without having to know the actual index.
And now that we have an array on the document, we can query it by using the array contains operator inside of where, and that will give us all of the recipes that contain avocado.
Now sometimes you might have an array that contains IDs of other documents in the database.
But how do you actually fetch the full documents in this array?
Do it in JavaScript by mapping all of the ID strings to an array of promises that get the document, then run them together with promise dot all.
One thing you should generally avoid doing is setting a time stamp from your front end code because the user's clock might not be synchronized properly.
If you need to set a time stamp on a document, use the Firestore server time stamp.
That ensures that all users are sharing the same clock.
Another thing you might wanna do is increment a counter, like the score of the game.
You can change the value of the counter atomically without knowing its current value by using the increment field value.
Now Firestore only supports 1 write per document per second, although you can burst above that value.
So if you have a ton of writes happening on a single document, You can set up a distributed counter, which is now very easy to do because there is a Firebase extension that supports it.
And speaking of atomic, Sometimes you might have rights that need to succeed or fail together.
Maybe the user completes the game, you write the score, and then you want to update the user's lifetime score.
You can ensure that these operations happen together by setting up a batch write.
This will commit them together, but roll back to the previous state if any of the writes fail.
Now Firestore is a great solution for the vast majority of use cases, but sometimes you might need a full relational database.
If you need a full relational database, Check out my video on integrating MySQL into a Firebase project.
Or if you need full text search, check out my Algolia integration video.
Now one of the most important things to do as a Firebase developer is set rules before you deploy to production.
If you deploy an app without good security rules in place, your customer's data could be compromised, and someone could make destructive rights to your database.
Currently, our database is in lock mode, which means we're safe.
But now let's go ahead and open up some operations for our users.
The first thing you should do is get used to using the simulator.
It allows you to pass mock requests to the database to see how the rules will be evaluated, But serious production apps should use the Firestore emulator.
This allows you to simulate the Firestore database in your local development environment, You can throw a whole bunch of different test cases at your rules to ensure that they're robust.
Note that there are 5 different types of operations a user can make on a document.
They can get a single document, a query of a list of documents, and they can create, update, and delete documents.
You can provide fine grained rules for each operation, or you can combine Then by using the read or write keywords.
If they share the same logic, just separate them with a comma.
When a rule is evaluated, there are 2 things that you'll look at, the request and the resource.
The request contains the user's authentication state as well as the incoming data that they're trying to write to the database.
The resource, On the other hand, is the data that already exists at this path in the database.
But in some cases, you might need to look elsewhere in the database to determine if a rule should be allowed.
Use the get keyword and then point to a path in the database, and you can use dollar sign parenthesis to interpolate values like the request auth user ID.
This gives you the value from this document, but keep in mind that you're charged a read every time this rule is evaluated.
Now you might notice That this is a very long line of code, and if we were using this frequently throughout the rules, we wouldn't want to have to repeat it all the time.
We can extract this logic into its own function called is admin, And now we have a much cleaner way to check for admin users.
Now let's switch gears to cloud storage.
A storage bucket is where you would put things like images, videos, and raw files.
You have a default bucket, which is where you would normally save your user generated content, but you can create additional buckets as well.
You might want an additional bucket for Firestore backups, which you can set to coldline, which will save you some money.
Now when you upload a file to a storage bucket, there is a storage location and a download URL.
If the user needs to access this file again in the future, I recommend saving both values to the Firestore database.
You can use the storage location to replace or delete the file in the future or the download URL to access the file in your app.
But don't worry too much if you forgot to save the file path in the database because you can use the storage ref from URL and point to either the full path in the storage bucket or to the download URL to access that file.
Sometimes you might want to list out all the files in a directory in the bucket.
Simply make a reference to the path to the directory, and then use the list all method to get all the files at that location.
You can upload a file by simply making a reference to a file path and then putting the raw file that you want to upload.
You can calculate the progress of an upload by listening to the state changed event, then divide the bytes transferred by the total bytes in the file.
If you have multiple files to upload, feel free to upload them all at the same time.
Firebase will automatically handle concurrency and upload them as efficiently as possible.
When you upload files, you might also want to save your own custom metadata about that file.
You might want to know what kind of device the user upload the file from, their user ID, and stuff like that.
If your users can upload image files, there's a good chance that you'll want to resize them to different resolutions for different devices.
You can now do that with a click of button using the Firebase image resizer extension.
At this point, we've been mostly looking at front end code, so now I want to switch gears to the back tip.
You can create your own command line utility for Firebase with 3 easy steps.
Go to your project settings and download the service account for your project.
In a node project, install Firebase Admin as a development dependency, then create a JS file that imports it and calls initialize app.
Firebase admin needs your service account, but it contains sensitive information.
The safest way to use it locally is to keep it somewhere private on your system, and then use an environment variable called Google application credentials.
But if you include the service account directly in your source code, make sure it's in your git ignore so it doesn't end up in a public repo somewhere.
One of my favorite things to do with an admin script is to seed the database with some dummy data.
Install Faker JS and then import it into your JavaScript file.
Then create a loop, and for each iteration, add a new document to the collection using Faker to automatically generate the dummy data.
Now run the script from the command line with node.
You should now see a bunch of dummy documents seeded in your database.
Now you can do a lot with the Firebase Admin SDK, but you can do even more with the rest APIs.
Check out the rest API documentation to find secret techniques that you didn't know about.
Earlier, I showed you how to back up Firestore from the command line, but you can also do it with the rest API.
This would allow you to set up a cron job to back up your database on a daily basis.
If you do use the REST API, you'll want to use the Google APIs NPM package.
This allows you to discover and interact with hundreds of different Google APIs, like AdWords, YouTube, and, of course, Firebase.
Creating an admin script can be useful, but in most cases, you'll be with Firebase Admin in a Cloud Function.
You can add Cloud Functions to your project by running Firebase init functions.
When you do this, I highly recommend using TypeScript because it does all the setup for you and will help you catch silly errors before they end up in production.
There's a few things we can do to improve the performance of a cold start on a cloud function and also reduce the CPU time that we're actually billed for.
Try to minimize the number of dependencies that you use in your functions.
More code to load and parse means a slower cold start time.
If you have values that can be shared between multiple function invocations, you can set them up as global variables.
When a function instance spins up in the cloud, it might be used multiple times, so global variables can be used across multiple calls improving performance.
When you design your Cloud Functions, they should always be item potent.
Cloud Functions are guaranteed to be invoked at least once, But they can be retried multiple times, so you wanna make sure that multiple calls to the same function produces the same result.
And you can use the context event ID to help you achieve that.
If you need to add more horsepower to a function, you can use run with to max out the memory at 2 gigabytes and the time out seconds to 540.
Now one thing you want to be really careful not to do is to create an infinite loop.
You might accidentally do this in Firestore by updating the same document that triggered the event.
In this example, we have an on write function that updates the same document that triggered the write.
So this will cause an infinite loop that will charge up your Firebase bill until you hit the quota limits.
It's not a good thing to do.
However, there are use cases when you might want the triggering function to update the same document.
You can avoid the infinite loop by checking if The after document is equal to the before document.
This will check for equality on the document path and its data, and that will stop the loop assuming your function is idempotent.
Background cloud functions must always return a promise.
You can ensure that always happens by using the async keyword in the function callback, Then you can use the await keyword for a much cleaner synchronous looking code.
Sometimes you might need a cloud function that communicates with other cloud functions or other GCP services.
You could use an HTTP function to handle that, but you would also need to implement some code to validate the request.
A better alternative would be to set up a pubsub function.
It allows you to pass messages between your internal services, and that's easier and more secure than exposing an HTTP endpoint.
You might also have endpoints that should only accessed by authenticated users.
In a regular HTTP function, you would need to extract the authorization header that you set in your front end code and then verify the ID token.
As an alternative, you can simplify both your back end and front end code by using callable functions.
It includes the auth context for the user, so you don't have to implement your own middleware to authenticate your functions.
A great use case is to delete an entire Firestore collection, which Should always be done on the back end because there might be tons of documents in a collection.
We can first authorize the operation by looking at the user ID.
Then we'll create a recursive function called batch delete.
It retrieves documents in batches of 100 and then deletes them.
This will ensure that we don't hit memory issues if we try to query millions of documents in a single go.
Now when implementing the actual logic for your back end code, consider breaking it down into small JavaScript functions.
This allows you to reuse code across multiple Deploy Cloud Functions, and it's also just easier to test.
Keep in mind that Cloud Functions provide a gateway to interact with other third party APIs.
Almost every good API also has a good Node JS library to go with it.
So, basically, anything you can build in Node JS, you can build in a Cloud Function.
When you're ready to go live, you can deploy all of your functions from the command line with a single command.
But on larger projects with dozens of functions, you may not want to deploy everything all at once.
You can append the name of the function to the end of this command to deploy a single function.
Despite your best efforts, your functions will very likely have some bugs.
The best way to prevent bugs is to run the Cloud Functions shell locally.
You can invoke your functions with mock data to test their behavior, and Firebase even provides a unit testing library.
Now your function still might break in production, so you can always look at the Firebase logs to see what's going wrong.
Or better yet, head over to Stackdriver where you can create your own custom dashboards boards and alerts for the things that you care about.
Earlier in the video, we set up analytics in our front end code.
But to get the most out of it, we'll want to track custom events and user properties.
Try to pinpoint the events or user behaviors that you think are most important to turning that user into a paying customer, then use Firebase Analytics to record those events.
Firebase will aggregate some of the data automatically, but you can create your own audiences based on the type of user that you want to target.
Your marketing team will love audiences because you can target messaging to a specific type of user and also do things like AB testing and funnels.
And as a developer, You can actually use audiences to customize the UI based on your underlying analytics data.
The service will send key value pairs down to to your front end application, which you can use to conditionally show UI based on where that user is located, what audience they belong to, and so on.
You can also use the same data to send push notifications to your users using Firebase Cloud Messaging.
Instead of sending a bulk notification out to all of your users, Segment it to the users who actually want it and will benefit from it.
And with that, we have finally reached Firebase tip number 100.
Leverage machine learning within your app.
You can do this in multiple ways with Firebase.
Use predictions to guess when a user is going to buy your product, use ML Kit to implement AI driven features out of the box, Things like object detection and smart reply, or build your own image classification models with AutoML.
And you can even export all of your analytics and Firestore data to BigQuery and use that raw data to train your own TensorFlow models from scratch.
And that is all of the Firebase tips that exist in the world.
If you have your own additional tips, Leave them in the comments below, and I'll pick a couple of the best ones to win a t shirt later this week.
I'm gonna go ahead and wrap things up there.
Hopefully, you found something useful in here.
Thanks for watching, and I will talk to you soon.

Speaker 0: Welcome to my top 10 Firebase tips. Welcome to my top 25 Firebase tips. Nope. Welcome to my top 100 Firebase tips. I've been working with Firebase for several years now.

I've made plenty of mistakes along the way, but I've also uncovered some secrets that you may not know about. So hopefully this video makes your experience with Firebase 100 times easier. If you're new here, like and subscribe. And if you're serious about building an app of Firebase, consider becoming a pro member at Fireship I tip. You'll get access to full project courses and a free t shirt if you sign up for life.

Or you can get a free t shirt by leaving the best Firebase tip in the comments below. The first thing you'll need is a Firebase project. If you're building a serious app, create 2 Firebase projects, one for development and one for production. This gives you a sandbox for testing and Experimenting, and you can keep your customer data pristine in the production project. In your production project, link Google Analytics.

Firebase can automatically set up analytics for iOS, Android, and the web. If you're working with a team, head over to the settings tab and then go to users and permissions. Assign roles based on the principle of least privilege, so team members only have access to the resources that they actually need. From there, head over to the data privacy tab and update your contact information to ensure you're in compliance with GDPR. Now click the button to add a new app to your Firebase project.

When you do that, it will give you an object with a bunch of credentials. Don't worry. These are perfectly safe in your front end code as long as you set up security rules, which we'll look at later. Upgrade your Firebase plan to Blaze. It's pay as you go, but you still get all of the free stuff that you would on the Spark tier.

But you still want to stay on top of cost, so head over to the GCP console and set up a budget alert for your project. Then monitor your monthly usage from the reports panel. This will tell you Exactly which services are costing you the most money. Make sure to install the Firebase command line tools globally on your system and also the Google Cloud SDK. A Firebase project is actually just a layer on top of a Google Cloud Platform project.

Once you've done this, you should have access to the Firebase command and the gcloud command on your local system. So now that we have a project set up, let's look at how we can actually deploy our code to this project. If you're building an iOS or Android app, use Firebase app distribution to distribute your app to testers. This will bypass TestFlight and the Google Play Store, making your life much easier. Now if you're building a web application, you're likely using a package manager like npm.

Install Firebase tools into the development environment for that project. And now you can write npm scripts that use the Firebase CLI tools. Now if you followed my earlier advice to set up different projects for development and production, you can use the project flag to set up different commands that specify the project. So here we have a command to deploy to our development project and another for our production project. Now after you've deployed your site, head over to the Firebase console, and you can see it's deployed at a cool domain called your project dot web dot app, or you can just connect your own custom domain.

And you're not limited to a single domain. For example, you might have an admin site and a customer facing site. They can both share the same Firebase project with multisite hosting. Then go into your Firebase JSON file, change the hosting value to an array, and set up different targets that represent the different sites you want to deploy. Now you're not just limited to static files when deploying to hosting.

You can actually rewrite traffic to a Cloud Function or to a Cloud Run instance. And that means you can do SSR with something like Angular Universal or Next. Js. You can also set up Firebase hosting rewrites for dynamic links. This allows you to dynamically send the user to the app with the best possible experience.

So if the user goes to a link on their iPhone, it will take them to a specific screen in the iPhone app. You can also specify headers on the static files in your hosting account. For example, if we wanted to change the core settings for all of the font files, we could do it like this. And Firebase Hosting will also cache our static files for better performance, but we can change the caching behavior by setting different cache headers here as well. And one cool thing you might do to extend Firebase Hosting is to set it up with Google Cloud Build.

So every git commit you make to your project, it will deploy a new version of your site to your hosting account. That's exactly what I do for Fireship IO. Firebase provides 2 different fully managed NoSQL databases. So how do you know which one to choose? I default to Cloud Firestore because it has more powerful query capabilities.

It also costs less per gigabyte stored. However, real time database does not charge for rights, So it can be a great option if you have data that's updated frequently like an IoT sensor or something along those lines. But when it comes to pricing, you really shouldn't worry about it too much. Don't even trip, dawg. Firebase overall is very inexpensive, and it will take a decent number of monthly active users before you even break out of the free tier.

Unless you make a silly mistake, you'll be paying much less than you would be with other cloud solutions. A more important thing to worry about is that you back up your data on a regular basis. Set up a dedicated cloud storage bucket for backups, and then you can back up your entire database with a single command. When you create your based for the first time, set it in locked mode. It's safer to start with a locked down database than incrementally allow operations as they become necessary.

After you've created a Firestore collection, go ahead and click the filter icon, and you'll see that you can make queries directly from the Firebase console. And it even provides some code for your query that you can copy and paste to using your app source code. In fact, let's go ahead and switch gears and jump into the source code for a JavaScript application. Now the way you import Firebase depends on the flavor of JavaScript you're using. You can see the import syntax here for CommonJS, ES 6, and TypeScript.

But all of these are actually wrong because they're importing from Firebase directly. Your code will work, but it will create a huge JavaScript bundle that will slow down your app. The correct way to use Firebase is to import from the Firebase app namespace and then import these services that you plan on using, aka progressive enhancement. In any case, Firebase is a pretty big dependency. So if you're loading it with a script tag, You'll wanna use the defer keyword on that script to ensure it loads after the actual DOM or HTML has been parsed.

But if you're using a framework, then you shouldn't have to worry about this. Angular app should use AngularFire, which integrates with change detection and the Angular router. If you use React on the front end, the ReactFire library was just undeprecated, and it provides support for hooks and suspense. You have RXFire to integrate with RxJS, which works great in frameworks like Svelte. Then outside of the web, you have support for all kinds of different other frameworks in Firebase extended like Flutter, Arduino, and many others.

When you first add Firebase to a project, there's a couple of no brainer services that you'll definitely wanna use, such as performance monitoring. With a single line of code, we can see how well our app performs out in the wild, giving us metrics like first contentful paint across all devices using our app. The next one is Crashlytics, which is only relevant to native mobile apps. It's very easy to set up, and it will give you error reporting and crash reporting throughout your entire application and automatically open issues so you can address those problems. And lastly, we have Firebase Analytics.

With a single line of code, we'll get the default reporting from Google Analytics, giving us insight about the behavior of our users. Now in your source code, one of the first things you'll likely wanna do is determine if a user is logged in or not. There are 2 main ways to do this. You can pull the current user at any time by calling auth current user. This is usually best for handling events, like when the user clicks a button and then you want to grab their auth record and do something afterwards.

The other way to get the current user is to always be listening to the current auth state. In this case, you provide a callback function to listen to changes to the auth state, like when the user signs in or signs out. In either case, I recommend getting good at asynchronous JavaScript to be test with Firebase. Understanding async await is very useful for the first approach, then understanding callbacks and functional programming is very useful for the second approach. When a user attempts to log in, something might go wrong.

It might be your fault as the developer or the user's fault. In any case, you'll want to make sure that you catch these and then create a default handler that routes them to a visual UI element like a dialogue. A cool trick you can do with Firebase auth is to register a user lazily. For example, you might first have a user sign in anonymously, which will give you a user ID that you can tie to the database. Then later in the onboarding process, you can collect their email or link social accounts like Twitter, Facebook, Google, etcetera.

Now certain authentication methods like email password may need to send emails to your users for things like email verification and resetting passwords. Sometimes you might want to control this process on your own, which you can do with custom email action handlers, And you can even bring your own custom SMTP email server. Now one of the most important aspects of any application is managing relational data. Let's check out a few common techniques for connecting our users to the Firestore database. We can create a one to one relationship where the user has one document in Fire store by first retrieving their user ID, then we'll make a reference to a collection and set the document ID as the user ID.

Every user ID is unique, So it guarantees that that user can only have one document in that collection. Now if it's possible that data already exists there, you might want to use the merge true option. This will ensure that any data that already exists there won't be overwritten. The merge true option just makes it a nondestructive update. Another common relationship is one to many.

A user might have many orders, but an order belongs to one user. The best way to handle this type of relationship is to use a subcollection. In the last example, we created a document with a user ID, and we know that every subcollection under that document is owned by that user. But sometimes you might run into a situation where you want to query orders across all the users in your database. Firebase provides a special method that allows you to group subcollections and query them together.

Collection group will find all of the collections that share the name orders, group them together, allowing you to make a single query against all of them. And another very common relationship is many to many. In this case, we have a single collection called chats, and each chat document can be associated with multiple users. We can associate multiple users to multiple chats by embedding their user IDs on the chat document using a map of key value pairs. The key is the user ID, and then I'm going to duplicate the display name in case we want to show that in the UI.

Data duplication is perfectly okay in NoSQL. It can optimize for performance and costs, but it works best with values that are immutable or that don't need to be updated very often. And now that we have a map object on this document where each key in that map is a user ID. We can query it by using dot notation in our queries, like order by members dot user ID. Now that we've modeled some data and made some queries, we need to decide if we want our data in real time format or not.

If you're trying to optimize pricing and don't think you'll need real time updates For your data, you can just call query git to retrieve the data once and then not listen to any future updates. But if you are building a feature where the UI should react To change this in real time, you'll want to use query on snapshot, then run a callback function anytime the underlying data changes. On a collection query, when you listen to docs, You'll get a new array anytime there's a change to the underlying data, but you might want to know exactly which documents were added, modified, or removed. Doc changes provides an array of all the documents that changed, their old index, new index, and the change type. Another awesome thing about Firestore is that it's able to work offline.

If the Internet goes out and the user's still trying to send rights to the database, Firestore will still update the UI and then send those rights to the actual database and commit them after the Internet comes back online. And you can even make this work across multiple browser tabs by setting the synchronized tabs option to true. Now one question I get a lot is how do I use emoji characters in my code? Well, they're actually just u t f eight characters, which means you can use them in a regular string. And that also means that you can use them in your Firestore documents and make queries against them.

Another trick you might wanna use is to match a wildcard string. For example, if we wanted to query all of the Fast and the Furious movie titles. Create a starting point and then make your ending point a tilde character. This will match all the documents that start with the Fast and the Furious title. And with that, we have reached the halfway mark.

Let's take a quick break. Welcome back. Sometimes you might have a compound query where you chain together multiple query conditions. This query won't work by default because it requires an index, but don't create the index manually. Let your app throw an error, then click the link to the Firestore console to create the index automatically.

One of the most powerful data types in Firestore is a list. We can add a list to a document by simply setting it with a JavaScript array. But we might decide later that any good Firebase recipe needs to include a pineapple. We can use the Firestore array union method to ensure that the array includes exactly 1 pineapple. Or we might decide later on that maybe squid wasn't such a good idea in this recipe, so we can remove it by using the array remove method without having to know the actual index.

And now that we have an array on the document, we can query it by using the array contains operator inside of where, and that will give us all of the recipes that contain avocado. Now sometimes you might have an array that contains IDs of other documents in the database. But how do you actually fetch the full documents in this array? Do it in JavaScript by mapping all of the ID strings to an array of promises that get the document, then run them together with promise dot all. One thing you should generally avoid doing is setting a time stamp from your front end code because the user's clock might not be synchronized properly.

If you need to set a time stamp on a document, use the Firestore server time stamp. That ensures that all users are sharing the same clock. Another thing you might wanna do is increment a counter, like the score of the game. You can change the value of the counter atomically without knowing its current value by using the increment field value. Now Firestore only supports 1 write per document per second, although you can burst above that value.

So if you have a ton of writes happening on a single document, You can set up a distributed counter, which is now very easy to do because there is a Firebase extension that supports it. And speaking of atomic, Sometimes you might have rights that need to succeed or fail together. Maybe the user completes the game, you write the score, and then you want to update the user's lifetime score. You can ensure that these operations happen together by setting up a batch write. This will commit them together, but roll back to the previous state if any of the writes fail.

Now Firestore is a great solution for the vast majority of use cases, but sometimes you might need a full relational database. If you need a full relational database, Check out my video on integrating MySQL into a Firebase project. Or if you need full text search, check out my Algolia integration video. Now one of the most important things to do as a Firebase developer is set rules before you deploy to production. If you deploy an app without good security rules in place, your customer's data could be compromised, and someone could make destructive rights to your database.

Currently, our database is in lock mode, which means we're safe. But now let's go ahead and open up some operations for our users. The first thing you should do is get used to using the simulator. It allows you to pass mock requests to the database to see how the rules will be evaluated, But serious production apps should use the Firestore emulator. This allows you to simulate the Firestore database in your local development environment, You can throw a whole bunch of different test cases at your rules to ensure that they're robust.

Note that there are 5 different types of operations a user can make on a document. They can get a single document, a query of a list of documents, and they can create, update, and delete documents. You can provide fine grained rules for each operation, or you can combine Then by using the read or write keywords. If they share the same logic, just separate them with a comma. When a rule is evaluated, there are 2 things that you'll look at, the request and the resource.

The request contains the user's authentication state as well as the incoming data that they're trying to write to the database. The resource, On the other hand, is the data that already exists at this path in the database. But in some cases, you might need to look elsewhere in the database to determine if a rule should be allowed. Use the get keyword and then point to a path in the database, and you can use dollar sign parenthesis to interpolate values like the request auth user ID. This gives you the value from this document, but keep in mind that you're charged a read every time this rule is evaluated.

Now you might notice That this is a very long line of code, and if we were using this frequently throughout the rules, we wouldn't want to have to repeat it all the time. We can extract this logic into its own function called is admin, And now we have a much cleaner way to check for admin users. Now let's switch gears to cloud storage. A storage bucket is where you would put things like images, videos, and raw files. You have a default bucket, which is where you would normally save your user generated content, but you can create additional buckets as well.

You might want an additional bucket for Firestore backups, which you can set to coldline, which will save you some money. Now when you upload a file to a storage bucket, there is a storage location and a download URL. If the user needs to access this file again in the future, I recommend saving both values to the Firestore database. You can use the storage location to replace or delete the file in the future or the download URL to access the file in your app. But don't worry too much if you forgot to save the file path in the database because you can use the storage ref from URL and point to either the full path in the storage bucket or to the download URL to access that file.

Sometimes you might want to list out all the files in a directory in the bucket. Simply make a reference to the path to the directory, and then use the list all method to get all the files at that location. You can upload a file by simply making a reference to a file path and then putting the raw file that you want to upload. You can calculate the progress of an upload by listening to the state changed event, then divide the bytes transferred by the total bytes in the file. If you have multiple files to upload, feel free to upload them all at the same time.

Firebase will automatically handle concurrency and upload them as efficiently as possible. When you upload files, you might also want to save your own custom metadata about that file. You might want to know what kind of device the user upload the file from, their user ID, and stuff like that. If your users can upload image files, there's a good chance that you'll want to resize them to different resolutions for different devices. You can now do that with a click of button using the Firebase image resizer extension.

At this point, we've been mostly looking at front end code, so now I want to switch gears to the back tip. You can create your own command line utility for Firebase with 3 easy steps. Go to your project settings and download the service account for your project. In a node project, install Firebase Admin as a development dependency, then create a JS file that imports it and calls initialize app. Firebase admin needs your service account, but it contains sensitive information.

The safest way to use it locally is to keep it somewhere private on your system, and then use an environment variable called Google application credentials. But if you include the service account directly in your source code, make sure it's in your git ignore so it doesn't end up in a public repo somewhere. One of my favorite things to do with an admin script is to seed the database with some dummy data. Install Faker JS and then import it into your JavaScript file. Then create a loop, and for each iteration, add a new document to the collection using Faker to automatically generate the dummy data.

Now run the script from the command line with node. You should now see a bunch of dummy documents seeded in your database. Now you can do a lot with the Firebase Admin SDK, but you can do even more with the rest APIs. Check out the rest API documentation to find secret techniques that you didn't know about. Earlier, I showed you how to back up Firestore from the command line, but you can also do it with the rest API.

This would allow you to set up a cron job to back up your database on a daily basis. If you do use the REST API, you'll want to use the Google APIs NPM package. This allows you to discover and interact with hundreds of different Google APIs, like AdWords, YouTube, and, of course, Firebase. Creating an admin script can be useful, but in most cases, you'll be with Firebase Admin in a Cloud Function. You can add Cloud Functions to your project by running Firebase init functions.

When you do this, I highly recommend using TypeScript because it does all the setup for you and will help you catch silly errors before they end up in production. There's a few things we can do to improve the performance of a cold start on a cloud function and also reduce the CPU time that we're actually billed for. Try to minimize the number of dependencies that you use in your functions. More code to load and parse means a slower cold start time. If you have values that can be shared between multiple function invocations, you can set them up as global variables.

When a function instance spins up in the cloud, it might be used multiple times, so global variables can be used across multiple calls improving performance. When you design your Cloud Functions, they should always be item potent. Cloud Functions are guaranteed to be invoked at least once, But they can be retried multiple times, so you wanna make sure that multiple calls to the same function produces the same result. And you can use the context event ID to help you achieve that. If you need to add more horsepower to a function, you can use run with to max out the memory at 2 gigabytes and the time out seconds to 540.

Now one thing you want to be really careful not to do is to create an infinite loop. You might accidentally do this in Firestore by updating the same document that triggered the event. In this example, we have an on write function that updates the same document that triggered the write. So this will cause an infinite loop that will charge up your Firebase bill until you hit the quota limits. It's not a good thing to do.

However, there are use cases when you might want the triggering function to update the same document. You can avoid the infinite loop by checking if The after document is equal to the before document. This will check for equality on the document path and its data, and that will stop the loop assuming your function is idempotent. Background cloud functions must always return a promise. You can ensure that always happens by using the async keyword in the function callback, Then you can use the await keyword for a much cleaner synchronous looking code.

Sometimes you might need a cloud function that communicates with other cloud functions or other GCP services. You could use an HTTP function to handle that, but you would also need to implement some code to validate the request. A better alternative would be to set up a pubsub function. It allows you to pass messages between your internal services, and that's easier and more secure than exposing an HTTP endpoint. You might also have endpoints that should only accessed by authenticated users.

In a regular HTTP function, you would need to extract the authorization header that you set in your front end code and then verify the ID token. As an alternative, you can simplify both your back end and front end code by using callable functions. It includes the auth context for the user, so you don't have to implement your own middleware to authenticate your functions. A great use case is to delete an entire Firestore collection, which Should always be done on the back end because there might be tons of documents in a collection. We can first authorize the operation by looking at the user ID.

Then we'll create a recursive function called batch delete. It retrieves documents in batches of 100 and then deletes them. This will ensure that we don't hit memory issues if we try to query millions of documents in a single go. Now when implementing the actual logic for your back end code, consider breaking it down into small JavaScript functions. This allows you to reuse code across multiple Deploy Cloud Functions, and it's also just easier to test.

Keep in mind that Cloud Functions provide a gateway to interact with other third party APIs. Almost every good API also has a good Node JS library to go with it. So, basically, anything you can build in Node JS, you can build in a Cloud Function. When you're ready to go live, you can deploy all of your functions from the command line with a single command. But on larger projects with dozens of functions, you may not want to deploy everything all at once.

You can append the name of the function to the end of this command to deploy a single function. Despite your best efforts, your functions will very likely have some bugs. The best way to prevent bugs is to run the Cloud Functions shell locally. You can invoke your functions with mock data to test their behavior, and Firebase even provides a unit testing library. Now your function still might break in production, so you can always look at the Firebase logs to see what's going wrong.

Or better yet, head over to Stackdriver where you can create your own custom dashboards boards and alerts for the things that you care about. Earlier in the video, we set up analytics in our front end code. But to get the most out of it, we'll want to track custom events and user properties. Try to pinpoint the events or user behaviors that you think are most important to turning that user into a paying customer, then use Firebase Analytics to record those events. Firebase will aggregate some of the data automatically, but you can create your own audiences based on the type of user that you want to target.

Your marketing team will love audiences because you can target messaging to a specific type of user and also do things like AB testing and funnels. And as a developer, You can actually use audiences to customize the UI based on your underlying analytics data. The service will send key value pairs down to to your front end application, which you can use to conditionally show UI based on where that user is located, what audience they belong to, and so on. You can also use the same data to send push notifications to your users using Firebase Cloud Messaging. Instead of sending a bulk notification out to all of your users, Segment it to the users who actually want it and will benefit from it.

And with that, we have finally reached Firebase tip number 100. Leverage machine learning within your app. You can do this in multiple ways with Firebase. Use predictions to guess when a user is going to buy your product, use ML Kit to implement AI driven features out of the box, Things like object detection and smart reply, or build your own image classification models with AutoML. And you can even export all of your analytics and Firestore data to BigQuery and use that raw data to train your own TensorFlow models from scratch.

And that is all of the Firebase tips that exist in the world. If you have your own additional tips, Leave them in the comments below, and I'll pick a couple of the best ones to win a t shirt later this week. I'm gonna go ahead and wrap things up there. Hopefully, you found something useful in here. Thanks for watching, and I will talk to you soon.
Welcome to my top 10 Firebase tips. Welcome to my top 25 Firebase tips. Nope. Welcome to my top 100 Firebase tips. I've been working with Firebase for several years now. I've made plenty of mistakes along the way, but I've also uncovered some secrets that you may not know about. So hopefully this video makes your experience with Firebase 100 times easier. If you're new here, like and subscribe. And if you're serious about building an app of Firebase, consider becoming a pro member at Fireship I tip. You'll get access to full project courses and a free t shirt if you sign up for life. Or you can get a free t shirt by leaving the best Firebase tip in the comments below. The first thing you'll need is a Firebase project. If you're building a serious app, create 2 Firebase projects, one for development and one for production.
This gives you a sandbox for testing and Experimenting, and you can keep your customer data pristine in the production project. In your production project, link Google Analytics. Firebase can automatically set up analytics for iOS, Android, and the web. If you're working with a team, head over to the settings tab and then go to users and permissions.
google
Assign roles based on the principle of least privilege, so team members only have access to the resources that they actually need. From there, head over to the data privacy tab and update your contact information to ensure you're in compliance with GDPR.
Now click the button to add a new app to your Firebase project. When you do that, it will give you an object with a bunch of credentials. Don't worry. These are perfectly safe in your front end code as long as you set up security rules, which we'll look at later. Upgrade your Firebase plan to Blaze. It's pay as you go, but you still get all of the free stuff that you would on the Spark tier. But you still want to stay on top of cost, so head over to the GCP console and set up a budget alert for your project. Then monitor your monthly usage from the reports panel.
billing
security
This will tell you Exactly which services are costing you the most money. Make sure to install the Firebase command line tools globally on your system and also the Google Cloud SDK. A Firebase project is actually just a layer on top of a Google Cloud Platform project. Once you've done this, you should have access to the Firebase command and the gcloud command on your local system. So now that we have a project set up, let's look at how we can actually deploy our code to this project. If you're building an iOS or Android app, use Firebase app distribution to distribute your app to testers.
This will bypass TestFlight and the Google Play Store, making your life much easier. Now if you're building a web application, you're likely using a package manager like npm. Install Firebase tools into the development environment for that project. And now you can write npm scripts that use the Firebase CLI tools. Now if you followed my earlier advice to set up different projects for development and production, you can use the project flag to set up different commands that specify the project.
software development
software
google
So here we have a command to deploy to our development project and another for our production project. Now after you've deployed your site, head over to the Firebase console, and you can see it's deployed at a cool domain called your project dot web dot app, or you can just connect your own custom domain. And you're not limited to a single domain. For example, you might have an admin site and a customer facing site. They can both share the same Firebase project with multisite hosting. Then go into your Firebase JSON file, change the hosting value to an array, and set up different targets that represent the different sites you want to deploy. Now you're not just limited to static files when deploying to hosting. You can actually rewrite traffic to a Cloud Function or to a Cloud Run instance. And that means you can do SSR with something like Angular Universal or Next. Js. You can also set up Firebase hosting rewrites for dynamic links. This allows you to dynamically send the user to the app with the best possible experience. So if the user goes to a link on their iPhone, it will take them to a specific screen in the iPhone app. You can also specify headers on the static files in your hosting account. For example, if we wanted to change the core settings for all of the font files, we could do it like this. And Firebase Hosting will also cache our static files for better performance, but we can change the caching behavior by setting different cache headers here as well. And one cool thing you might do to extend Firebase Hosting is to set it up with Google Cloud Build. So every git commit you make to your project, it will deploy a new version of your site to your hosting account.
That's exactly what I do for Fireship IO. Firebase provides 2 different fully managed NoSQL databases. So how do you know which one to choose? I default to Cloud Firestore because it has more powerful query capabilities. It also costs less per gigabyte stored. However, real time database does not charge for rights, So it can be a great option if you have data that's updated frequently like an IoT sensor or something along those lines.
databases
data management
amazon
But when it comes to pricing, you really shouldn't worry about it too much. Don't even trip, dawg. Firebase overall is very inexpensive, and it will take a decent number of monthly active users before you even break out of the free tier.
Unless you make a silly mistake, you'll be paying much less than you would be with other cloud solutions. A more important thing to worry about is that you back up your data on a regular basis. Set up a dedicated cloud storage bucket for backups, and then you can back up your entire database with a single command. When you create your based for the first time, set it in locked mode. It's safer to start with a locked down database than incrementally allow operations as they become necessary. After you've created a Firestore collection, go ahead and click the filter icon, and you'll see that you can make queries directly from the Firebase console. And it even provides some code for your query that you can copy and paste to using your app source code.
databases
data management
In fact, let's go ahead and switch gears and jump into the source code for a JavaScript application. Now the way you import Firebase depends on the flavor of JavaScript you're using. You can see the import syntax here for CommonJS, ES 6, and TypeScript. But all of these are actually wrong because they're importing from Firebase directly. Your code will work, but it will create a huge JavaScript bundle that will slow down your app. The correct way to use Firebase is to import from the Firebase app namespace and then import these services that you plan on using, aka progressive enhancement. In any case, Firebase is a pretty big dependency. So if you're loading it with a script tag, You'll wanna use the defer keyword on that script to ensure it loads after the actual DOM or HTML has been parsed. But if you're using a framework, then you shouldn't have to worry about this. Angular app should use AngularFire, which integrates with change detection and the Angular router. If you use React on the front end, the ReactFire library was just undeprecated, and it provides support for hooks and suspense. You have RXFire to integrate with RxJS, which works great in frameworks like Svelte. Then outside of the web, you have support for all kinds of different other frameworks in Firebase extended like Flutter, Arduino, and many others. When you first add Firebase to a project, there's a couple of no brainer services that you'll definitely wanna use, such as performance monitoring.
With a single line of code, we can see how well our app performs out in the wild, giving us metrics like first contentful paint across all devices using our app. The next one is Crashlytics, which is only relevant to native mobile apps. It's very easy to set up, and it will give you error reporting and crash reporting throughout your entire application and automatically open issues so you can address those problems.
programming
software
phones
And lastly, we have Firebase Analytics. With a single line of code, we'll get the default reporting from Google Analytics, giving us insight about the behavior of our users. Now in your source code, one of the first things you'll likely wanna do is determine if a user is logged in or not. There are 2 main ways to do this. You can pull the current user at any time by calling auth current user. This is usually best for handling events, like when the user clicks a button and then you want to grab their auth record and do something afterwards. The other way to get the current user is to always be listening to the current auth state. In this case, you provide a callback function to listen to changes to the auth state, like when the user signs in or signs out. In either case, I recommend getting good at asynchronous JavaScript to be test with Firebase. Understanding async await is very useful for the first approach, then understanding callbacks and functional programming is very useful for the second approach. When a user attempts to log in, something might go wrong. It might be your fault as the developer or the user's fault. In any case, you'll want to make sure that you catch these and then create a default handler that routes them to a visual UI element like a dialogue. A cool trick you can do with Firebase auth is to register a user lazily. For example, you might first have a user sign in anonymously, which will give you a user ID that you can tie to the database.
Then later in the onboarding process, you can collect their email or link social accounts like Twitter, Facebook, Google, etcetera. Now certain authentication methods like email password may need to send emails to your users for things like email verification and resetting passwords. Sometimes you might want to control this process on your own, which you can do with custom email action handlers, And you can even bring your own custom SMTP email server. Now one of the most important aspects of any application is managing relational data. Let's check out a few common techniques for connecting our users to the Firestore database. We can create a one to one relationship where the user has one document in Fire store by first retrieving their user ID, then we'll make a reference to a collection and set the document ID as the user ID.
email
data management
databases
customer support
Every user ID is unique, So it guarantees that that user can only have one document in that collection. Now if it's possible that data already exists there, you might want to use the merge true option. This will ensure that any data that already exists there won't be overwritten. The merge true option just makes it a nondestructive update. Another common relationship is one to many.
A user might have many orders, but an order belongs to one user. The best way to handle this type of relationship is to use a subcollection. In the last example, we created a document with a user ID, and we know that every subcollection under that document is owned by that user. But sometimes you might run into a situation where you want to query orders across all the users in your database. Firebase provides a special method that allows you to group subcollections and query them together. Collection group will find all of the collections that share the name orders, group them together, allowing you to make a single query against all of them. And another very common relationship is many to many. In this case, we have a single collection called chats, and each chat document can be associated with multiple users.
databases
management
customers
We can associate multiple users to multiple chats by embedding their user IDs on the chat document using a map of key value pairs. The key is the user ID, and then I'm going to duplicate the display name in case we want to show that in the UI.
Data duplication is perfectly okay in NoSQL. It can optimize for performance and costs, but it works best with values that are immutable or that don't need to be updated very often. And now that we have a map object on this document where each key in that map is a user ID. We can query it by using dot notation in our queries, like order by members dot user ID. Now that we've modeled some data and made some queries, we need to decide if we want our data in real time format or not. If you're trying to optimize pricing and don't think you'll need real time updates For your data, you can just call query git to retrieve the data once and then not listen to any future updates. But if you are building a feature where the UI should react To change this in real time, you'll want to use query on snapshot, then run a callback function anytime the underlying data changes. On a collection query, when you listen to docs, You'll get a new array anytime there's a change to the underlying data, but you might want to know exactly which documents were added, modified, or removed.
databases
data management
data
data analysis
Doc changes provides an array of all the documents that changed, their old index, new index, and the change type. Another awesome thing about Firestore is that it's able to work offline.
If the Internet goes out and the user's still trying to send rights to the database, Firestore will still update the UI and then send those rights to the actual database and commit them after the Internet comes back online. And you can even make this work across multiple browser tabs by setting the synchronized tabs option to true.
databases
Now one question I get a lot is how do I use emoji characters in my code? Well, they're actually just u t f eight characters, which means you can use them in a regular string. And that also means that you can use them in your Firestore documents and make queries against them. Another trick you might wanna use is to match a wildcard string. For example, if we wanted to query all of the Fast and the Furious movie titles. Create a starting point and then make your ending point a tilde character. This will match all the documents that start with the Fast and the Furious title. And with that, we have reached the halfway mark. Let's take a quick break. Welcome back. Sometimes you might have a compound query where you chain together multiple query conditions.
This query won't work by default because it requires an index, but don't create the index manually. Let your app throw an error, then click the link to the Firestore console to create the index automatically. One of the most powerful data types in Firestore is a list. We can add a list to a document by simply setting it with a JavaScript array.
databases
But we might decide later that any good Firebase recipe needs to include a pineapple. We can use the Firestore array union method to ensure that the array includes exactly 1 pineapple. Or we might decide later on that maybe squid wasn't such a good idea in this recipe, so we can remove it by using the array remove method without having to know the actual index.
And now that we have an array on the document, we can query it by using the array contains operator inside of where, and that will give us all of the recipes that contain avocado. Now sometimes you might have an array that contains IDs of other documents in the database.
databases
But how do you actually fetch the full documents in this array? Do it in JavaScript by mapping all of the ID strings to an array of promises that get the document, then run them together with promise dot all. One thing you should generally avoid doing is setting a time stamp from your front end code because the user's clock might not be synchronized properly. If you need to set a time stamp on a document, use the Firestore server time stamp. That ensures that all users are sharing the same clock.
Another thing you might wanna do is increment a counter, like the score of the game. You can change the value of the counter atomically without knowing its current value by using the increment field value. Now Firestore only supports 1 write per document per second, although you can burst above that value.
gambling
So if you have a ton of writes happening on a single document, You can set up a distributed counter, which is now very easy to do because there is a Firebase extension that supports it.
And speaking of atomic, Sometimes you might have rights that need to succeed or fail together. Maybe the user completes the game, you write the score, and then you want to update the user's lifetime score. You can ensure that these operations happen together by setting up a batch write. This will commit them together, but roll back to the previous state if any of the writes fail. Now Firestore is a great solution for the vast majority of use cases, but sometimes you might need a full relational database. If you need a full relational database, Check out my video on integrating MySQL into a Firebase project. Or if you need full text search, check out my Algolia integration video.
databases
games
Now one of the most important things to do as a Firebase developer is set rules before you deploy to production.
If you deploy an app without good security rules in place, your customer's data could be compromised, and someone could make destructive rights to your database. Currently, our database is in lock mode, which means we're safe. But now let's go ahead and open up some operations for our users. The first thing you should do is get used to using the simulator. It allows you to pass mock requests to the database to see how the rules will be evaluated, But serious production apps should use the Firestore emulator. This allows you to simulate the Firestore database in your local development environment, You can throw a whole bunch of different test cases at your rules to ensure that they're robust. Note that there are 5 different types of operations a user can make on a document. They can get a single document, a query of a list of documents, and they can create, update, and delete documents. You can provide fine grained rules for each operation, or you can combine Then by using the read or write keywords. If they share the same logic, just separate them with a comma. When a rule is evaluated, there are 2 things that you'll look at, the request and the resource. The request contains the user's authentication state as well as the incoming data that they're trying to write to the database. The resource, On the other hand, is the data that already exists at this path in the database. But in some cases, you might need to look elsewhere in the database to determine if a rule should be allowed. Use the get keyword and then point to a path in the database, and you can use dollar sign parenthesis to interpolate values like the request auth user ID. This gives you the value from this document, but keep in mind that you're charged a read every time this rule is evaluated. Now you might notice That this is a very long line of code, and if we were using this frequently throughout the rules, we wouldn't want to have to repeat it all the time.
security
data
logic
operations
databases
data management
programming
data analysis
documentation
law
We can extract this logic into its own function called is admin, And now we have a much cleaner way to check for admin users. Now let's switch gears to cloud storage. A storage bucket is where you would put things like images, videos, and raw files. You have a default bucket, which is where you would normally save your user generated content, but you can create additional buckets as well. You might want an additional bucket for Firestore backups, which you can set to coldline, which will save you some money. Now when you upload a file to a storage bucket, there is a storage location and a download URL. If the user needs to access this file again in the future, I recommend saving both values to the Firestore database. You can use the storage location to replace or delete the file in the future or the download URL to access the file in your app. But don't worry too much if you forgot to save the file path in the database because you can use the storage ref from URL and point to either the full path in the storage bucket or to the download URL to access that file. Sometimes you might want to list out all the files in a directory in the bucket. Simply make a reference to the path to the directory, and then use the list all method to get all the files at that location. You can upload a file by simply making a reference to a file path and then putting the raw file that you want to upload. You can calculate the progress of an upload by listening to the state changed event, then divide the bytes transferred by the total bytes in the file. If you have multiple files to upload, feel free to upload them all at the same time. Firebase will automatically handle concurrency and upload them as efficiently as possible. When you upload files, you might also want to save your own custom metadata about that file. You might want to know what kind of device the user upload the file from, their user ID, and stuff like that. If your users can upload image files, there's a good chance that you'll want to resize them to different resolutions for different devices. You can now do that with a click of button using the Firebase image resizer extension. At this point, we've been mostly looking at front end code, so now I want to switch gears to the back tip. You can create your own command line utility for Firebase with 3 easy steps. Go to your project settings and download the service account for your project. In a node project, install Firebase Admin as a development dependency, then create a JS file that imports it and calls initialize app.
Firebase admin needs your service account, but it contains sensitive information. The safest way to use it locally is to keep it somewhere private on your system, and then use an environment variable called Google application credentials. But if you include the service account directly in your source code, make sure it's in your git ignore so it doesn't end up in a public repo somewhere.
security
One of my favorite things to do with an admin script is to seed the database with some dummy data. Install Faker JS and then import it into your JavaScript file.
Then create a loop, and for each iteration, add a new document to the collection using Faker to automatically generate the dummy data. Now run the script from the command line with node. You should now see a bunch of dummy documents seeded in your database. Now you can do a lot with the Firebase Admin SDK, but you can do even more with the rest APIs. Check out the rest API documentation to find secret techniques that you didn't know about. Earlier, I showed you how to back up Firestore from the command line, but you can also do it with the rest API.
databases
This would allow you to set up a cron job to back up your database on a daily basis. If you do use the REST API, you'll want to use the Google APIs NPM package. This allows you to discover and interact with hundreds of different Google APIs, like AdWords, YouTube, and, of course, Firebase.
google
databases
Creating an admin script can be useful, but in most cases, you'll be with Firebase Admin in a Cloud Function. You can add Cloud Functions to your project by running Firebase init functions. When you do this, I highly recommend using TypeScript because it does all the setup for you and will help you catch silly errors before they end up in production. There's a few things we can do to improve the performance of a cold start on a cloud function and also reduce the CPU time that we're actually billed for. Try to minimize the number of dependencies that you use in your functions. More code to load and parse means a slower cold start time. If you have values that can be shared between multiple function invocations, you can set them up as global variables. When a function instance spins up in the cloud, it might be used multiple times, so global variables can be used across multiple calls improving performance. When you design your Cloud Functions, they should always be item potent. Cloud Functions are guaranteed to be invoked at least once, But they can be retried multiple times, so you wanna make sure that multiple calls to the same function produces the same result. And you can use the context event ID to help you achieve that. If you need to add more horsepower to a function, you can use run with to max out the memory at 2 gigabytes and the time out seconds to 540. Now one thing you want to be really careful not to do is to create an infinite loop. You might accidentally do this in Firestore by updating the same document that triggered the event. In this example, we have an on write function that updates the same document that triggered the write. So this will cause an infinite loop that will charge up your Firebase bill until you hit the quota limits. It's not a good thing to do. However, there are use cases when you might want the triggering function to update the same document. You can avoid the infinite loop by checking if The after document is equal to the before document. This will check for equality on the document path and its data, and that will stop the loop assuming your function is idempotent. Background cloud functions must always return a promise. You can ensure that always happens by using the async keyword in the function callback, Then you can use the await keyword for a much cleaner synchronous looking code. Sometimes you might need a cloud function that communicates with other cloud functions or other GCP services. You could use an HTTP function to handle that, but you would also need to implement some code to validate the request. A better alternative would be to set up a pubsub function. It allows you to pass messages between your internal services, and that's easier and more secure than exposing an HTTP endpoint. You might also have endpoints that should only accessed by authenticated users. In a regular HTTP function, you would need to extract the authorization header that you set in your front end code and then verify the ID token. As an alternative, you can simplify both your back end and front end code by using callable functions. It includes the auth context for the user, so you don't have to implement your own middleware to authenticate your functions. A great use case is to delete an entire Firestore collection, which Should always be done on the back end because there might be tons of documents in a collection. We can first authorize the operation by looking at the user ID. Then we'll create a recursive function called batch delete. It retrieves documents in batches of 100 and then deletes them. This will ensure that we don't hit memory issues if we try to query millions of documents in a single go. Now when implementing the actual logic for your back end code, consider breaking it down into small JavaScript functions. This allows you to reuse code across multiple Deploy Cloud Functions, and it's also just easier to test. Keep in mind that Cloud Functions provide a gateway to interact with other third party APIs. Almost every good API also has a good Node JS library to go with it. So, basically, anything you can build in Node JS, you can build in a Cloud Function. When you're ready to go live, you can deploy all of your functions from the command line with a single command. But on larger projects with dozens of functions, you may not want to deploy everything all at once.
You can append the name of the function to the end of this command to deploy a single function. Despite your best efforts, your functions will very likely have some bugs. The best way to prevent bugs is to run the Cloud Functions shell locally. You can invoke your functions with mock data to test their behavior, and Firebase even provides a unit testing library. Now your function still might break in production, so you can always look at the Firebase logs to see what's going wrong.
bugs
Or better yet, head over to Stackdriver where you can create your own custom dashboards boards and alerts for the things that you care about.
Earlier in the video, we set up analytics in our front end code. But to get the most out of it, we'll want to track custom events and user properties. Try to pinpoint the events or user behaviors that you think are most important to turning that user into a paying customer, then use Firebase Analytics to record those events. Firebase will aggregate some of the data automatically, but you can create your own audiences based on the type of user that you want to target.
data management
data
databases
Your marketing team will love audiences because you can target messaging to a specific type of user and also do things like AB testing and funnels. And as a developer, You can actually use audiences to customize the UI based on your underlying analytics data. The service will send key value pairs down to to your front end application, which you can use to conditionally show UI based on where that user is located, what audience they belong to, and so on.
customer support
marketing
customers
advertising
telecommunications
networking
You can also use the same data to send push notifications to your users using Firebase Cloud Messaging. Instead of sending a bulk notification out to all of your users, Segment it to the users who actually want it and will benefit from it.
And with that, we have finally reached Firebase tip number 100. Leverage machine learning within your app. You can do this in multiple ways with Firebase. Use predictions to guess when a user is going to buy your product, use ML Kit to implement AI driven features out of the box, Things like object detection and smart reply, or build your own image classification models with AutoML. And you can even export all of your analytics and Firestore data to BigQuery and use that raw data to train your own TensorFlow models from scratch.
machine learning
artificial intelligence
modeling
data
neural networks
And that is all of the Firebase tips that exist in the world. If you have your own additional tips, Leave them in the comments below, and I'll pick a couple of the best ones to win a t shirt later this week. I'm gonna go ahead and wrap things up there. Hopefully, you found something useful in here. Thanks for watching, and I will talk to you soon.
Welcome to my top 10 Firebase tips. Welcome to my top 25 Firebase tips. Nope. Welcome to my top 100 Firebase tips. I've been working with Firebase for several years now. I've made plenty of mistakes along the way, but I've also uncovered some secrets that you may not know about. So hopefully this video makes your experience with Firebase 100 times easier. If you're new here, like and subscribe. And if you're serious about building an app of Firebase, consider becoming a pro member at Fireship I tip. You'll get access to full project courses and a free t shirt if you sign up for life. Or you can get a free t shirt by leaving the best Firebase tip in the comments below. The first thing you'll need is a Firebase project. If you're building a serious app, create 2 Firebase projects, one for development and one for production. This gives you a sandbox for testing and Experimenting, and you can keep your customer data pristine in the production project. In your production project, link Google Analytics. Firebase can automatically set up analytics for iOS, Android, and the web. If you're working with a team, head over to the settings tab and then go to users and permissions. Assign roles based on the principle of least privilege, so team members only have access to the resources that they actually need. From there, head over to the data privacy tab and update your contact information to ensure you're in compliance with GDPR. Now click the button to add a new app to your Firebase project. When you do that, it will give you an object with a bunch of credentials. Don't worry. These are perfectly safe in your front end code as long as you set up security rules, which we'll look at later. Upgrade your Firebase plan to Blaze. It's pay as you go, but you still get all of the free stuff that you would on the Spark tier. But you still want to stay on top of cost, so head over to the GCP console and set up a budget alert for your project. Then monitor your monthly usage from the reports panel. This will tell you Exactly which services are costing you the most money. Make sure to install the Firebase command line tools globally on your system and also the Google Cloud SDK. A Firebase project is actually just a layer on top of a Google Cloud Platform project. Once you've done this, you should have access to the Firebase command and the gcloud command on your local system. So now that we have a project set up, let's look at how we can actually deploy our code to this project. If you're building an iOS or Android app, use Firebase app distribution to distribute your app to testers. This will bypass TestFlight and the Google Play Store, making your life much easier. Now if you're building a web application, you're likely using a package manager like npm. Install Firebase tools into the development environment for that project. And now you can write npm scripts that use the Firebase CLI tools. Now if you followed my earlier advice to set up different projects for development and production, you can use the project flag to set up different commands that specify the project. So here we have a command to deploy to our development project and another for our production project. Now after you've deployed your site, head over to the Firebase console, and you can see it's deployed at a cool domain called your project dot web dot app, or you can just connect your own custom domain. And you're not limited to a single domain. For example, you might have an admin site and a customer facing site. They can both share the same Firebase project with multisite hosting. Then go into your Firebase JSON file, change the hosting value to an array, and set up different targets that represent the different sites you want to deploy. Now you're not just limited to static files when deploying to hosting. You can actually rewrite traffic to a Cloud Function or to a Cloud Run instance. And that means you can do SSR with something like Angular Universal or Next. Js. You can also set up Firebase hosting rewrites for dynamic links. This allows you to dynamically send the user to the app with the best possible experience. So if the user goes to a link on their iPhone, it will take them to a specific screen in the iPhone app. You can also specify headers on the static files in your hosting account. For example, if we wanted to change the core settings for all of the font files, we could do it like this. And Firebase Hosting will also cache our static files for better performance, but we can change the caching behavior by setting different cache headers here as well. And one cool thing you might do to extend Firebase Hosting is to set it up with Google Cloud Build. So every git commit you make to your project, it will deploy a new version of your site to your hosting account. That's exactly what I do for Fireship IO. Firebase provides 2 different fully managed NoSQL databases. So how do you know which one to choose? I default to Cloud Firestore because it has more powerful query capabilities. It also costs less per gigabyte stored. However, real time database does not charge for rights, So it can be a great option if you have data that's updated frequently like an IoT sensor or something along those lines. But when it comes to pricing, you really shouldn't worry about it too much. Don't even trip, dawg. Firebase overall is very inexpensive, and it will take a decent number of monthly active users before you even break out of the free tier. Unless you make a silly mistake, you'll be paying much less than you would be with other cloud solutions. A more important thing to worry about is that you back up your data on a regular basis. Set up a dedicated cloud storage bucket for backups, and then you can back up your entire database with a single command. When you create your based for the first time, set it in locked mode. It's safer to start with a locked down database than incrementally allow operations as they become necessary. After you've created a Firestore collection, go ahead and click the filter icon, and you'll see that you can make queries directly from the Firebase console. And it even provides some code for your query that you can copy and paste to using your app source code. In fact, let's go ahead and switch gears and jump into the source code for a JavaScript application. Now the way you import Firebase depends on the flavor of JavaScript you're using. You can see the import syntax here for CommonJS, ES 6, and TypeScript. But all of these are actually wrong because they're importing from Firebase directly. Your code will work, but it will create a huge JavaScript bundle that will slow down your app. The correct way to use Firebase is to import from the Firebase app namespace and then import these services that you plan on using, aka progressive enhancement. In any case, Firebase is a pretty big dependency. So if you're loading it with a script tag, You'll wanna use the defer keyword on that script to ensure it loads after the actual DOM or HTML has been parsed. But if you're using a framework, then you shouldn't have to worry about this. Angular app should use AngularFire, which integrates with change detection and the Angular router. If you use React on the front end, the ReactFire library was just undeprecated, and it provides support for hooks and suspense. You have RXFire to integrate with RxJS, which works great in frameworks like Svelte. Then outside of the web, you have support for all kinds of different other frameworks in Firebase extended like Flutter, Arduino, and many others. When you first add Firebase to a project, there's a couple of no brainer services that you'll definitely wanna use, such as performance monitoring. With a single line of code, we can see how well our app performs out in the wild, giving us metrics like first contentful paint across all devices using our app. The next one is Crashlytics, which is only relevant to native mobile apps. It's very easy to set up, and it will give you error reporting and crash reporting throughout your entire application and automatically open issues so you can address those problems. And lastly, we have Firebase Analytics. With a single line of code, we'll get the default reporting from Google Analytics, giving us insight about the behavior of our users. Now in your source code, one of the first things you'll likely wanna do is determine if a user is logged in or not. There are 2 main ways to do this. You can pull the current user at any time by calling auth current user. This is usually best for handling events, like when the user clicks a button and then you want to grab their auth record and do something afterwards. The other way to get the current user is to always be listening to the current auth state. In this case, you provide a callback function to listen to changes to the auth state, like when the user signs in or signs out. In either case, I recommend getting good at asynchronous JavaScript to be test with Firebase. Understanding async await is very useful for the first approach, then understanding callbacks and functional programming is very useful for the second approach. When a user attempts to log in, something might go wrong. It might be your fault as the developer or the user's fault. In any case, you'll want to make sure that you catch these and then create a default handler that routes them to a visual UI element like a dialogue. A cool trick you can do with Firebase auth is to register a user lazily. For example, you might first have a user sign in anonymously, which will give you a user ID that you can tie to the database. Then later in the onboarding process, you can collect their email or link social accounts like Twitter, Facebook, Google, etcetera. Now certain authentication methods like email password may need to send emails to your users for things like email verification and resetting passwords. Sometimes you might want to control this process on your own, which you can do with custom email action handlers, And you can even bring your own custom SMTP email server. Now one of the most important aspects of any application is managing relational data. Let's check out a few common techniques for connecting our users to the Firestore database. We can create a one to one relationship where the user has one document in Fire store by first retrieving their user ID, then we'll make a reference to a collection and set the document ID as the user ID. Every user ID is unique, So it guarantees that that user can only have one document in that collection. Now if it's possible that data already exists there, you might want to use the merge true option. This will ensure that any data that already exists there won't be overwritten. The merge true option just makes it a nondestructive update. Another common relationship is one to many. A user might have many orders, but an order belongs to one user. The best way to handle this type of relationship is to use a subcollection. In the last example, we created a document with a user ID, and we know that every subcollection under that document is owned by that user. But sometimes you might run into a situation where you want to query orders across all the users in your database. Firebase provides a special method that allows you to group subcollections and query them together. Collection group will find all of the collections that share the name orders, group them together, allowing you to make a single query against all of them. And another very common relationship is many to many. In this case, we have a single collection called chats, and each chat document can be associated with multiple users. We can associate multiple users to multiple chats by embedding their user IDs on the chat document using a map of key value pairs. The key is the user ID, and then I'm going to duplicate the display name in case we want to show that in the UI. Data duplication is perfectly okay in NoSQL. It can optimize for performance and costs, but it works best with values that are immutable or that don't need to be updated very often. And now that we have a map object on this document where each key in that map is a user ID. We can query it by using dot notation in our queries, like order by members dot user ID. Now that we've modeled some data and made some queries, we need to decide if we want our data in real time format or not. If you're trying to optimize pricing and don't think you'll need real time updates For your data, you can just call query git to retrieve the data once and then not listen to any future updates. But if you are building a feature where the UI should react To change this in real time, you'll want to use query on snapshot, then run a callback function anytime the underlying data changes. On a collection query, when you listen to docs, You'll get a new array anytime there's a change to the underlying data, but you might want to know exactly which documents were added, modified, or removed. Doc changes provides an array of all the documents that changed, their old index, new index, and the change type. Another awesome thing about Firestore is that it's able to work offline. If the Internet goes out and the user's still trying to send rights to the database, Firestore will still update the UI and then send those rights to the actual database and commit them after the Internet comes back online. And you can even make this work across multiple browser tabs by setting the synchronized tabs option to true. Now one question I get a lot is how do I use emoji characters in my code? Well, they're actually just u t f eight characters, which means you can use them in a regular string. And that also means that you can use them in your Firestore documents and make queries against them. Another trick you might wanna use is to match a wildcard string. For example, if we wanted to query all of the Fast and the Furious movie titles. Create a starting point and then make your ending point a tilde character. This will match all the documents that start with the Fast and the Furious title. And with that, we have reached the halfway mark. Let's take a quick break. Welcome back. Sometimes you might have a compound query where you chain together multiple query conditions. This query won't work by default because it requires an index, but don't create the index manually. Let your app throw an error, then click the link to the Firestore console to create the index automatically. One of the most powerful data types in Firestore is a list. We can add a list to a document by simply setting it with a JavaScript array. But we might decide later that any good Firebase recipe needs to include a pineapple. We can use the Firestore array union method to ensure that the array includes exactly 1 pineapple. Or we might decide later on that maybe squid wasn't such a good idea in this recipe, so we can remove it by using the array remove method without having to know the actual index. And now that we have an array on the document, we can query it by using the array contains operator inside of where, and that will give us all of the recipes that contain avocado. Now sometimes you might have an array that contains IDs of other documents in the database. But how do you actually fetch the full documents in this array? Do it in JavaScript by mapping all of the ID strings to an array of promises that get the document, then run them together with promise dot all. One thing you should generally avoid doing is setting a time stamp from your front end code because the user's clock might not be synchronized properly. If you need to set a time stamp on a document, use the Firestore server time stamp. That ensures that all users are sharing the same clock. Another thing you might wanna do is increment a counter, like the score of the game. You can change the value of the counter atomically without knowing its current value by using the increment field value. Now Firestore only supports 1 write per document per second, although you can burst above that value. So if you have a ton of writes happening on a single document, You can set up a distributed counter, which is now very easy to do because there is a Firebase extension that supports it. And speaking of atomic, Sometimes you might have rights that need to succeed or fail together. Maybe the user completes the game, you write the score, and then you want to update the user's lifetime score. You can ensure that these operations happen together by setting up a batch write. This will commit them together, but roll back to the previous state if any of the writes fail. Now Firestore is a great solution for the vast majority of use cases, but sometimes you might need a full relational database. If you need a full relational database, Check out my video on integrating MySQL into a Firebase project. Or if you need full text search, check out my Algolia integration video. Now one of the most important things to do as a Firebase developer is set rules before you deploy to production. If you deploy an app without good security rules in place, your customer's data could be compromised, and someone could make destructive rights to your database. Currently, our database is in lock mode, which means we're safe. But now let's go ahead and open up some operations for our users. The first thing you should do is get used to using the simulator. It allows you to pass mock requests to the database to see how the rules will be evaluated, But serious production apps should use the Firestore emulator. This allows you to simulate the Firestore database in your local development environment, You can throw a whole bunch of different test cases at your rules to ensure that they're robust. Note that there are 5 different types of operations a user can make on a document. They can get a single document, a query of a list of documents, and they can create, update, and delete documents. You can provide fine grained rules for each operation, or you can combine Then by using the read or write keywords. If they share the same logic, just separate them with a comma. When a rule is evaluated, there are 2 things that you'll look at, the request and the resource. The request contains the user's authentication state as well as the incoming data that they're trying to write to the database. The resource, On the other hand, is the data that already exists at this path in the database. But in some cases, you might need to look elsewhere in the database to determine if a rule should be allowed. Use the get keyword and then point to a path in the database, and you can use dollar sign parenthesis to interpolate values like the request auth user ID. This gives you the value from this document, but keep in mind that you're charged a read every time this rule is evaluated. Now you might notice That this is a very long line of code, and if we were using this frequently throughout the rules, we wouldn't want to have to repeat it all the time. We can extract this logic into its own function called is admin, And now we have a much cleaner way to check for admin users. Now let's switch gears to cloud storage. A storage bucket is where you would put things like images, videos, and raw files. You have a default bucket, which is where you would normally save your user generated content, but you can create additional buckets as well. You might want an additional bucket for Firestore backups, which you can set to coldline, which will save you some money. Now when you upload a file to a storage bucket, there is a storage location and a download URL. If the user needs to access this file again in the future, I recommend saving both values to the Firestore database. You can use the storage location to replace or delete the file in the future or the download URL to access the file in your app. But don't worry too much if you forgot to save the file path in the database because you can use the storage ref from URL and point to either the full path in the storage bucket or to the download URL to access that file. Sometimes you might want to list out all the files in a directory in the bucket. Simply make a reference to the path to the directory, and then use the list all method to get all the files at that location. You can upload a file by simply making a reference to a file path and then putting the raw file that you want to upload. You can calculate the progress of an upload by listening to the state changed event, then divide the bytes transferred by the total bytes in the file. If you have multiple files to upload, feel free to upload them all at the same time. Firebase will automatically handle concurrency and upload them as efficiently as possible. When you upload files, you might also want to save your own custom metadata about that file. You might want to know what kind of device the user upload the file from, their user ID, and stuff like that. If your users can upload image files, there's a good chance that you'll want to resize them to different resolutions for different devices. You can now do that with a click of button using the Firebase image resizer extension. At this point, we've been mostly looking at front end code, so now I want to switch gears to the back tip. You can create your own command line utility for Firebase with 3 easy steps. Go to your project settings and download the service account for your project. In a node project, install Firebase Admin as a development dependency, then create a JS file that imports it and calls initialize app. Firebase admin needs your service account, but it contains sensitive information. The safest way to use it locally is to keep it somewhere private on your system, and then use an environment variable called Google application credentials. But if you include the service account directly in your source code, make sure it's in your git ignore so it doesn't end up in a public repo somewhere. One of my favorite things to do with an admin script is to seed the database with some dummy data. Install Faker JS and then import it into your JavaScript file. Then create a loop, and for each iteration, add a new document to the collection using Faker to automatically generate the dummy data. Now run the script from the command line with node. You should now see a bunch of dummy documents seeded in your database. Now you can do a lot with the Firebase Admin SDK, but you can do even more with the rest APIs. Check out the rest API documentation to find secret techniques that you didn't know about. Earlier, I showed you how to back up Firestore from the command line, but you can also do it with the rest API. This would allow you to set up a cron job to back up your database on a daily basis. If you do use the REST API, you'll want to use the Google APIs NPM package. This allows you to discover and interact with hundreds of different Google APIs, like AdWords, YouTube, and, of course, Firebase. Creating an admin script can be useful, but in most cases, you'll be with Firebase Admin in a Cloud Function. You can add Cloud Functions to your project by running Firebase init functions. When you do this, I highly recommend using TypeScript because it does all the setup for you and will help you catch silly errors before they end up in production. There's a few things we can do to improve the performance of a cold start on a cloud function and also reduce the CPU time that we're actually billed for. Try to minimize the number of dependencies that you use in your functions. More code to load and parse means a slower cold start time. If you have values that can be shared between multiple function invocations, you can set them up as global variables. When a function instance spins up in the cloud, it might be used multiple times, so global variables can be used across multiple calls improving performance. When you design your Cloud Functions, they should always be item potent. Cloud Functions are guaranteed to be invoked at least once, But they can be retried multiple times, so you wanna make sure that multiple calls to the same function produces the same result. And you can use the context event ID to help you achieve that. If you need to add more horsepower to a function, you can use run with to max out the memory at 2 gigabytes and the time out seconds to 540. Now one thing you want to be really careful not to do is to create an infinite loop. You might accidentally do this in Firestore by updating the same document that triggered the event. In this example, we have an on write function that updates the same document that triggered the write. So this will cause an infinite loop that will charge up your Firebase bill until you hit the quota limits. It's not a good thing to do. However, there are use cases when you might want the triggering function to update the same document. You can avoid the infinite loop by checking if The after document is equal to the before document. This will check for equality on the document path and its data, and that will stop the loop assuming your function is idempotent. Background cloud functions must always return a promise. You can ensure that always happens by using the async keyword in the function callback, Then you can use the await keyword for a much cleaner synchronous looking code. Sometimes you might need a cloud function that communicates with other cloud functions or other GCP services. You could use an HTTP function to handle that, but you would also need to implement some code to validate the request. A better alternative would be to set up a pubsub function. It allows you to pass messages between your internal services, and that's easier and more secure than exposing an HTTP endpoint. You might also have endpoints that should only accessed by authenticated users. In a regular HTTP function, you would need to extract the authorization header that you set in your front end code and then verify the ID token. As an alternative, you can simplify both your back end and front end code by using callable functions. It includes the auth context for the user, so you don't have to implement your own middleware to authenticate your functions. A great use case is to delete an entire Firestore collection, which Should always be done on the back end because there might be tons of documents in a collection. We can first authorize the operation by looking at the user ID. Then we'll create a recursive function called batch delete. It retrieves documents in batches of 100 and then deletes them. This will ensure that we don't hit memory issues if we try to query millions of documents in a single go. Now when implementing the actual logic for your back end code, consider breaking it down into small JavaScript functions. This allows you to reuse code across multiple Deploy Cloud Functions, and it's also just easier to test. Keep in mind that Cloud Functions provide a gateway to interact with other third party APIs. Almost every good API also has a good Node JS library to go with it. So, basically, anything you can build in Node JS, you can build in a Cloud Function. When you're ready to go live, you can deploy all of your functions from the command line with a single command. But on larger projects with dozens of functions, you may not want to deploy everything all at once. You can append the name of the function to the end of this command to deploy a single function. Despite your best efforts, your functions will very likely have some bugs. The best way to prevent bugs is to run the Cloud Functions shell locally. You can invoke your functions with mock data to test their behavior, and Firebase even provides a unit testing library. Now your function still might break in production, so you can always look at the Firebase logs to see what's going wrong. Or better yet, head over to Stackdriver where you can create your own custom dashboards boards and alerts for the things that you care about. Earlier in the video, we set up analytics in our front end code. But to get the most out of it, we'll want to track custom events and user properties. Try to pinpoint the events or user behaviors that you think are most important to turning that user into a paying customer, then use Firebase Analytics to record those events. Firebase will aggregate some of the data automatically, but you can create your own audiences based on the type of user that you want to target. Your marketing team will love audiences because you can target messaging to a specific type of user and also do things like AB testing and funnels. And as a developer, You can actually use audiences to customize the UI based on your underlying analytics data. The service will send key value pairs down to to your front end application, which you can use to conditionally show UI based on where that user is located, what audience they belong to, and so on. You can also use the same data to send push notifications to your users using Firebase Cloud Messaging. Instead of sending a bulk notification out to all of your users, Segment it to the users who actually want it and will benefit from it. And with that, we have finally reached Firebase tip number 100. Leverage machine learning within your app. You can do this in multiple ways with Firebase. Use predictions to guess when a user is going to buy your product, use ML Kit to implement AI driven features out of the box, Things like object detection and smart reply, or build your own image classification models with AutoML. And you can even export all of your analytics and Firestore data to BigQuery and use that raw data to train your own TensorFlow models from scratch. And that is all of the Firebase tips that exist in the world. If you have your own additional tips, Leave them in the comments below, and I'll pick a couple of the best ones to win a t shirt later this week. I'm gonna go ahead and wrap things up there. Hopefully, you found something useful in here. Thanks for watching, and I will talk to you soon.
Welcome
welcome
to
to
my
my
top
top
10
10
Firebase
firebase
tips.
tips
Welcome
welcome
to
to
my
my
top
top
25
25
Firebase
firebase
tips.
tips
Nope.
nope
Welcome
welcome
to
to
my
my
top
top
100
100
Firebase
firebase
tips.
tips
I've
i've
been
been
working
working
with
with
Firebase
firebase
for
for
several
several
years
years
now.
now
I've
i've
made
made
plenty
plenty
of
of
mistakes
mistakes
along
along
the
the
way,
way
but
but
I've
i've
also
also
uncovered
uncovered
some
some
secrets
secrets
that
that
you
you
may
may
not
not
know
know
about.
about
So
so
hopefully
hopefully
this
this
video
video
makes
makes
your
your
experience
experience
with
with
Firebase
firebase
100
100
times
times
easier.
easier
If
if
you're
you're
new
new
here,
here
like
like
and
and
subscribe.
subscribe
And
and
if
if
you're
you're
serious
serious
about
about
building
building
an
an
app
app
of
of
Firebase,
firebase
consider
consider
becoming
becoming
a
a
pro
pro
member
member
at
at
Fireship
fireship
I
i
tip.
tip
You'll
you'll
get
get
access
access
to
to
full
full
project
project
courses
courses
and
and
a
a
free
free
t
t
shirt
shirt
if
if
you
you
sign
sign
up
up
for
for
life.
life
Or
or
you
you
can
can
get
get
a
a
free
free
t
t
shirt
shirt
by
by
leaving
leaving
the
the
best
best
Firebase
firebase
tip
tip
in
in
the
the
comments
comments
below.
below
The
the
first
first
thing
thing
you'll
you'll
need
need
is
is
a
a
Firebase
firebase
project.
project
If
if
you're
you're
building
building
a
a
serious
serious
app,
app
create
create
2
2
Firebase
firebase
projects,
projects
one
one
for
for
development
development
and
and
one
one
for
for
production.
production
This
this
gives
gives
you
you
a
a
sandbox
sandbox
for
for
testing
testing
and
and
Experimenting,
experimenting
and
and
you
you
can
can
keep
keep
your
your
customer
customer
data
data
pristine
pristine
in
in
the
the
production
production
project.
project
In
in
your
your
production
production
project,
project
link
link
Google
google
Analytics.
analytics
Firebase
firebase
can
can
automatically
automatically
set
set
up
up
analytics
analytics
for
for
iOS,
ios
Android,
android
and
and
the
the
web.
web
If
if
you're
you're
working
working
with
with
a
a
team,
team
head
head
over
over
to
to
the
the
settings
settings
tab
tab
and
and
then
then
go
go
to
to
users
users
and
and
permissions.
permissions
Assign
assign
roles
roles
based
based
on
on
the
the
principle
principle
of
of
least
least
privilege,
privilege
so
so
team
team
members
members
only
only
have
have
access
access
to
to
the
the
resources
resources
that
that
they
they
actually
actually
need.
need
From
from
there,
there
head
head
over
over
to
to
the
the
data
data
privacy
privacy
tab
tab
and
and
update
update
your
your
contact
contact
information
information
to
to
ensure
ensure
you're
you're
in
in
compliance
compliance
with
with
GDPR.
gdpr
Now
now
click
click
the
the
button
button
to
to
add
add
a
a
new
new
app
app
to
to
your
your
Firebase
firebase
project.
project
When
when
you
you
do
do
that,
that
it
it
will
will
give
give
you
you
an
an
object
object
with
with
a
a
bunch
bunch
of
of
credentials.
credentials
Don't
don't
worry.
worry
These
these
are
are
perfectly
perfectly
safe
safe
in
in
your
your
front
front
end
end
code
code
as
as
long
long
as
as
you
you
set
set
up
up
security
security
rules,
rules
which
which
we'll
we'll
look
look
at
at
later.
later
Upgrade
upgrade
your
your
Firebase
firebase
plan
plan
to
to
Blaze.
blaze
It's
it's
pay
pay
as
as
you
you
go,
go
but
but
you
you
still
still
get
get
all
all
of
of
the
the
free
free
stuff
stuff
that
that
you
you
would
would
on
on
the
the
Spark
spark
tier.
tier
But
but
you
you
still
still
want
want
to
to
stay
stay
on
on
top
top
of
of
cost,
cost
so
so
head
head
over
over
to
to
the
the
GCP
gcp
console
console
and
and
set
set
up
up
a
a
budget
budget
alert
alert
for
for
your
your
project.
project
Then
then
monitor
monitor
your
your
monthly
monthly
usage
usage
from
from
the
the
reports
reports
panel.
panel
This
this
will
will
tell
tell
you
you
Exactly
exactly
which
which
services
services
are
are
costing
costing
you
you
the
the
most
most
money.
money
Make
make
sure
sure
to
to
install
install
the
the
Firebase
firebase
command
command
line
line
tools
tools
globally
globally
on
on
your
your
system
system
and
and
also
also
the
the
Google
google
Cloud
cloud
SDK.
sdk
A
a
Firebase
firebase
project
project
is
is
actually
actually
just
just
a
a
layer
layer
on
on
top
top
of
of
a
a
Google
google
Cloud
cloud
Platform
platform
project.
project
Once
once
you've
you've
done
done
this,
this
you
you
should
should
have
have
access
access
to
to
the
the
Firebase
firebase
command
command
and
and
the
the
gcloud
gcloud
command
command
on
on
your
your
local
local
system.
system
So
so
now
now
that
that
we
we
have
have
a
a
project
project
set
set
up,
up
let's
let's
look
look
at
at
how
how
we
we
can
can
actually
actually
deploy
deploy
our
our
code
code
to
to
this
this
project.
project
If
if
you're
you're
building
building
an
an
iOS
ios
or
or
Android
android
app,
app
use
use
Firebase
firebase
app
app
distribution
distribution
to
to
distribute
distribute
your
your
app
app
to
to
testers.
testers
This
this
will
will
bypass
bypass
TestFlight
testflight
and
and
the
the
Google
google
Play
play
Store,
store
making
making
your
your
life
life
much
much
easier.
easier
Now
now
if
if
you're
you're
building
building
a
a
web
web
application,
application
you're
you're
likely
likely
using
using
a
a
package
package
manager
manager
like
like
npm.
npm
Install
install
Firebase
firebase
tools
tools
into
into
the
the
development
development
environment
environment
for
for
that
that
project.
project
And
and
now
now
you
you
can
can
write
write
npm
npm
scripts
scripts
that
that
use
use
the
the
Firebase
firebase
CLI
cli
tools.
tools
Now
now
if
if
you
you
followed
followed
my
my
earlier
earlier
advice
advice
to
to
set
set
up
up
different
different
projects
projects
for
for
development
development
and
and
production,
production
you
you
can
can
use
use
the
the
project
project
flag
flag
to
to
set
set
up
up
different
different
commands
commands
that
that
specify
specify
the
the
project.
project
So
so
here
here
we
we
have
have
a
a
command
command
to
to
deploy
deploy
to
to
our
our
development
development
project
project
and
and
another
another
for
for
our
our
production
production
project.
project
Now
now
after
after
you've
you've
deployed
deployed
your
your
site,
site
head
head
over
over
to
to
the
the
Firebase
firebase
console,
console
and
and
you
you
can
can
see
see
it's
it's
deployed
deployed
at
at
a
a
cool
cool
domain
domain
called
called
your
your
project
project
dot
dot
web
web
dot
dot
app,
app
or
or
you
you
can
can
just
just
connect
connect
your
your
own
own
custom
custom
domain.
domain
And
and
you're
you're
not
not
limited
limited
to
to
a
a
single
single
domain.
domain
For
for
example,
example
you
you
might
might
have
have
an
an
admin
admin
site
site
and
and
a
a
customer
customer
facing
facing
site.
site
They
they
can
can
both
both
share
share
the
the
same
same
Firebase
firebase
project
project
with
with
multisite
multisite
hosting.
hosting
Then
then
go
go
into
into
your
your
Firebase
firebase
JSON
json
file,
file
change
change
the
the
hosting
hosting
value
value
to
to
an
an
array,
array
and
and
set
set
up
up
different
different
targets
targets
that
that
represent
represent
the
the
different
different
sites
sites
you
you
want
want
to
to
deploy.
deploy
Now
now
you're
you're
not
not
just
just
limited
limited
to
to
static
static
files
files
when
when
deploying
deploying
to
to
hosting.
hosting
You
you
can
can
actually
actually
rewrite
rewrite
traffic
traffic
to
to
a
a
Cloud
cloud
Function
function
or
or
to
to
a
a
Cloud
cloud
Run
run
instance.
instance
And
and
that
that
means
means
you
you
can
can
do
do
SSR
ssr
with
with
something
something
like
like
Angular
angular
Universal
universal
or
or
Next.
next
Js.
js
You
you
can
can
also
also
set
set
up
up
Firebase
firebase
hosting
hosting
rewrites
rewrites
for
for
dynamic
dynamic
links.
links
This
this
allows
allows
you
you
to
to
dynamically
dynamically
send
send
the
the
user
user
to
to
the
the
app
app
with
with
the
the
best
best
possible
possible
experience.
experience
So
so
if
if
the
the
user
user
goes
goes
to
to
a
a
link
link
on
on
their
their
iPhone,
iphone
it
it
will
will
take
take
them
them
to
to
a
a
specific
specific
screen
screen
in
in
the
the
iPhone
iphone
app.
app
You
you
can
can
also
also
specify
specify
headers
headers
on
on
the
the
static
static
files
files
in
in
your
your
hosting
hosting
account.
account
For
for
example,
example
if
if
we
we
wanted
wanted
to
to
change
change
the
the
core
core
settings
settings
for
for
all
all
of
of
the
the
font
font
files,
files
we
we
could
could
do
do
it
it
like
like
this.
this
And
and
Firebase
firebase
Hosting
hosting
will
will
also
also
cache
cache
our
our
static
static
files
files
for
for
better
better
performance,
performance
but
but
we
we
can
can
change
change
the
the
caching
caching
behavior
behavior
by
by
setting
setting
different
different
cache
cache
headers
headers
here
here
as
as
well.
well
And
and
one
one
cool
cool
thing
thing
you
you
might
might
do
do
to
to
extend
extend
Firebase
firebase
Hosting
hosting
is
is
to
to
set
set
it
it
up
up
with
with
Google
google
Cloud
cloud
Build.
build
So
so
every
every
git
git
commit
commit
you
you
make
make
to
to
your
your
project,
project
it
it
will
will
deploy
deploy
a
a
new
new
version
version
of
of
your
your
site
site
to
to
your
your
hosting
hosting
account.
account
That's
that's
exactly
exactly
what
what
I
i
do
do
for
for
Fireship
fireship
IO.
io
Firebase
firebase
provides
provides
2
2
different
different
fully
fully
managed
managed
NoSQL
nosql
databases.
databases
So
so
how
how
do
do
you
you
know
know
which
which
one
one
to
to
choose?
choose
I
i
default
default
to
to
Cloud
cloud
Firestore
firestore
because
because
it
it
has
has
more
more
powerful
powerful
query
query
capabilities.
capabilities
It
it
also
also
costs
costs
less
less
per
per
gigabyte
gigabyte
stored.
stored
However,
however
real
real
time
time
database
database
does
does
not
not
charge
charge
for
for
rights,
rights
So
so
it
it
can
can
be
be
a
a
great
great
option
option
if
if
you
you
have
have
data
data
that's
that's
updated
updated
frequently
frequently
like
like
an
an
IoT
iot
sensor
sensor
or
or
something
something
along
along
those
those
lines.
lines
But
but
when
when
it
it
comes
comes
to
to
pricing,
pricing
you
you
really
really
shouldn't
shouldn't
worry
worry
about
about
it
it
too
too
much.
much
Don't
don't
even
even
trip,
trip
dawg.
dawg
Firebase
firebase
overall
overall
is
is
very
very
inexpensive,
inexpensive
and
and
it
it
will
will
take
take
a
a
decent
decent
number
number
of
of
monthly
monthly
active
active
users
users
before
before
you
you
even
even
break
break
out
out
of
of
the
the
free
free
tier.
tier
Unless
unless
you
you
make
make
a
a
silly
silly
mistake,
mistake
you'll
you'll
be
be
paying
paying
much
much
less
less
than
than
you
you
would
would
be
be
with
with
other
other
cloud
cloud
solutions.
solutions
A
a
more
more
important
important
thing
thing
to
to
worry
worry
about
about
is
is
that
that
you
you
back
back
up
up
your
your
data
data
on
on
a
a
regular
regular
basis.
basis
Set
set
up
up
a
a
dedicated
dedicated
cloud
cloud
storage
storage
bucket
bucket
for
for
backups,
backups
and
and
then
then
you
you
can
can
back
back
up
up
your
your
entire
entire
database
database
with
with
a
a
single
single
command.
command
When
when
you
you
create
create
your
your
based
based
for
for
the
the
first
first
time,
time
set
set
it
it
in
in
locked
locked
mode.
mode
It's
it's
safer
safer
to
to
start
start
with
with
a
a
locked
locked
down
down
database
database
than
than
incrementally
incrementally
allow
allow
operations
operations
as
as
they
they
become
become
necessary.
necessary
After
after
you've
you've
created
created
a
a
Firestore
firestore
collection,
collection
go
go
ahead
ahead
and
and
click
click
the
the
filter
filter
icon,
icon
and
and
you'll
you'll
see
see
that
that
you
you
can
can
make
make
queries
queries
directly
directly
from
from
the
the
Firebase
firebase
console.
console
And
and
it
it
even
even
provides
provides
some
some
code
code
for
for
your
your
query
query
that
that
you
you
can
can
copy
copy
and
and
paste
paste
to
to
using
using
your
your
app
app
source
source
code.
code
In
in
fact,
fact
let's
let's
go
go
ahead
ahead
and
and
switch
switch
gears
gears
and
and
jump
jump
into
into
the
the
source
source
code
code
for
for
a
a
JavaScript
javascript
application.
application
Now
now
the
the
way
way
you
you
import
import
Firebase
firebase
depends
depends
on
on
the
the
flavor
flavor
of
of
JavaScript
javascript
you're
you're
using.
using
You
you
can
can
see
see
the
the
import
import
syntax
syntax
here
here
for
for
CommonJS,
commonjs
ES
es
6,
6
and
and
TypeScript.
typescript
But
but
all
all
of
of
these
these
are
are
actually
actually
wrong
wrong
because
because
they're
they're
importing
importing
from
from
Firebase
firebase
directly.
directly
Your
your
code
code
will
will
work,
work
but
but
it
it
will
will
create
create
a
a
huge
huge
JavaScript
javascript
bundle
bundle
that
that
will
will
slow
slow
down
down
your
your
app.
app
The
the
correct
correct
way
way
to
to
use
use
Firebase
firebase
is
is
to
to
import
import
from
from
the
the
Firebase
firebase
app
app
namespace
namespace
and
and
then
then
import
import
these
these
services
services
that
that
you
you
plan
plan
on
on
using,
using
aka
aka
progressive
progressive
enhancement.
enhancement
In
in
any
any
case,
case
Firebase
firebase
is
is
a
a
pretty
pretty
big
big
dependency.
dependency
So
so
if
if
you're
you're
loading
loading
it
it
with
with
a
a
script
script
tag,
tag
You'll
you'll
wanna
wanna
use
use
the
the
defer
defer
keyword
keyword
on
on
that
that
script
script
to
to
ensure
ensure
it
it
loads
loads
after
after
the
the
actual
actual
DOM
dom
or
or
HTML
html
has
has
been
been
parsed.
parsed
But
but
if
if
you're
you're
using
using
a
a
framework,
framework
then
then
you
you
shouldn't
shouldn't
have
have
to
to
worry
worry
about
about
this.
this
Angular
angular
app
app
should
should
use
use
AngularFire,
angularfire
which
which
integrates
integrates
with
with
change
change
detection
detection
and
and
the
the
Angular
angular
router.
router
If
if
you
you
use
use
React
react
on
on
the
the
front
front
end,
end
the
the
ReactFire
reactfire
library
library
was
was
just
just
undeprecated,
undeprecated
and
and
it
it
provides
provides
support
support
for
for
hooks
hooks
and
and
suspense.
suspense
You
you
have
have
RXFire
rxfire
to
to
integrate
integrate
with
with
RxJS,
rxjs
which
which
works
works
great
great
in
in
frameworks
frameworks
like
like
Svelte.
svelte
Then
then
outside
outside
of
of
the
the
web,
web
you
you
have
have
support
support
for
for
all
all
kinds
kinds
of
of
different
different
other
other
frameworks
frameworks
in
in
Firebase
firebase
extended
extended
like
like
Flutter,
flutter
Arduino,
arduino
and
and
many
many
others.
others
When
when
you
you
first
first
add
add
Firebase
firebase
to
to
a
a
project,
project
there's
there's
a
a
couple
couple
of
of
no
no
brainer
brainer
services
services
that
that
you'll
you'll
definitely
definitely
wanna
wanna
use,
use
such
such
as
as
performance
performance
monitoring.
monitoring
With
with
a
a
single
single
line
line
of
of
code,
code
we
we
can
can
see
see
how
how
well
well
our
our
app
app
performs
performs
out
out
in
in
the
the
wild,
wild
giving
giving
us
us
metrics
metrics
like
like
first
first
contentful
contentful
paint
paint
across
across
all
all
devices
devices
using
using
our
our
app.
app
The
the
next
next
one
one
is
is
Crashlytics,
crashlytics
which
which
is
is
only
only
relevant
relevant
to
to
native
native
mobile
mobile
apps.
apps
It's
it's
very
very
easy
easy
to
to
set
set
up,
up
and
and
it
it
will
will
give
give
you
you
error
error
reporting
reporting
and
and
crash
crash
reporting
reporting
throughout
throughout
your
your
entire
entire
application
application
and
and
automatically
automatically
open
open
issues
issues
so
so
you
you
can
can
address
address
those
those
problems.
problems
And
and
lastly,
lastly
we
we
have
have
Firebase
firebase
Analytics.
analytics
With
with
a
a
single
single
line
line
of
of
code,
code
we'll
we'll
get
get
the
the
default
default
reporting
reporting
from
from
Google
google
Analytics,
analytics
giving
giving
us
us
insight
insight
about
about
the
the
behavior
behavior
of
of
our
our
users.
users
Now
now
in
in
your
your
source
source
code,
code
one
one
of
of
the
the
first
first
things
things
you'll
you'll
likely
likely
wanna
wanna
do
do
is
is
determine
determine
if
if
a
a
user
user
is
is
logged
logged
in
in
or
or
not.
not
There
there
are
are
2
2
main
main
ways
ways
to
to
do
do
this.
this
You
you
can
can
pull
pull
the
the
current
current
user
user
at
at
any
any
time
time
by
by
calling
calling
auth
auth
current
current
user.
user
This
this
is
is
usually
usually
best
best
for
for
handling
handling
events,
events
like
like
when
when
the
the
user
user
clicks
clicks
a
a
button
button
and
and
then
then
you
you
want
want
to
to
grab
grab
their
their
auth
auth
record
record
and
and
do
do
something
something
afterwards.
afterwards
The
the
other
other
way
way
to
to
get
get
the
the
current
current
user
user
is
is
to
to
always
always
be
be
listening
listening
to
to
the
the
current
current
auth
auth
state.
state
In
in
this
this
case,
case
you
you
provide
provide
a
a
callback
callback
function
function
to
to
listen
listen
to
to
changes
changes
to
to
the
the
auth
auth
state,
state
like
like
when
when
the
the
user
user
signs
signs
in
in
or
or
signs
signs
out.
out
In
in
either
either
case,
case
I
i
recommend
recommend
getting
getting
good
good
at
at
asynchronous
asynchronous
JavaScript
javascript
to
to
be
be
test
test
with
with
Firebase.
firebase
Understanding
understanding
async
async
await
await
is
is
very
very
useful
useful
for
for
the
the
first
first
approach,
approach
then
then
understanding
understanding
callbacks
callbacks
and
and
functional
functional
programming
programming
is
is
very
very
useful
useful
for
for
the
the
second
second
approach.
approach
When
when
a
a
user
user
attempts
attempts
to
to
log
log
in,
in
something
something
might
might
go
go
wrong.
wrong
It
it
might
might
be
be
your
your
fault
fault
as
as
the
the
developer
developer
or
or
the
the
user's
user's
fault.
fault
In
in
any
any
case,
case
you'll
you'll
want
want
to
to
make
make
sure
sure
that
that
you
you
catch
catch
these
these
and
and
then
then
create
create
a
a
default
default
handler
handler
that
that
routes
routes
them
them
to
to
a
a
visual
visual
UI
ui
element
element
like
like
a
a
dialogue.
dialogue
A
a
cool
cool
trick
trick
you
you
can
can
do
do
with
with
Firebase
firebase
auth
auth
is
is
to
to
register
register
a
a
user
user
lazily.
lazily
For
for
example,
example
you
you
might
might
first
first
have
have
a
a
user
user
sign
sign
in
in
anonymously,
anonymously
which
which
will
will
give
give
you
you
a
a
user
user
ID
id
that
that
you
you
can
can
tie
tie
to
to
the
the
database.
database
Then
then
later
later
in
in
the
the
onboarding
onboarding
process,
process
you
you
can
can
collect
collect
their
their
email
email
or
or
link
link
social
social
accounts
accounts
like
like
Twitter,
twitter
Facebook,
facebook
Google,
google
etcetera.
etcetera
Now
now
certain
certain
authentication
authentication
methods
methods
like
like
email
email
password
password
may
may
need
need
to
to
send
send
emails
emails
to
to
your
your
users
users
for
for
things
things
like
like
email
email
verification
verification
and
and
resetting
resetting
passwords.
passwords
Sometimes
sometimes
you
you
might
might
want
want
to
to
control
control
this
this
process
process
on
on
your
your
own,
own
which
which
you
you
can
can
do
do
with
with
custom
custom
email
email
action
action
handlers,
handlers
And
and
you
you
can
can
even
even
bring
bring
your
your
own
own
custom
custom
SMTP
smtp
email
email
server.
server
Now
now
one
one
of
of
the
the
most
most
important
important
aspects
aspects
of
of
any
any
application
application
is
is
managing
managing
relational
relational
data.
data
Let's
let's
check
check
out
out
a
a
few
few
common
common
techniques
techniques
for
for
connecting
connecting
our
our
users
users
to
to
the
the
Firestore
firestore
database.
database
We
we
can
can
create
create
a
a
one
one
to
to
one
one
relationship
relationship
where
where
the
the
user
user
has
has
one
one
document
document
in
in
Fire
fire
store
store
by
by
first
first
retrieving
retrieving
their
their
user
user
ID,
id
then
then
we'll
we'll
make
make
a
a
reference
reference
to
to
a
a
collection
collection
and
and
set
set
the
the
document
document
ID
id
as
as
the
the
user
user
ID.
id
Every
every
user
user
ID
id
is
is
unique,
unique
So
so
it
it
guarantees
guarantees
that
that
that
that
user
user
can
can
only
only
have
have
one
one
document
document
in
in
that
that
collection.
collection
Now
now
if
if
it's
it's
possible
possible
that
that
data
data
already
already
exists
exists
there,
there
you
you
might
might
want
want
to
to
use
use
the
the
merge
merge
true
true
option.
option
This
this
will
will
ensure
ensure
that
that
any
any
data
data
that
that
already
already
exists
exists
there
there
won't
won't
be
be
overwritten.
overwritten
The
the
merge
merge
true
true
option
option
just
just
makes
makes
it
it
a
a
nondestructive
nondestructive
update.
update
Another
another
common
common
relationship
relationship
is
is
one
one
to
to
many.
many
A
a
user
user
might
might
have
have
many
many
orders,
orders
but
but
an
an
order
order
belongs
belongs
to
to
one
one
user.
user
The
the
best
best
way
way
to
to
handle
handle
this
this
type
type
of
of
relationship
relationship
is
is
to
to
use
use
a
a
subcollection.
subcollection
In
in
the
the
last
last
example,
example
we
we
created
created
a
a
document
document
with
with
a
a
user
user
ID,
id
and
and
we
we
know
know
that
that
every
every
subcollection
subcollection
under
under
that
that
document
document
is
is
owned
owned
by
by
that
that
user.
user
But
but
sometimes
sometimes
you
you
might
might
run
run
into
into
a
a
situation
situation
where
where
you
you
want
want
to
to
query
query
orders
orders
across
across
all
all
the
the
users
users
in
in
your
your
database.
database
Firebase
firebase
provides
provides
a
a
special
special
method
method
that
that
allows
allows
you
you
to
to
group
group
subcollections
subcollections
and
and
query
query
them
them
together.
together
Collection
collection
group
group
will
will
find
find
all
all
of
of
the
the
collections
collections
that
that
share
share
the
the
name
name
orders,
orders
group
group
them
them
together,
together
allowing
allowing
you
you
to
to
make
make
a
a
single
single
query
query
against
against
all
all
of
of
them.
them
And
and
another
another
very
very
common
common
relationship
relationship
is
is
many
many
to
to
many.
many
In
in
this
this
case,
case
we
we
have
have
a
a
single
single
collection
collection
called
called
chats,
chats
and
and
each
each
chat
chat
document
document
can
can
be
be
associated
associated
with
with
multiple
multiple
users.
users
We
we
can
can
associate
associate
multiple
multiple
users
users
to
to
multiple
multiple
chats
chats
by
by
embedding
embedding
their
their
user
user
IDs
ids
on
on
the
the
chat
chat
document
document
using
using
a
a
map
map
of
of
key
key
value
value
pairs.
pairs
The
the
key
key
is
is
the
the
user
user
ID,
id
and
and
then
then
I'm
i'm
going
going
to
to
duplicate
duplicate
the
the
display
display
name
name
in
in
case
case
we
we
want
want
to
to
show
show
that
that
in
in
the
the
UI.
ui
Data
data
duplication
duplication
is
is
perfectly
perfectly
okay
okay
in
in
NoSQL.
nosql
It
it
can
can
optimize
optimize
for
for
performance
performance
and
and
costs,
costs
but
but
it
it
works
works
best
best
with
with
values
values
that
that
are
are
immutable
immutable
or
or
that
that
don't
don't
need
need
to
to
be
be
updated
updated
very
very
often.
often
And
and
now
now
that
that
we
we
have
have
a
a
map
map
object
object
on
on
this
this
document
document
where
where
each
each
key
key
in
in
that
that
map
map
is
is
a
a
user
user
ID.
id
We
we
can
can
query
query
it
it
by
by
using
using
dot
dot
notation
notation
in
in
our
our
queries,
queries
like
like
order
order
by
by
members
members
dot
dot
user
user
ID.
id
Now
now
that
that
we've
we've
modeled
modeled
some
some
data
data
and
and
made
made
some
some
queries,
queries
we
we
need
need
to
to
decide
decide
if
if
we
we
want
want
our
our
data
data
in
in
real
real
time
time
format
format
or
or
not.
not
If
if
you're
you're
trying
trying
to
to
optimize
optimize
pricing
pricing
and
and
don't
don't
think
think
you'll
you'll
need
need
real
real
time
time
updates
updates
For
for
your
your
data,
data
you
you
can
can
just
just
call
call
query
query
git
git
to
to
retrieve
retrieve
the
the
data
data
once
once
and
and
then
then
not
not
listen
listen
to
to
any
any
future
future
updates.
updates
But
but
if
if
you
you
are
are
building
building
a
a
feature
feature
where
where
the
the
UI
ui
should
should
react
react
To
to
change
change
this
this
in
in
real
real
time,
time
you'll
you'll
want
want
to
to
use
use
query
query
on
on
snapshot,
snapshot
then
then
run
run
a
a
callback
callback
function
function
anytime
anytime
the
the
underlying
underlying
data
data
changes.
changes
On
on
a
a
collection
collection
query,
query
when
when
you
you
listen
listen
to
to
docs,
docs
You'll
you'll
get
get
a
a
new
new
array
array
anytime
anytime
there's
there's
a
a
change
change
to
to
the
the
underlying
underlying
data,
data
but
but
you
you
might
might
want
want
to
to
know
know
exactly
exactly
which
which
documents
documents
were
were
added,
added
modified,
modified
or
or
removed.
removed
Doc
doc
changes
changes
provides
provides
an
an
array
array
of
of
all
all
the
the
documents
documents
that
that
changed,
changed
their
their
old
old
index,
index
new
new
index,
index
and
and
the
the
change
change
type.
type
Another
another
awesome
awesome
thing
thing
about
about
Firestore
firestore
is
is
that
that
it's
it's
able
able
to
to
work
work
offline.
offline
If
if
the
the
Internet
internet
goes
goes
out
out
and
and
the
the
user's
user's
still
still
trying
trying
to
to
send
send
rights
rights
to
to
the
the
database,
database
Firestore
firestore
will
will
still
still
update
update
the
the
UI
ui
and
and
then
then
send
send
those
those
rights
rights
to
to
the
the
actual
actual
database
database
and
and
commit
commit
them
them
after
after
the
the
Internet
internet
comes
comes
back
back
online.
online
And
and
you
you
can
can
even
even
make
make
this
this
work
work
across
across
multiple
multiple
browser
browser
tabs
tabs
by
by
setting
setting
the
the
synchronized
synchronized
tabs
tabs
option
option
to
to
true.
true
Now
now
one
one
question
question
I
i
get
get
a
a
lot
lot
is
is
how
how
do
do
I
i
use
use
emoji
emoji
characters
characters
in
in
my
my
code?
code
Well,
well
they're
they're
actually
actually
just
just
u
u
t
t
f
f
eight
eight
characters,
characters
which
which
means
means
you
you
can
can
use
use
them
them
in
in
a
a
regular
regular
string.
string
And
and
that
that
also
also
means
means
that
that
you
you
can
can
use
use
them
them
in
in
your
your
Firestore
firestore
documents
documents
and
and
make
make
queries
queries
against
against
them.
them
Another
another
trick
trick
you
you
might
might
wanna
wanna
use
use
is
is
to
to
match
match
a
a
wildcard
wildcard
string.
string
For
for
example,
example
if
if
we
we
wanted
wanted
to
to
query
query
all
all
of
of
the
the
Fast
fast
and
and
the
the
Furious
furious
movie
movie
titles.
titles
Create
create
a
a
starting
starting
point
point
and
and
then
then
make
make
your
your
ending
ending
point
point
a
a
tilde
tilde
character.
character
This
this
will
will
match
match
all
all
the
the
documents
documents
that
that
start
start
with
with
the
the
Fast
fast
and
and
the
the
Furious
furious
title.
title
And
and
with
with
that,
that
we
we
have
have
reached
reached
the
the
halfway
halfway
mark.
mark
Let's
let's
take
take
a
a
quick
quick
break.
break
Welcome
welcome
back.
back
Sometimes
sometimes
you
you
might
might
have
have
a
a
compound
compound
query
query
where
where
you
you
chain
chain
together
together
multiple
multiple
query
query
conditions.
conditions
This
this
query
query
won't
won't
work
work
by
by
default
default
because
because
it
it
requires
requires
an
an
index,
index
but
but
don't
don't
create
create
the
the
index
index
manually.
manually
Let
let
your
your
app
app
throw
throw
an
an
error,
error
then
then
click
click
the
the
link
link
to
to
the
the
Firestore
firestore
console
console
to
to
create
create
the
the
index
index
automatically.
automatically
One
one
of
of
the
the
most
most
powerful
powerful
data
data
types
types
in
in
Firestore
firestore
is
is
a
a
list.
list
We
we
can
can
add
add
a
a
list
list
to
to
a
a
document
document
by
by
simply
simply
setting
setting
it
it
with
with
a
a
JavaScript
javascript
array.
array
But
but
we
we
might
might
decide
decide
later
later
that
that
any
any
good
good
Firebase
firebase
recipe
recipe
needs
needs
to
to
include
include
a
a
pineapple.
pineapple
We
we
can
can
use
use
the
the
Firestore
firestore
array
array
union
union
method
method
to
to
ensure
ensure
that
that
the
the
array
array
includes
includes
exactly
exactly
1
1
pineapple.
pineapple
Or
or
we
we
might
might
decide
decide
later
later
on
on
that
that
maybe
maybe
squid
squid
wasn't
wasn't
such
such
a
a
good
good
idea
idea
in
in
this
this
recipe,
recipe
so
so
we
we
can
can
remove
remove
it
it
by
by
using
using
the
the
array
array
remove
remove
method
method
without
without
having
having
to
to
know
know
the
the
actual
actual
index.
index
And
and
now
now
that
that
we
we
have
have
an
an
array
array
on
on
the
the
document,
document
we
we
can
can
query
query
it
it
by
by
using
using
the
the
array
array
contains
contains
operator
operator
inside
inside
of
of
where,
where
and
and
that
that
will
will
give
give
us
us
all
all
of
of
the
the
recipes
recipes
that
that
contain
contain
avocado.
avocado
Now
now
sometimes
sometimes
you
you
might
might
have
have
an
an
array
array
that
that
contains
contains
IDs
ids
of
of
other
other
documents
documents
in
in
the
the
database.
database
But
but
how
how
do
do
you
you
actually
actually
fetch
fetch
the
the
full
full
documents
documents
in
in
this
this
array?
array
Do
do
it
it
in
in
JavaScript
javascript
by
by
mapping
mapping
all
all
of
of
the
the
ID
id
strings
strings
to
to
an
an
array
array
of
of
promises
promises
that
that
get
get
the
the
document,
document
then
then
run
run
them
them
together
together
with
with
promise
promise
dot
dot
all.
all
One
one
thing
thing
you
you
should
should
generally
generally
avoid
avoid
doing
doing
is
is
setting
setting
a
a
time
time
stamp
stamp
from
from
your
your
front
front
end
end
code
code
because
because
the
the
user's
user's
clock
clock
might
might
not
not
be
be
synchronized
synchronized
properly.
properly
If
if
you
you
need
need
to
to
set
set
a
a
time
time
stamp
stamp
on
on
a
a
document,
document
use
use
the
the
Firestore
firestore
server
server
time
time
stamp.
stamp
That
that
ensures
ensures
that
that
all
all
users
users
are
are
sharing
sharing
the
the
same
same
clock.
clock
Another
another
thing
thing
you
you
might
might
wanna
wanna
do
do
is
is
increment
increment
a
a
counter,
counter
like
like
the
the
score
score
of
of
the
the
game.
game
You
you
can
can
change
change
the
the
value
value
of
of
the
the
counter
counter
atomically
atomically
without
without
knowing
knowing
its
its
current
current
value
value
by
by
using
using
the
the
increment
increment
field
field
value.
value
Now
now
Firestore
firestore
only
only
supports
supports
1
1
write
write
per
per
document
document
per
per
second,
second
although
although
you
you
can
can
burst
burst
above
above
that
that
value.
value
So
so
if
if
you
you
have
have
a
a
ton
ton
of
of
writes
writes
happening
happening
on
on
a
a
single
single
document,
document
You
you
can
can
set
set
up
up
a
a
distributed
distributed
counter,
counter
which
which
is
is
now
now
very
very
easy
easy
to
to
do
do
because
because
there
there
is
is
a
a
Firebase
firebase
extension
extension
that
that
supports
supports
it.
it
And
and
speaking
speaking
of
of
atomic,
atomic
Sometimes
sometimes
you
you
might
might
have
have
rights
rights
that
that
need
need
to
to
succeed
succeed
or
or
fail
fail
together.
together
Maybe
maybe
the
the
user
user
completes
completes
the
the
game,
game
you
you
write
write
the
the
score,
score
and
and
then
then
you
you
want
want
to
to
update
update
the
the
user's
user's
lifetime
lifetime
score.
score
You
you
can
can
ensure
ensure
that
that
these
these
operations
operations
happen
happen
together
together
by
by
setting
setting
up
up
a
a
batch
batch
write.
write
This
this
will
will
commit
commit
them
them
together,
together
but
but
roll
roll
back
back
to
to
the
the
previous
previous
state
state
if
if
any
any
of
of
the
the
writes
writes
fail.
fail
Now
now
Firestore
firestore
is
is
a
a
great
great
solution
solution
for
for
the
the
vast
vast
majority
majority
of
of
use
use
cases,
cases
but
but
sometimes
sometimes
you
you
might
might
need
need
a
a
full
full
relational
relational
database.
database
If
if
you
you
need
need
a
a
full
full
relational
relational
database,
database
Check
check
out
out
my
my
video
video
on
on
integrating
integrating
MySQL
mysql
into
into
a
a
Firebase
firebase
project.
project
Or
or
if
if
you
you
need
need
full
full
text
text
search,
search
check
check
out
out
my
my
Algolia
algolia
integration
integration
video.
video
Now
now
one
one
of
of
the
the
most
most
important
important
things
things
to
to
do
do
as
as
a
a
Firebase
firebase
developer
developer
is
is
set
set
rules
rules
before
before
you
you
deploy
deploy
to
to
production.
production
If
if
you
you
deploy
deploy
an
an
app
app
without
without
good
good
security
security
rules
rules
in
in
place,
place
your
your
customer's
customer's
data
data
could
could
be
be
compromised,
compromised
and
and
someone
someone
could
could
make
make
destructive
destructive
rights
rights
to
to
your
your
database.
database
Currently,
currently
our
our
database
database
is
is
in
in
lock
lock
mode,
mode
which
which
means
means
we're
we're
safe.
safe
But
but
now
now
let's
let's
go
go
ahead
ahead
and
and
open
open
up
up
some
some
operations
operations
for
for
our
our
users.
users
The
the
first
first
thing
thing
you
you
should
should
do
do
is
is
get
get
used
used
to
to
using
using
the
the
simulator.
simulator
It
it
allows
allows
you
you
to
to
pass
pass
mock
mock
requests
requests
to
to
the
the
database
database
to
to
see
see
how
how
the
the
rules
rules
will
will
be
be
evaluated,
evaluated
But
but
serious
serious
production
production
apps
apps
should
should
use
use
the
the
Firestore
firestore
emulator.
emulator
This
this
allows
allows
you
you
to
to
simulate
simulate
the
the
Firestore
firestore
database
database
in
in
your
your
local
local
development
development
environment,
environment
You
you
can
can
throw
throw
a
a
whole
whole
bunch
bunch
of
of
different
different
test
test
cases
cases
at
at
your
your
rules
rules
to
to
ensure
ensure
that
that
they're
they're
robust.
robust
Note
note
that
that
there
there
are
are
5
5
different
different
types
types
of
of
operations
operations
a
a
user
user
can
can
make
make
on
on
a
a
document.
document
They
they
can
can
get
get
a
a
single
single
document,
document
a
a
query
query
of
of
a
a
list
list
of
of
documents,
documents
and
and
they
they
can
can
create,
create
update,
update
and
and
delete
delete
documents.
documents
You
you
can
can
provide
provide
fine
fine
grained
grained
rules
rules
for
for
each
each
operation,
operation
or
or
you
you
can
can
combine
combine
Then
then
by
by
using
using
the
the
read
read
or
or
write
write
keywords.
keywords
If
if
they
they
share
share
the
the
same
same
logic,
logic
just
just
separate
separate
them
them
with
with
a
a
comma.
comma
When
when
a
a
rule
rule
is
is
evaluated,
evaluated
there
there
are
are
2
2
things
things
that
that
you'll
you'll
look
look
at,
at
the
the
request
request
and
and
the
the
resource.
resource
The
the
request
request
contains
contains
the
the
user's
user's
authentication
authentication
state
state
as
as
well
well
as
as
the
the
incoming
incoming
data
data
that
that
they're
they're
trying
trying
to
to
write
write
to
to
the
the
database.
database
The
the
resource,
resource
On
on
the
the
other
other
hand,
hand
is
is
the
the
data
data
that
that
already
already
exists
exists
at
at
this
this
path
path
in
in
the
the
database.
database
But
but
in
in
some
some
cases,
cases
you
you
might
might
need
need
to
to
look
look
elsewhere
elsewhere
in
in
the
the
database
database
to
to
determine
determine
if
if
a
a
rule
rule
should
should
be
be
allowed.
allowed
Use
use
the
the
get
get
keyword
keyword
and
and
then
then
point
point
to
to
a
a
path
path
in
in
the
the
database,
database
and
and
you
you
can
can
use
use
dollar
dollar
sign
sign
parenthesis
parenthesis
to
to
interpolate
interpolate
values
values
like
like
the
the
request
request
auth
auth
user
user
ID.
id
This
this
gives
gives
you
you
the
the
value
value
from
from
this
this
document,
document
but
but
keep
keep
in
in
mind
mind
that
that
you're
you're
charged
charged
a
a
read
read
every
every
time
time
this
this
rule
rule
is
is
evaluated.
evaluated
Now
now
you
you
might
might
notice
notice
That
that
this
this
is
is
a
a
very
very
long
long
line
line
of
of
code,
code
and
and
if
if
we
we
were
were
using
using
this
this
frequently
frequently
throughout
throughout
the
the
rules,
rules
we
we
wouldn't
wouldn't
want
want
to
to
have
have
to
to
repeat
repeat
it
it
all
all
the
the
time.
time
We
we
can
can
extract
extract
this
this
logic
logic
into
into
its
its
own
own
function
function
called
called
is
is
admin,
admin
And
and
now
now
we
we
have
have
a
a
much
much
cleaner
cleaner
way
way
to
to
check
check
for
for
admin
admin
users.
users
Now
now
let's
let's
switch
switch
gears
gears
to
to
cloud
cloud
storage.
storage
A
a
storage
storage
bucket
bucket
is
is
where
where
you
you
would
would
put
put
things
things
like
like
images,
images
videos,
videos
and
and
raw
raw
files.
files
You
you
have
have
a
a
default
default
bucket,
bucket
which
which
is
is
where
where
you
you
would
would
normally
normally
save
save
your
your
user
user
generated
generated
content,
content
but
but
you
you
can
can
create
create
additional
additional
buckets
buckets
as
as
well.
well
You
you
might
might
want
want
an
an
additional
additional
bucket
bucket
for
for
Firestore
firestore
backups,
backups
which
which
you
you
can
can
set
set
to
to
coldline,
coldline
which
which
will
will
save
save
you
you
some
some
money.
money
Now
now
when
when
you
you
upload
upload
a
a
file
file
to
to
a
a
storage
storage
bucket,
bucket
there
there
is
is
a
a
storage
storage
location
location
and
and
a
a
download
download
URL.
url
If
if
the
the
user
user
needs
needs
to
to
access
access
this
this
file
file
again
again
in
in
the
the
future,
future
I
i
recommend
recommend
saving
saving
both
both
values
values
to
to
the
the
Firestore
firestore
database.
database
You
you
can
can
use
use
the
the
storage
storage
location
location
to
to
replace
replace
or
or
delete
delete
the
the
file
file
in
in
the
the
future
future
or
or
the
the
download
download
URL
url
to
to
access
access
the
the
file
file
in
in
your
your
app.
app
But
but
don't
don't
worry
worry
too
too
much
much
if
if
you
you
forgot
forgot
to
to
save
save
the
the
file
file
path
path
in
in
the
the
database
database
because
because
you
you
can
can
use
use
the
the
storage
storage
ref
ref
from
from
URL
url
and
and
point
point
to
to
either
either
the
the
full
full
path
path
in
in
the
the
storage
storage
bucket
bucket
or
or
to
to
the
the
download
download
URL
url
to
to
access
access
that
that
file.
file
Sometimes
sometimes
you
you
might
might
want
want
to
to
list
list
out
out
all
all
the
the
files
files
in
in
a
a
directory
directory
in
in
the
the
bucket.
bucket
Simply
simply
make
make
a
a
reference
reference
to
to
the
the
path
path
to
to
the
the
directory,
directory
and
and
then
then
use
use
the
the
list
list
all
all
method
method
to
to
get
get
all
all
the
the
files
files
at
at
that
that
location.
location
You
you
can
can
upload
upload
a
a
file
file
by
by
simply
simply
making
making
a
a
reference
reference
to
to
a
a
file
file
path
path
and
and
then
then
putting
putting
the
the
raw
raw
file
file
that
that
you
you
want
want
to
to
upload.
upload
You
you
can
can
calculate
calculate
the
the
progress
progress
of
of
an
an
upload
upload
by
by
listening
listening
to
to
the
the
state
state
changed
changed
event,
event
then
then
divide
divide
the
the
bytes
bytes
transferred
transferred
by
by
the
the
total
total
bytes
bytes
in
in
the
the
file.
file
If
if
you
you
have
have
multiple
multiple
files
files
to
to
upload,
upload
feel
feel
free
free
to
to
upload
upload
them
them
all
all
at
at
the
the
same
same
time.
time
Firebase
firebase
will
will
automatically
automatically
handle
handle
concurrency
concurrency
and
and
upload
upload
them
them
as
as
efficiently
efficiently
as
as
possible.
possible
When
when
you
you
upload
upload
files,
files
you
you
might
might
also
also
want
want
to
to
save
save
your
your
own
own
custom
custom
metadata
metadata
about
about
that
that
file.
file
You
you
might
might
want
want
to
to
know
know
what
what
kind
kind
of
of
device
device
the
the
user
user
upload
upload
the
the
file
file
from,
from
their
their
user
user
ID,
id
and
and
stuff
stuff
like
like
that.
that
If
if
your
your
users
users
can
can
upload
upload
image
image
files,
files
there's
there's
a
a
good
good
chance
chance
that
that
you'll
you'll
want
want
to
to
resize
resize
them
them
to
to
different
different
resolutions
resolutions
for
for
different
different
devices.
devices
You
you
can
can
now
now
do
do
that
that
with
with
a
a
click
click
of
of
button
button
using
using
the
the
Firebase
firebase
image
image
resizer
resizer
extension.
extension
At
at
this
this
point,
point
we've
we've
been
been
mostly
mostly
looking
looking
at
at
front
front
end
end
code,
code
so
so
now
now
I
i
want
want
to
to
switch
switch
gears
gears
to
to
the
the
back
back
tip.
tip
You
you
can
can
create
create
your
your
own
own
command
command
line
line
utility
utility
for
for
Firebase
firebase
with
with
3
3
easy
easy
steps.
steps
Go
go
to
to
your
your
project
project
settings
settings
and
and
download
download
the
the
service
service
account
account
for
for
your
your
project.
project
In
in
a
a
node
node
project,
project
install
install
Firebase
firebase
Admin
admin
as
as
a
a
development
development
dependency,
dependency
then
then
create
create
a
a
JS
js
file
file
that
that
imports
imports
it
it
and
and
calls
calls
initialize
initialize
app.
app
Firebase
firebase
admin
admin
needs
needs
your
your
service
service
account,
account
but
but
it
it
contains
contains
sensitive
sensitive
information.
information
The
the
safest
safest
way
way
to
to
use
use
it
it
locally
locally
is
is
to
to
keep
keep
it
it
somewhere
somewhere
private
private
on
on
your
your
system,
system
and
and
then
then
use
use
an
an
environment
environment
variable
variable
called
called
Google
google
application
application
credentials.
credentials
But
but
if
if
you
you
include
include
the
the
service
service
account
account
directly
directly
in
in
your
your
source
source
code,
code
make
make
sure
sure
it's
it's
in
in
your
your
git
git
ignore
ignore
so
so
it
it
doesn't
doesn't
end
end
up
up
in
in
a
a
public
public
repo
repo
somewhere.
somewhere
One
one
of
of
my
my
favorite
favorite
things
things
to
to
do
do
with
with
an
an
admin
admin
script
script
is
is
to
to
seed
seed
the
the
database
database
with
with
some
some
dummy
dummy
data.
data
Install
install
Faker
faker
JS
js
and
and
then
then
import
import
it
it
into
into
your
your
JavaScript
javascript
file.
file
Then
then
create
create
a
a
loop,
loop
and
and
for
for
each
each
iteration,
iteration
add
add
a
a
new
new
document
document
to
to
the
the
collection
collection
using
using
Faker
faker
to
to
automatically
automatically
generate
generate
the
the
dummy
dummy
data.
data
Now
now
run
run
the
the
script
script
from
from
the
the
command
command
line
line
with
with
node.
node
You
you
should
should
now
now
see
see
a
a
bunch
bunch
of
of
dummy
dummy
documents
documents
seeded
seeded
in
in
your
your
database.
database
Now
now
you
you
can
can
do
do
a
a
lot
lot
with
with
the
the
Firebase
firebase
Admin
admin
SDK,
sdk
but
but
you
you
can
can
do
do
even
even
more
more
with
with
the
the
rest
rest
APIs.
apis
Check
check
out
out
the
the
rest
rest
API
api
documentation
documentation
to
to
find
find
secret
secret
techniques
techniques
that
that
you
you
didn't
didn't
know
know
about.
about
Earlier,
earlier
I
i
showed
showed
you
you
how
how
to
to
back
back
up
up
Firestore
firestore
from
from
the
the
command
command
line,
line
but
but
you
you
can
can
also
also
do
do
it
it
with
with
the
the
rest
rest
API.
api
This
this
would
would
allow
allow
you
you
to
to
set
set
up
up
a
a
cron
cron
job
job
to
to
back
back
up
up
your
your
database
database
on
on
a
a
daily
daily
basis.
basis
If
if
you
you
do
do
use
use
the
the
REST
rest
API,
api
you'll
you'll
want
want
to
to
use
use
the
the
Google
google
APIs
apis
NPM
npm
package.
package
This
this
allows
allows
you
you
to
to
discover
discover
and
and
interact
interact
with
with
hundreds
hundreds
of
of
different
different
Google
google
APIs,
apis
like
like
AdWords,
adwords
YouTube,
youtube
and,
and
of
of
course,
course
Firebase.
firebase
Creating
creating
an
an
admin
admin
script
script
can
can
be
be
useful,
useful
but
but
in
in
most
most
cases,
cases
you'll
you'll
be
be
with
with
Firebase
firebase
Admin
admin
in
in
a
a
Cloud
cloud
Function.
function
You
you
can
can
add
add
Cloud
cloud
Functions
functions
to
to
your
your
project
project
by
by
running
running
Firebase
firebase
init
init
functions.
functions
When
when
you
you
do
do
this,
this
I
i
highly
highly
recommend
recommend
using
using
TypeScript
typescript
because
because
it
it
does
does
all
all
the
the
setup
setup
for
for
you
you
and
and
will
will
help
help
you
you
catch
catch
silly
silly
errors
errors
before
before
they
they
end
end
up
up
in
in
production.
production
There's
there's
a
a
few
few
things
things
we
we
can
can
do
do
to
to
improve
improve
the
the
performance
performance
of
of
a
a
cold
cold
start
start
on
on
a
a
cloud
cloud
function
function
and
and
also
also
reduce
reduce
the
the
CPU
cpu
time
time
that
that
we're
we're
actually
actually
billed
billed
for.
for
Try
try
to
to
minimize
minimize
the
the
number
number
of
of
dependencies
dependencies
that
that
you
you
use
use
in
in
your
your
functions.
functions
More
more
code
code
to
to
load
load
and
and
parse
parse
means
means
a
a
slower
slower
cold
cold
start
start
time.
time
If
if
you
you
have
have
values
values
that
that
can
can
be
be
shared
shared
between
between
multiple
multiple
function
function
invocations,
invocations
you
you
can
can
set
set
them
them
up
up
as
as
global
global
variables.
variables
When
when
a
a
function
function
instance
instance
spins
spins
up
up
in
in
the
the
cloud,
cloud
it
it
might
might
be
be
used
used
multiple
multiple
times,
times
so
so
global
global
variables
variables
can
can
be
be
used
used
across
across
multiple
multiple
calls
calls
improving
improving
performance.
performance
When
when
you
you
design
design
your
your
Cloud
cloud
Functions,
functions
they
they
should
should
always
always
be
be
item
item
potent.
potent
Cloud
cloud
Functions
functions
are
are
guaranteed
guaranteed
to
to
be
be
invoked
invoked
at
at
least
least
once,
once
But
but
they
they
can
can
be
be
retried
retried
multiple
multiple
times,
times
so
so
you
you
wanna
wanna
make
make
sure
sure
that
that
multiple
multiple
calls
calls
to
to
the
the
same
same
function
function
produces
produces
the
the
same
same
result.
result
And
and
you
you
can
can
use
use
the
the
context
context
event
event
ID
id
to
to
help
help
you
you
achieve
achieve
that.
that
If
if
you
you
need
need
to
to
add
add
more
more
horsepower
horsepower
to
to
a
a
function,
function
you
you
can
can
use
use
run
run
with
with
to
to
max
max
out
out
the
the
memory
memory
at
at
2
2
gigabytes
gigabytes
and
and
the
the
time
time
out
out
seconds
seconds
to
to
540.
540
Now
now
one
one
thing
thing
you
you
want
want
to
to
be
be
really
really
careful
careful
not
not
to
to
do
do
is
is
to
to
create
create
an
an
infinite
infinite
loop.
loop
You
you
might
might
accidentally
accidentally
do
do
this
this
in
in
Firestore
firestore
by
by
updating
updating
the
the
same
same
document
document
that
that
triggered
triggered
the
the
event.
event
In
in
this
this
example,
example
we
we
have
have
an
an
on
on
write
write
function
function
that
that
updates
updates
the
the
same
same
document
document
that
that
triggered
triggered
the
the
write.
write
So
so
this
this
will
will
cause
cause
an
an
infinite
infinite
loop
loop
that
that
will
will
charge
charge
up
up
your
your
Firebase
firebase
bill
bill
until
until
you
you
hit
hit
the
the
quota
quota
limits.
limits
It's
it's
not
not
a
a
good
good
thing
thing
to
to
do.
do
However,
however
there
there
are
are
use
use
cases
cases
when
when
you
you
might
might
want
want
the
the
triggering
triggering
function
function
to
to
update
update
the
the
same
same
document.
document
You
you
can
can
avoid
avoid
the
the
infinite
infinite
loop
loop
by
by
checking
checking
if
if
The
the
after
after
document
document
is
is
equal
equal
to
to
the
the
before
before
document.
document
This
this
will
will
check
check
for
for
equality
equality
on
on
the
the
document
document
path
path
and
and
its
its
data,
data
and
and
that
that
will
will
stop
stop
the
the
loop
loop
assuming
assuming
your
your
function
function
is
is
idempotent.
idempotent
Background
background
cloud
cloud
functions
functions
must
must
always
always
return
return
a
a
promise.
promise
You
you
can
can
ensure
ensure
that
that
always
always
happens
happens
by
by
using
using
the
the
async
async
keyword
keyword
in
in
the
the
function
function
callback,
callback
Then
then
you
you
can
can
use
use
the
the
await
await
keyword
keyword
for
for
a
a
much
much
cleaner
cleaner
synchronous
synchronous
looking
looking
code.
code
Sometimes
sometimes
you
you
might
might
need
need
a
a
cloud
cloud
function
function
that
that
communicates
communicates
with
with
other
other
cloud
cloud
functions
functions
or
or
other
other
GCP
gcp
services.
services
You
you
could
could
use
use
an
an
HTTP
http
function
function
to
to
handle
handle
that,
that
but
but
you
you
would
would
also
also
need
need
to
to
implement
implement
some
some
code
code
to
to
validate
validate
the
the
request.
request
A
a
better
better
alternative
alternative
would
would
be
be
to
to
set
set
up
up
a
a
pubsub
pubsub
function.
function
It
it
allows
allows
you
you
to
to
pass
pass
messages
messages
between
between
your
your
internal
internal
services,
services
and
and
that's
that's
easier
easier
and
and
more
more
secure
secure
than
than
exposing
exposing
an
an
HTTP
http
endpoint.
endpoint
You
you
might
might
also
also
have
have
endpoints
endpoints
that
that
should
should
only
only
accessed
accessed
by
by
authenticated
authenticated
users.
users
In
in
a
a
regular
regular
HTTP
http
function,
function
you
you
would
would
need
need
to
to
extract
extract
the
the
authorization
authorization
header
header
that
that
you
you
set
set
in
in
your
your
front
front
end
end
code
code
and
and
then
then
verify
verify
the
the
ID
id
token.
token
As
as
an
an
alternative,
alternative
you
you
can
can
simplify
simplify
both
both
your
your
back
back
end
end
and
and
front
front
end
end
code
code
by
by
using
using
callable
callable
functions.
functions
It
it
includes
includes
the
the
auth
auth
context
context
for
for
the
the
user,
user
so
so
you
you
don't
don't
have
have
to
to
implement
implement
your
your
own
own
middleware
middleware
to
to
authenticate
authenticate
your
your
functions.
functions
A
a
great
great
use
use
case
case
is
is
to
to
delete
delete
an
an
entire
entire
Firestore
firestore
collection,
collection
which
which
Should
should
always
always
be
be
done
done
on
on
the
the
back
back
end
end
because
because
there
there
might
might
be
be
tons
tons
of
of
documents
documents
in
in
a
a
collection.
collection
We
we
can
can
first
first
authorize
authorize
the
the
operation
operation
by
by
looking
looking
at
at
the
the
user
user
ID.
id
Then
then
we'll
we'll
create
create
a
a
recursive
recursive
function
function
called
called
batch
batch
delete.
delete
It
it
retrieves
retrieves
documents
documents
in
in
batches
batches
of
of
100
100
and
and
then
then
deletes
deletes
them.
them
This
this
will
will
ensure
ensure
that
that
we
we
don't
don't
hit
hit
memory
memory
issues
issues
if
if
we
we
try
try
to
to
query
query
millions
millions
of
of
documents
documents
in
in
a
a
single
single
go.
go
Now
now
when
when
implementing
implementing
the
the
actual
actual
logic
logic
for
for
your
your
back
back
end
end
code,
code
consider
consider
breaking
breaking
it
it
down
down
into
into
small
small
JavaScript
javascript
functions.
functions
This
this
allows
allows
you
you
to
to
reuse
reuse
code
code
across
across
multiple
multiple
Deploy
deploy
Cloud
cloud
Functions,
functions
and
and
it's
it's
also
also
just
just
easier
easier
to
to
test.
test
Keep
keep
in
in
mind
mind
that
that
Cloud
cloud
Functions
functions
provide
provide
a
a
gateway
gateway
to
to
interact
interact
with
with
other
other
third
third
party
party
APIs.
apis
Almost
almost
every
every
good
good
API
api
also
also
has
has
a
a
good
good
Node
node
JS
js
library
library
to
to
go
go
with
with
it.
it
So,
so
basically,
basically
anything
anything
you
you
can
can
build
build
in
in
Node
node
JS,
js
you
you
can
can
build
build
in
in
a
a
Cloud
cloud
Function.
function
When
when
you're
you're
ready
ready
to
to
go
go
live,
live
you
you
can
can
deploy
deploy
all
all
of
of
your
your
functions
functions
from
from
the
the
command
command
line
line
with
with
a
a
single
single
command.
command
But
but
on
on
larger
larger
projects
projects
with
with
dozens
dozens
of
of
functions,
functions
you
you
may
may
not
not
want
want
to
to
deploy
deploy
everything
everything
all
all
at
at
once.
once
You
you
can
can
append
append
the
the
name
name
of
of
the
the
function
function
to
to
the
the
end
end
of
of
this
this
command
command
to
to
deploy
deploy
a
a
single
single
function.
function
Despite
despite
your
your
best
best
efforts,
efforts
your
your
functions
functions
will
will
very
very
likely
likely
have
have
some
some
bugs.
bugs
The
the
best
best
way
way
to
to
prevent
prevent
bugs
bugs
is
is
to
to
run
run
the
the
Cloud
cloud
Functions
functions
shell
shell
locally.
locally
You
you
can
can
invoke
invoke
your
your
functions
functions
with
with
mock
mock
data
data
to
to
test
test
their
their
behavior,
behavior
and
and
Firebase
firebase
even
even
provides
provides
a
a
unit
unit
testing
testing
library.
library
Now
now
your
your
function
function
still
still
might
might
break
break
in
in
production,
production
so
so
you
you
can
can
always
always
look
look
at
at
the
the
Firebase
firebase
logs
logs
to
to
see
see
what's
what's
going
going
wrong.
wrong
Or
or
better
better
yet,
yet
head
head
over
over
to
to
Stackdriver
stackdriver
where
where
you
you
can
can
create
create
your
your
own
own
custom
custom
dashboards
dashboards
boards
boards
and
and
alerts
alerts
for
for
the
the
things
things
that
that
you
you
care
care
about.
about
Earlier
earlier
in
in
the
the
video,
video
we
we
set
set
up
up
analytics
analytics
in
in
our
our
front
front
end
end
code.
code
But
but
to
to
get
get
the
the
most
most
out
out
of
of
it,
it
we'll
we'll
want
want
to
to
track
track
custom
custom
events
events
and
and
user
user
properties.
properties
Try
try
to
to
pinpoint
pinpoint
the
the
events
events
or
or
user
user
behaviors
behaviors
that
that
you
you
think
think
are
are
most
most
important
important
to
to
turning
turning
that
that
user
user
into
into
a
a
paying
paying
customer,
customer
then
then
use
use
Firebase
firebase
Analytics
analytics
to
to
record
record
those
those
events.
events
Firebase
firebase
will
will
aggregate
aggregate
some
some
of
of
the
the
data
data
automatically,
automatically
but
but
you
you
can
can
create
create
your
your
own
own
audiences
audiences
based
based
on
on
the
the
type
type
of
of
user
user
that
that
you
you
want
want
to
to
target.
target
Your
your
marketing
marketing
team
team
will
will
love
love
audiences
audiences
because
because
you
you
can
can
target
target
messaging
messaging
to
to
a
a
specific
specific
type
type
of
of
user
user
and
and
also
also
do
do
things
things
like
like
AB
ab
testing
testing
and
and
funnels.
funnels
And
and
as
as
a
a
developer,
developer
You
you
can
can
actually
actually
use
use
audiences
audiences
to
to
customize
customize
the
the
UI
ui
based
based
on
on
your
your
underlying
underlying
analytics
analytics
data.
data
The
the
service
service
will
will
send
send
key
key
value
value
pairs
pairs
down
down
to
to
to
to
your
your
front
front
end
end
application,
application
which
which
you
you
can
can
use
use
to
to
conditionally
conditionally
show
show
UI
ui
based
based
on
on
where
where
that
that
user
user
is
is
located,
located
what
what
audience
audience
they
they
belong
belong
to,
to
and
and
so
so
on.
on
You
you
can
can
also
also
use
use
the
the
same
same
data
data
to
to
send
send
push
push
notifications
notifications
to
to
your
your
users
users
using
using
Firebase
firebase
Cloud
cloud
Messaging.
messaging
Instead
instead
of
of
sending
sending
a
a
bulk
bulk
notification
notification
out
out
to
to
all
all
of
of
your
your
users,
users
Segment
segment
it
it
to
to
the
the
users
users
who
who
actually
actually
want
want
it
it
and
and
will
will
benefit
benefit
from
from
it.
it
And
and
with
with
that,
that
we
we
have
have
finally
finally
reached
reached
Firebase
firebase
tip
tip
number
number
100.
100
Leverage
leverage
machine
machine
learning
learning
within
within
your
your
app.
app
You
you
can
can
do
do
this
this
in
in
multiple
multiple
ways
ways
with
with
Firebase.
firebase
Use
use
predictions
predictions
to
to
guess
guess
when
when
a
a
user
user
is
is
going
going
to
to
buy
buy
your
your
product,
product
use
use
ML
ml
Kit
kit
to
to
implement
implement
AI
ai
driven
driven
features
features
out
out
of
of
the
the
box,
box
Things
things
like
like
object
object
detection
detection
and
and
smart
smart
reply,
reply
or
or
build
build
your
your
own
own
image
image
classification
classification
models
models
with
with
AutoML.
automl
And
and
you
you
can
can
even
even
export
export
all
all
of
of
your
your
analytics
analytics
and
and
Firestore
firestore
data
data
to
to
BigQuery
bigquery
and
and
use
use
that
that
raw
raw
data
data
to
to
train
train
your
your
own
own
TensorFlow
tensorflow
models
models
from
from
scratch.
scratch
And
and
that
that
is
is
all
all
of
of
the
the
Firebase
firebase
tips
tips
that
that
exist
exist
in
in
the
the
world.
world
If
if
you
you
have
have
your
your
own
own
additional
additional
tips,
tips
Leave
leave
them
them
in
in
the
the
comments
comments
below,
below
and
and
I'll
i'll
pick
pick
a
a
couple
couple
of
of
the
the
best
best
ones
ones
to
to
win
win
a
a
t
t
shirt
shirt
later
later
this
this
week.
week
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
wrap
wrap
things
things
up
up
there.
there
Hopefully,
hopefully
you
you
found
found
something
something
useful
useful
in
in
here.
here
Thanks
thanks
for
for
watching,
watching
and
and
I
i
will
will
talk
talk
to
to
you
you
soon.
soon
success
The speakers discuss how to build successful reminded user experiences and optimize data collection and query in real time using cloud solutions and emoji characters in code. They also explain how to set up server to back up a database and set rules before deploying to production apps. The importance of proper security and the use of a subitor for data management is emphasized. The speakers also recommend setting up a server to back up a database and using Cloud function variables and async keywords for machine learning and AI-driven features.
100 Firebase Tips, Tricks, and Screw-ups
Welcome to my top 10 Firebase tips. Welcome to my top 25 Firebase tips. Nope. Welcome to my top 100 Firebase tips. I've been working with Firebase for several years now. I've made plenty of mistakes along the way, but I've also uncovered some secrets that you may not know about. So hopefully this video makes your experience with Firebase 100 times easier. If you're new here, like and subscribe. And if you're serious about building an app of Firebase, consider becoming a pro member at Fireship I tip. You'll get access to full project courses and a free t shirt if you sign up for life. Or you can get a free t shirt by leaving the best Firebase tip in the comments below. The first thing you'll need is a Firebase project. If you're building a serious app, create 2 Firebase projects, one for development and one for production. This gives you a sandbox for testing and Experimenting, and you can keep your customer data pristine in the production project. In your production project, link Google Analytics. Firebase can automatically set up analytics for iOS, Android, and the web. If you're working with a team, head over to the settings tab and then go to users and permissions. Assign roles based on the principle of least privilege, so team members only have access to the resources that they actually need. From there, head over to the data privacy tab and update your contact information to ensure you're in compliance with GDPR. Now click the button to add a new app to your Firebase project. When you do that, it will give you an object with a bunch of credentials. Don't worry. These are perfectly safe in your front end code as long as you set up security rules, which we'll look at later. Upgrade your Firebase plan to Blaze. It's pay as you go, but you still get all of the free stuff that you would on the Spark tier. But you still want to stay on top of cost, so head over to the GCP console and set up a budget alert for your project. Then monitor your monthly usage from the reports panel. This will tell you Exactly which services are costing you the most money. Make sure to install the Firebase command line tools globally on your system and also the Google Cloud SDK. A Firebase project is actually just a layer on top of a Google Cloud Platform project. Once you've done this, you should have access to the Firebase command and the gcloud command on your local system. So now that we have a project set up, let's look at how we can actually deploy our code to this project. If you're building an iOS or Android app, use Firebase app distribution to distribute your app to testers. This will bypass TestFlight and the Google Play Store, making your life much easier. Now if you're building a web application, you're likely using a package manager like npm. Install Firebase tools into the development environment for that project. And now you can write npm scripts that use the Firebase CLI tools. Now if you followed my earlier advice to set up different projects for development and production, you can use the project flag to set up different commands that specify the project. So here we have a command to deploy to our development project and another for our production project. Now after you've deployed your site, head over to the Firebase console, and you can see it's deployed at a cool domain called your project dot web dot app, or you can just connect your own custom domain. And you're not limited to a single domain. For example, you might have an admin site and a customer facing site. They can both share the same Firebase project with multisite hosting. Then go into your Firebase JSON file, change the hosting value to an array, and set up different targets that represent the different sites you want to deploy. Now you're not just limited to static files when deploying to hosting. You can actually rewrite traffic to a Cloud Function or to a Cloud Run instance. And that means you can do SSR with something like Angular Universal or Next. Js. You can also set up Firebase hosting rewrites for dynamic links. This allows you to dynamically send the user to the app with the best possible experience. So if the user goes to a link on their iPhone, it will take them to a specific screen in the iPhone app. You can also specify headers on the static files in your hosting account. For example, if we wanted to change the core settings for all of the font files, we could do it like this. And Firebase Hosting will also cache our static files for better performance, but we can change the caching behavior by setting different cache headers here as well. And one cool thing you might do to extend Firebase Hosting is to set it up with Google Cloud Build. So every git commit you make to your project, it will deploy a new version of your site to your hosting account. That's exactly what I do for Fireship IO. Firebase provides 2 different fully managed NoSQL databases. So how do you know which one to choose? I default to Cloud Firestore because it has more powerful query capabilities. It also costs less per gigabyte stored. However, real time database does not charge for rights, So it can be a great option if you have data that's updated frequently like an IoT sensor or something along those lines. But when it comes to pricing, you really shouldn't worry about it too much. Don't even trip, dawg. Firebase overall is very inexpensive, and it will take a decent number of monthly active users before you even break out of the free tier. Unless you make a silly mistake, you'll be paying much less than you would be with other cloud solutions. A more important thing to worry about is that you back up your data on a regular basis. Set up a dedicated cloud storage bucket for backups, and then you can back up your entire database with a single command. When you create your based for the first time, set it in locked mode. It's safer to start with a locked down database than incrementally allow operations as they become necessary. After you've created a Firestore collection, go ahead and click the filter icon, and you'll see that you can make queries directly from the Firebase console. And it even provides some code for your query that you can copy and paste to using your app source code. In fact, let's go ahead and switch gears and jump into the source code for a JavaScript application. Now the way you import Firebase depends on the flavor of JavaScript you're using. You can see the import syntax here for CommonJS, ES 6, and TypeScript. But all of these are actually wrong because they're importing from Firebase directly. Your code will work, but it will create a huge JavaScript bundle that will slow down your app. The correct way to use Firebase is to import from the Firebase app namespace and then import these services that you plan on using, aka progressive enhancement. In any case, Firebase is a pretty big dependency. So if you're loading it with a script tag, You'll wanna use the defer keyword on that script to ensure it loads after the actual DOM or HTML has been parsed. But if you're using a framework, then you shouldn't have to worry about this. Angular app should use AngularFire, which integrates with change detection and the Angular router. If you use React on the front end, the ReactFire library was just undeprecated, and it provides support for hooks and suspense. You have RXFire to integrate with RxJS, which works great in frameworks like Svelte. Then outside of the web, you have support for all kinds of different other frameworks in Firebase extended like Flutter, Arduino, and many others. When you first add Firebase to a project, there's a couple of no brainer services that you'll definitely wanna use, such as performance monitoring. With a single line of code, we can see how well our app performs out in the wild, giving us metrics like first contentful paint across all devices using our app. The next one is Crashlytics, which is only relevant to native mobile apps. It's very easy to set up, and it will give you error reporting and crash reporting throughout your entire application and automatically open issues so you can address those problems. And lastly, we have Firebase Analytics. With a single line of code, we'll get the default reporting from Google Analytics, giving us insight about the behavior of our users. Now in your source code, one of the first things you'll likely wanna do is determine if a user is logged in or not. There are 2 main ways to do this. You can pull the current user at any time by calling auth current user. This is usually best for handling events, like when the user clicks a button and then you want to grab their auth record and do something afterwards. The other way to get the current user is to always be listening to the current auth state. In this case, you provide a callback function to listen to changes to the auth state, like when the user signs in or signs out. In either case, I recommend getting good at asynchronous JavaScript to be test with Firebase. Understanding async await is very useful for the first approach, then understanding callbacks and functional programming is very useful for the second approach. When a user attempts to log in, something might go wrong. It might be your fault as the developer or the user's fault. In any case, you'll want to make sure that you catch these and then create a default handler that routes them to a visual UI element like a dialogue. A cool trick you can do with Firebase auth is to register a user lazily. For example, you might first have a user sign in anonymously, which will give you a user ID that you can tie to the database. Then later in the onboarding process, you can collect their email or link social accounts like Twitter, Facebook, Google, etcetera. Now certain authentication methods like email password may need to send emails to your users for things like email verification and resetting passwords. Sometimes you might want to control this process on your own, which you can do with custom email action handlers, And you can even bring your own custom SMTP email server. Now one of the most important aspects of any application is managing relational data. Let's check out a few common techniques for connecting our users to the Firestore database. We can create a one to one relationship where the user has one document in Fire store by first retrieving their user ID, then we'll make a reference to a collection and set the document ID as the user ID. Every user ID is unique, So it guarantees that that user can only have one document in that collection. Now if it's possible that data already exists there, you might want to use the merge true option. This will ensure that any data that already exists there won't be overwritten. The merge true option just makes it a nondestructive update. Another common relationship is one to many. A user might have many orders, but an order belongs to one user. The best way to handle this type of relationship is to use a subcollection. In the last example, we created a document with a user ID, and we know that every subcollection under that document is owned by that user. But sometimes you might run into a situation where you want to query orders across all the users in your database. Firebase provides a special method that allows you to group subcollections and query them together. Collection group will find all of the collections that share the name orders, group them together, allowing you to make a single query against all of them. And another very common relationship is many to many. In this case, we have a single collection called chats, and each chat document can be associated with multiple users. We can associate multiple users to multiple chats by embedding their user IDs on the chat document using a map of key value pairs. The key is the user ID, and then I'm going to duplicate the display name in case we want to show that in the UI. Data duplication is perfectly okay in NoSQL. It can optimize for performance and costs, but it works best with values that are immutable or that don't need to be updated very often. And now that we have a map object on this document where each key in that map is a user ID. We can query it by using dot notation in our queries, like order by members dot user ID. Now that we've modeled some data and made some queries, we need to decide if we want our data in real time format or not. If you're trying to optimize pricing and don't think you'll need real time updates For your data, you can just call query git to retrieve the data once and then not listen to any future updates. But if you are building a feature where the UI should react To change this in real time, you'll want to use query on snapshot, then run a callback function anytime the underlying data changes. On a collection query, when you listen to docs, You'll get a new array anytime there's a change to the underlying data, but you might want to know exactly which documents were added, modified, or removed. Doc changes provides an array of all the documents that changed, their old index, new index, and the change type. Another awesome thing about Firestore is that it's able to work offline. If the Internet goes out and the user's still trying to send rights to the database, Firestore will still update the UI and then send those rights to the actual database and commit them after the Internet comes back online. And you can even make this work across multiple browser tabs by setting the synchronized tabs option to true. Now one question I get a lot is how do I use emoji characters in my code? Well, they're actually just u t f eight characters, which means you can use them in a regular string. And that also means that you can use them in your Firestore documents and make queries against them. Another trick you might wanna use is to match a wildcard string. For example, if we wanted to query all of the Fast and the Furious movie titles. Create a starting point and then make your ending point a tilde character. This will match all the documents that start with the Fast and the Furious title. And with that, we have reached the halfway mark. Let's take a quick break. Welcome back. Sometimes you might have a compound query where you chain together multiple query conditions. This query won't work by default because it requires an index, but don't create the index manually. Let your app throw an error, then click the link to the Firestore console to create the index automatically. One of the most powerful data types in Firestore is a list. We can add a list to a document by simply setting it with a JavaScript array. But we might decide later that any good Firebase recipe needs to include a pineapple. We can use the Firestore array union method to ensure that the array includes exactly 1 pineapple. Or we might decide later on that maybe squid wasn't such a good idea in this recipe, so we can remove it by using the array remove method without having to know the actual index. And now that we have an array on the document, we can query it by using the array contains operator inside of where, and that will give us all of the recipes that contain avocado. Now sometimes you might have an array that contains IDs of other documents in the database. But how do you actually fetch the full documents in this array? Do it in JavaScript by mapping all of the ID strings to an array of promises that get the document, then run them together with promise dot all. One thing you should generally avoid doing is setting a time stamp from your front end code because the user's clock might not be synchronized properly. If you need to set a time stamp on a document, use the Firestore server time stamp. That ensures that all users are sharing the same clock. Another thing you might wanna do is increment a counter, like the score of the game. You can change the value of the counter atomically without knowing its current value by using the increment field value. Now Firestore only supports 1 write per document per second, although you can burst above that value. So if you have a ton of writes happening on a single document, You can set up a distributed counter, which is now very easy to do because there is a Firebase extension that supports it. And speaking of atomic, Sometimes you might have rights that need to succeed or fail together. Maybe the user completes the game, you write the score, and then you want to update the user's lifetime score. You can ensure that these operations happen together by setting up a batch write. This will commit them together, but roll back to the previous state if any of the writes fail. Now Firestore is a great solution for the vast majority of use cases, but sometimes you might need a full relational database. If you need a full relational database, Check out my video on integrating MySQL into a Firebase project. Or if you need full text search, check out my Algolia integration video. Now one of the most important things to do as a Firebase developer is set rules before you deploy to production. If you deploy an app without good security rules in place, your customer's data could be compromised, and someone could make destructive rights to your database. Currently, our database is in lock mode, which means we're safe. But now let's go ahead and open up some operations for our users. The first thing you should do is get used to using the simulator. It allows you to pass mock requests to the database to see how the rules will be evaluated, But serious production apps should use the Firestore emulator. This allows you to simulate the Firestore database in your local development environment, You can throw a whole bunch of different test cases at your rules to ensure that they're robust. Note that there are 5 different types of operations a user can make on a document. They can get a single document, a query of a list of documents, and they can create, update, and delete documents. You can provide fine grained rules for each operation, or you can combine Then by using the read or write keywords. If they share the same logic, just separate them with a comma. When a rule is evaluated, there are 2 things that you'll look at, the request and the resource. The request contains the user's authentication state as well as the incoming data that they're trying to write to the database. The resource, On the other hand, is the data that already exists at this path in the database. But in some cases, you might need to look elsewhere in the database to determine if a rule should be allowed. Use the get keyword and then point to a path in the database, and you can use dollar sign parenthesis to interpolate values like the request auth user ID. This gives you the value from this document, but keep in mind that you're charged a read every time this rule is evaluated. Now you might notice That this is a very long line of code, and if we were using this frequently throughout the rules, we wouldn't want to have to repeat it all the time. We can extract this logic into its own function called is admin, And now we have a much cleaner way to check for admin users. Now let's switch gears to cloud storage. A storage bucket is where you would put things like images, videos, and raw files. You have a default bucket, which is where you would normally save your user generated content, but you can create additional buckets as well. You might want an additional bucket for Firestore backups, which you can set to coldline, which will save you some money. Now when you upload a file to a storage bucket, there is a storage location and a download URL. If the user needs to access this file again in the future, I recommend saving both values to the Firestore database. You can use the storage location to replace or delete the file in the future or the download URL to access the file in your app. But don't worry too much if you forgot to save the file path in the database because you can use the storage ref from URL and point to either the full path in the storage bucket or to the download URL to access that file. Sometimes you might want to list out all the files in a directory in the bucket. Simply make a reference to the path to the directory, and then use the list all method to get all the files at that location. You can upload a file by simply making a reference to a file path and then putting the raw file that you want to upload. You can calculate the progress of an upload by listening to the state changed event, then divide the bytes transferred by the total bytes in the file. If you have multiple files to upload, feel free to upload them all at the same time. Firebase will automatically handle concurrency and upload them as efficiently as possible. When you upload files, you might also want to save your own custom metadata about that file. You might want to know what kind of device the user upload the file from, their user ID, and stuff like that. If your users can upload image files, there's a good chance that you'll want to resize them to different resolutions for different devices. You can now do that with a click of button using the Firebase image resizer extension. At this point, we've been mostly looking at front end code, so now I want to switch gears to the back tip. You can create your own command line utility for Firebase with 3 easy steps. Go to your project settings and download the service account for your project. In a node project, install Firebase Admin as a development dependency, then create a JS file that imports it and calls initialize app. Firebase admin needs your service account, but it contains sensitive information. The safest way to use it locally is to keep it somewhere private on your system, and then use an environment variable called Google application credentials. But if you include the service account directly in your source code, make sure it's in your git ignore so it doesn't end up in a public repo somewhere. One of my favorite things to do with an admin script is to seed the database with some dummy data. Install Faker JS and then import it into your JavaScript file. Then create a loop, and for each iteration, add a new document to the collection using Faker to automatically generate the dummy data. Now run the script from the command line with node. You should now see a bunch of dummy documents seeded in your database. Now you can do a lot with the Firebase Admin SDK, but you can do even more with the rest APIs. Check out the rest API documentation to find secret techniques that you didn't know about. Earlier, I showed you how to back up Firestore from the command line, but you can also do it with the rest API. This would allow you to set up a cron job to back up your database on a daily basis. If you do use the REST API, you'll want to use the Google APIs NPM package. This allows you to discover and interact with hundreds of different Google APIs, like AdWords, YouTube, and, of course, Firebase. Creating an admin script can be useful, but in most cases, you'll be with Firebase Admin in a Cloud Function. You can add Cloud Functions to your project by running Firebase init functions. When you do this, I highly recommend using TypeScript because it does all the setup for you and will help you catch silly errors before they end up in production. There's a few things we can do to improve the performance of a cold start on a cloud function and also reduce the CPU time that we're actually billed for. Try to minimize the number of dependencies that you use in your functions. More code to load and parse means a slower cold start time. If you have values that can be shared between multiple function invocations, you can set them up as global variables. When a function instance spins up in the cloud, it might be used multiple times, so global variables can be used across multiple calls improving performance. When you design your Cloud Functions, they should always be item potent. Cloud Functions are guaranteed to be invoked at least once, But they can be retried multiple times, so you wanna make sure that multiple calls to the same function produces the same result. And you can use the context event ID to help you achieve that. If you need to add more horsepower to a function, you can use run with to max out the memory at 2 gigabytes and the time out seconds to 540. Now one thing you want to be really careful not to do is to create an infinite loop. You might accidentally do this in Firestore by updating the same document that triggered the event. In this example, we have an on write function that updates the same document that triggered the write. So this will cause an infinite loop that will charge up your Firebase bill until you hit the quota limits. It's not a good thing to do. However, there are use cases when you might want the triggering function to update the same document. You can avoid the infinite loop by checking if The after document is equal to the before document. This will check for equality on the document path and its data, and that will stop the loop assuming your function is idempotent. Background cloud functions must always return a promise. You can ensure that always happens by using the async keyword in the function callback, Then you can use the await keyword for a much cleaner synchronous looking code. Sometimes you might need a cloud function that communicates with other cloud functions or other GCP services. You could use an HTTP function to handle that, but you would also need to implement some code to validate the request. A better alternative would be to set up a pubsub function. It allows you to pass messages between your internal services, and that's easier and more secure than exposing an HTTP endpoint. You might also have endpoints that should only accessed by authenticated users. In a regular HTTP function, you would need to extract the authorization header that you set in your front end code and then verify the ID token. As an alternative, you can simplify both your back end and front end code by using callable functions. It includes the auth context for the user, so you don't have to implement your own middleware to authenticate your functions. A great use case is to delete an entire Firestore collection, which Should always be done on the back end because there might be tons of documents in a collection. We can first authorize the operation by looking at the user ID. Then we'll create a recursive function called batch delete. It retrieves documents in batches of 100 and then deletes them. This will ensure that we don't hit memory issues if we try to query millions of documents in a single go. Now when implementing the actual logic for your back end code, consider breaking it down into small JavaScript functions. This allows you to reuse code across multiple Deploy Cloud Functions, and it's also just easier to test. Keep in mind that Cloud Functions provide a gateway to interact with other third party APIs. Almost every good API also has a good Node JS library to go with it. So, basically, anything you can build in Node JS, you can build in a Cloud Function. When you're ready to go live, you can deploy all of your functions from the command line with a single command. But on larger projects with dozens of functions, you may not want to deploy everything all at once. You can append the name of the function to the end of this command to deploy a single function. Despite your best efforts, your functions will very likely have some bugs. The best way to prevent bugs is to run the Cloud Functions shell locally. You can invoke your functions with mock data to test their behavior, and Firebase even provides a unit testing library. Now your function still might break in production, so you can always look at the Firebase logs to see what's going wrong. Or better yet, head over to Stackdriver where you can create your own custom dashboards boards and alerts for the things that you care about. Earlier in the video, we set up analytics in our front end code. But to get the most out of it, we'll want to track custom events and user properties. Try to pinpoint the events or user behaviors that you think are most important to turning that user into a paying customer, then use Firebase Analytics to record those events. Firebase will aggregate some of the data automatically, but you can create your own audiences based on the type of user that you want to target. Your marketing team will love audiences because you can target messaging to a specific type of user and also do things like AB testing and funnels. And as a developer, You can actually use audiences to customize the UI based on your underlying analytics data. The service will send key value pairs down to to your front end application, which you can use to conditionally show UI based on where that user is located, what audience they belong to, and so on. You can also use the same data to send push notifications to your users using Firebase Cloud Messaging. Instead of sending a bulk notification out to all of your users, Segment it to the users who actually want it and will benefit from it. And with that, we have finally reached Firebase tip number 100. Leverage machine learning within your app. You can do this in multiple ways with Firebase. Use predictions to guess when a user is going to buy your product, use ML Kit to implement AI driven features out of the box, Things like object detection and smart reply, or build your own image classification models with AutoML. And you can even export all of your analytics and Firestore data to BigQuery and use that raw data to train your own TensorFlow models from scratch. And that is all of the Firebase tips that exist in the world. If you have your own additional tips, Leave them in the comments below, and I'll pick a couple of the best ones to win a t shirt later this week. I'm gonna go ahead and wrap things up there. Hopefully, you found something useful in here. Thanks for watching, and I will talk to you soon.
The speakers discuss how to build successful reminded user experiences and optimize data collection and query in real time using cloud solutions and emoji characters in code. They also explain how to set up server to back up a database and set rules before deploying to production apps. The importance of proper security and the use of a subitor for data management is emphasized. The speakers also recommend setting up a server to back up a database and using Cloud function variables and async keywords for machine learning and AI-driven features.

        [INST]
        You are youtuber called Fireship you make engaging high-intensity and entertaining coding tutorials and tech news. 
        you covers a wide range of topics relevant to programmers, aiming to help them learn and improve their skills quickly.
        
        Given the title of the video : 100 Firebase Tips, Tricks, and Screw-ups 
        and a small summary : The speakers discuss how to build successful reminded user experiences and optimize data collection and query in real time using cloud solutions and emoji characters in code. They also explain how to set up server to back up a database and set rules before deploying to production apps. The importance of proper security and the use of a subitor for data management is emphasized. The speakers also recommend setting up a server to back up a database and using Cloud function variables and async keywords for machine learning and AI-driven features.
        [/INST]
        
        Generate the video : Welcome to my top 10 Firebase tips. Welcome to my top 25 Firebase tips. Nope. Welcome to my top 100 Firebase tips. I've been working with Firebase for several years now. I've made plenty of mistakes along the way, but I've also uncovered some secrets that you may not know about. So hopefully this video makes your experience with Firebase 100 times easier. If you're new here, like and subscribe. And if you're serious about building an app of Firebase, consider becoming a pro member at Fireship I tip. You'll get access to full project courses and a free t shirt if you sign up for life. Or you can get a free t shirt by leaving the best Firebase tip in the comments below. The first thing you'll need is a Firebase project. If you're building a serious app, create 2 Firebase projects, one for development and one for production. This gives you a sandbox for testing and Experimenting, and you can keep your customer data pristine in the production project. In your production project, link Google Analytics. Firebase can automatically set up analytics for iOS, Android, and the web. If you're working with a team, head over to the settings tab and then go to users and permissions. Assign roles based on the principle of least privilege, so team members only have access to the resources that they actually need. From there, head over to the data privacy tab and update your contact information to ensure you're in compliance with GDPR. Now click the button to add a new app to your Firebase project. When you do that, it will give you an object with a bunch of credentials. Don't worry. These are perfectly safe in your front end code as long as you set up security rules, which we'll look at later. Upgrade your Firebase plan to Blaze. It's pay as you go, but you still get all of the free stuff that you would on the Spark tier. But you still want to stay on top of cost, so head over to the GCP console and set up a budget alert for your project. Then monitor your monthly usage from the reports panel. This will tell you Exactly which services are costing you the most money. Make sure to install the Firebase command line tools globally on your system and also the Google Cloud SDK. A Firebase project is actually just a layer on top of a Google Cloud Platform project. Once you've done this, you should have access to the Firebase command and the gcloud command on your local system. So now that we have a project set up, let's look at how we can actually deploy our code to this project. If you're building an iOS or Android app, use Firebase app distribution to distribute your app to testers. This will bypass TestFlight and the Google Play Store, making your life much easier. Now if you're building a web application, you're likely using a package manager like npm. Install Firebase tools into the development environment for that project. And now you can write npm scripts that use the Firebase CLI tools. Now if you followed my earlier advice to set up different projects for development and production, you can use the project flag to set up different commands that specify the project. So here we have a command to deploy to our development project and another for our production project. Now after you've deployed your site, head over to the Firebase console, and you can see it's deployed at a cool domain called your project dot web dot app, or you can just connect your own custom domain. And you're not limited to a single domain. For example, you might have an admin site and a customer facing site. They can both share the same Firebase project with multisite hosting. Then go into your Firebase JSON file, change the hosting value to an array, and set up different targets that represent the different sites you want to deploy. Now you're not just limited to static files when deploying to hosting. You can actually rewrite traffic to a Cloud Function or to a Cloud Run instance. And that means you can do SSR with something like Angular Universal or Next. Js. You can also set up Firebase hosting rewrites for dynamic links. This allows you to dynamically send the user to the app with the best possible experience. So if the user goes to a link on their iPhone, it will take them to a specific screen in the iPhone app. You can also specify headers on the static files in your hosting account. For example, if we wanted to change the core settings for all of the font files, we could do it like this. And Firebase Hosting will also cache our static files for better performance, but we can change the caching behavior by setting different cache headers here as well. And one cool thing you might do to extend Firebase Hosting is to set it up with Google Cloud Build. So every git commit you make to your project, it will deploy a new version of your site to your hosting account. That's exactly what I do for Fireship IO. Firebase provides 2 different fully managed NoSQL databases. So how do you know which one to choose? I default to Cloud Firestore because it has more powerful query capabilities. It also costs less per gigabyte stored. However, real time database does not charge for rights, So it can be a great option if you have data that's updated frequently like an IoT sensor or something along those lines. But when it comes to pricing, you really shouldn't worry about it too much. Don't even trip, dawg. Firebase overall is very inexpensive, and it will take a decent number of monthly active users before you even break out of the free tier. Unless you make a silly mistake, you'll be paying much less than you would be with other cloud solutions. A more important thing to worry about is that you back up your data on a regular basis. Set up a dedicated cloud storage bucket for backups, and then you can back up your entire database with a single command. When you create your based for the first time, set it in locked mode. It's safer to start with a locked down database than incrementally allow operations as they become necessary. After you've created a Firestore collection, go ahead and click the filter icon, and you'll see that you can make queries directly from the Firebase console. And it even provides some code for your query that you can copy and paste to using your app source code. In fact, let's go ahead and switch gears and jump into the source code for a JavaScript application. Now the way you import Firebase depends on the flavor of JavaScript you're using. You can see the import syntax here for CommonJS, ES 6, and TypeScript. But all of these are actually wrong because they're importing from Firebase directly. Your code will work, but it will create a huge JavaScript bundle that will slow down your app. The correct way to use Firebase is to import from the Firebase app namespace and then import these services that you plan on using, aka progressive enhancement. In any case, Firebase is a pretty big dependency. So if you're loading it with a script tag, You'll wanna use the defer keyword on that script to ensure it loads after the actual DOM or HTML has been parsed. But if you're using a framework, then you shouldn't have to worry about this. Angular app should use AngularFire, which integrates with change detection and the Angular router. If you use React on the front end, the ReactFire library was just undeprecated, and it provides support for hooks and suspense. You have RXFire to integrate with RxJS, which works great in frameworks like Svelte. Then outside of the web, you have support for all kinds of different other frameworks in Firebase extended like Flutter, Arduino, and many others. When you first add Firebase to a project, there's a couple of no brainer services that you'll definitely wanna use, such as performance monitoring. With a single line of code, we can see how well our app performs out in the wild, giving us metrics like first contentful paint across all devices using our app. The next one is Crashlytics, which is only relevant to native mobile apps. It's very easy to set up, and it will give you error reporting and crash reporting throughout your entire application and automatically open issues so you can address those problems. And lastly, we have Firebase Analytics. With a single line of code, we'll get the default reporting from Google Analytics, giving us insight about the behavior of our users. Now in your source code, one of the first things you'll likely wanna do is determine if a user is logged in or not. There are 2 main ways to do this. You can pull the current user at any time by calling auth current user. This is usually best for handling events, like when the user clicks a button and then you want to grab their auth record and do something afterwards. The other way to get the current user is to always be listening to the current auth state. In this case, you provide a callback function to listen to changes to the auth state, like when the user signs in or signs out. In either case, I recommend getting good at asynchronous JavaScript to be test with Firebase. Understanding async await is very useful for the first approach, then understanding callbacks and functional programming is very useful for the second approach. When a user attempts to log in, something might go wrong. It might be your fault as the developer or the user's fault. In any case, you'll want to make sure that you catch these and then create a default handler that routes them to a visual UI element like a dialogue. A cool trick you can do with Firebase auth is to register a user lazily. For example, you might first have a user sign in anonymously, which will give you a user ID that you can tie to the database. Then later in the onboarding process, you can collect their email or link social accounts like Twitter, Facebook, Google, etcetera. Now certain authentication methods like email password may need to send emails to your users for things like email verification and resetting passwords. Sometimes you might want to control this process on your own, which you can do with custom email action handlers, And you can even bring your own custom SMTP email server. Now one of the most important aspects of any application is managing relational data. Let's check out a few common techniques for connecting our users to the Firestore database. We can create a one to one relationship where the user has one document in Fire store by first retrieving their user ID, then we'll make a reference to a collection and set the document ID as the user ID. Every user ID is unique, So it guarantees that that user can only have one document in that collection. Now if it's possible that data already exists there, you might want to use the merge true option. This will ensure that any data that already exists there won't be overwritten. The merge true option just makes it a nondestructive update. Another common relationship is one to many. A user might have many orders, but an order belongs to one user. The best way to handle this type of relationship is to use a subcollection. In the last example, we created a document with a user ID, and we know that every subcollection under that document is owned by that user. But sometimes you might run into a situation where you want to query orders across all the users in your database. Firebase provides a special method that allows you to group subcollections and query them together. Collection group will find all of the collections that share the name orders, group them together, allowing you to make a single query against all of them. And another very common relationship is many to many. In this case, we have a single collection called chats, and each chat document can be associated with multiple users. We can associate multiple users to multiple chats by embedding their user IDs on the chat document using a map of key value pairs. The key is the user ID, and then I'm going to duplicate the display name in case we want to show that in the UI. Data duplication is perfectly okay in NoSQL. It can optimize for performance and costs, but it works best with values that are immutable or that don't need to be updated very often. And now that we have a map object on this document where each key in that map is a user ID. We can query it by using dot notation in our queries, like order by members dot user ID. Now that we've modeled some data and made some queries, we need to decide if we want our data in real time format or not. If you're trying to optimize pricing and don't think you'll need real time updates For your data, you can just call query git to retrieve the data once and then not listen to any future updates. But if you are building a feature where the UI should react To change this in real time, you'll want to use query on snapshot, then run a callback function anytime the underlying data changes. On a collection query, when you listen to docs, You'll get a new array anytime there's a change to the underlying data, but you might want to know exactly which documents were added, modified, or removed. Doc changes provides an array of all the documents that changed, their old index, new index, and the change type. Another awesome thing about Firestore is that it's able to work offline. If the Internet goes out and the user's still trying to send rights to the database, Firestore will still update the UI and then send those rights to the actual database and commit them after the Internet comes back online. And you can even make this work across multiple browser tabs by setting the synchronized tabs option to true. Now one question I get a lot is how do I use emoji characters in my code? Well, they're actually just u t f eight characters, which means you can use them in a regular string. And that also means that you can use them in your Firestore documents and make queries against them. Another trick you might wanna use is to match a wildcard string. For example, if we wanted to query all of the Fast and the Furious movie titles. Create a starting point and then make your ending point a tilde character. This will match all the documents that start with the Fast and the Furious title. And with that, we have reached the halfway mark. Let's take a quick break. Welcome back. Sometimes you might have a compound query where you chain together multiple query conditions. This query won't work by default because it requires an index, but don't create the index manually. Let your app throw an error, then click the link to the Firestore console to create the index automatically. One of the most powerful data types in Firestore is a list. We can add a list to a document by simply setting it with a JavaScript array. But we might decide later that any good Firebase recipe needs to include a pineapple. We can use the Firestore array union method to ensure that the array includes exactly 1 pineapple. Or we might decide later on that maybe squid wasn't such a good idea in this recipe, so we can remove it by using the array remove method without having to know the actual index. And now that we have an array on the document, we can query it by using the array contains operator inside of where, and that will give us all of the recipes that contain avocado. Now sometimes you might have an array that contains IDs of other documents in the database. But how do you actually fetch the full documents in this array? Do it in JavaScript by mapping all of the ID strings to an array of promises that get the document, then run them together with promise dot all. One thing you should generally avoid doing is setting a time stamp from your front end code because the user's clock might not be synchronized properly. If you need to set a time stamp on a document, use the Firestore server time stamp. That ensures that all users are sharing the same clock. Another thing you might wanna do is increment a counter, like the score of the game. You can change the value of the counter atomically without knowing its current value by using the increment field value. Now Firestore only supports 1 write per document per second, although you can burst above that value. So if you have a ton of writes happening on a single document, You can set up a distributed counter, which is now very easy to do because there is a Firebase extension that supports it. And speaking of atomic, Sometimes you might have rights that need to succeed or fail together. Maybe the user completes the game, you write the score, and then you want to update the user's lifetime score. You can ensure that these operations happen together by setting up a batch write. This will commit them together, but roll back to the previous state if any of the writes fail. Now Firestore is a great solution for the vast majority of use cases, but sometimes you might need a full relational database. If you need a full relational database, Check out my video on integrating MySQL into a Firebase project. Or if you need full text search, check out my Algolia integration video. Now one of the most important things to do as a Firebase developer is set rules before you deploy to production. If you deploy an app without good security rules in place, your customer's data could be compromised, and someone could make destructive rights to your database. Currently, our database is in lock mode, which means we're safe. But now let's go ahead and open up some operations for our users. The first thing you should do is get used to using the simulator. It allows you to pass mock requests to the database to see how the rules will be evaluated, But serious production apps should use the Firestore emulator. This allows you to simulate the Firestore database in your local development environment, You can throw a whole bunch of different test cases at your rules to ensure that they're robust. Note that there are 5 different types of operations a user can make on a document. They can get a single document, a query of a list of documents, and they can create, update, and delete documents. You can provide fine grained rules for each operation, or you can combine Then by using the read or write keywords. If they share the same logic, just separate them with a comma. When a rule is evaluated, there are 2 things that you'll look at, the request and the resource. The request contains the user's authentication state as well as the incoming data that they're trying to write to the database. The resource, On the other hand, is the data that already exists at this path in the database. But in some cases, you might need to look elsewhere in the database to determine if a rule should be allowed. Use the get keyword and then point to a path in the database, and you can use dollar sign parenthesis to interpolate values like the request auth user ID. This gives you the value from this document, but keep in mind that you're charged a read every time this rule is evaluated. Now you might notice That this is a very long line of code, and if we were using this frequently throughout the rules, we wouldn't want to have to repeat it all the time. We can extract this logic into its own function called is admin, And now we have a much cleaner way to check for admin users. Now let's switch gears to cloud storage. A storage bucket is where you would put things like images, videos, and raw files. You have a default bucket, which is where you would normally save your user generated content, but you can create additional buckets as well. You might want an additional bucket for Firestore backups, which you can set to coldline, which will save you some money. Now when you upload a file to a storage bucket, there is a storage location and a download URL. If the user needs to access this file again in the future, I recommend saving both values to the Firestore database. You can use the storage location to replace or delete the file in the future or the download URL to access the file in your app. But don't worry too much if you forgot to save the file path in the database because you can use the storage ref from URL and point to either the full path in the storage bucket or to the download URL to access that file. Sometimes you might want to list out all the files in a directory in the bucket. Simply make a reference to the path to the directory, and then use the list all method to get all the files at that location. You can upload a file by simply making a reference to a file path and then putting the raw file that you want to upload. You can calculate the progress of an upload by listening to the state changed event, then divide the bytes transferred by the total bytes in the file. If you have multiple files to upload, feel free to upload them all at the same time. Firebase will automatically handle concurrency and upload them as efficiently as possible. When you upload files, you might also want to save your own custom metadata about that file. You might want to know what kind of device the user upload the file from, their user ID, and stuff like that. If your users can upload image files, there's a good chance that you'll want to resize them to different resolutions for different devices. You can now do that with a click of button using the Firebase image resizer extension. At this point, we've been mostly looking at front end code, so now I want to switch gears to the back tip. You can create your own command line utility for Firebase with 3 easy steps. Go to your project settings and download the service account for your project. In a node project, install Firebase Admin as a development dependency, then create a JS file that imports it and calls initialize app. Firebase admin needs your service account, but it contains sensitive information. The safest way to use it locally is to keep it somewhere private on your system, and then use an environment variable called Google application credentials. But if you include the service account directly in your source code, make sure it's in your git ignore so it doesn't end up in a public repo somewhere. One of my favorite things to do with an admin script is to seed the database with some dummy data. Install Faker JS and then import it into your JavaScript file. Then create a loop, and for each iteration, add a new document to the collection using Faker to automatically generate the dummy data. Now run the script from the command line with node. You should now see a bunch of dummy documents seeded in your database. Now you can do a lot with the Firebase Admin SDK, but you can do even more with the rest APIs. Check out the rest API documentation to find secret techniques that you didn't know about. Earlier, I showed you how to back up Firestore from the command line, but you can also do it with the rest API. This would allow you to set up a cron job to back up your database on a daily basis. If you do use the REST API, you'll want to use the Google APIs NPM package. This allows you to discover and interact with hundreds of different Google APIs, like AdWords, YouTube, and, of course, Firebase. Creating an admin script can be useful, but in most cases, you'll be with Firebase Admin in a Cloud Function. You can add Cloud Functions to your project by running Firebase init functions. When you do this, I highly recommend using TypeScript because it does all the setup for you and will help you catch silly errors before they end up in production. There's a few things we can do to improve the performance of a cold start on a cloud function and also reduce the CPU time that we're actually billed for. Try to minimize the number of dependencies that you use in your functions. More code to load and parse means a slower cold start time. If you have values that can be shared between multiple function invocations, you can set them up as global variables. When a function instance spins up in the cloud, it might be used multiple times, so global variables can be used across multiple calls improving performance. When you design your Cloud Functions, they should always be item potent. Cloud Functions are guaranteed to be invoked at least once, But they can be retried multiple times, so you wanna make sure that multiple calls to the same function produces the same result. And you can use the context event ID to help you achieve that. If you need to add more horsepower to a function, you can use run with to max out the memory at 2 gigabytes and the time out seconds to 540. Now one thing you want to be really careful not to do is to create an infinite loop. You might accidentally do this in Firestore by updating the same document that triggered the event. In this example, we have an on write function that updates the same document that triggered the write. So this will cause an infinite loop that will charge up your Firebase bill until you hit the quota limits. It's not a good thing to do. However, there are use cases when you might want the triggering function to update the same document. You can avoid the infinite loop by checking if The after document is equal to the before document. This will check for equality on the document path and its data, and that will stop the loop assuming your function is idempotent. Background cloud functions must always return a promise. You can ensure that always happens by using the async keyword in the function callback, Then you can use the await keyword for a much cleaner synchronous looking code. Sometimes you might need a cloud function that communicates with other cloud functions or other GCP services. You could use an HTTP function to handle that, but you would also need to implement some code to validate the request. A better alternative would be to set up a pubsub function. It allows you to pass messages between your internal services, and that's easier and more secure than exposing an HTTP endpoint. You might also have endpoints that should only accessed by authenticated users. In a regular HTTP function, you would need to extract the authorization header that you set in your front end code and then verify the ID token. As an alternative, you can simplify both your back end and front end code by using callable functions. It includes the auth context for the user, so you don't have to implement your own middleware to authenticate your functions. A great use case is to delete an entire Firestore collection, which Should always be done on the back end because there might be tons of documents in a collection. We can first authorize the operation by looking at the user ID. Then we'll create a recursive function called batch delete. It retrieves documents in batches of 100 and then deletes them. This will ensure that we don't hit memory issues if we try to query millions of documents in a single go. Now when implementing the actual logic for your back end code, consider breaking it down into small JavaScript functions. This allows you to reuse code across multiple Deploy Cloud Functions, and it's also just easier to test. Keep in mind that Cloud Functions provide a gateway to interact with other third party APIs. Almost every good API also has a good Node JS library to go with it. So, basically, anything you can build in Node JS, you can build in a Cloud Function. When you're ready to go live, you can deploy all of your functions from the command line with a single command. But on larger projects with dozens of functions, you may not want to deploy everything all at once. You can append the name of the function to the end of this command to deploy a single function. Despite your best efforts, your functions will very likely have some bugs. The best way to prevent bugs is to run the Cloud Functions shell locally. You can invoke your functions with mock data to test their behavior, and Firebase even provides a unit testing library. Now your function still might break in production, so you can always look at the Firebase logs to see what's going wrong. Or better yet, head over to Stackdriver where you can create your own custom dashboards boards and alerts for the things that you care about. Earlier in the video, we set up analytics in our front end code. But to get the most out of it, we'll want to track custom events and user properties. Try to pinpoint the events or user behaviors that you think are most important to turning that user into a paying customer, then use Firebase Analytics to record those events. Firebase will aggregate some of the data automatically, but you can create your own audiences based on the type of user that you want to target. Your marketing team will love audiences because you can target messaging to a specific type of user and also do things like AB testing and funnels. And as a developer, You can actually use audiences to customize the UI based on your underlying analytics data. The service will send key value pairs down to to your front end application, which you can use to conditionally show UI based on where that user is located, what audience they belong to, and so on. You can also use the same data to send push notifications to your users using Firebase Cloud Messaging. Instead of sending a bulk notification out to all of your users, Segment it to the users who actually want it and will benefit from it. And with that, we have finally reached Firebase tip number 100. Leverage machine learning within your app. You can do this in multiple ways with Firebase. Use predictions to guess when a user is going to buy your product, use ML Kit to implement AI driven features out of the box, Things like object detection and smart reply, or build your own image classification models with AutoML. And you can even export all of your analytics and Firestore data to BigQuery and use that raw data to train your own TensorFlow models from scratch. And that is all of the Firebase tips that exist in the world. If you have your own additional tips, Leave them in the comments below, and I'll pick a couple of the best ones to win a t shirt later this week. I'm gonna go ahead and wrap things up there. Hopefully, you found something useful in here. Thanks for watching, and I will talk to you soon.
        