3 ms·
What did you move to? We've been using NextJS as a frontend with somehelpful server-side/api handling, but the backend is done in Django. We are basically just
by vdfs 1y ago
What did you move to? We've been using NextJS as a frontend with somehelpful server-side/api handling, but the backend is done in Django. We are basically just using ReactJS with the convenience of NextJS (like file based routing)
- t-writescode 1y agoNot OP; but when I was thinking about using Next.JS, and doing a deep investigation, I came to the decision that, for server-side rendering, I'm quite happy to use Kotlin and Ktor (my backend is also Kotlin - I have a lot of client-types, which is why they're separate), and I've been quite happy with Ktor's html dsl + htmx for speed. And Kotlin + Ktor feels very good to write in on serverside. Fast, easy and fluent to write in, like Ruby; but with Java's ecosystem, speed and types.
- catgirlinspace 1y agoHow are you doing reusable components with the html dsl? From the little bit I’ve tried ktor this was something I could not figure out and it kinda just pushed me away since I couldn’t find anything.
- t-writescode 1y agoTo build reusable components, I end up using a mix of a lot of extension functions and Kotlin's function pointer syntax. So, the components themselves will look something like this: fun HtmlBlockTag.radioButtonWithLabel( groupName: String, id: String, hidden: Boolean = false, radioButtonFunc: (INPUT.() -> Unit)? = null, func: LABEL.() -> Unit ) { radioInput(name=groupName) { this.id = id this.hidden = hidden radioButtonFunc?.invoke(this) } label { this.htmlFor = id; func() } } And then use of them will be like this: call.respondHtml { body { div(CSS_CLASS_NAME) { radioButtonWIthLabel(MORE_CSS_CLASS_NAME, "group", "id") { +"Text for the label" } } } } More complicated examples just extend that quite a lot. I've also got whole files dedicated to single extension functions that end up being a whole section that I can place anywhere. --- And then to test those single-function components, I'll do something like this: class SingleSectionTest { private suspend fun ApplicationTestBuilder.buildApplicationAndCall( data: DataUsedForSection ): Document { application { routing { get("test") { call.respondHtml { body { renderSingleSection(data) } } } } } val response = client.get("test") val body = Jsoup.parse(response.bodyAsText()) return body; } @Test fun `simple test case`() = testApplication { val data = DataUsedForSection("a", "b", "c") val body = buildApplicationAndCall(data) // all the asserts } } And so on. Is this what you were wondering? Or would you like a different sort of example?
- catgirlinspace 1y agoThat's pretty much what I was looking for, thank you for sharing! I think that's probably the nicest way I've seen to do it, annoying that Kotlin seems to force you to add it as a child (? idk the word...) of an existing HTML tag, wish you could just import a component or something :(
- t-writescode 1y agoKotlin calls those "Extensions" [0], and yeah, they can be pretty annoying. I first learned about them in C# and I had a bunch of frustrations with them, especially when I found some code on StackOverflow or Microsoft's docs and they'd use one of those methods and it just plain wouldn't be there for me because I hadn't downloaded the right nuget package or anything. I've gotten more used to them and I get why they can be so great now; but there's still some real annoyances with them I just can't shake (like the import problem and the related "where is this code?!" problem) --- Purely importing a component that's just a simple class, like you can do in Java/Typescript with their jsx and tsx files would be pretty cool, yeah. You could fake it by making a data class and adding a fun renderInto(tag: HtmlBlockTag) { ... } type method, but with how Ktor's Dsl is implemented, you're still going to need to connect it into the giant StringBuilder (or whatever) that the dsl is building to. To help me get something close to that idea, I tend to dedicate whole files to bigger components and even name the file the same as the root HtmlBlockTag Extension method (like RadioButtonWithLabel.kt if I did it for the earlier one). Those files are great because you can put a bunch of helper methods in the same file and keep it all contained, a lot like a class. [0] https://kotlinlang.org/docs/extensions.html https://kotlinlang.org/docs/extensions.html
- twodave 1y agoWe have some other projects that are Angular, and NextJS was sort of a proof of concept for us. The goal is to just have one front-end framework for our devs to work with (and keep up to date, ugh!), so we’re folding those deploys back into our Angular family of features.
- TranquilMarmot 1y agoHave you checked out https://astro.build/ https://astro.build/ yet? You can drop in any framework where you need it, so if you need to bring along those Angular components you can but you can also lean on React if you need it.
- twodave 1y agoNo, and on a cursory look it doesn’t seem very aligned with our goals anyhow.
- TranquilMarmot 1y agoI like Remix a lot better for this use case than Next.js. Much simpler, easier to host on your own servers. Astro is also really nice and easy to learn and host.