It seems there’s a feature treadmill at work here where projects inexorably bloat as they get popular. But we tried “compose tools in the Unix way” with grunt too, and that led to spaghetti scripts, unique to each project, that were hard to reason about. I wonder if there is a middle way that can prevent the tool from giving in to the pressure to add features.
Babel was necessary because core syntaxes were changing so fast. Webpack’s sprawling nature was needed because there were so many alternate dialects, module systems to support, etc. Esbuild is only possible because we’ve generally converged on TypeScript, JSX, ES modules, etc. It knows what you probably were going to configure webpack to do anyway, so it can just do it.
So I wouldn’t call it a “treadmill”, I’d call it growing pains
However I think the “Cambrian explosion” point here makes a lot of sense.
Maybe things are going to calm down a bit? I could believe it. But I just don't see the churn stopping. The browser-as-OS is going to keep getting new features, which JS must bind to. And some users are going to use old browsers that don't support them. So the runtime is inexorably fragmented, vs. say a server-side environment where you mostly write code for a well-known runtime that you get to define.
And what about when everybody starts using wasm to compile other languages into JS? Another explosion of tooling and changes to how we do web development is just round the corner.
Regardless of whether we're coming to the end of it, I think it's more specific than just "growing pains" though - it's not just that we're fixing issues, it's that we're repeatedly throwing away old tools in favor of smaller, more-focused new tools, that then in turn grow in scope over time.
I'm not even mad at all this; I think it's a fundamental part of how software languages and communities make progress; there's no real path for a language/tool/framework to get _smaller_, so they either increase in scope or stay the same, with the latter being quite rare, and both options giving a path for some other thing to supersede them.
I just think it's most pronounced in the JS ecosystem, and find it amusing that we've come full circle on so many of these points, again - although I believe with genuine improvements on the previous iterations. (So more like a spiral; the same location in some dimensions, but with a higher elevation.)
I would say this is a far off possibility. The need to write WASM code rarely surfaces for the average SPA, and really seems like its more applicable to games or sites with heavy processing needs.
For better or worse, it's going to be JS/TS for a long while yet.
This is not imminent from a developer’s perspective, but I think it is close on the “language evolution” timescale. As in, soon enough that I’m not sure we will have a long period where JS stabilizes before wasm revolutionizes it again.
Not a high-confidence prediction either way though.
> [… a list of features that are already done…]
> After that point, I will consider esbuild to be relatively complete. I'm planning for esbuild to reach a mostly stable state and then stop accumulating more features. This will involve saying "no" to requests for adding major features to esbuild itself. I don't think esbuild should become an all-in-one solution for all frontend needs. In particular, I want to avoid the pain and problems of the "webpack config" model where the underlying tool is too flexible and usability suffers.
That said, now quoting you…
> But we tried “compose tools in the Unix way” with grunt too, and that led to spaghetti scripts, unique to each project, that were hard to reason about.
In this respect, ESBuild’s firm stance has a major strength, and a major weakness:
- Strength: the Unix philosophy is easy to achieve, with esbuild-plugin-pipe[2]. There’s just one, simple plugin API, everything follows that same format
- Weakness: since ESBuild doesn’t expose its AST, plugins are often slow which can undermine the benefits of the tool
I think by the time we even care about the performance of a plugin being "golang" fast, we will have rome built in rust.
Rome will be the full kit and caboodle at native speeds (bundler, tree shaking compiler, linter, type checker, etc...), whereas esbuild will be the rome-lite for when you just want to bundle some code and have it done.
I certainly care about it being faster than estree-*/babel. There are a lot of static analysis and optimization things I’d like to do that are slow enough in JS to negate a lot of ESBuild’s advantage.
> we will have rome built in rust.
> Rome will be the full kit and caboodle at native speeds (bundler, tree shaking compiler, linter, type checker, etc...), whereas esbuild will be the rome-lite for when you just want to bundle some code and have it done.
Is Rome-Rust doing something special to optimize arbitrary AST-based plugins written in JS? I hadn’t heard that but I’d be interested if it is.
Don't recall perf being the win with Webpack, Webpack was "Web-Pack" because it allowed you to use CommonJS to co-locate external assets (SVGs, CSS, etc) with code, and then being able to produce distinct bundles from that dependency graph. Grunt had no clue what your source dep graph looked like, you had to build your own pipeline (specifying dependent tasks for each task). Of course, now everybody has their own Webpack config that alters some input or output, but it's a considerably more powerful tool than Grunt ever was.
Angular ships with a working config out of the box, and I hope I never, ever will have to tweak that to fix a build.
You're forgetting the 6 months where everyone rewrote everything with Gulp.
And the one guy writing it is Evan Wallace, co-founder and CTO of Figma. I don't know how he has the time!
> Instead of attempting to get one of [HTML/SVG/JS Canvas] to work, we implemented everything from scratch using WebGL. Our renderer is a highly-optimized tile-based engine with support for masking, blurring, dithered gradients, blend modes, nested layer opacity, and more. All rendering is done on the GPU and is fully anti-aliased. Internally our code looks a lot like a browser inside a browser; we have our own DOM, our own compositor, our own text layout engine, and we’re thinking about adding a render tree just like the one browsers use to render HTML.
To most people, esbuild would be a full-time job. Based on the above, it seems that to Evan it's a fraction of the work he did in Figma's early days all at once!
This was the reason that Phoenix 1.6 switched away from webpack to esbuild, apparently half the reported issues were webpack related!
When Redux was first released in 2015, it was deliberately designed to be minimal and extensible. Other Flux libraries at the time had various forms of async handling built in (support for dispatching actions via promises, etc). Dan and Andrew wanted to avoid locking users in to any single form of async handling [0], so the middleware API was designed to let users pick their preferred async approach and syntax.
Similarly, the store setup process was entirely left up to users to add whatever middleware, enhancers, and other configuration users felt was appropriate. The docs were also always unopinionated about preferred file structures, how to organize logic, etc.
Over time, it became very clear that users _wanted_ more specific guidance about how to structure their apps, and wanted Redux itself to build in default setup and configuration.
As a result, we wrote a "Style Guide" docs page [1] that lists our recommended best practices, and created our official Redux Toolkit package [2] as the standard way to write Redux logic. RTK was designed to solve the most common problems and use cases we saw in the ecosystem [3], including store setup, defining reducers, immutable update logic, and even creating entire "slices" of state at once.
RTK has been extremely successful - we routinely get users telling us how much they enjoy using RTK [4], even if they disliked "vanilla Redux" previously.
We also recently released a new "RTK Query" API [5] [6] in RTK 1.6, which is a built-in data fetching and caching API inspired by libraries like Apollo and React Query. Again, similar theme - we looked at what users were doing and what pain points they were running into, and built an official API to help address those use cases.
[0] https://blog.isquaredsoftware.com/2017/09/presentation-might...
[1] https://redux.js.org/style-guide/style-guide
[2] https://redux-toolkit.js.org
[3] https://blog.isquaredsoftware.com/2019/10/redux-starter-kit-...
[4] https://www.reddit.com/r/reactjs/comments/px6kxy/redux_toolk...
[5] https://redux-toolkit.js.org/rtk-query/overview
[6] https://redux.js.org/tutorials/essentials/part-7-rtk-query-b...
Also, in case of working on an Electron project: How well does it handle main/render/preload compile targets and handling of native modules and linking?
Electron-forge is, for instance, the recommended toolchain for building Electron apps and the Webpack stuff is a particular pain in the ass.
It’s not. It doesn’t do hot reloading, and it’s one of the features the author rejected I think.
I guess Vite provides a nice development experience but is built on esbuild.
I'm also a huge fan of HMR, and esbuild in the past has been anti-HMR.
The config is beyond minimal. If you're using webpack you may want to look away now :-)
import { resolve } from 'path'
import { defineConfig } from 'vite'
import reactRefresh from '@vitejs/plugin-react-refresh'
export default defineConfig({
plugins: [reactRefresh()],
build: {
rollupOptions: {
input: {
index: resolve(__dirname, 'index.html'),
}
},
sourcemap: true
},
esbuild: {
jsxInject: `import * as React from "react"`
},
resolve: {
alias: [
{ find: '@', replacement: '/src' },
]
},
})I chose my now "nom de plume" way back in zeros for its seeming originality and simplicity, when compared to my rather common and unwieldy "real" Polish name.
1. It's not just a faster replacement for a single %tool_name% in your build chain: for the vast majority of cases, it's the whole "chain" in a single cli command if you're doing it right.
That is, you don't just stick it inside, say, webpack as a faster replacement for babel (although you can). No, you look carefully through your webpack configs and its myriad of plugins, ask yourself whether you really need to inline css in jsx in png while simultaneously optimizing it for IE 4.0, realize you don't, through out the whole thing, and use esbuild instead.
I have two 50K+ LOC projects using esbuild, and I would use it even if it was slower than webpack/babel/tsc simply not to worry about the build chain breaking due to an update to some obscure dependency or plugin.
2. It is fast because it's written from scratch to do a set of particular things and do it fast, not just because it's Go and parallelized.
If you look at the commit log you will notice a lot of performance tweaks. If you look into the issues, you will find a lot of requests for additional features rejected, often due to possible negative performance impact.
3. The most impressive part about esbuild development is not just that it's one guy writing it: it is the level of support and documentation he manages to provide alongside.
The release notes alone are a good course into nitty-gritty details of the web ecosystem: all the addressed edge cases are explained in detail. To top it all off--all opened issues, no matter how uninformed they seem, find a courteous response.