Episode #2: Rapid Side Projects with Cloudflare Workers and Workers Sites
In episode #2, we'll look at options for developing APIs locally with node and mocha to build out more complex side projects.
Hi everybody, my name's Steve Pack, coming to you live here from the Berkeley studios, tastefully decorated to look like a working from home house with an 18 month old, which would be accurate.
Great to have you again. This is episode two of what I hope to be a series of basically using Cloudflare Workers to build side projects.
A few things before we start, I thought I'd just mention, so like at Cloudflare today, basically the whole company is doing sort of bias training and, you know, like a series of workshops put on by Afro flare employee resource group to sort of, you know, help folks get across all the issues that are out there and, you know, what we can do to help sort of level the playing field and make things, you know, better for everyone, both the Cloudflare and in general.
But we all agree that, you know, those folks of us would think scheduled on Cloudflare TV, we need to get out there and do them.
So, you know, happy to be with you here today. But I just wanted to share that that's happening at Cloudflare today.
So at any time you can email in questions, live studio at Cloudflare TV.
We don't have a sort of interactive version yet, but that will come.
Little disclaimer, I don't write code day to day, like, well, every day at Cloudflare as my job.
I don't like write a lot of workers, you know, as part of my role at Cloudflare.
So that's why I'm really framing this as this is me at home feed on the coffee table, hacking away on side projects using workers.
And so take it in that spirit. The product and engineering team have lots of good segments on, you know, on workers.
And, you know, obviously the documentation is the, you know, is the is the real source.
So with that, we're going to look at today's is taking a step further.
So first episode, like I showed you my environment, like we registered a new domain, was converted 10.cf.
We added that to Cloudflare. We created a skeleton Vue.js website, published that to Cloudflare's edge, 200 sites around the world with an easy command and then built a little, you know, client side app that just converted bytes to kilobytes, megabytes, gigabytes, et cetera.
And then we showed how easy it was to deploy and update that.
I then also gave you a little sneak sort of look at a fully featured side project I'd worked on called no time for books.com showing like a more interactive website with API and using storage to sort of show how far you can push workers as a platform that it's not just sort of like a stateless serverless function as a service platform, but you can do a lot more with it.
So I'm going to share my screen and we'll talk a bit about we're going to try get done today.
So we should be sharing this out of the way sharing thing.
So a couple of things we're going to look at. Yeah. So basically I want to want to like move from just a pure client-side app that we did and to look at what it would take to add an API.
So you might remember I did this byte converter doesn't really make sense to have an API for a byte converter.
So it's like what are other interesting conversions that I might want to do?
I'm originally Australian, you know, it's like I said living in California now.
So I sometimes want to look at the, you know, Australian dollar to US exchange rate.
So I'm going to sort of just build my own little converter that does that there are obviously sites to do this, but this is going to be an example of, you know, a front end an API that calls out to some other API and you know, we might might add a bit more to it over time.
But really I guess the focus is just getting started and how I go about building these things be interested to hear, you know, either via questions or you know on Twitter or anything like that of how I'm, you know, other folks do this.
This is not the way this is just a way so let's let's get into it.
Okay, so we have currently just this client-side app and like I said, we're going to we're going to add an API to support this.
So we used a bit of Wrangler last time you might recall and we used it with a shortcut to initialize a project to be a workers site.
There are lots of other templates that come with Wrangler to help you get started.
There's a hello world. There's a rust version. Ah, I hope you can see my shirt from the rust very first rust conference in Portland was cool.
These rust rust is great.
Okay, so we're going to create an API using this router. Template so it's think of it like a node Express router like that's a paradigm.
A lot of folks are familiar with and so that's I think sort of the goal of this router is to provide something sort of familiar, you know, it's it works a bit differently in workers compared to you know to node, but the concepts are the same.
So I've just created that hopefully you can see. See this here on my screen. Just add a bit more.
Zoom there. So prototypical worker, right? You've got this at event listener for a fetch event.
So any request that hits this worker is going to invoke this code.
Um, we'll talk a little in a little bit about how we differentiate between this worker, which is going to be my API versus the the UI that we deployed.
That's using routes, but I'll show you that. So we handle the request and we pass in the request and the handle request creates this router which this template is helpfully pulled in.
So that's the thing that's doing the routing for us.
And you can sort of get a sense here of how it works like based on these It's like wildcard routes.
We're doing different responses or either responding statically or, you know, calling into some other handler, which is this and in this example, it just returns some Jason.
So like we're going to basically take this start adding routes that You know work for our sort of site.
We're going to build so it's probably you could imagine something like forward slash API forward slash FX.
And then, you know, the currency want to see something like that.
Alright, so I like to start like and a lot of what we're going to do today is doing local stuff.
That's how I sort of like to develop but I think it's worth just like at least knowing that we've got like our API deployed.
I find that helpful. So account ID.
We're just going to fill this in. You can get that from there on your From the URL bar.
We're going to call this the converter API 10 API. So I'm going to say this isn't workers dev project.
If you remember from episode one workers dev is sort of you get that like workers dot dev temporary domain, whereas this is actually a real Domain or zone as we call it in Cloudflare.
So we're going to use that to scroll down here can find my Zone ID to put in And then for the route.
I think last week we did it here in the yeah in the in the UI.
Generally, it's better to do these things in in config files right infrastructure is code.
And so What we're gonna do is we want to basically have a route that looks something like this.
So, but we want to this API.
So we just want to match API requests. So something like Converter 10 CF, but I want API.
And so that's going to be the route. And so I think Wrangler is actually just going to do that for us.
You might notice a problem here or might look like a problem that, you know, isn't every request going to hit this and return You know, invoke the worker for the UI.
The answer is, the answer is no. And that's because the most Most specific route wins so forward slash API star is That's interesting.
Ah, I just I just tried to publish the UI again. Yeah, the most the most specific route wins so forward slash API.
Forward slash star will be We'll have a higher order of precedence and converted 10 CF board slash star.
So that's how that works.
I mean, also, depending on how you structure your site like you might want to have a converted 10 CF forward slash UI or something like that.
Multiple ways to skin the cat. Okay, so that's Actually, let's, let's let that finish.
So, um, yeah. Again, we're looking to sort of set up some local stuff here. I'm going to use mocha for tests.
I'm going to show a little bit about how You know, some things don't exist locally that do exist at runtime.
So you might have to mock some things out.
I should also mention there's a tool that ships within Wrangler that's in alpha at the moment called Wrangler dev that does give you a far more realistic dev environment and we'll probably get to that.
In a future episode, I think half hour we have today will probably be limited to just sort of like, you know, purely local things.
But Yeah, let's see. There we go. That's cool. Okay, um, So it looks like Wrangler already automatically created the route for us, which is cool.
So let's just confirm that in the UI. Indeed.
So, and, you know, as associated the worker as well. So, you know, this is sort of starting to show right like, you know, you need to be living in the in the UI, like if you're a sort of a console like command line and, you know, VS code oriented developer, you can definitely do that.
So looking at the code. It looked like If we go to the route, we get a hello worker, you know, depending on where we go, we get these sort of results.
So let's just check that that's sort of happening as we expect.
Do we get anything Resource not found. I get anything Responding for Cool.
Well, the other ones food. So it looks like we get some Jason Yeah, so Pretty quick there.
As you can see, to go from are just like initializing API with this default router project and seeing it live 200 cities around the world high performance reliable all that stuff.
All that good stuff that talked about last episode.
Okay, so we actually want to do something. Um, like I like to do some tests.
So I'm going to create a file folder test. We're going to go in there. And we're gonna I sort of tend to start out.
I'm just sort of having everything in one test file.
And then as it gets bigger to break it out on just means I can sort of get started with something sooner.
And just to speed up this a bit so you don't have to painfully watch me type absolutely everything.
Let me pull in Couple of things to get started and just make sure that you know we've got the very basics.
So I'm going to use the most basic assertion library.
And then let's pull in The right syntax.
Okay, so, um, it's just Just want to make sure that we can get mocha running.
So we're going to write code here. Close all that off. And we're gonna say Okay.
I got that right. No files town tests. So do I have to be in test. Again, right from the root.
Okay, so mocha runs. It's cool. Right now I want to test some actual code.
So the way I tend to structure. My like side projects for API's is sort of with handlers.
Just a pattern in my head. I don't know whether it's from ASP net or no.
They're the things I've used the most over the years. So for this project we're doing We say a like Forex converter.
So let's say we want a Route that something like rates.
And I think probably the more restful sort of thing is like, you know, you do the pair and have something Whatever the syntax is I just know from experience.
That's a bit more work to to pause that. So I'm actually going to do it with query params.
So, Here we're doing handler. We get a request return a response.
So I'm actually going to create a handler. Alright, so I'm going to say And then that handler.
Is how I'm going to Handle The request and we've got the request.
They're being passed, you know, all the way, all the way from the top. So that means so and let's Can Kill some of this.
I'll leave that here just to sort of be a good guide of You know, we might want to do Okay, so I need a handler.
Right. And so you can imagine like that is the sort of thing that we might want to test and we might want to spend some time sort of playing with the API and the, you know, the sort of shape of this before you know we start deploying and dealing with sort of, I guess, like, you know, more integration issues.
So we're going to want to handle a request. And For now, let's say I'm going to return a new response and we had a good example up here of what that could be.
Let's just say Hello. And so this would be the sort of thing Michael want to test.
So let's just start with that.
So this can be our Rate handler. Can say returns response. So go let handler equal new rate handler.
Okay, we don't have it yet. So first thing Like how I like to do this.
Is sort of with a just module that exports of all of the things that I want to test.
So this like this has no like this isn't going to be used by the, you know, the workers runtime.
Whoa. You didn't your keyboard. So I'm going to export Export that And that way I should be available to me.
So to Import that I'm going to cheat again and just take one that I've done earlier.
So you have to see me type it all out.
So you can see I get that once, once you do this required dot dot index, you know, you then start getting your tell us IntelliSense, which is nice.
So it all, you know, it all just all just works.
You get this sort of nice development. Experience.
So what are we doing, we're expecting that rate handler returns a Response.
At the moment, it's synchronous.
I will leave it at that for now. Make a sink in a bit.
So we're going to say let response. Equals In real time, I'm getting chat messages from the cloud flag gear heads chat showing me giving me suggestions on how to fix my Fix my 72 Chevelle.
Thanks, Gregory. I'll get back to you on that.
And we just want to assert that there's something there. So, you know, we'll definitely do more with that.
But I know there's a few sort of dragons getting set up.
So I want to like share with you how to fix those. And again, like the very may well be better official answers of how to do this again part time hacker had on here.
This is how I do it just when I want to get get code written quickly like out there quickly and just getting into this sort of, you know, Test.
I was a code debug test sort of cycle. Okay, so add event lister is not defined like the like running in Mocha like this.
This isn't a thing. There's no like a run time that is setting these things.
Whereas when this runs on for workers, there will be.
And so just to get going. Get past this quickly. I tend to just add a simple check to say if that thing is defined, which it will be at runtime workers, then, you know respond because I'm looking at just testing this vanilla class like we don't need that for now.
So that should get us past that success. One thing just while we're here, like in the I guess little hacks to easily code locally.
And again, probably, probably the workers EM is engineering managers got his head in his hands as I as I do these hacks, but You should do your own episode in show the people how to do it the right way.
Okay. This is another one. It didn't didn't happen here.
But if we You know, if we were to run this to look run this on the workers runtime module would also be undefined.
So I'm just going to put that check in here.
And that's, that's sort of it to like be able to just sort of get going with this like Sort of local development cycle.
Okay, so my handler doesn't really do anything.
But let's, let's just make sure that are what I have done.
So returning. Hello, when we get a request to rates that that much at least works.
Before I go sort of too far down this road time check. Wow. Seven minutes man time flies when you coding.
Oh yes, that was something I didn't add to my disclaimer, the First episode I practiced a lot and it took ages.
And so I got what's done in half an hour.
This time I didn't prepare at all. So sorry folks, you're going to be suffering the results of that won't get quite as much done, but it's a bit more realistic.
Okay. Error. What can we do from here few options. We could go to the dashboard and have a look at the error.
In fact, let's not let's not say what we could do.
Let's go and do it. Because this is sort of real world. Like, you know, how would you go about it.
Design requests. Cut off the list earlier so that I can see workers.
This is more important. Okay. So what do we convert a 10 API that 1110 so sorry this 101 basically means there's an exception, you'll notice I have no track hatch not returning any errors.
You know, like, as you get more sophisticated with your workers, you'll do things like, you know, log to a like a lovely or, you know, paper trail like things like that.
You know, there's lots of different ways to to handle errors.
But one sort of easy thing when you're getting started is just to come in and actually see the request in the Dash.
And the other way is there's a there's actually a dedicated tool for this which we'll have a look at as well.
So let's see if we get some clues. T dot handler is not a function.
Okay. While we're here though, let's see if I have to do any special setup to to use Wrangler tail Wrangler tail is friggin awesome it.
Yeah, it basically connects to the workers runtime and can stream logs to your To your command line in real time.
So how good is that? So I didn't even need to go in the dash right like I can look at it right here and you know, this is the sort of development environment.
I like KT dot handler is not a function. All right, sounds pretty significant problem.
So right handler is a function handle.
It's a function turns response. Okay, let me take a look.
Let's say is not a function.
So it seems to it's not null. It's not erring on this. It's just saying that handle is not a function.
So that's sort of surprising one helpful thing when you've actually been able to do a few of these is I'm not going to go into the details of this.
But you have You know, here's one I prepared earlier sort of things.
So, so we don't spend too much time you watching me painfully do this.
Okay, so this is actually a closure. So we're meant to actually provide, you know, a method that takes a request and handles it fair enough.
So What do we got three minutes to go.
So, See what we can do in that time.
Where are we API.
So, Cool. That's important. As my phone buzzes time check three minutes to go.
What are we saying here request is not defined.
Yeah, that's true.
So, let's Stay We're going to mock this out at some point. Spots is not defined.
Aha. So, um, this isn't like this is defined in the like The sort of web API's so Mozilla by far the best docs in in this area.
Shout out Mozilla So that's not defined in the runtime for node.
So we've got some options here like around what to like what we want to mock out the way I typically do this is like I'll keep this sort of top level function super simple.
It'll just call something else. Like You know something like And then like I'll focus on this on testing this so I don't have to mock this I think I have actually sort of, you know, mock this and other and other projects.
We might do that in a future In a future episode.
But again, like this is where the crux of my logic, the bulk of my logic is going to be.
So this is where I want to take the time.
Okay, um, looks like we're out of time. So thanks for joining. Um, we've got a little bit further creating a skeleton API.
We deployed it, you know, returns sort of basic responses.
We've debugged our first era. And so it feels like we're now in a place where we can really start iterating more quickly, which is where I like to be.
Jade. Jade Wang is up next presenting what's going to be a super interesting segment.
She's talking to a CEO founder of like, um, you know, her journey and all the different journeys.
We all take in for entrepreneurs.
So look forward to that. Farewell. Thanks for joining. See you next time.