Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Cloudflare output adapter #470

Open
Tracked by #197
aralroca opened this issue Sep 11, 2024 · 13 comments
Open
Tracked by #197

Create Cloudflare output adapter #470

aralroca opened this issue Sep 11, 2024 · 13 comments
Assignees
Labels
enhancement New feature or request Winter Of Code 4.0

Comments

@aralroca
Copy link
Collaborator

aralroca commented Sep 11, 2024

The idea is similar to the current Vercel adapter but adapted to Cloudflare.

@aralroca aralroca mentioned this issue Sep 11, 2024
25 tasks
@aralroca aralroca self-assigned this Sep 11, 2024
@aralroca aralroca added the enhancement New feature or request label Sep 11, 2024
@AlbertSabate AlbertSabate self-assigned this Nov 1, 2024
@AlbertSabate
Copy link
Collaborator

I'm taking this amazing task. Let's see if we can have something solid soon :)

Currently, I will be working to implement it. Roadmap:

  • Cloudflare workers running full SSR on workers.
  • Cloudflare pages running the static site.
  • Cloudflare pages implementing the api routes on workers.

Currently, I found the following issue:

WebAssembly.instantiate(): Wasm code generation disallowed by embedder
cloudflare/next-on-pages#704
cloudflare/next-on-pages#704 (comment)

Seems like not only Cloudflare but Vercel not support this feature.

Affected line on Brisa:

const { instance } = await WebAssembly.instantiate(wasmBinary, {

This will be a blocker to do the deployment on cloud providers. Is there any workaround to replace this funcion for soemthing else @aralroca ?

@aralroca
Copy link
Collaborator Author

aralroca commented Nov 1, 2024

@AlbertSabate this hash in runtime is only used for the version hash of Brisa for the constants and we can improve this using a macro, so we can avoid it in a easy way!

VERSION_HASH: hash(version),

We could also remove WASM. Or put it open-source in another repo if someone wants to use Bun's hash (Bun.hash) compatible with Node.js and Deno. But in our case, we could avoid its use in run-time. I'll look into it later! 💪🏽

@aralroca
Copy link
Collaborator Author

aralroca commented Nov 1, 2024

Ahg, is not possible to move it to macro, because BigInt is not allowed:

error: cannot coerce BigInt (HeapBigInt) to Bun's AST. Please return a simpler type

@aralroca
Copy link
Collaborator Author

aralroca commented Nov 1, 2024

@AlbertSabate I removed the WASM instance on 0.1.4-canary.2 💪🏽 The only difference is that before the rpc file has a hash of the Brisa version, now just the Brisa number version:

Screenshot 2024-11-01 at 22 22 27

It was unnecessary, the hash was calculated in runtime... The first idea was to move it to a macro, but bigInt is not comparable with Bun macros, then I thought that nothing really happens if instead of the hash we put directly the version, so we simplify the code and delete the WASM instance to make the hash in other runtimes like Node.js, but at the same time it was incompatible with Cloudflare... That's it, problem solved.

@AlbertSabate
Copy link
Collaborator

Roger that! I'll keep going with the integration. Thank you @aralroca :)

@AlbertSabate
Copy link
Collaborator

Development is paused because we have to change a bit the build of brisa in order to accomodate cf pages.

https://developers.cloudflare.com/pages/functions/routing/#single-path-segments
https://developers.cloudflare.com/pages/functions/middleware/

Every route should be able to be executed without imports and being standalone, as cf does not support loading dynamic routes RoutingFilePath of Brisa require a folder called pages.
Example:
pages/index should be able to run by itself whatever is in this page. No externals.

@aralroca
Copy link
Collaborator Author

aralroca commented Nov 15, 2024

Standalone is because you can transport and run the build anywhere without external deps, which is not bundled and is the step we have to do. This will also improve the req/sec since the dynamic imports we saw that worsen a lot this aspect and making everything bundled will also solve this.

@aralroca
Copy link
Collaborator Author

aralroca commented Nov 15, 2024

Maybe I would add an extra step to do this bundled process, but I would keep the unbundled option as other cloud providers can use each page with a different handler. The default would be bundled. This would also open the door to make a “binary”, related to this other issue by @ansarizafar.

In brisa.config:

{
  "standaloneFormat": "bundled" // Options: "bundled" (default), "binary", "unbundled"
}

What do you think of the proposal @AlbertSabate and @ansarizafar?

@AlbertSabate
Copy link
Collaborator

AlbertSabate commented Nov 15, 2024

Sooo, my understanding on bundled will be for a single file for all routes. Like output brisa.js and here runs everything.

It will be good to have this bundled options, but I also would like if possible to have a bundle per route. I think this way we will cover all cases. Think that aws lambdas are limited by size also and computing time counts, so good idea to be able to make it more specific.

"standaloneFormat": "bundled" // Options: "bundled" (default), "bundled-routes", "binary", "unbundled"

@aralroca
Copy link
Collaborator Author

aralroca commented Nov 15, 2024

mmm... okey, but if we bundled each route, what is expected, that each one is a server? I don't think it can connect correctly with the handlers of the cloud providers. For example Vercel expects each route to be:

export default function(req, res) { /* ...*/ }

Are we sure this is what each cloud provider expects? I don't think there is a convention for it, or is there? What does Cloudflare expect?

@AlbertSabate
Copy link
Collaborator

Similar to cloudflare yes.

Server after all is on the cloud provider... On the case of cloudflare you are receving only the request, environments and context. And you have to create the response and return it. Same for lambda and lambda edge, they exepct a response on the return on the handler. No server involved on brisas code. I'm unsure how vercel works, but should be similar, no?

The beauty of cloud providers is that you don't have to manage the servers.

What I think we need is something like:

const response = brisa(request, envs);
return response;

No CLI, no server. Those 2 goes on the side if you want to use nodejs or bunjs or deno 2.

@aralroca
Copy link
Collaborator Author

aralroca commented Nov 15, 2024

If the bundled route is with this format export default function(req) { /* ...*/ } can you integrate it with Cloudflare?

@AlbertSabate
Copy link
Collaborator

AlbertSabate commented Nov 15, 2024

Should be possible with the adapter. Adapter will bundle that brisa file together with the cf wrapper. It will be nice if we can inject environments somehow. Cloudflare allow to have sercrets and pass many nice to have information.

So users will have 2 options:

  1. Bundled version, it uses the router of brisa and everything as brisa has defined, using _worker.js single file
  2. Bundled per file route, so user can use cloudflare router and optimize code per route, so every function has less code and therefore should be more performant. Using functions folder.

Because for a small pages, probably file size is redundant, but once your code has 100 pages with 200 components, the impact will be higher. Cold start and file size is key in AWS lambda edge for example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Winter Of Code 4.0
Projects
None yet
Development

No branches or pull requests

2 participants