Hey! I'm back here with another tutorial/guide. Today, we'll be looking at Serverless.
An intro to serverless
What is serverless?
Serverless is where you don't have a backend. Yes, that's right. You only code the frontend, and use SaaS (Software as a Service) and BaaS (Backend as a Service) for the backend. An example of SaaS is Firebase. We'll be using it in this tutorial.
Should I go serverless?
I don't like serverless. I like to have control over my backend, my database and my users, but for some people, it is amazing, because you don't need a backend developer. Since the backend is already made for you, you just need to make the frontend.
What are the advantages of serverless?
There are many advantages to serverless. First of all, there is less code. You don't have to code the backend because it has already been done for you. Second, serverless scales well. Most, if not all of these SaaSes have a generous free tier which you can then upgrade to one of their paid plans if your software grows.
Are there any disadvantages?
Yes. Your users and your database are left in the mercy of these companies. This might not be that bad, because they usually have very good security, but this also means that you have very less, if any, control over your users, database, and the backend itself. There is no REST api, or graphql layer usually, and you will have to use the SaaS's SDK. Speaking of SDKs, usually, most services only have first party SDKs for javascript. If you use any other language, like python or c# for web development (like me), you usually have to use a third party library
The app
Now that we're done with the explaining, let's make the applicaiton.
What we'll be building
We'll make a realtime updating chat application using svelte as the frontend framework and firebase as the backend. We'll use Firebase Auth to authenticate users using email/password and Google signin. We'll then be using Firebase Firestore for the database. Firestore also has a special feature that allows us to listen to changes in the database, which we'll use to build the app. Along with serverless, you'll also learn things like routing in svelte and cleansing cuss words. Try out the app here. Please keep it clean!
Creating a svelte app
For the frontend framework, or compiler rather, we'll be using Svelte. It is a very easy to learn framework, and is also rather new, but the main advantage of svelte is that it is small, very small. The final gzipped application will be much smaller in size compared to similar apps in other frameworks.
To create a brand new svelte app,
npx degit sveltejs/template serverless-chat
cd serverless-chat
npm install
I prefer typescript instead of javascript, so I'm gonna convert my svelte app to typescript. You can skip this if you want, but you will have to change the code samples a little.
node scripts/setupTypescript.js
Creating a firebase project
We'll be using firebase as our SaaS/BaaS because firebase has many useful services like authentication, databases and storage, plus, they also integrate with each other, which is crutial. If you decide to use Auth0 instead of firebase auth and Fauna instead of firebase firestore (database), then you will find it harder to connect the two, but since both services are made by the same provider, we should be able to skip that step.
Let's create our firebase project. Head over to the firebase console and sign in/up to firebase using your google account.
Follow these steps to initialise firebase:
Create firebase project
Create firebase app
Configure firebase auth and firebase firestore
Tip: Of course, you can change the name of the project and app to whatever you like.
Saving your firebase config
If you remember, in the second video, I copied the config object firebase provided to me. We need this object, because it will allow us to connect firebase to our svelte app. Create a new file src/firebase_config.ts
or src/firebase_config.js
if you're not using Typescript and enter this in it.
// src/firebase_config.ts
export default {
// your firebase config object here
}
Tip: Remember to add this file to your
.gitignore
and other ignores.Tip: Lost your firebase config? Don't worry, you can get it from the firebase settings.
Connect firebase to svelte
First, we need the firebase sdk. Install it by typing:
npm install firebase
Now, let's create a file that will initialise firebase for us. I'll put it in src/services/firebase.ts
, but you can do it wherever.
// src/services/firebase.ts
import firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import config from "../firebase_config";
firebase.initializeApp(config);
// Auth
export const auth = firebase.auth();
export const googleAuth = new firebase.auth.GoogleAuthProvider();
// Firestore
export const firestore = firebase.firestore();
Coding the app
Let's first make the homepage. We'll be using routing to allow routes like /chat
instead of having everything on one page. To do that, we will need a router. I recommend page.js
, and that's what we'll be using. There are other routers, but I like this one, because it not only works for svelte, but also works for all other apps, even raw HTML!
If you want robust routing, and also other features like SSR, I recommend sapper, the Next.js for svelte!
Let's start by installing page.js:
npm install page
If you're using typescript, you will also need to install types for page.js:
npm install -D @types/page
Initialise the router
Let's clear the contents of App.svelte
. We don't need it. Now, we'll use page.js to route in svelte.
<!-- src/App.svelte -->
<!-- The lang="ts" is there because I'm using typescript -->
<script lang="ts">
import router from "page";
import Index from "./routes/index.svelte";
let page;
let params = {};
router("/", () => page = Index)
router.start();
</script>
<svelte:component this={page} {params} />
You can see how easy it is to setup routing in svelte.
Tip: The
svelte:component
tag is used to render a component dynamically. Thethis
attribute is the component, and any other attribute passed goes to the component. This is how we route in svelte.
Also, we need to make our app SPA compatible, so let's do just that. In package.json
, in the start
script, change it to:
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv public -s --host",
"validate": "svelte-check"
},
Tip: The
--host
option just exposes your server on your network, but the-s
option makes the app SPA compatible.
Styles
We're pro developers here. Nobody's got time for CSS (lmao just kidding). Let's use a CSS library to speed things up. I'm gonna use W3.CSS because it is small and easy to learn. You can download it from here or use a CDN like cdnjs. Modify public/index.html
to include w3.css like so
<!-- public/index.html -->
<!-- in head tag -->
<link rel="stylesheet" href="https://w3schools.com/w3css/4/w3.css" />
<!-- or use your downloaded w3.css (place it in the public directory -->
<link rel="stylesheet" href="/w3.css" />
While we're there in
index.html
, you might want to change the site title.
I'm also gonna include fontawesome for icons.
Auth component
For simplicity, I'm gonna put Login and Register in one component, src/components/Auth.svelte
<!-- src/components/Auth.svelte -->
<script lang="ts">
import {fade} from "svelte/transition"
import ErrorAlert from "./ErrorAlert.svelte";
export let authMode: "login" | "register" = "register";
let isAuthenticated = false;
let err: string | null = null;
function login() {}
function register() {}
function logout() {}
function google() {}
</script>
<div class="w3-card-4" style="width: 40%; margin: 1rem auto">
{#if !isAuthenticated}
<div class="w3-container">
<h2 class="w3-center">{authMode === "login" ? "Login" : "Register"} to Serverless Chat</h2>
</div>
<div class="w3-container">
<div class="w3-bar w3-center w3-border-bottom w3-border-gray w3-text-dark-gray">
<button on:click={() => authMode = "login"} class="w3-bar-item w3-button w3-text-center {authMode === "login" && "w3-blue"}" style="width: 50%">LOGIN</button>
<button on:click={() => authMode = "register"} class="w3-bar-item w3-button w3-text-center {authMode === "register" && "w3-blue"}" style="width: 50%">REGISTER</button>
</div>
<!-- Email login/register forms -->
{#if authMode === "login"}
<form in:fade on:submit|preventDefault={login}>
{#if err}
<ErrorAlert message={err} />
{/if}
<h4>Login</h4>
<p>
<label for="l-email">Email</label>
<input type="email" class="w3-input w3-border" placeholder="Enter your email" id="l-email">
</p>
<p>
<label for="l-password">Password</label>
<input type="password" class="w3-input w3-border" placeholder="Enter your password" id="l-password">
</p>
<p>
<button type="submit" class="w3-button w3-blue">Login</button>
<button on:click={() => authMode = "register"} type="button" class="w3-button w3-light-gray">Register</button>
</p>
</form>
{:else}
<form in:fade on:submit|preventDefault={register}>
{#if err}
<ErrorAlert message={err} />
{/if}
<h4>Register</h4>
<p>
<label for="r-email">Email</label>
<input type="email" class="w3-input w3-border" placeholder="Enter your email" id="r-email">
</p>
<p>
<label for="r-password">Password</label>
<input type="password" class="w3-input w3-border" placeholder="Enter a password" id="r-password">
</p>
<p>
<label for="r-cpassword">Confirm Password</label>
<input type="password" class="w3-input w3-border" placeholder="Re-enter that password" id="r-cpassword">
</p>
<p>
<button type="submit" class="w3-button w3-blue">Register</button>
<button on:click={() => authMode = "login"} type="button" class="w3-button w3-light-gray">Login</button>
</p>
</form>
{/if}
<hr>
<p>
<button class="w3-button w3-blue" style="width: 100%" on:click={google}><i class="fab fa-google"></i> Sign in with Google</button>
</p>
</div>
{:else}
<div class="w3-container">
<h2>Logged in</h2>
</div>
<div class="w3-container">
<p class="w3-large w3-text-green w3-center"><i class="fas fa-check fa-5x"></i></p>
<p class="w3-center">Logged in</p>
<p>
<button class="w3-button w3-blue" style="width: 100%" on:click={logout}>Log out</button>
</p>
</div>
{/if}
</div>
static/components/ErrorAlert.svelte
:
<script lang="ts">
export let message;
</script>
<div class="w3-panel w3-pale-red w3-text-red w3-leftbar w3-border-red">
{message}
</div>
Index page
If you noticed, in App.svelte
, we have a /
route with points to src/routes/index.svelte
. We don't have that yet, so let's make it!
<!-- src/routes/index.svelte -->
<script lang="ts">
import Auth from "../components/Auth.svelte";
</script>
<h1 class="w3-jumbo w3-center">Serverless Chat</h1>
<p class="w3-large w3-center">Please log in</p>
<Auth />
Run the app
Let's run the app:
npm run dev
And if you now visit localhost:5000, you should see a login page with no functionality. We're gonna save that for the next part. Here's the next part!
Top comments (4)
I encountered an error when I used your
services/firebase.ts
template...should be:
according to this:
stackoverflow.com/questions/519181...
...and indeed, your own code:
github.com/arnu515/serverless-chat...
Ah yeah! Thanks! I'm gonna change it
The github code for the above project is available here
The second part is out!