DAVID EAST: I'm
going to show you how to get started
with Firebase Hosting and how to set it up
with GitHub Actions so you can generate a preview
channel for every single pull request. Firebase Hosting allows you
to deploy static websites and server code to a blazing
fast global infrastructure. All you need is a computer with
Node.js and Java downloaded. But if you don't have
those, don't worry. Just check the links
in the description. But, for now, let's dive in. Here in my editor, I have a
very simple folder structure for my simple website,
which is made with Next.js. If you're not
familiar with Next.js, it's a tool for building
sites with React. Now, I'm going to take
this site and deploy it to Firebase Hosting. On the command line, I'm going
to install the Firebase CLI. Now, you might see
a lot of people out there install it globally
with the -g flag like this. And this is fine, depending
on your situation and setup. But I'm going to do it locally,
which means NPM will download the CLI within the
node_modules folder, and I can use it by tapping
into node_modules/.bin/firebase. This is more verbose, but you
will avoid any sudo permission issues. Once it's downloaded, the
first thing you need to do is log in with your Firebase
account using firebase login. This will take you out
to the browser to log in. And once you're done, you'll
come back to the terminal. Quick tip, though. If you're managing
multiple accounts, check out firebase login:add and
provide an email to add another account, and also Firebase
login:use with that email to switch between accounts. Now run
node_modules/.bin/firebase init hosting. This is going to take
us through a wizard and ask us a few questions. First, you need a project. You can create one
here in the terminal or you can go out to
the Firebase Console. I have one already so I'm
just going to type it in. Now it's going to ask for
your public directory. The files inside
the public directory is what Firebase hosting
deploys as your site. In this case, Next.js
will build my site and export it to a
folder named out. Now you get to decide
whether you're configuring it as a single-page app. So if you're building a SPA
with Angular, React, or Vue, or something like that,
you want to say yes. But since this is a
static, generated site, I'm going to say no. Now, for this step, for setting
up automatic builds and deploys with GitHub, I'm going to say no
because we're going to set that up in just a minute. And, just like that, our initial
configuration is complete. Before I deploy the site, I
want to be able to set it up to serve locally. And I can do that with the
Firebase Emulator Suite, which allows you to run several
different Firebase services locally or
in CI/CD environments. Run node_modules/.bin/firebase
init emulators. Right now, we're just
going to select hosting. And I'll use port
5033 because I like to avoid common port numbers. And I'll use the
defaults for the rest. Now, a lot of modern website
tooling, like Next.js, requires a build step to
take from something like JSX and turn that into HTML and CSS. If you go into
package.json, you can see that there is
an NPM script called Build which will run
Next.js's build command and then its export to
generate it as a static site. I'm going to run this before
I serve the site locally and deploy. Now to run locally, run
firebase emulator start and open your browser up to the port. And, just like that, we have
our site running locally. So I feel good about it. It's time to deploy. Run node_modules/.bin/firebase
deploy. And, as a side note,
you can provide a flag of --only hosting to
make sure you deploy only for Firebase Hosting, because
the Firebase CLI can deploy a lot of other things, as
well, such as Cloud Functions and security roles. Once the deployment
is successful, you can access the site at
your project ID .web.app. And, just like that, we have
our site running in production with an SSL cert. So let's take a second
and dive into the details. How does Firebase Hosting know
what project to deploy to? And what if you wanted to
tailor your server configuration to do custom things like add
headers or set up redirects? Well, all of that is
managed in two files, .firebaserc and firebase.json. For the most part, .firebaserc
is managed with Firebase CLI so don't worry
too much about it. Just know that it
contains the projects that your site can deploy to. Now firebase.json contains
server configuration capabilities that
you should know. You can set custom redirects
so when a request comes in at one source, you redirect
it to a new destination. And you can set the type,
which is an HTTP 301 or a 302, so either temporary
or permanent. And this is really
helpful if you need to redirect
a user to content that's located on a new path. You can add custom headers
for one or multiple paths. Let's say you were hosting
API data from a JSON endpoint. If you want to set the data to
allow requests from any origin, you can set the
Access-Control-Allow-Origin header to *. This is lovingly known as
Cross-Origin Resource Sharing, or CORS. Now I'm going to move on to
one of my favorite features, preview channels. It's great that we
can deploy this site, but it's really
important to have a place where we can stage
new changes before going to production. So Firebase Hosting has a
feature called preview channels where you can deploy
a version of your site to a generated, short-lived URL. And preview channels work really
great in a GitHub workflow. You can set up a
GitHub Action that will deploy a preview channel
for every single pull request. And the Firebase CLI will
generate the entire workflow for you. Before I get into the
GitHub Action workflow, I want to show you
how you can manually deploy to a preview channel. Run on the command line
node_modules/.bin/firebase hosting:channel:deploy
and provide an ID. You can also provide
a flag to customize how long the preview channel
will live for with --expires. This is going to
deploy everything in my public folder,
which is named out, to a generated URL that
will live for two days. You can see right
here that we have what the ID was-- in my case,
stage-- and then a generated set of characters and numbers. And let's open this
in the browser. So this is the same
site as we had before, but it now lives at its own
generated, short-lived URL. If you want to delete the
preview channel before it expires, you can list all of
your active preview channels with hosting:channel:list,
and this will tell you all of the channel IDs, latest
release times, their URL, and their expire time. So you can see that a live
channel never expires. To delete the channel, run
hosting:channel:delete with the channel ID. So in this case, I'll
run it with stage. And make sure you
confirm yes to delete. All right, now that you know
the basics of preview channel commands, let's set up preview
channels with GitHub Actions. The first thing you're going to
need is a repository in GitHub. Right here, I just have a
brand new repository I created. And I'm going to need to set
it up with my current project. So I'm going to add the
remote and set my main branch so I can push it to GitHub. So here in the
terminal, I'm just going to paste in that
command from GitHub. And I'm also going to
set up my main branch. The goal is that I
want to be able to push a pull request per branch. So in this case, next will get
pushed up to GitHub, compared against main, and every
time that happens, it will generate a preview
channel per pull request. So, first, I need to
check out main and push up my current changes to GitHub. So here in GitHub, I
have my main branch pushed up with just
my basic website files, but none of my Firebase
hosting configuration. I'm going to add that
via a pull request by pushing a new
branch up to GitHub. And that will kick
off a GitHub Action that will generate
a preview channel. So here in the
terminal, I'm going to check out my next
branch, which will be the basis of the pull request. And then I'm going
to see the modified files by running git status. And we can see that my
firebase.json and my RC have not been added. So I'll run git add
and a commit message. To set up preview channels
with GitHub actions, run firebase init
hosting:github. Just like before, this is
going to open up a wizard. It first will log
you in with GitHub. That will require you to go out
to a URL and then come back. And then you provide
the GitHub repository that you want to set
up the workflow for. This follows a
user/repository name format. Behind the scenes, this is going
to go out, download a service account, and upload it
to GitHub's secret store and so GitHub Actions can
deploy on your behalf. Now, this is a
very important bit. It's going to ask me if it
wants to run a build script on the workflow. And, for me, that answer is yes. Just like I showed
before, in package.json, I have a build command
that runs Next's build and Next's export in order
to generate my static site. So every single time I have
a GitHub Action that runs, I want it to run this build
command before deploying. So I'm going to mark yes. At this point, we're
going to provide, what is the build script? The default is to run npm ci
and then npm run build. npm ci is very similar to
running npm install, but it is optimized for
continuous integration environments, such
as GitHub Actions. And then after it
runs npm ci, it's going to run my build
command, and that will generate out my site. This works for my workflow,
but make sure to check your own so it works for yours. The next question
asks if you want to set up a deployment
to the live channel when a PR is merged. And this is saying,
I've accepted the PR and I want to deploy to my live
channel, which, in most cases, is the production site. I'm going to say yes. And, lastly, it's
going to ask me, what is the name of the
GitHub branch associated with your live channel? For most cases, this is
going to be the main branch, because main is the source
of truth for most GitHub repositories. And your production
or live channel will be associated with that. This is going to create
a .github folder with two workflow YAML files in it,
one for when a merge happens to the main branch and
one on a pull request. You don't have to
edit any of these. These are all generated by us. All you need to do at this
point is just check them in. Over on the command
line, I'm going to run git status to see
our modified folders. And only .github, so I'm going
to add that and run a commit message. And then I'm going to
push this branch up to GitHub by supplying
the -u for upstream, the origin, and then
the name of the branch. Over in GitHub,
it's going to let us know that we have a
new branch in which we can create a pull request off of. So I'm going to give that a name
and then click the Create pull request button. At this point,
it's going to start running checks, which sometimes
take just a second to show up. And it's going to start
with this yellow circle, letting you know that the checks
haven't been completed yet. But if you want to
see what's going on, you can click this Details
link and it will take you over to the GitHub Actions
section, where you can watch the action run. It's going to run
through all these steps. And once it's done,
it will deploy it to the preview channel
and we can see that by going back to
the pull request. And we have a comment
from the GitHub Actions bot with our generated URL. If you go to that
link, you'll just see that it's the same site
we were running in production and the same site
we're running locally, but now it's just running on
the generated preview channel. And, by default, it will
expire in seven days. Now, back in GitHub, I'm going
to merge this pull request. And, once that's done,
I can delete the branch but go back to the
main page for the repo. And if we look up
here, we can see there's this little yellow dot. And that means that the
merge action is running. So we merge the pull
request into main, and that's going to deploy
out to our live channel. And, just like before, we
can check out all the steps as it runs. Once it's done, it's going to be
available on the live channel, which, again, is your
project ID .web.app. So that's how you get started
with Firebase Hosting. And stay tuned,
because I'm going to be covering a full
beginner to advanced course on Firebase Hosting soon that
covers advanced firebase.json configurations, setting up
JavaScript framework builds, and also doing server backends
with Cloud Functions and Cloud Run. Leave a comment if you
have any questions, and let us know what
tools or frameworks that you're using
with Firebase Hosting. So that's all for today and
I will see you next time.