Honestly, TypeScript and React are in such a good space now that adopting those two is a near no brainer. You need discipline to not bring in millions of other dependencies.
I've done the whole "I'll write it all in JS by hand" to a ludicrous degree: https://luduxia.com/whichwayround (and the rest) and while there were advantages when this started I am now looking to port the useful bits over to saner ways for future maintenance.
do you use React capabilities exclusively for state management? I have found that they inevitably fall apart when things get sufficiently complex, which has me reaching for one of the many MANY 'other' state management libraries.... which then sometimes has me reaching for other related things, which then....
I see lot of frontend people say this (since their baseline is "nothing"), but as someone who's used to compiled languages, all JS-ecosystem tooling is quite atrocious. It's still missing many of the useful basics that other ecosystems take for granted.
The way around this is to build your own tools. For instance, I used esbuild as a library to write a custom obfuscator that links the hand written JS and GLSL together. (This is why the shader link symbols are also obfuscated).
I came from many years of compiled languages in the games industry. I would not assume the current state of React and TypeScript is bad, far from it. There are reasons this stuff has eaten away at more native approaches, or inspired things like SwiftUI.
Edit to add: To also add that in my time I've seen more WebKit added to games in order to do the UI. For instance, that Sim City which was always connected to the cloud, or big bits of the PS4 interface.
I have never met an existing ecosystem where building your tools did not make your life easier, at least in the short term. The trick is knowing when to abandon them in favour of a standard solution.
To put this in perspective one team I was on built their own Android NDK, until the normal one caught up.
Can you describe some of those basics? In my experience, the JS ecosystem is surprisingly good, and most of the issues tend to be due to a lack of experience rather than directly tooling issues. For example, NPM is one of the better package managers out there, but like all package managers, if you haphazardly chuck dependencies at it, and don't pay attention to what you're going, you're going to have issues. A lot of people run into those sorts of issues and assume that this is a general NPM problem, but it doesn't have to be that way.
Two blatant ones: 1. conditional compilation (typecheck and use these apis only in some environments), and 2. being able to compile "hello world" in under 1 second. I know I keep finding more but these ones I can't even write trivial programs without running into.
I've been trying to emulate conditional compilation using multiple directories, but that runs into problems with each tool using different path lookup logic.
This sounds more like lack of knowledge/experience of the tooling rather than problems with the tooling itself.
Many build tools will “tree-shake” unused code and support conditionals when compiling their bundles.
Build time varies considerably depending on the tooling you use and the size/complexity of the project, and is definitely much slower than many other languages, but while developing people will use incremental builds which can complete faster than you can type a new statement.
Ignoring the massive vtable problem for a moment ...
If tree shaking is so good, show me how to write something like this:
* when targeting browser, use dom
* when targeting node, use process/fs
* typescript should bail out if a mixture of APIs is used. That is, the type-checking must be done twice - once for browser-only, once for node-only.
(nodejs is also rather abominable for implementing APIs that really, really only make sense in browsers, like `navigator`, breaking everybody's runtime detection, but all non-browser environments require evil hacks anyway)
The obvious way is to use separate configs for each target - most bundlers support running these builds in parallel.
It seems like you are trying to do something in a specific way instead of using the available tooling correctly. That’s not a problem with the tool. You just need to RTFM
As for the “massive vtable problem”, that’s not even a tooling issue. Why are you even using JavaScript if that’s a problem for you.
For your case 1 my extended obfuscator does do preprocessor style stuff, but that is a giant hack.
For case 2 you can use esbuild, not something like webpack. Sub second builds are completely normal if you pick the right bundler. Tbh esbuild is the killer thing that moved this mode of js development into being acceptable from a total mess.
The problem with `esbuild` is that it silently does the wrong thing whenever there are type errors. The main job of a compiler is producing error messages; actually producing an output file is secondary.
`tsc` is so slow that it seems the least bad approach in use is "automatically run it asynchronously in the background", which is not confidence-inspiring.
You can separate type checking and building. Have tsc to check types and esbuild to build. These can run in parallel, or at different stages of your pipeline.
The background asynchronous incremental typechecking is how most typescript devs are working anyway, as issues are immediately highlighted or otherwise output in your dev environment of choice (whether that be inline, or as output in the console).
I've done the whole "I'll write it all in JS by hand" to a ludicrous degree: https://luduxia.com/whichwayround (and the rest) and while there were advantages when this started I am now looking to port the useful bits over to saner ways for future maintenance.