News for hackers. Stuff that matters.
Re:Second-Guessing the Modern Web by notJim on Thursday September 21, 2023 @08:15PM (#37606246)
I think a big reason that old-school server-side rendering (i.e., templates) isn't popular anymore is that templating languages are horrible and stuck in 2005. An underrated pro of react [1] + typescript is that you get to write your UI logic in regular typescript, and you get real function signatures for all your UI components. This makes it way easier to write reusable components, because you can specify the arguments, and write regular unit tests against them, etc.

With most templating languages, there is no defined function signature (with arguments and types specified), so you get to read through the template to figure out what data to pass in. This makes it very hard to make things reusable. And similarly, templating languages are often some bizarre, janky custom language with pipes and stuff.

At a previous employer, we actually solved this problem. We implemented a pattern that gave us real typed interfaces for UI components rendered with templates on the server. We were doing this the same year that React came out, and clearly had some of the same thoughts as Dan Abramov did, although not in the browser.

I recently started a side-project in javascript for the first time in years, and was surprised to discover that there is apparently no modern open-source library for rendering server side components, other than rendering react on the server of course. Your options are basically react or using some shitty templating language. I went with react.

1: When I say react, please understand it to mean any of the nice modern frontend libraries, like react, vue (is this still a thing?), svelte, etc.

Re:Second-Guessing the Modern Web by simonw on Thursday September 21, 2023 @08:19PM (#37606273)
I find the popularity of JSX-style templating really surprising.

    <div>
      <h1>Conditional Display and Looping in JSX</h1>
      <ul>
        {this.state.items.map(item => (
          item.show ? <li key={item.id}>{item.name}</li> : null
        ))}
      </ul>
    </div>
That seems like such an unintuitive way of implementing loops and if statements!

I helped design the Django template language, where the above would look like this instead:

    <div>
      <h1>Conditional Display and Looping in Django Template</h1>
      <ul>
        {% for item in items %}
          {% if item.show %}
            <li>{{ item.name }}</li>
          {% endif %}
        {% endfor %}
      </ul>
    </div>
I do like the type signature aspect of it that you're talking about - I've found myself wanting that for Django templates in the past, to the point that I've started figuring out patterns for populating templates using typed Python dataclasses as opposed to anything-goes-dictionaries.
Re:Second-Guessing the Modern Web by jakelazaroff on Thursday September 21, 2023 @08:34PM (#37606401)
Here's my perspective, as someone who's done a lot of JavaScript app development and recently onboarded into a Django app:

- JSX composes normal JavaScript expressions. That means that every operator/function/etc I have access to in JavaScript is also available within JSX. With Django templates, I need to create a custom tag or filter.

- JSX desugars to a normal JavaScript expressions. That means I can store it in a variable, return it from a function, etc.

- JSX returns a structured object, rather than a string. That means it can be used to support output formats other than text. This isn't so much of an advantage for web dev, where everything is a string, but it's a "least worst" situation if you use other targets like React Three Fiber, React Native, etc.

- The aforementioned type safety is nice!

On the other hand, I imagine Django templates are significantly more welcoming if you're more familiar with HTML than JavaScript.

By the way, the ternary in your JSX example can be removed by filtering the array:

    <div>
      <h1>Conditional Display and Looping in JSX</h1>
      <ul>
        {this.state.items
          .filter(item => item.show)
          .map(item => <li key={item.id}>{item.name}</li>)}
      </ul>
    </div>
Re:Second-Guessing the Modern Web by 38 on Thursday September 21, 2023 @10:10PM (#37607069)
> By the way, the ternary in your JSX example can be removed by filtering the array

that doesn't make it more readable. its still a blob of typical unreadable functional garbage.

Re:Second-Guessing the Modern Web by the__alchemist on Thursday September 21, 2023 @08:23PM (#37606313)
I love Django. I will be the first to throw spears at modern JS dev. Django's template language works well for simple cases. By design, it is restrictive compared to a proper programming language. I find this to be problematic.

For things beyond if/for statements, the solution is usually to write custom tags in a DSL that I have a hard time grokking. With JS, you can write arbitrary logic in an imperative language.

Re:Second-Guessing the Modern Web by simonw on Thursday September 21, 2023 @08:33PM (#37606390)
Personally I've come to prefer the design of Jinja, because it supports a larger set of Python syntax. I like that Jinja lets you use full Python expressions.

We designed Django (back in ~2003) with the idea that it should be usable by frontend developers who just worked in HTML and CSS, which isn't really a category that exists much today any more.

We used {% %} for tags rather than XML-style partly because we wanted the tags to remain visible in Dreamweaver!

Re:Second-Guessing the Modern Web by yawaramin on Friday September 22, 2023 @12:32AM (#37607897)
Nowadays I highly recommend HTML embedding libraries directly in the programming language. E.g. ScalaTags https://com-lihaoyi.github.io/scalatags/ or (my own) https://github.com/yawaramin/dream-html

Yes, you give up the ability of designers and frontend-only people to easily work with the HTML templates. But in exchange you get quite a lot.

Re:Second-Guessing the Modern Web by lpcrealmadrid on Thursday September 21, 2023 @08:34PM (#37606405)
Came here to agree with this. Beyond basic conditionals and loops, Django templates get really hard to read IMO. Combine that with “sprinkling in” some HTMX and Alpine and you’ve got the making of a true headache that no one wants to work with, even though it technically gets the job done
Re:Second-Guessing the Modern Web by c-hendricks on Thursday September 21, 2023 @08:23PM (#37606306)
Unintuitive? It's just JavaScript, probably indistinguishable from any language that has ternary statements and .map methods.
Re:Second-Guessing the Modern Web by simonw on Thursday September 21, 2023 @08:29PM (#37606351)
Yeah, it's unintuitive.

I'm not sure how to back that up... just look at it! Weirdest way I've ever seen to implement an if statement in a template.

Re:Second-Guessing the Modern Web by jwells89 on Thursday September 21, 2023 @08:51PM (#37606520)
What makes it weird for me is the filter/map/etc with an implicit destination, since function chains like that usually get rolled into a variable. It'd get you a compiler warning in Swift or Kotlin ("Result of call to 'map' is unused", etc). Agree that a for loop reads better in this case.
Re:Second-Guessing the Modern Web by jakelazaroff on Thursday September 21, 2023 @09:00PM (#37606569)
I suppose that depends on whether you look at it as a templating DSL within a JavaScript expression, or expressions within a templating language.

A `for` loop doesn't really make sense from the JS expression viewpoint — `for` loops in JS are statements, and in languages that do treat them as expressions they usually evaluate to the last iteration of the loop. From there, the filter/map makes more sense, since it's an expression that evaluates to an array of template-y stuff.

If you see it primarily as a templating langauge, though, the `for` loop makes way more sense — every iteration, it's adding a string to the template.

Re:Second-Guessing the Modern Web by zogrodea on Thursday September 21, 2023 @09:08PM (#37606631)
I agree that React's (and maybe other frameworks? I don't know them) conditional rendering syntax is very odd.

Like {my_bool && <Component />} instead of (if my_bool then <Component /> else null).

Or {my_bool || <Component />} (which is harder to express in most other languages because of Javascript considering truthy/falsy values instead of boolean true/false).

I am a fan of the UI-as-code approaches (as opposed to UI-as-markup or server-templating approaches) that React has though because of the other arguments you see in this thread, although the syntax could be better for React specifically. Elm is honestly pretty great in my opinion, and Flutter also has a nice language for describing UI as code. React just has less-than-optimal syntax.

I don't have a problem with map, though, except that I would like to extract the mapping function out of the "main view" into its own parameterised function that takes a list of whatever it needs.

Re:Second-Guessing the Modern Web by Scarbutt on Thursday September 21, 2023 @08:32PM (#37606383)
A subset of Javascript though.
Re:Second-Guessing the Modern Web by TylerE on Thursday September 21, 2023 @09:26PM (#37606748)
Personally I think ternarys should die in a fire. I despise them. Like, of all the thing validly deserving of syntactic sugar... that's the case that's "important"? It's neither especially common, nor is the sugar very nice to read.

As soon as you need a 3rd leg you have to rewrite it as a full blown if/case/whatever anyway.

Re:Second-Guessing the Modern Web by jakelazaroff on Thursday September 21, 2023 @10:37PM (#37607213)
Not sure why this is getting downvotes. Ternaries are at best a necessary evil in JSX. We'll all be rejoicing when pattern matching finally lands in JS [1].

[1] https://github.com/tc39/proposal-pattern-matching

Re:Second-Guessing the Modern Web by Scarbutt on Thursday September 21, 2023 @08:31PM (#37606370)
I wonder why JSX didn't just go all the way with the language (arrays and objects) to represent html tags and attributes, it would have cut the noise by 50%.
Re:Second-Guessing the Modern Web by arkis22 on Thursday September 21, 2023 @08:55PM (#37606546)
If you do proper server side rendering you wouldnt even have if statements in the template. your backend code should have divided everything into correct buckets for you to iterate through them. application logic shouldnt be in your view.
Re:Second-Guessing the Modern Web by ickelbawd on Thursday September 21, 2023 @08:59PM (#37606562)
Maybe because you’re thinking of it like a template language. It is not. It is JavaScript through and through. And mapping over an array is quite idiomatic. So are ternary operators. If you really prefer you can pop that out into a for loop with a full-blown if statement, but that’s not very common—at least not in React.

I think the long history of being served over the wire drove the community to prefer shorter, more terse code.

Re:Second-Guessing the Modern Web by 38 on Thursday September 21, 2023 @10:08PM (#37607045)
> Maybe because you’re thinking of it like a template language.

I think they just looked at the JavaScript example, and realized how ugly/unreadable it was, and said "I can do better", and they did. the Django example is actually clear and readable about whats going on.

the fact that the community converged on the current monstrosity should bring great sadness, not rationalizations.

Re:Second-Guessing the Modern Web by ickelbawd on Thursday September 21, 2023 @10:58PM (#37607328)
It’s not rationalization. It’s preference. There were plenty of templating languages in Javascript before React came along.
Re:Second-Guessing the Modern Web by lmm on Thursday September 21, 2023 @08:48PM (#37606502)
I've still found nothing that can match up to what Wicket was doing 10+ years ago. Your are self-contained, and know how to render their own markup. Any "templates" live with the components and are tightly coupled to them. Control flow lives in code and code alone; your markup specifies ids where your code can attach components, but there's no way for your markup to call back into your code, so you avoid spaghetti. It's wonderful.
Re:Second-Guessing the Modern Web by dpe82 on Thursday September 21, 2023 @09:10PM (#37606644)
I've run into this same issue when developing a DSL for generating language bindings and doing data serialization. Not having compile-time type safety is such a pain.

So I'm extending the language to feature statically typed string templates as well. It currently targets (generates) C++, but I'll add other language targets in the future.

It's still a work in progress but I just flipped the repository public in case you want to follow along as I work: https://github.com/dpemmons/typedef

Re:Second-Guessing the Modern Web by yawaramin on Thursday September 21, 2023 @09:28PM (#37606769)
> templating languages are horrible and stuck in 2005. An underrated pro of react [1] + typescript is that you get to write your UI logic in regular typescript,

Yeah exactly, which is why I always recommend DSLs that embed HTML directly in the language. E.g. https://com-lihaoyi.github.io/scalatags/ or (my own) https://github.com/yawaramin/dream-html

They make writing HTML a breeze with the full power of the programming language available.

> We were doing this the same year that React came out, and clearly had some of the same thoughts as Dan Abramov did

Dan Abramov is not the original creator of React. That was Jordan Walke: https://www.youtube.com/watch?v=GW0rj4sNH2w