wingerlang
wingerlang•9mo ago

Deno Deploy - is it possible to have 2 servers running?

Maybe Im using it completely wrong, but locally when i develop I have two Deno servers running: Backend - deno server at port 8080 Frontend - Deno / Fresh server at port 8000 My backend is mainly used as a standalone REST-API. My fronend then sends fetch-requests to the API. The problem is this. At deno deploy, I can only point to one server. How do I come around this? Thanks in advance!
14 Replies
marvinh.
marvinh.•9mo ago
Deno deploy is a serverless function platform. So there isn't a server running in the classic sense. You can certainly create multiple projects (each project = 1 function) and have them communicate with each other. Given that the backend is likely closely tied to the frontend it may make more sense to run them both in the same function though
wingerlang
wingerlang•9mo ago
Thanks for the reply! Isn't it more pure to seperate them? For instance, I could create an mobile app or text interface that only need the data, seems bad practice's to merge them. But in my case, since they are both written in TS i obviously share some code and they currently share repo. Seems like this use case is not supported? Or should I have two deno projects that point to the same repo but with different entry points?
marvinh.
marvinh.•9mo ago
The use case is supported. Instead of creating two servers, create two functions I don't think it's bad practice. For projects that only have one UI it's totally fine. If you have multiple UIs an API abstraction layer may make sense
wingerlang
wingerlang•9mo ago
Yeah, and I might have two UI soon. But Ive read some about Deno but obviously im still very noobish - what is even "two functions" refering to here? I mean the backend is deno http with Oak, starting like this: await app.listen({ port: 8080 }); The frontend is in another folder all together and starts like this: await start(manifest, config);
marvinh.
marvinh.•9mo ago
you can think of a serverless function as being a server that spins up when needed and shuts down when it has done it's thing and no new request comes in. In very laymans terms it's basically a short lived server In your case you'd create one deploy project with the oak server and one for fresh and have them talk to each other Note that having them both in the same function would likely be better for performance. There can be multiple functions of the same project running at the same time. So there is no need for manual server scaling like you'd do in a classic setup
wingerlang
wingerlang•9mo ago
Thanks for the very detailed explanations! But lets say Ill go for that strat in the beginning, how do I wire up the code? Right now, I start the REST-API as a ordinary deno server, and then I have the isolated Fresh app in /frontend/(main.ts)?
marvinh.
marvinh.•9mo ago
Both Fresh and oak expose a .handler() method. So you can either create a socket via Deno.serve() and branch off to oak or Fresh manually, or spin up oak inside Fresh as a /api middleware
wingerlang
wingerlang•9mo ago
Hmm alright, sounds very promising. Ill try to find some online resource to read more about that particular problem. My goto strategy is traversing lots of youtube-guides, but very lacking thus far! Sorry for not understanding this concept that well. Just nu sure how to "spin up" a fresh-instance or oak. I'm reading as much as I can to try figure it out, but so far no success
fro.profesional
fro.profesional•9mo ago
For oak you should use the handler method https://github.com/oakserver/oak#handle-method You can chose to use it inside your fresh app Or you can use the Deno.serve to pass the request https://deno.land/api?s=Deno.serve
Deno
Deno.serve | Runtime APIs | Deno
Serves HTTP requests with the given handler.
GitHub
GitHub - oakserver/oak: A middleware framework for handling HTTP wi...
A middleware framework for handling HTTP with Deno 🐿️ 🦕 - GitHub - oakserver/oak: A middleware framework for handling HTTP with Deno 🐿️ 🦕
wingerlang
wingerlang•9mo ago
Thanks for the reply. I think the documentation is written in a way that it presumes some knowledge I do not have. I cannot really connect the dots how I glue my frontend with the backend using oak/deno. Should I somehow move the "await start(manifest, config);" Im using to start the Fresh app, in some handler-method along side the await app.listen({ port: 8080 }); Im already using for the backend?
fro.profesional
fro.profesional•9mo ago
The easy way, would be create a route “api” in your fresh app, since the route gets a Request, you can directly pass the req obj to your Oak handler Have you tried that?
wingerlang
wingerlang•9mo ago
Im not sure how to "pass the req object" to the Oak handler. Every time I look at code it seems a bit different. I actually still dont get if I can/should have two servers to separate frontend/backend or if you mean that I should just move all backend-code into the frontend somehow. Im trying hard to understand but just dont get it yet, sorry for that.
fro.profesional
fro.profesional•9mo ago
import { Application } from "https://deno.land/x/oak@v12.6.1/mod.ts";

const app = new Application();

app.use((ctx) => ctx.response.body = "Hello world");

Deno.serve(async (req) => {
return (await app.handle(req))!
})
import { Application } from "https://deno.land/x/oak@v12.6.1/mod.ts";

const app = new Application();

app.use((ctx) => ctx.response.body = "Hello world");

Deno.serve(async (req) => {
return (await app.handle(req))!
})
@wingerlang do you understand what is happening here? Do you see Deno.serve starts the server and has an obj that is the request?
Deno.serve(async (req) => {
Deno.serve(async (req) => {
You can pass that request to your Oak app:
await app.handle(req)
await app.handle(req)
And it will run whatever you have in your app, based on the request, and will return a response The important part is that you can use your Oak app as long as you pass the Request, and it will give you a Response Now, on your fresh app, you can create a route that has a handler, docs: https://fresh.deno.dev/docs/getting-started/custom-handlers. From the docs:
The handler has access to the Request object that backs the request to the route and must return a Response object.
That is essentially what this does:
await app.handle(req)
await app.handle(req)
So with the above example, you can create a Fresh route similar to this:
import { Application } from "https://deno.land/x/oak@v12.6.1/mod.ts";
+import { Handler } from "$fresh/server.ts";

const app = new Application();
app.use((ctx) => ctx.response.body = "Hello world");

-Deno.serve(async (req) => {
- return (await app.handle(req))!
-})

+export const handler: Handler = async (req) => {
+ return (await app.handle(req))!
+}
import { Application } from "https://deno.land/x/oak@v12.6.1/mod.ts";
+import { Handler } from "$fresh/server.ts";

const app = new Application();
app.use((ctx) => ctx.response.body = "Hello world");

-Deno.serve(async (req) => {
- return (await app.handle(req))!
-})

+export const handler: Handler = async (req) => {
+ return (await app.handle(req))!
+}
wingerlang
wingerlang•9mo ago
Thanks for the reply! I will for sure deep dive on the code snippets tomorrow 🙂