v0.4 Hosted Docs (WIP) #188
Replies: 4 comments 16 replies
-
As I've been building out the documentation, I've been getting more real-world experience as a user of Bud. The following is a somewhat unstructured brain dump so please feel free to jump in anywhere and share your thoughts. I'm writing this primarily to share my thinking in the hopes that you will share your ideas too! I need your fresh perspective! Before diving in, let me discuss the current Bud behavior. Current UI BehaviorAt a high-level, you define controllers that respond to requests and render views. You create controllers in the
Bud uses file-based routing, so to render the Svelte views are compiled by Bud into JS and loaded into a V8 VM. Then for each request, the controller's return value gets serialized into JSON and rendered to HTML inside the a V8 VM: In psuedo-code that looks like this: // on boot
const vm = new V8()
const show_post = readFile("posts/show.svelte.js") // svelte view compiled to server-side JS
vm.loadScript(show_post)
// per request
function show(request) {
const post = controller.show(request.params.id)
const html = vm.eval(`show_post.render(${JSON.stringify(post)})`)
return response.html(html)
} There are some perceived and real problems with this design. I'll start with the perceived problem: Perceived Problem with Directory StructureRails and Laravel separate views and controllers into separate folders. This has the following benefits:
But it also comes with a cost:
Most of the newer web frameworks choose to co-locate views with controllers and I'm wondering if I should change this in Bud. We could totally do:
I tend to lean towards this for a couple reasons:
What's holding me back is:
Real Problems with SSR in Go
Possible DirectionsRemix IntegrationBy having ownership over the runtime, we could offload views support to a framework like Remix. Remix's interface is an HTTP handler, so we could define a compatible runtime for Remix to run within similar to remix-cloudflare-workers, remix-deno or remix-node. What I like about this idea is that I think Remix nailed the data flow. It's all in one file, it flows in one direction and there's clear boundaries between server-side and client-side. Remix code example// Load the component. Called server-side
export async function loader({ params })
const { productId } = params;
const product = await db.products.get(productid);
return json(product)
}
// Rendered from params
export default function Route() {
const product useLoaderData();
return (
<>
<h2>Edit Product #{product.idk</h2>
<Form method="post">
<input type="text" ame="nme" defaultvalue={product.name} />
<input type="number name="price" defaultValue={product.price} />
<button type="submit">Save</button>
</Form>
</>
)
}
// Respond to the form. Called server-side.
export async function action({ params, request }) {
const { productid } parans;
const form await request.formbata();
const name = form.get("nane");
const price form.get("price");
const product = await db.products.edit({ id: productid, name, price: 3 });
return redirect("/products/${product.id}");
} And if you think about Go's core strength over Node.js, it's that Go has its own scheduler that takes advantage of multi-process architectures. Since Node is single-threaded, you can bring a Node.js server to its knees by doing anything computationally expensive in one of its handlers. This becomes increasingly difficult to avoid at scale and it's why packages like blocked were created at Segment. The industry has moved towards Serverless to remedy this design flaw, but then you're distributing your compute and you have additional problems you need to deal with like too many serverless functions hitting limited resources (like a database). Bud could be one of many bases that power Remix. That's an interesting idea. I have one major problem with this though. You're moving more and more code into Typescript/Javascript. The controllers would now be in JS and it's not clear why the models wouldn't be in JS too. If we move Bud this way, Bud becomes more like the backend framework for a UI framework rather than a self-contained full-stack web framework. The benefits:
The cons:
Stick with the Current PlanContinue on the current course:
Problems:
Re-focus on
|
Beta Was this translation helpful? Give feedback.
-
I'm in favor of the focus on I'm also looking into alpinejs as recommended by @barelyhuman . It looks like a good fit for this project too! |
Beta Was this translation helpful? Give feedback.
-
My $.02: Svelte is a pretty killer part of Bud, and I'd be sad to see it replaced with My biggest gripe with Svelte also let me get rid of my Less CSS pipeline because having CSS scoped to the That being said, my frontend experience is somewhat limited. Bud was my intro to Svelte. This is more about Svelte > re: Remix, I'm having a hard time imagining writing server code in JS. Part of the reason for using Bud in the first place is to have Go server-side. If it's not there, I'm not sure what Bud has to do with Go anymore. 🤔 |
Beta Was this translation helpful? Give feedback.
-
Thank you so much for sharing your thoughts 🙌 To recap, the 3 things that were weighing on my mind:
Here's what I'm thinking now: 1. Is it worth changing rendering solutions to simplify the internals and boost Bud's performance?I also find Svelte (or other virtual DOM frameworks) support to be one of Bud's killer features, but I understand that for simpler needs html and html/template are good choices. I realized that most of my issues with supporting JS frameworks is that V8 is complex and CGO is slow, but there was an exciting new development last week. Goja got class support! I tested it out and it turns out to be the last ES2015 feature needed to render Svelte views into HTML. Using Goja for SSR is both operationally simpler and also faster! No more CGO! There's still going to be some JS gaps between what ESBuild transpiles down to and what Goja can evaluate, but those will close over time and we can help them there too. I'll be working on transitioning Bud to using Goja instead of V8 for v0.3.0. As far as other rendering solutions, I'm trying to abstract out the view renderer right now and I'm thinking of exposing this publicly so you can bring your own view renderer. If this experiment works, I'm thinking of keeping Bud focused on just Svelte, but then adding text/template or React support is 2. Where should we draw the line between the handoff from Go to JS?I've decided that the input needs to be serializable between Go and JS. JS to HTML is a pure transformation function. This keeps it simple & fast. Then the JS VM remains focused on rendering and only implements a small set of global functions (e.g. fetch, setTimeout, console.log, etc). It does not have access to the request data, instead certain request data is provided as context to Svelte (and React). This is similar to what Sveltekit does with their $app/stores. 3. Should we co-locate views and controllers?Still not sure about this one! Thoughts very much welcome! Update: The roadmap above has been updated to reflect this direction. I also scoped it down to just having docs that maybe have a single top section for the landing page. |
Beta Was this translation helpful? Give feedback.
-
Goals
Deliverable
Bud has documentation live on https://livebud.com/ and a demo of the new Bud features that were built to make the documentation site possible.
Tasks
Beta Was this translation helpful? Give feedback.
All reactions