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.