8 ms·
Why Htmx Does Not Have a Build Step
- meowtimemania 3y agoI just threw away an admin site written with trpc+react and rewrote it with htmx. Deleting so much code felt glorious. Everything feels more simple and as a result adding features is so much easier.
- PaulHoule 3y agoI've seen Typescript programs break between versions of Typescript more than I've seen happen in any other programming language.
- klysm 3y agoBreak meaning no longer type check or behaviorally not work?
- teaearlgraycold 3y agoI personally haven’t seen this. What kind of issues have you seen?
- Tade0 3y agoThe GP could be referring to situations where libraries have strict bounds which versions of TypeScript they work with. It's most visible in the Angular ecosystem, where both the core library and additional stuff have such bounds. For this reason Angular updates are often a terrible experience for everyone involved.
- PaulHoule 3y agoI've had trouble where the build fails with various TS#### error messages, most of the time there was some change in Typescript syntax. I guess if you use those bounds you have less of those problems.
- teaearlgraycold 3y agoThe only time I used Angular was when I had to because I was working at Google. I'd never use it outside of Google after that experience.
- nraf 3y agoI’ve found Angular updates to be mostly painless since they’ve automated most of the migrations using `ng update`. That said, I do wait 2-3 months to give time for dependencies to update.
- beanjuiceII 3y agoI have not either, and i work with over 5 million lines of typescript codebases.
- deleted 3y ago[deleted]
- ComputerGuru 3y agoMe too, but it's usually because of the weird way TypeScript was built as a thin veneer over JavaScript. Unlike a proper strongly-type, statically-compiled language with a consistent underlying framework where unsound behavior is adversarially sought out and eliminated in the very design of the language from the start, TypeScript started off as just bolting types on to JavaScript and progressed to actually sanity checking the code that a JavaScript runtime happily accepts. I just ran into a case yesterday where some code ported from JavaScript to TypeScript five or more years ago once more wouldn't compile after upgrading from TypeScript 5.1.x to 5.2.x and in this case it was a DOM event handler that for some reason (probably copy-and-paste from another location in the codebase) had a `return foo;` in a couple of the conditional statements in the event handler callback. Now obviously event handlers don't return anything, and anything they do return is ignored (perfectly normal for JavaScript). TypeScript didn't error out on that, but it did error out because not all the code paths returned a value, so it was no longer able to infer the return type. A function (that returns a value) that can execute along some logic path without returning a value is a soundness issue. Granted it didn't actually cause any problems (as the return value was always ignored in all cases, the solution was to just remove the `return` statements that never should have been there) but tsc incidentally caught something funky that never should have been in the code in the first place. So if you view incremental tsc releases as "tightening down all the bolts" then I think its behavior makes sense. I wish tsc caught everything from the start, but I'm only ever happy to see that my code no longer compiles because it means that something tsc *wrongly* accepted before is now being caught - which usually means that potentially errant runtime behavior has been identified and this is a chance for me to correct it. Which is, after all, the whole point of turning JavaScript into a compiled language - so I can catch errors (or at least as many as the TypeScript language is empowered to and the TypeScript compiler is smart enough to) at compile-time rather than at run-time. (But I'm not primarily a web developer, I hate loosely-typed languages, I absolutely abhor runtime errors, and I think any soundness holes in a language should be treated alarm bells left and right, so perhaps my opinion is not actually reflective of the average webdev.)
- dgb23 3y agoUpgrading JS dependencies is a nightmare. That includes build/dev dependencies. Part of my job is to maintain more than 50 web projects. That includes streamlining, refactoring, upgrading, optimization etc. Some of them are a decade old. The most painful and time consuming part is dealing with JS issues. To anyone reading this: cut the fat and do it early. A little bit of perceived “DX” is not worth writing “npm install”. Just write the code that needs to be written in a straight forward manner. Lean on standards and don’t get distracted by fads. Prioritize stability. Use libraries that do so as well.
- debug-desperado 3y agoThis is usually the Typescript team tightening up some "loose" behavior that should have had saner defaults. For instance, the catch block default typing changed from unknown from any. The bigger issue I've found is when you're using 3rd party type definitions for some library you can't always trust them to be correct or updated. It's a major risk for the soundness of your build.
- pictur 3y agoThe answer is simple: it offers simple things as a simple library. I really liked the effort to explain this so long. You shouldn't even be satisfied with that, my friend. I'm looking forward to the htmx nutshell book. you can write it.
- bingemaker 3y ago> It’s certainly not true for Python, or Java, or C As far as the C code that I've seen from the past (early 2000s), they do compile pretty fine even today. I doubt if "C" belongs there.
- tedunangst 3y agoI think gets() was the only function removed from C11? That complaint seemed really odd.
- dvdkon 3y agoI've had lots of old C code refuse to compile on new compilers out-of-the-box, not to mention that you'll likely need to track down old versions of dependencies as well. Sure, you can always get it all to compile with no changes to the code, but the process can be arduous and the result can basically have its own OS's worth in libraries attached to it (not that modern languages are any better here...).
- torstenvl 3y agoThis was a bizarre comment in the OP article, with an even more bizarre reasoning: they "all have versioning mechanisms where opting for new language features will force you off of deprecated APIs" C code from 1999 will, unless written by a literal psychic, not have "opt[ed] for new language features" that arose in the interim.
- semiquaver 3y agoCrossing my fingers that the proposal for allowing (browser-ignored) type annotations in javascript progresses: https://tc39.es/proposal-type-annotations/ https://tc39.es/proposal-type-annotations/ Between that, HTTP2/3 and ES modules many of the downsides for building apps with no compile step are almost completely mitigated.
- benatkin 3y agoWouldn't that conflict with possible future optional static typing? It's only Stage 1. I'm hoping it doesn't make it in its current form. Some good discussion in the issues, though: https://github.com/tc39/proposal-type-annotations/issues https://github.com/tc39/proposal-type-annotations/issues
- Someone1234 3y agoCan you explain why the two proposals would "conflict?" Seems like they're proposing the same thing to me.
- benatkin 3y agoIt would be hard to separate ignored ones from ones that would use a possible future optional static typing system. They would possibly have to use a different, uglier syntax.
- Someone1234 3y agoI'm not sure I follow. Both proposals are suggesting that browser's engines ignore the syntax completely to allow some other, external, process to check them. They use slightly different wording but are describing the same basic idea: This syntax will be ignored entirely and then optional/other process can use this area for whatever.
- benatkin 3y agoThere are other languages that have optional static typing that don't treat types as comments. JavaScript could evolve to add support for this.
- ikekkdcjkfke 3y agoI remember going from just having to hit F5 to waiting for a "hot" reload, angular js -> angular 2. Sad times
- peferron 3y agoI like hot module reloads more than F5 since it preserves the state of the page. I don't use Angular though, but with Vite + React it's extremely quick.
- yellow_lead 3y agoI tried to use htmx but the client side templates extension (allowing you to transform json into html client side using a template) doesn't support json arrays. Maybe I don't understand the right way of doing things with htmx, but returning large amounts of html seemed like it's a waste of bandwidth to me. That said, I appreciate htmx not having a build step. Even tailwind gets annoying to me.
- nisegami 3y agoIt's not surprising that HTMX didn't allow you to do that because that's pretty explicitly not what it wants to be. HTMX is all about sending HTML over the wire, not JSON. If your HTML/JSON is gzipped, it shouldn't be significantly different in terms of bandwidth. Plus, you're not bundling nearly as much javascript with your site compared to a heavy client side framework, not to mention savings from avoiding processing more than just the DOM update on the client.
- loloquwowndueo 3y agoReturning partial HTML from endpoints is the whole point of htmx. If your endpoint returns json and you’re trying to convert that to HTML to use with htmx, don’t bother - just use another “traditional” Js framework. I highly recommend the “building hypermedia systems” book (free at https://hypermedia.systems/ https://hypermedia.systems/) so you can understand the HTML/ hypermedia architecture of which htmx is a key component and how it’s meant to be used.
- yellow_lead 3y agoThanks, will take a look at the book. Your points make sense, but having an extension dedicated to this made me think returning JSON may be ok.
- loloquwowndueo 3y agoIf you have an endpoint that returns json and you can’t change for legacy, historical, compliance reasons, it might make some sense to integrate with an application that uses htmx the way it was intended and only needs that one weird legacy endpoint returning json to be converted to HTML client side. That sounds like the use case for that extension - the other explanation is someone wanting to jump on the htmx bandwagon without understanding the philosophy, and so trying to keep returning json, converting to HTML on the client and then trying to shoehorn this into a hypermedia architecture :)
- simonw 3y agoI liked Julia Evans' take on this: https://jvns.ca/blog/2023/02/16/writing-javascript-without-a-build-system/ https://jvns.ca/blog/2023/02/16/writing-javascript-without-a... """ My goal is that if I have a site that I made 3 or 5 years ago, I’d like to be able to, in 20 minutes: - get the source from github on a new computer - make some changes - put it on the internet """ Front-end build scripts make sense for projects that are constantly developed by a team that is actively ready to incrementally fix any problems that come up. For sites that only get maintained every year or so (and I have plenty of those myself) my experience is that they often cause more problems than they solve. I also found that I started really enjoying JavaScript development again once I gave myself permission to ignore the npm/webpack/etc script world entirely and just write regular code that runs in browsers!
- alexpetros 3y agoI can't believe I forgot about this! I love Julia's writing, I cited a different blog post of hers in this piece.
- Raed667 3y agoI don't understand this issue. With a proper `package-lock` and `nvm` i picked up 3 or 4 year-old projects, installed everything with one `npm install`, made my changes and never faced a problem. Edit: I remember facing one issue with `node-gyp` but that was just a poor choice of packages that were trying to be too native.
- cxr 3y agoExperiences vary wildly. > With a proper `package.lock` I've never heard of package.lock. Are you as familiar with the subject as the general tone of your comment implies?
- Raed667 3y agoMy bad I meant `package-lock`, updated for clarity. > Especially when the old project in question is not yours Then it falls out of the stated scope of "updating my small website once every 5 years or so"
- ComputerGuru 3y agoI agree with the main points in the post and certainly understand how they could push one in the direction that htmx has taken, but for me (and I posted a long comment along these lines as a reply in this thread elsewhere) the benefit of TypeScript isn't just the type safety but also that it forces you to explicitly provide more strongly-structured, parseable context info (regarding your intent in the codebase) that can be used to further empower static analysis tools (whether it's the TypeScript compiler or various linters à la eslint and co) to pick up on discrepancies between what the code is supposed to do and what the code does. I view JS as a particularly unreliable language to build solid (as in dependable, consistent, coherent, and sound) projects in, and the various build tools are just ways to at least partially overcome those inherent shortcomings of the language. Transpiling from ESNext to ES5, merging disparate source components, etc are all just icing on the cake and not the real reason to use TypeScript (though I am surprised that the article talked about its ECMAScript version restrictions caused by IE11 support but didn't talk about how w/ TypeScript you can use language-level (not library-level) features such as the spread operator, for ... of, async/await, etc. and have them automatically converted/transpiled to functional equivalents that work on ES5 browsers). Just look at how the various @typescript-eslint/* packages can supplant basic eslint rules, replacing them with more precise variants¹ by using the extra information provided by the TypeScript AST instead of just the info surfaced by the JavaScript AST. ¹ Let alone the existence of the hundreds of additional lints that are only possible for TypeScript codebases.
- NelsonMinar 3y agoI love this, particularly its clear-eyed summary of some of the tradeoffs. Gonna be honest: build systems have completely robbed the joy from writing simple frontend hacks for me. I no longer use them, which means I just can't use a whole lot of Javascript frameworks and libaries. Oh well.
- spankalee 3y agoCompilers should be optional, in a two senses of the word: 1. Even if you use a language like TypeScript in your library, your users shouldn't have to. Provide types to them, even provide features like decorators, but have first-class and ergonomic ways for plain JS users to accomplish the same task. 2. Frameworks don't need compilers. All the reasons those that do claim to have them: especially performance, ergonomics, are disproven as requirement by libraries that meet or exceed them on those axes. You especially don't need to fork JS and HTML, and doing so fragments the web dev ecosystem, and causes tool friction, for very little gain. You can offer a compiler, but it should be an optional optimizer. However, even as compilers should be optional, I also think they should be possible. If users want TypeScript to check their work, and especially if they're in large teams and organizations where extra checks help collaboration, your approach shouldn't prevent it. And if you're doing things in a language without traditionally good static analysis tools, like HTML, you should try to provide them, otherwise your approach really doesn't scale due to ever-increasing fragility as your code base and team size grows.
- max_ 3y agoI was recommending htmx to some of my friends and they asked me "What does it add?" I told them that it's value proposition was not that it "added" anything but that it "eliminated" things, like build systems, configs, and the need to use js frameworks in incidences where it's an overkill (which in my experience is majority of the cases) HTMX is a good example/manifestation of Nassim Taleb's "Via Negative" heuristic i.e some systems can improved simply by the removal of components that are dangerous, ineffective or cause friction. As opposed to trying to improve systems by trying to add components that we think will make a system better. [0] A lot of technology is focused on improvement by adding, but I think we should start thinking more in this paradigm of improvement by subtracting — subtraction complexity that makes systems more difficult to maintain & build upon. [0]: https://coffeeandjunk.com/via-negativa/ https://coffeeandjunk.com/via-negativa/
- dunk010 3y agoReminds me of this: https://programmingisterrible.com/post/139222674273/write-code-that-is-easy-to-delete-not-easy-to https://programmingisterrible.com/post/139222674273/write-co... “Write code that is easy to delete, not easy to extend.”
- yawaramin 3y ago“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” ― Antoine de Saint-Exupéry
- cdcarter 3y ago"do more and more with less and less until eventually you can do everything with nothing" - R Buckminster Fuller
- jmull 3y agoWell... there still has to be a reason to use htmx, or else why not cut it too?
- dventimi 3y ago
- can3p 3y agoI think build systems are a very big reason for the mess javascript is in nowadays. - Typescript is very light from the code transformation point of view. If anyone remembers the output of babel especially for async/await + the way module imports are implemented generates a really hard to read code and the "best practices" about hiding the state make things a lot harder. Just think about the fact that back in the days (tm) it was common to inspect the state of the app and change it full lisp style and now the js console can mostly be used for quick code tests and looking around when execution is stopped at breakpoint and you can't see that much anyway because of how the code is generated. - The whole babel thing still feels like a madness to me. Yeah, you're getting some new language features but for the price of non obvious code transformation that makes you need source maps (and you need to make them work and maintain that) and all the rest - Build step + npm results in on controlled bloat of the js bundle. `npm install <random-component>` may inflate you bundle by 500kb easily - And with all that there is still a quite big trouble with requiring necessary modules for the use on frontend. Just think that there is still no simple way to require all css provided by a library from npm Another big problem on my opinion is the propagation of "write once/use everywhere" approach. It works sometimes yeah, but you need to sell your soul for that: you'll have to use something like next.js and that implies that you're bound to use node.js and then you either do all your development in node or have another service doing stuff in the language of your choice and then have a node service as a templating layer and then you need containers and orchestration and so on which makes it a technically challenging project for something that almost for sure can be done in some trivial set of technologies if this requirement had been dropped. One could argue that we need a different approach with libraries that acknowledges that frontend is distinct world and aims to provide ready made components specifically for the web with an easy setup and no/minimal dependencies. Maybe even with a vendor folder like approach, since the won't be too much code anyway. That should be enough for 99.999% of projects and the rest can use the full scale approach and embrace complexity if they really need it.
- mamcx 3y agoDependency hell IS hell. I broke my dev machine because a bad application of reps + brew, and triying to reinstall all was a messy mess. Now I doing things with nix, and is almost good, yet I can't escape dependency hell completely...
- TheCapeGreek 3y agoI like that the trend cycle is now moving towards simpler systems with good DX instead of yet another React competitor.
- sebazzz 3y ago> Would code written in those TypeScript versions compile unmodified in today’s TypeScript compiler (version 5.1 at the time of writing)? Maybe, maybe not. Definitely not. Typescript upgrades are nearly always breaking in some way. But the fun really starts when upgrading typings (type definitions), or when a library that used to have no typings starts including typings which are more often than not not compatible with the 3rd party typings causing a whole headache by itself. I love the concept of Typescript but I’m glad I left it behind in favor of Blazor (laugh if you want). It allows me to focus on the customer problems in the limited time I have rather than fixing my build for the Nth time. Also, lately the Typescript type system has become more complex and the typings itself have also grown more complex, with things like: export type SomeType = IPickOne<SomeOtherType,SomeProperty> | IPickExcept<SomeOtherType2,SomeProperty2>; Utterly insane and you need to pre-compile the types in your mind or rely on auto-complete to understand them. I get idea that some parts of the front-end ecosystem are designed to be busy work, or at least usually turn out to be. But not all of us work in a SaaS development team that can affort 30% or 40% to just play with front-end build systems. Some of us work for clients instead, and need to make the best of the time we have. And more often than not, that means excluding risk factors like large parts of the NPM ecosystem. Limiting things to some simple gulp, dart-sass and some terser to “build” the front-end.
- jsmm 3y agoMaybe, slightly off-topic. I recently started developing with htmx and go and it's been really very productive for me as I am not a front end developer. But there are still some usecases, where I need to use JS, like a simple 'hide and show password field'. I had to use htmx:on JavaScript to make it work. I am for no build as it keeps development and debugging simpler.
- emadda 3y agoI often use vanilla esbuild installed via NPM. I feel like this build step would still work in 5 to 10 years: - esbuild is compiled into a single binary for each target system so has minimal dependencies. - NPM makes the version immutable, and will download the same binary version on ‘npm install’. - I will use .tsx as my extension but use only pure JS, this gets me IDE suggestions without writing TS types, which works well for small projects. Compared to webpack, esbuild seems unbreakable.