Run More Languages On Cloudflare Workers
Presented by: Jen Vaccaro, Cody Koeninger
Originally aired on October 11, 2021 @ 10:00 PM - 10:30 PM EDT
Learn about the new multi-language support for Workers, allowing developers to now write code in the languages they know and love, including JavaScript, C, C++, Python, Go, Rust, Scala, Kotlin, and even COBOL."
English
Serverless
Cloudflare Workers
Transcript (Beta)
All right, so let's get started, Cody. I'm really excited to be talking to you on our second day of serverless week.
We've had a lot of announcements going out this this week.
And I think people are really excited on the language, broad language support that we've been announcing.
So I thought that before we dive into that. Maybe you can give a brief introduction, who you are.
I know this is your Cloudflare TV debut.
And I can also give give a quick intro before we dive into this.
Sounds good. So I'm an engineering manager for the team that does the distributed data aspects of workers.
So KB and whatever the top secret storage at the edge projects we can't talk about are Cool.
All right. And how long have you been with Cloudflare?
I've been with Cloudflare about half a year. Okay, cool. All right.
And I'm Jen Vaccaro. I'm the product marketing manager for workers. Pretty new.
I've only been here for just about two months. And I'm coming from Intel on the server side.
So I'm excited to be talking with you about serverless. All right.
So why don't you start by giving us an overview. What have you, what has your team been working on for serverless week?
So my team's mostly heads down on unrelated things.
So I personally kicked in a little time on serverless week.
And my goal there was really that when we when we launched workers. It was, it was pretty clear that we had support for JavaScript and for any language to compile the WebAssembly.
But we hadn't really done much talking about all the other languages that can compile the JavaScript.
And so my goal there was really to just get like a broad shallow swath Across a bunch of different languages for kind of a hello world level of experience on workers.
And the idea there is really to emphasize that like workers doesn't care what generated the JavaScript that's running.
So as long as you have a compiler for your language that can Admit JavaScript that's, you know, under Megan size and is using the JavaScript API.
You already have like chances are I can run on workers. So can you share with us.
What are the new languages that we've announced today that will have support for for workers.
Sure. So the Hello World templates that we announced today are for Python, Scala, Kotlin, Reason, and Dart.
And Part of that was based on You know language popularity and You know from RedMonk from Stack Overflow in terms of what languages developers especially love And it's, it's also a question of what has like good high quality JavaScript compilers available.
Gotcha.
Gotcha. Yeah, that's pretty cool. Maybe some people have recently seen the RedMonk language rankings that have come out.
And I think when we were talking to some of those folks earlier, they were a little surprised to see Python and how much that it has risen in in those rankings.
So it's, yeah, it's good to see that we're able to support that.
And for those who don't know and haven't checked out those rankings Cloudflare Workers, we are sponsoring that And so people should definitely check that out and you'll see some of those languages and now with these templates that Cody is talking about for workers.
So that's pretty exciting. And so how can users.
Is there ways that users can start contributing to this. Yeah, for sure.
So, you know, like in the in the Hacker News thread about the blog post. Somebody was like, hey, this looks like ClojureScript might work really well on this and You know, if you're, if you're listening, or if you read the post and you're thinking, hey, I wonder if language that I know about that I like would work on this Really, it's just a question of if you're able to get a small like Hello World style example compiled to JavaScript, you're welcome to go ahead and submit a PR For adding a link to that template to our to our workers docs and I'm happy to help people out with, you know, aspects of polishing a PR is making sure that the regular generate templates work.
Okay, that kind of thing. And do we have plans for any future languages that will be building out these templates for Yeah, absolutely.
So there's a there's a pretty good list of Languages that have JavaScript compilers that have been going through and there, there are still plenty of languages left on that list to investigate.
Gotcha. Yeah, I know there was somebody in one of the blog comments who was asking about go Um, so there's a existing third party projects using tiny go on wasm and I've done a little bit of investigation on go for JS.
The go for JS thing not quite ready for primetime. We'll see if it gets there, but the wasm side of it.
It's my understanding that people have already used that so Gotcha.
Cool. And so, of course, this gives our community just added flexibility, they can have the preference to choose the language that they are most comfortable in.
But are there any other sort of big benefits that we want them to be aware of.
So I think I think it's really a question of two things.
One, do you care enough about the feature set of your language to You'll use something that's a little off the beaten path right now.
Or two, do you have like existing library code that it makes sense to be able to run on workers like those are those are really the two main main thing.
So in terms of like language features for me, I'm a, I'm a pretty big proponent of Like modern statically type languages like I really like having the Feeling of safety that comes with things like exhaustively checked pattern matching right so I can say like Hey, there are exactly seven kinds of widgets.
And if I go write code that's dealing with widgets and I'm only dealing with six of them like the compilers got my back.
It'll say, hey, you forgot about case XYZ right like I get a good sense from that.
Other people get a good sense from, you know, being able to have like really short turnaround times throw stuff at the wall and see what sticks and There's, there's definitely there's definitely like the preference aspect of that.
And then there's the aspect of like, you know, if I have existing validation logic that I was running on my origin.
I would really like to be able to run it on workers and it's, you know, Going to fit in a worker just fine.
And it's just a question of compiling an existing language to JavaScript or Rasm.
I think that's another use case that can make a lot of sense.
Well, definitely be interesting to see what some of the folks in our community using workers are able to come up with as well.
That's great. So why don't we spend some time and you know you detailed in the blog, how to get started.
And I thought maybe we can do a quick demo, we can start with kind of showing how this works a little under the hood, maybe starting with a Python example.
See if my Screen share Working okay How does it look Looks good.
Maybe we can maybe make it a little bigger. Tuning in.
How's that Just one more one slightly bigger. And I think we'll be good. Yeah, I think that's good.
Cool. Okay, so the blog posts examples are using Wrangler Wrangler is really just a convenient way to interact with our API's for uploading JavaScript, like if you really just have some JavaScript.
There's an HTTP API, you can use to upload The other benefit of Wrangler is it has templates.
So in this case, there's an existing GitHub project and what Wrangler was going to do is clone that and then do some real simple template substitution for things like author name and name of the project.
And you can see In the project structure there. There's going to be a Wrangler configuration file a web pack config, which in this case is how we've set up the compiler that's going to compile Python to JavaScript.
Your source code index.py and then installation instructions in the readme So for Python, assuming that you already have Python 3.7 installed and We're transcript recommends using virtually and be but you could also install transcript globally.
If you wanted to Set up there looks like Getting a virtually and be going And then Entering that And then installing transcripts, which, like I said, is the compiler that takes Python code and compiles it into JavaScript so that it can run on on workers.
So to be clear, this is assuming that the way you're using it here in this demo is assuming that that users or anyone following along already has Wrangler, but you don't necessarily need Wrangler to So you don't, you don't need Wrangler to interact with workers in general.
Like I said, there's like if if you if you have your own Hello World or other template or other way you've produced whatever JavaScript, you've had Cloudflare has documented HTTP API's you can use to upload a given script.
The benefit of Wrangler here is like a way to Quickly start up a project and and template it Yeah, and it's, it's pretty easy to to download as well and get started.
Alright, so, so let's see. Want to walk us through any any pointers here and what you want, what you did.
I know we were talking Syntax on the index.py file.
Sure. So at this point. The transcript is installed or regular bill is going to do here is run webpack and then webpack is going to run transcript and then package that all into a single JavaScript file.
And then as far as What the code actually looks like It's really pretty similar to like a JavaScript example of the Hello World.
You're gonna have this this global function here out of it list where And we're going to be listening for fetch events and then we give that anonymous function.
So Python syntax that's going to be a lambda.
And then what that's going to do is call this respond with method on the event.
So in this case, like add event listener is a JavaScript function respond with is a JavaScript method on JavaScript object.
And then we're going to call our function that we've defined to return a new response object.
There's a little bit of an oddity and that you're manually calling the constructor on this JavaScript object.
There's a link in the blog post for a little more explanation.
If you want to write a wrapper. So that you could just call response on its own.
That's, that's definitely an option. But the important, important point to make here is that if you're looking at existing Cloudflare documentation for a JavaScript call right like whether that's, you know, my KB namespace I get As long as you can write that call, it will get compiled to the equivalent JavaScript call and you'll be able to use that API.
And that's, that's one benefit of Python.
In this case, not being statically typed is it's not going to check a compile time that that function are all you know actually exists.
It just better exist at runtime and the Cloudflare workers environment.
Right, right. So, so I see you've gone to Wrangler build.
Were you going to Wrangler publish Yes, so Wrangler publish.
We'll go ahead and push that up. Actually, so when I installed it, it suggested that I needed to put in my account ID.
I'm just going to go ahead and copy and my existing one.
And for anyone watching it as to get your account ID. As soon as you've signed up for a Cloudflare account, you'll be able to go into that page and on the left.
Sort of left hand corner on the side, you'll able you're able to copy and click your account ID and it's important to remember to put that into your Wrangler dot com file under account ID.
So we're not showing all of that back end process, but that that's kind of the back end that that you would need to do.
Cool. Alright, so this is a little example on the what we've been building out here for Python.
Is it still Still building. I know. So it's published at this point.
So you can Go ahead and go to That browser, you'll get back to the world.
And if we wanted to edit the world and repush it, we could Nice. That's exciting.
So we also were talking about some of the other languages we've enabled. So one of the other ones we were discussing was Reason and Scala.
So I don't know if you want to show us something quick there talk through that.
So one of the reasons.
One of the reasons reason is interesting. Is that it's compiler.
Generates JavaScript that in some ways is actually better and smaller than handwritten JavaScript like You know, I mentioned that one of the one of the things that you need to make sure given compiler can do is generate reasonably small code.
So like that Python Hello World example has probably 70 K of Python runtime associated with it.
Which is fine. Like you just need to fit within the one limit that reason in this case.
Is a JavaScript like syntax for an existing language called OCaml.
It's been around a long time. Has a really good type system. What's interesting about it is that this, you know, this reason syntax gets turned into really pretty tiny JavaScript.
So this generate buckles script is the name of the compiler that will take OCaml or Reason code and turn it into JavaScript.
But you, you may also even notice that like it's doing function in lining right like here we just have a direct call to add event listener.
And the respond with is going to go and take a look at the event request and not do anything with it and just return a hard code response directly.
And the reason for that being like the compiler can tell that like all this function is ever going to do is return a constant response.
So we might as well just in line it So that's really like that's, that's impressive from a like overall size perspective.
And the language is also really nice.
Like you get all the, you know, niceties of a modern static type language.
So, And I think, I think one another point to make here is that like these these type declarations that we're using to explain to the compiler what the expected Argument and respond or return types for these Cloudflare API's that we're calling are like none of that ends up in the JavaScript out there, right, like that's all strictly compile time checking And, and what about Scala.
I mean, I don't think we'll have time to go too deep into that.
But I did kind of want to touch on it.
And if you could answer what Scala to JavaScript compiler are we using and let us know what other things we might need to keep in mind to install to get that up and running.
Sure, so The Scala, Scala to JavaScript compiler we're using is called Scala.js.
And the nice thing about that is that It has an existing plugin for SPT, which is pretty much Pretty much a standard build tool for the Scala world.
There's some people use Gradle or some alternatives, but SPT is still a pretty standard build tool.
So really all that's necessary is to enable this plugin.
And then if you want to bring in some of the existing Type definitions for things like web workers.
There's these dependencies on the Scala.js library and Scala.js DOM The other nice thing about it is that it'll go ahead and generate a single JavaScript file with with all of your code in it.
So you don't have to mess around with like webpack or another bundler.
And so this case, what I've done is just set up the build to output that to an index.js file, which is where ranker by default is going to expect to find the JavaScript file that it's that it's uploaded to Cloudflare when you run publish And pretty, you know, pretty normal Code lab for Scala project in terms of like you've got a main objects and a main method.
So, No, that's fine.
So if we're wanting to use KB probably like the first thing somebody might run into is okay.
So the way KB interface works is basically just calling methods on a global object that you configure that's whatever the name of your KB namespaces.
In this case, my KB namespace. I'm just going to call KB. So I went ahead and have set up a an object that contains any any types that I want to tell Scala to expect to be available in global scope.
The implementation of those. I'm not going to write down.
It's just like native native in this case being JavaScript native code that's made available by by workers.
And then this KB namespace type really all I have to worry about.
There are the methods that actually intend to call So I don't have to go worry about like either writing or finding type definitions for the entirety of the workers.
That's really just stuff that I need.
In this case, I'm just going to be using get input and maybe delete So again, get is pretty straightforward.
It's going to get it's going to, I mean, give it the name of my key.
It's going to give me a KB value back and there's a native implementation of that.
Likewise for put So this KB value is just like a simple small areas for the fact that it's going to be an asynchronous Java JavaScript promise.
So we're not going to get a string back directly. We're going to get a string at some point in the future.
Once the call is complete. So that's this JavaScript promise is like JavaScript promise semantics.
So things like automatically flattening that kind of thing.
And that may not necessarily be what you want.
If you're used to Scala semantics around concurrency. So in Scala, kind of the equivalent wrapper type for asynchronous computation would be a future.
And I can convert back and forth between a Scala future or JavaScript promise by using these two future methods.
Right. So I've got my global object.
I've got my KB namespace on it. I'm going to get key out of it. I'm going to turn that into a Scala future And then I'm going to map over at to turn that into the response that I want.
And in the case that it's a failed like it's an asynchronous failure of some kind, go ahead and turn that into a user visible response.
So this, this style is a little more like functional programming oriented in terms of like if I wanted to add another transformation step in there.
I would probably just go put in Another map, etc, etc.
Some people prefer to write like more imperative code and to just use async await where they would say, like, I'm going to assign a value to this and I'm just going to await the asynchronous computation.
So there's there's a there's a Scala project in general for doing async await syntax.
But this doesn't need to just be with Scala, right? So there, yeah. So there are there are other languages that have async await syntax like TypeScript does, Kotlin does.
But the point, the point here being because async await syntax in Scala is just implemented is essentially sugar on top of futures.
The same Scala async await syntax will also work if you want to have a Scala JS project.
I've done examples of that.
I can put examples up later. And one of the other pieces.
I don't know if you touched on it, but I know we were talking about it earlier was talking about the new definition for the handle request.
Yeah, so this kind of gets back to what I was saying earlier about pattern matching and that just being kind of like a very nice way to get both like conciseness and also more safety than you would if you were just like doing raw if-else statements over strings or that kind of thing.
So the idea here is they're basically two things we want to look at when we're dispatching our request.
We want to look at the method like are they trying to get or put and then the URL path.
So in this case, just using the URL path like the first component of it being the key, second component of it being the value.
If they call get, it doesn't make sense for them to call get with both a key and a value.
That's probably an error. If they were calling put and only providing a key, that's also an error.
But we don't have to do like if method equals get, then if URL split array is a length of four, then do this.
We can just say, hey, I want to match on this case that looks like get So these components are up front or like I don't care.
So like the method and the domain name, I really just care about the path component and then dispatch out to the function.
Likewise for put. So in this case, I have like a catch all so that I know there's always going to be a valid value returned.
If I didn't have that catch all and I had like exhaustive checking on all the available HTTP methods and the potential sizes of array, the compiler would say like, hey, did you think about HTTP method.delete or did you think about cases when like array had something other than four items in it.
And, you know, it's kind of watching your back to make sure you're saying something that's going to be meaningful at runtime.
Great.
So I know you, as we mentioned in the beginning, a lot of this is detailed in your blog.
Are there other places on our documentation or whatnot that people can kind of start digging into to get started on some of this.
Yeah, so really the best, the best thing in our documentation is the templates gallery has links to examples and a bunch of different languages.
So the hello worlds that we have here linked from there, but there are also some more detailed examples.
I'm probably going to do KB equivalents in other languages and link those as well.
So yeah, I would say really the best, the best starting point are the templates.
You can get a like a known working project and then start making your own tweaks to explore what's going to work for you.
And for everyone listening, that's on our Cloudflare Workers page and you can go pretty quickly on that page down to our documentation.
This is, this has been really helpful, Cody. I appreciate you talking about this with us.
Maybe we'll give people just a quick summary recap. So We're today we've launched some new support for languages that we hadn't really had support for in the past.
So those would include Python, Scala, Kotlin, Write, COBOL, Reason.
Anyone, any others I'm missing? Dart. Dart. Yep. And like, like Cody said, you can, you know, be engaged in our community.
We're definitely going to be watching out if you're If there's some other language and you're able to get up and running the hello world.
We want to know about it and Cody and his team like he started out saying that they're looking for ways to expand upon this in different languages in the future.
So we're excited there. And since this is serverless week I thought maybe I can give our listeners, a little bit of a preview on what we have coming and a little quick recap on what we've had in Coming in the past or the other from yesterday.
So yesterday, a lot of people you might have tuned in here to hear about our new workers unbound.
Which is just released for extending our CPU limits.
So our customers in this new beta can use workers to build out more computationally intensive workload.
So we're excited that we had that yesterday, Cody Announced this in his blog today on language and definitely stay tuned.
We have a lot coming out on security on the developer experience and On speed for for workers.
So we're really excited. Stay tuned to the rest of what we have going on this week and Cody.
It was really great talking to you about this and I hope people learned as much as I did from our conversation.