[HN Gopher] Why Is Esbuild Fast?
       ___________________________________________________________________
        
       Why Is Esbuild Fast?
        
       Author : mef
       Score  : 229 points
       Date   : 2021-02-16 15:07 UTC (7 hours ago)
        
 (HTM) web link (esbuild.github.io)
 (TXT) w3m dump (esbuild.github.io)
        
       | lefrenchy wrote:
       | I've really wanted to use Esbuild in my projects but I haven't
       | figured out a great way to get the desired functionality I want:
       | 
       | I'd like to be able to transpile my code but keep the same
       | directory structure in the output. For example, I have an
       | index.js file that exports all my components and I'd like to just
       | create a "build" folder output with the same exact file
       | structure, but with all the files exported from index.js having
       | been transpiled.
       | 
       | Does anyone know if that is supported?
        
         | keb_ wrote:
         | Hey, I was trying to do this same thing for a TypeScript
         | project I was bootstrapping. Digging around the issue tracker,
         | I recall the maintainer stating that this is currently not in
         | the scope of esbuild, and that swc[0] might be better suited
         | for this.
         | 
         | Personally, I wrote a crude JS script using the esbuild
         | transform API + node-watch to compile .ts files and copy
         | files/folders during development. This is all very recent, so I
         | can't ensure that it's bulletproof quite yet.
         | 
         | [0] https://swc.rs/
        
         | joshum97 wrote:
         | Esbuild does have a JS transform API, so you could write a
         | command line tool that walks the file system (Babel, ESLint,
         | Prettier, etc. all do this so you have examples), transforms
         | each file, and writes the code back out. Snowpack's build
         | command also does this.
        
       | TheRealPomax wrote:
       | I've started using microbuild instead of parcel/webpack, and
       | while I'd like to know how this compares, microbuild is so small,
       | and so far, that I have no reason to actually try that benchmark
       | myself. Would be nice to see how it compares in the graph,
       | though.
        
       | crazypython wrote:
       | I just serve my ESM modules directly from the filesystem. It
       | works well, builds in literally 0 seconds.
       | 
       | You also don't need a transpiler like Babel if you drop support
       | for IE11. Almost all ES6 features- such as classes, proxies,
       | arrow functions, and async are supported by modern browsers and
       | their older versions. As long as you avoid features like static,
       | private, and ??=, you get instant compile times.
       | 
       | It's not 2015. You don't need a transpiler to write modern
       | JavaScript. As of writing, the latest version of Safari is 14 and
       | the latest version of Chrome is 88. These features fully work in
       | Safari 13 and Chrome 70, which have less than 1% of marketshare.
        
         | brundolf wrote:
         | I would say the primary motivators at this point have shifted
         | from browser compatibility to syntaxes like TypeScript and JSX
         | that will (likely) never be supported natively
        
           | crazypython wrote:
           | > I would say the primary motivators at this point have
           | shifted from browser compatibility to syntaxes like
           | TypeScript and JSX that will (likely) never be supported
           | natively
           | 
           | I suggest using a single-pass transpiler like Surcase[0] that
           | doesn't translate to IE11-compatible syntax, and just loops
           | through the string once, avoiding generating an AST- making
           | it much faster- removing TypeScript annotations and
           | desugaring JSX.
           | 
           | If you additionally need to support IE11, you can use a
           | development build with Surcase and a production build with a
           | bundler like Snowpack. C/C++ developers have been doing
           | things like this for ages: compiling files as objects during
           | development, and compiling them into one big binary for
           | production.
           | 
           | [0]: https://github.com/alangpierce/sucrase
        
         | nicoburns wrote:
         | Alas, many of us still need to support IE11. We alas get a lot
         | of value out of TypeScript, which needs to be transpiled. <1
         | second with esbuild is pretty good!
        
           | runarberg wrote:
           | You can annotate your code with JSDoc comments and get the
           | full value of TypeScript while just writing JavaScript
           | without any transpilation step[1]. It won't help you with
           | IE11 support though.
           | 
           | 1: https://www.typescriptlang.org/docs/handbook/intro-to-js-
           | ts....
        
             | pitaj wrote:
             | That's a helpful feature but it's by no means a replacement
             | for Typescript. You _do not_ get the full value with just
             | inline comments, in fact that usage is extremely limited.
        
           | crazypython wrote:
           | Here's my suggestion if you want faster builds:
           | 
           | In development, use an index.html that loads it directly from
           | the filesystem, using a single-pass annotation remover such
           | as https://github.com/alangpierce/sucrase A single-pass
           | transpiler doesn't build an AST, instead just looping over
           | everything once, which will surely make it faster than
           | esbuild.
           | 
           | In production, use a bundler like snowpack.
        
             | ljm wrote:
             | What you're saying there is: in development, use sucrase.
             | In production, use sucrase.
             | 
             | And saying it quite a lot in this thread.
        
               | crazypython wrote:
               | Sorry, I meant to say use snowpack.
        
         | SahAssar wrote:
         | If you have any third party dependencies you still need
         | something like snowpack though, right?
        
           | crazypython wrote:
           | I don't have any third-party dependencies. We all agree the
           | JS ecosystem sucks.
           | 
           | When I do, I use a script tag, and put it before my ESM
           | modules:                   <script
           | src="/scripts/data/contractor.js"></script>
           | 
           | Use them via global variables.
           | 
           | I generally avoid third-party JavaScript modules for
           | performance and maintainability reasons. When I do use them,
           | I'll frequently vendorize them (put them in my source tree)
           | and make ESM modules for them.
        
             | thitcanh wrote:
             | So you're the one writing everything from scratch even
             | though the wheel has already been invented and perfected
             | and tested over years by many developers.
             | 
             | Also your website is serving dozens of cascading files
             | instead of a single minified one.
             | 
             | Feels like 2010 to me.
        
               | ratww wrote:
               | It's the opposite.
               | 
               | Bundlers aren't the "wheels" here. The real "wheels" here
               | are ESM modules, which have been available in every
               | modern browser for a while. Bundlers are just pre-wheel,
               | prehistoric, stopgap technology from the 2010s that we
               | should be moving away from.
               | 
               | And there's no problem serving multiple files in 2020
               | because we have HTTP2 multiplexing now. In fact, it's
               | probably more efficient than using bundling, because you
               | can cache much better. Minification is also virtually
               | unnecessary with Brotli, and not minifying has the added
               | benefit of making the debugging experience much better.
               | 
               | And bundlers haven't been "perfected". Not even close.
               | Webpack is without a doubt the worst piece of technology
               | in my stack right now, together with Babel. Those two are
               | terrible by themselves, but they also manage to "infect"
               | other things elsewhere in my stack: for example, ESLint
               | and Jest need Webpack/Babel plugins to work.
        
             | antihero wrote:
             | > We all agree the JS ecosystem sucks.
             | 
             | I mean there's a lot of garbage out there as with any
             | ecosystem but saying "we all agree the JS ecosystem sucks"
             | reeks of immaturity.
        
             | SahAssar wrote:
             | Right, but that is basically saying we should all go back
             | to something similar to before npm/bower/etc.
             | 
             | I love using plain ESM and I prefer to pull in stuff that
             | only relies on that. But when I need graphing on a single
             | page I'm not going to try to vendor Vega and I'm not going
             | to pull it in on all pages. When I need xls parsing I don't
             | want to vendor xls.js and maintain the diff myself.
             | 
             | So I have to use something like snowpack to make it work
             | with my ESM system and dynamic imports.
             | 
             | If you don't have to require heavy libraries for certain
             | pages then that's great and I encourage to use pure ESM
             | without build systems for that, but you should also
             | recognize that not all use-cases are ready for it.
             | 
             | Currently I use snowpack to handle dependencies but still
             | run all my own code unbundled and unminified.
        
               | crazypython wrote:
               | For Vega, I would use the pre-built minified ES5 version:
               | https://github.com/vega/vega#es5-support
               | 
               | Add a <script src=> tag.
               | 
               | Access it by object destructuring a global variable. You
               | can access ES5 stuff from ES6, just let ES5 run first.
        
               | [deleted]
        
             | johnghanks wrote:
             | > I don't have any third-party dependencies
             | 
             | So your use-case is niche. Why even bother commenting? If
             | you want a pat on your back and a cookie you're not going
             | to get either here.
        
           | largemoose421 wrote:
           | If you're using straight ESM then you don't need any build
           | tool a lot of the time. If I need any 3rd party module it's
           | either include it in global using an ES5 library, or use
           | https://www.skypack.dev/ which has a ESM ready built module
           | of most npm packages that you can import directly in your
           | code.
        
         | krainboltgreene wrote:
         | > You also don't need a transpiler like Babel if you drop
         | support for IE11
         | 
         | I really dislike this line of thought: Babel isn't just a
         | polyfill tool. It's an incredible way to enhance your code.
         | Further, the future of javascript changes isn't static and
         | shouldn't be.
        
         | ko27 wrote:
         | 1. How do you handle npm dependencies that don't expose ES
         | modules?
         | 
         | 2. How do you handle the performance impact of your browser
         | doing multiple sequantial requests because it doesn't know your
         | whole dependecy tree?
        
           | crazypython wrote:
           | > 1. How do you handle npm dependencies that don't expose ES
           | modules?
           | 
           | See my comment above.
           | 
           | > 2. How do you handle the performance impact of your browser
           | doing multiple sequantial requests because it doesn't know
           | your whole dependecy tree?
           | 
           | Put all your dependencies in the HTML file, so it fetches
           | them all in parallel. So instead of just loading the root
           | application file and forcing the browser to resolve
           | dependencies:                   <script type="module"
           | src="/scripts/app.js" defer></script>
           | 
           | Load the dependencies like this:                   <script
           | type="module" src="/scripts/lib/gui.js" defer></script>
           | <script type="module" src="/scripts/lib/guielements.js"
           | defer></script>         <script type="module"
           | src="/scripts/lib/network.js" defer></script>         <script
           | type="module" src="/scripts/lib/input.js" defer></script>
           | <script type="module" src="/scripts/lib/rendering.js"
           | defer></script>         <script type="module"
           | src="/scripts/lib/sockets.js" defer></script>         <script
           | type="module" src="/scripts/lib/world.js" defer></script>
           | <script type="module" src="/scripts/lib/ui/classupgrades.js"
           | defer></script>         <script type="module"
           | src="/scripts/lib/ui/toasts.js" defer></script>
           | <script type="module" src="/scripts/lib/netstore/minimap.js"
           | defer></script>              <script type="module"
           | src="/scripts/data/configuration.js" defer></script>
           | <script type="module" src="/scripts/app.js" defer></script>
           | 
           | You can see a demonstration of this technique on my
           | production site, a complex JavaScript SPA that loads
           | everything (including dynamic content) in less than one
           | second: http://vnav.io
           | 
           | For a small performance boost, you can load smaller files
           | first via <link rel=preload>.
        
             | keb_ wrote:
             | Hi, I tried accessing your site, but seems like it's stuck
             | in this weird reload loop. It never full loads.
             | 
             | I'm on Ubuntu 20.04 using the latest Firefox, if that
             | helps.
             | 
             | EDIT: Seems to load fine in Chromium.
        
               | crazypython wrote:
               | You probably have HTTPS Everywhere with EASE mode on.
        
               | keb_ wrote:
               | Thanks, the issue was Firefox's built-in "Enable HTTPS-
               | Only Mode".
        
               | wishinghand wrote:
               | Why wouldn't the site have HTTPS enabled?
        
               | true_religion wrote:
               | An artistic or deeply philosophical choice by the author
               | that, in order to view their work, you must permit
               | yourself to be man-in-the-middled?
        
               | crazypython wrote:
               | Mixed Content: HTTPS sites cannot connect to HTTP
               | resources. The game needs to dynamically scale without
               | expensive load balancers in front. Until I get dynamic
               | DNS and HTTPS working, the site will not have HTTPS.
        
             | antihero wrote:
             | So your solution to build systems has absolutely none of
             | the benefits that build system do in fact bring, or the
             | ecosystem of a language that you might consider terrible
             | but actually has a decent amount of quality re-useable
             | code. But this works for your very specific use-case?
        
             | xyzzy_plugh wrote:
             | This is terrible advice.
             | 
             | > Put all your dependencies in the HTML file, so it fetches
             | them all in parallel.
             | 
             | > ...
             | 
             | > You can see a demonstration of this technique on my
             | production site, a complex JavaScript SPA that loads
             | everything (including dynamic content) in less than one
             | second
             | 
             | But it doesn't work like this in practice! There is a limit
             | to the number of concurrent connections a browser will
             | make, Chrome for example is <=10 IIRC. You can see this in
             | the waterfall:
             | 
             | `rendering.js`, the last `.js` in the queue, stalled for
             | 300ms.
             | 
             | Additionally, each round trip is dependent on:
             | 
             | - The user's latency
             | 
             | - Your server's response time
             | 
             | So with each connection there is overhead. You would be
             | much better served concatenating these files.
             | 
             | `util.js` took 510ms, of which 288ms was spent stalled
             | (i.e. waiting for a connection) after which spent 220ms
             | waiting (time-to-first-byte).
             | 
             | Furthermore, Lighthouse gives your page a performance score
             | of 60, which isn't great. Key metrics:
             | 
             | - 1.7 seconds to paint (which is okay)
             | 
             | - 7.7 seconds to interactive (which is terrible)
             | 
             | Finally, why on earth are you redirecting to HTTP after
             | serving an HTTPS response? This makes your page load even
             | slower:                   if (window.location.protocol ===
             | "https:") {             window.location.href = 'http:' +
             | window.location.href.slice().slice(6);         }
        
             | ko27 wrote:
             | Thanks for the response, but IMO both of those solutions
             | are strictly worse than having a build step that takes care
             | of it.
             | 
             | Also, there are tools that only bundle npm deps, like
             | Snowpack or Vite. I think those would be perfect for your
             | use case.
        
       | jamra wrote:
       | I wish the Angular team put some work into integrating. They are
       | instead doubling down on webpack which is frustrating. After they
       | back stepped regarding the bazel build system I thought that all
       | was lost. Then this beauty came out. Unfortunately it's not as
       | interesting as the incremental compiler.
        
         | kylecordes wrote:
         | Incidentally, a new version of the Bazel rules_nodejs, which
         | somewhat confusingly has both browser and no JavaScript
         | support, includes an esbuild rule.
         | 
         | As for Angular CLI which relies heavily on web pack, it has
         | years of grinding tweaking bug fixing work getting all the
         | right behaviors for all the cases. It's going to take a lot to
         | re-create that in a non-breaking way using something different
         | under the hood.
        
         | deanclatworthy wrote:
         | It's still early days for esbuild. If you follow the commit
         | history there are still some weird bugs. I'd give it a few
         | months to get these things ironed out (along with wider usage)
         | and it'll be good to go.
        
           | jamra wrote:
           | That would make my day. I have a 64GB RAM PC because I work
           | on 2 or 3 angular apps at a time and since my PC is the
           | fastest I also use it for CI builds on occasion. It's a
           | nightmare to wait 20 minutes for an optimized prod build. And
           | having to upgrade everyone's RAM so they can contribute to
           | the front end is horrible. We are past 10GB of RAM required
           | to start the dev server.
        
             | nicoburns wrote:
             | 10GB!! How big is this project!? Could you split it up
             | somehow?
        
               | jamra wrote:
               | We actually just worked on splitting it up into
               | libraries. The shared library might actually make the
               | ending build larger due to it being potentially
               | duplicated (I'm not certain about this until I test it).
               | Unfortunately that has to go on hold temporarily. It is a
               | large Healthcare application in the therapy space. The
               | ending build is actually fine, but the tooling eats RAM
               | like something else.
               | 
               | Little by little I take large third party libraries and
               | rewrite them on my own to drop 5MB includes. I'm sure
               | that is part of it. Devextreme and Syncfusion are
               | libraries I would strongly recommend avoiding.
        
               | jeremycarter wrote:
               | Syncfusion added 15MB to my bundle size :( I like their
               | components but they aren't lightweight by any means.
        
       | rtsao wrote:
       | There's also a substantial writeup on the architecture of esbuild
       | in the repo [1]. It is definitely worth a read if you are
       | interested in some of the inner workings of esbuild or are
       | curious how various bundler features are implemented. High-
       | quality, in-depth architectural docs for complex projects like
       | this are exceptionally rare.
       | 
       | [1]:
       | https://github.com/evanw/esbuild/blob/master/docs/architectu...
        
       | vhiremath4 wrote:
       | Evan Wallace (the author) is also the co-founder and CTO of
       | Figma. Absolutely remarkable engineer. His co-founder Dylan is an
       | investor in our company, and I can't seem to get in touch with
       | Evan at all because he's always super heads down on something
       | meaningful (such as esbuild). Mad respect for him.
        
       | finchisko wrote:
       | can esbuild used to do quick development builds with some dev
       | server, like serve node pkg? or just for prod builds? if so, how
       | the pipeline looks like?
        
         | deanclatworthy wrote:
         | Yep https://esbuild.github.io/api/#serve
        
       | bambam24 wrote:
       | Every year some other language claim they are better than JS and
       | they are all unpopular. Just get over it, JS won the war.
        
       | aero142 wrote:
       | Slightly tangential, but I really love the minimal but effective
       | site design here. It is minimal, responsive and easy to read. Is
       | this a theme or just the author being very effective and throwing
       | together a documentation site?
        
         | constexpr wrote:
         | It is also all custom:
         | https://github.com/esbuild/esbuild.github.io. YAML files that
         | get converted to plain static HTML pages. It's designed to work
         | well without any JavaScript. Even the animated graphs on the
         | home page are done without JavaScript.
        
       | Nathanba wrote:
       | it's fast because it doesnt do the thing that everyone else does
       | to be useful which is type checking
        
         | vijaybritto wrote:
         | Nope. This is wrong. It clearly mentions that its only a
         | Javascript and CSS bundler and nothing much. It doesnt try to
         | solve every problem in the JS world. None of the other bundlers
         | do type checking by themselves. They are always through
         | plugins.
        
         | nitsky wrote:
         | This is dishonest. In esbuild's benchmarks, webpack, rollup,
         | and parcel do not do typechecking either.
        
           | endergen wrote:
           | I like the idea of having type checking moved out of the
           | watch path, or at least be in a second window watching, so
           | building is faster. But you get your type checking errors
           | too.
           | 
           | You also have the editor finding issues for you, which is
           | where I want that caught.
        
             | kylecordes wrote:
             | Yes this seems like an excellent performance boost to
             | development. Parallelize type checking and compilation. We
             | all have these many-core machines now, and so many tools
             | that single thread the world unnecessarily.
        
             | pierreyoda wrote:
             | You may want to check out this webpack plugin [1], though
             | I'm not sure how much it could get you there.
             | 
             | [1] https://github.com/TypeStrong/fork-ts-checker-webpack-
             | plugin...
        
       | xPaw wrote:
       | I recently switched to using esbuild [0] and certainly is fast
       | for minifying js and even css!
       | 
       | For my site I basically only do minifying for js, and
       | bundling+minifying for css, and it all gets done in 0.2 seconds.
       | Right now the longest time in my deploy process is actually just
       | doing a git fetch (with depth=1).
       | 
       | [0]: https://twitter.com/thexpaw/status/1358124690347339778
        
       | dawkins wrote:
       | I switched from google closure to esbuild and it is amazing how
       | fast and well it works. It even generates smaller code in my use
       | case (200k lines app). Also the creator is really nice. He
       | implemented two features I requested right away, which surprised
       | me a lot. What a great project!
        
         | nitsky wrote:
         | I submitted a couple PRs to esbuild and also found the author
         | to be kind and helpful.
        
         | ratww wrote:
         | I've seen other interactions in the issue tracker and the
         | author has been nothing short of responsive and understanding.
         | This is a project worth contributing money to.
        
         | Zacru wrote:
         | Out of curiosity, was that with closure's simple or advanced
         | optimizations?
        
           | dawkins wrote:
           | Simple optimizations, Advanced always broke my code.
        
       | julian37 wrote:
       | > Every time you run your bundler, the JavaScript VM is seeing
       | your bundler's code for the first time without any optimization
       | hints.
       | 
       | Not necessarily so: https://v8.dev/blog/code-caching
        
       | filleokus wrote:
       | Esbuild looks amazing. It seems to have been written almost
       | exclusively by one guy (evanw) during 2020. Just the main JS
       | parser file [0] is 12k lines. According to the Github stats he
       | has committed 280k lines, that's almost 1000 lines per day every
       | day since he started. Amazingly productive.
       | 
       | [0]:
       | https://github.com/evanw/esbuild/blob/master/internal/js_par...
        
         | tengbretson wrote:
         | Name a better duo than Go and massive LoC counts.
        
           | throwaway894345 wrote:
           | Seems like esbuild and its users are getting a lot of value
           | out of those LoC counts.
        
           | mseepgood wrote:
           | Yup, it was literally designed for large-scale software
           | development. Good article
           | https://talks.golang.org/2012/splash.article
        
             | Spivak wrote:
             | I think Go is a genuinely fantastic experiment testing the
             | idea that it's actually easier to write and modify long,
             | boiler-platy, but painfully explicit code.
        
               | mseepgood wrote:
               | The syntax was designed to be "just right":
               | 
               | https://talks.golang.org/2012/goforc.slide#10
               | 
               | https://talks.golang.org/2012/goforc.slide#11
               | 
               | https://talks.golang.org/2012/goforc.slide#12
        
         | acid__ wrote:
         | evanw appears to be Evan Wallace, the cofounder and CTO of
         | Figma (!?)
        
           | skrebbel wrote:
           | I'm baffled and confused that he manages to run Figma and
           | work on esbuild at the same time.
        
             | acid__ wrote:
             | Same, hence the (!?). lol
        
           | aylmao wrote:
           | Yup, that's the one! He's also the author of
           | http://madebyevan.com/. I remember seeing that WebGL water
           | experiment many years ago and being blown away. That FSM
           | Designer came in handy for some classes where I had to draw
           | FSMs too.
        
         | lucideer wrote:
         | Just to put the 280k lines into perspective, deletion rate
         | seems close to addition rate[0]; measuring the number of
         | changes made to code is also a poor proxy for productivity, but
         | is at least not quite as bad as the pure "lines added" metric.
         | 
         | [0] https://github.com/evanw/esbuild/graphs/code-frequency
        
         | Thaxll wrote:
         | Look at how good the release notes are:
         | https://github.com/evanw/esbuild/releases
         | 
         | Some serious work there.
        
         | capableweb wrote:
         | Not to be the one who is the one, but 1k lines per day sounds
         | like the opposite of productive. If you still have to
         | add/remove such large swaths of code, you're surely doing
         | something weird.
         | 
         | Still a great achievement to produce a bundler and minifier as
         | a one-person team, but not sure we should use the amount of
         | code line changes as a measure for productivity.
        
           | edoceo wrote:
           | Not weird, it's early, messy development. Perfectly normal
           | (for me anyway)
        
           | conradev wrote:
           | If you read the linked page, it was a very intentional
           | decision:
           | 
           | > Everything in esbuild is written from scratch.
           | 
           | > There are a lot of performance benefits with writing
           | everything yourself instead of using 3rd-party libraries. You
           | can have performance in mind from the beginning, you can make
           | sure everything uses consistent data structures to avoid
           | expensive conversions, and you can make wide architectural
           | changes whenever necessary. The drawback is of course that
           | it's a lot of work.
           | 
           | > For example, many bundlers use the official TypeScript
           | compiler as a parser. But it was built to serve the goals of
           | the TypeScript compiler team and they do not have performance
           | as a top priority. Their code makes pretty heavy use of
           | megamorphic object shapes and unnecessary dynamic property
           | accesses (both well-known JavaScript speed bumps). And the
           | TypeScript parser appears to still run the type checker even
           | when type checking is disabled. None of these are an issue
           | with esbuild's custom TypeScript parser.
           | 
           | 1k lines per day sounds pretty reasonable when writing your
           | own TypeScript parser, among other components
        
             | endergen wrote:
             | He's also likely referencing existing implementations and
             | so likely can create more code faster than having to think
             | of everything from scratch.
             | 
             | He's obviously changing things to be more optimal as he
             | goes, not transcribing.
        
           | CharlesW wrote:
           | > _...1k lines per day sounds like the opposite of
           | productive._
           | 
           | Relevant Macintosh folklore: https://www.folklore.org/StoryVi
           | ew.py?story=Negative_2000_Li...
        
           | filleokus wrote:
           | Productivity might be the wrong word. Discipline, grit,
           | perseverance?
           | 
           | I've written parsers/lexers/code generators by hand for much
           | smaller toy languages with no thought about performance at
           | all and those were huge undertakings for me. I was just
           | trying to convey my impressedness with some numbers that we
           | can relate to somewhat.
           | 
           | But yeah, he has a "net" loc contribution of 284-148 = 136k
           | lines of code. Assuming the code base is resonable (which I
           | don't doubt), it's a pretty big project which he has built,
           | which I'm impressed by.
        
           | aylmao wrote:
           | > 1k lines per day sounds like the opposite of productive
           | 
           | Having built a compiler before, this seems normal, especially
           | since the parser is written manually (as opposed to
           | generated). Parsers are always _a lot_ of lines of code.
           | 
           | Not all of them are the most complex, and in fact a lot will
           | just be defining all the different nodes of your AST and
           | branching on them, which, as blocks do, tend to inflate code
           | a lot. I wouldn't expect a JavaScript parser to be any more
           | compact though, or the development (especially in a codebase
           | with few contributors) to be any less "thrashy".
        
         | werber wrote:
         | Seeing someone do almost daily work on a personal project, no
         | matter the commit size, is something i find awe inspiring
        
         | lhorie wrote:
         | > Just the main JS parser file [0] is 12k lines
         | 
         | While that is impressive, I think this is also an indication of
         | a problem: the grammar is becoming unwieldy. For example, even
         | for someone as prolific as Evan, he must decide between feature
         | depth (e.g. bundle splitting) and feature breadth (e.g.
         | implementing the equivalent to @babel/preset-flow, which is
         | used by both flow and hegel[0] type systems)[1]
         | 
         | Esbuild supporting Typescript and JSX is undoubtedly a
         | byproduct of these grammar extensions having become popular.
         | But supporting extra grammar extensions does add to complexity,
         | sometimes in non-trivial ways. In Typescript, for example, you
         | can import types using runtime import syntax, making it
         | ambiguous whether running side-effects from a library is
         | intentional or not. This gets problematic once you consider
         | treeshaking and not-really-standard things like conditional
         | resolution via package.json's `browser` field.
         | 
         | It gets even more fun when you realize that module resolution
         | isn't even specified, meaning that as far as a bundler is
         | concerned, something like `import 'lodash'` means completely
         | different things for a browser vs a project installed via npm
         | vs one installed via yarn v2...
         | 
         | [0] https://hegel.js.org/
         | 
         | [1] https://github.com/evanw/esbuild/issues/79
        
           | pbowyer wrote:
           | > It gets even more fun when you realize that module
           | resolution isn't even specified, meaning that as far as a
           | bundler is concerned, something like `import 'lodash'` means
           | completely different things for a browser vs a project
           | installed via npm vs one installed via yarn v2...
           | 
           | Ugh, why does it have to be different between npm and yarn
           | v2?
           | 
           | I'm an occasional JavaScripter and yetserday wrote an
           | automation with Puppeteer.
           | 
           | The first line I wrote was                   import puppeteer
           | from 'puppeteer'
           | 
           | only for Node to fail on that. I thought that syntaxt was
           | supported, but I had to change it to                   const
           | puppeteer = require('puppeteer');
           | 
           | I've no idea if it's a problem with my Node version (12) or
           | what, but it was a real "Huh?" moment.
        
             | jdlshore wrote:
             | Modules weren't production-grade until Node version 14.
             | Before that, it used CommonJS modules ("require" instead of
             | "import").
             | 
             | It's because Node was invented before EcmaScript modules
             | existed. CommonJS worked well and supporting both was
             | awkward, so the transition took a while.
        
             | acemarke wrote:
             | FWIW, that's not an `npm` vs `yarn` thing. That's a "Node
             | has only recently added support for ES module syntax and
             | it's still mostly experimental" thing:
             | 
             | - https://nodejs.org/api/esm.html
             | 
             | - https://nodejs.medium.com/node-js-version-14-available-
             | now-8...
        
         | umvi wrote:
         | > that's almost 1000 lines per day every day since he started.
         | Amazingly productive.
         | 
         | I know what you mean, but I also hate using lines of code per
         | day to measure productiveness, and I hate it when managers in
         | corporations look at number of lines added in PRs to measure
         | how productive a dev is.
        
           | helloguillecl wrote:
           | It is actually a good way to estimate the effort and
           | complexity of the problem if you know how incredibly
           | competent the programmer is.
        
             | hinkley wrote:
             | I don't know about anybody else but for me a good
             | approximation is the time interval between the first line
             | of code and the critical line of code. The better my
             | solution the shorter it often is. In particular, 'shorter'
             | in the sense that future functionality doesn't have to
             | constantly acknowledge that code, creating a tax on new
             | features that builds until the project dies.
             | 
             | I was going to say "start of coding" but some tasks are
             | just so boring that I may procrastinate on starting it.
             | That also indicates an element of difficulty (in giving a
             | shit), but not what we're trying to measure here.
             | 
             | I discovered the Mikado Method quite on my own as a
             | consequence of trying to tackle increasingly complex cases
             | of 'large-scale' or 'top-down' refactoring before accepting
             | that as the oxyest of morons. I was sold when I realized
             | that when you finally discover the crux of the problem, the
             | 'Rome' that all roads lead to, between half and 80% of the
             | code you just wrote isn't strictly necessary. Throwing it
             | all out wholesale is how you avoid code hoarding. Yes, once
             | in a while you go out to the proverbial trash can to pull
             | something back out that you actually did need, but the
             | tabula rasa aspect is profoundly useful psychologically,
             | especially for that 'tax' bit I mentioned above.
             | 
             | There is always some function in the middle of the call
             | tree, that if you add or change the meaning of an argument
             | then the feature or bug fix becomes a logical conclusion of
             | that new semantic. Either the code above it or below it
             | hardly needs to change, decoupling the feature from all but
             | a handful of functions/concerns.
             | 
             | A bad programmer will happily plow through adding a new
             | argument to fifteen method calls and then propagating that
             | change to a hundred call sites. And that code will be buggy
             | as hell because their coworkers have already written them
             | off. If it's too much code for others to review, you can be
             | sure there are bugs in it. And if you didn't listen the
             | last ten times people told you to stop writing so goddamned
             | much code, you aren't going to listen this time, either. So
             | have at it, sport. We'll just make sure you get the blame
             | for the bugs, until someone in management wakes up. If they
             | don't, then they see that the sections of code people
             | "won't touch" but you will are getting bigger, and mistake
             | your ownership of this code for a sign of prowess instead
             | of a sign that you are inspiring apathy in others.
        
           | novembermike wrote:
           | Eh, it's a useful proxy. 1000 lines a day isn't better than
           | 100 lines a day but both tell you that it's being actively
           | worked on.
        
         | searchableguy wrote:
         | Yup, impressive.
         | 
         | SWC, another competitor project written in rust is also handled
         | exclusively by a single person. Half a million lines of code
         | and they have even built a type checker for typescript which is
         | not included.
         | 
         | https://github.com/swc-project/swc/graphs/contributors
        
       | wildpeaks wrote:
       | Three things need to be pointed out:
       | 
       | 1. You can support IE11 without Babel (I got rid of it many years
       | ago already): Typescript has transpilation, and you can add
       | polyfills
       | 
       | 2. As much as I like JSDoc-augmented vanilla JS, it doesn't catch
       | nearly as much as real TS
       | 
       | 3. Webapps are made of more than just scripts, loaders are even
       | the big reason why Webpack got popular initially. Luckily,
       | Webpack 5 can automatically recognize assets referenced in "new
       | URL()" calls, so you don't need types for images or shaders
       | anymore.
        
       | crtc wrote:
       | TIL a new word: megamorphic
        
       | nerdponx wrote:
       | For the uneducated like me: if I am writing a NodeJS application
       | in Typescript, can I use this instead of the `tsc` Typescript
       | compiler CLI and get faster compile times?
        
         | dindresto wrote:
         | Yes for compiling, but without typechecking. You'll still need
         | tsc for that.
        
       | mpolun wrote:
       | swc (https://github.com/swc-project/swc) is a rust equivalent to
       | babel and has a bundler under development. Not sure how far along
       | it is.
       | 
       | That would be an interesting comparison of performance and
       | features.
        
         | nahuel0x wrote:
         | swc is more ambitious, it wants to re-implement all of tsc type
         | checking, not only transpiling: https://github.com/swc-
         | project/swc/issues/571
        
         | nicoburns wrote:
         | SWC looks cool, but esbuild is more mature I think. The bugs in
         | SWC's changelog make me pretty wary of using it in production
         | just yet.
        
       | jez wrote:
       | In posts talking about how someone made something fast, I see the
       | same idea repeat time after time: it has linear time complexity,
       | has great cache locality, and saturates all available processors.
       | 
       | It's annoying to me how much time I had to spend outside of
       | school before I realized that this is the real recipe for fast
       | code. In particular, even code that is nominally O(n^2) by
       | standard measures is still a _dis_ -economy of scale: the bigger
       | the problem the slower it gets. In school, there's a premium
       | given for finding a polynomial-time solution, but in practice
       | every job where I've been tasked with making something fast, only
       | linear time complexity was good enough.
       | 
       | In practice these linear algorithms tend to also be completely
       | data parallel and have great cache locality. Not only do these
       | properties make the code fast the second you harness them, but
       | then tend to be exceedingly simple architectures to maintain over
       | time.
       | 
       | For some other reading I really like on software performance in
       | the real world:
       | 
       | - https://blog.nelhage.com/post/why-sorbet-is-fast/
       | 
       | - https://blog.nelhage.com/post/reflections-on-performance/
        
         | hoseja wrote:
         | Quasilinear is still fine too.
        
         | mbar84 wrote:
         | > in practice every job where I've been tasked with making
         | something fast, only linear time complexity was good enough.
         | 
         | Presumably you weren't tasked with making something fast, were
         | linear time complexity was overkill. In other words, quadratic
         | complexity may have been fine in many cases, but you weren't
         | tasked to make those fast.
         | 
         | I'm not saying you claimed otherwise, but somebody might
         | misread you as saying "in practice, only linear time complexity
         | is ever good enough".
        
         | tshaddox wrote:
         | > but in practice every job where I've been tasked with making
         | something fast, only linear time complexity was good enough.
         | 
         | But of course we remember from our CS school that some things
         | simply cannot be done in linear time. I'm not sure what happens
         | when your employer tells you to sort a big list and insists
         | that only linear time complexity is good enough.
        
           | toast0 wrote:
           | At one job we used to joke "i don't care if it's right, as
           | long as it's fast"
           | 
           | Of course, it was only half a joke. For some pages, we really
           | did want data quickly, so we were willing to accept stale
           | data or somewhat inaccurate data, it that helped. For other
           | pages/sections, accuracy was more important so caching wasn't
           | possible or invalidation was critical.
           | 
           | But product design is always about tradeoffs between what
           | features are desirable, what features are possible, what
           | features are easy to build, and how features interact.
           | Features that are possible but not easy to build can
           | sometimes be replaced with features that are easy to build
           | and close enough.
        
           | jez wrote:
           | To that I find that the answer is usually: find ways to avoid
           | needing to sort the list! This is more viable for many
           | problems than you might otherwise think.
        
           | dbbk wrote:
           | > some things simply cannot be done in linear time
           | 
           | Boy am I glad I didn't take CS
        
             | pjscott wrote:
             | For example, a comparison-based sort can't do better than
             | O(n log n) time in general. More information here:
             | 
             | https://en.wikipedia.org/wiki/Comparison_sort
        
             | renewiltord wrote:
             | That's smart. I didn't take Physics and now I can travel
             | faster than EM waves in a vacuum.
        
             | ric2b wrote:
             | "I'm cool because I never learned some things"
        
             | legerdemain wrote:
             | Anything you didn't learn in Christian Science courses at
             | university, you can find and learn more at your local
             | Christian Science Reading Room! Most cities and towns in
             | the USA have one, and even many airports for people on the
             | go. If you're flying through SFO, you can visit the one in
             | terminal 2!
        
           | machiaweliczny wrote:
           | Radix sort exists
        
             | tshaddox wrote:
             | Good luck using that for a big list of strings!
        
               | lomereiter wrote:
               | If we are talking about linear in number of characters,
               | an easy answer is building a trie and traversing it left
               | to right. (Cache-friendly variation:
               | https://en.wikipedia.org/wiki/Burstsort)
        
           | [deleted]
        
       | jarym wrote:
       | Esbuild is certainly fast but I could never figure out how to get
       | it to preserve some symbols during minification (for when I want
       | to expose some class methods or properties publicly to external
       | consumers)
        
         | vijaybritto wrote:
         | Open an issue if you haven't. He is very responsive and
         | thoughtful considering he is the cofounder of Figma a company
         | which is rapidly growing.
        
         | rizky05 wrote:
         | esbuild has keepNames options to preserve that
        
       | asciident wrote:
       | Speaking of fast, that web page loaded instantaneously for me.
       | Gives me confidence in the product, despite being technically
       | unrelated.
        
       | christiansakai wrote:
       | Does esbuild work with font files that comes with css as well?
        
         | rizky05 wrote:
         | this can be supported using plugin.
        
       | jannes wrote:
       | Esbuild is awesome! I tried it on my latest project and the speed
       | has blown me away, even though it doesn't replace the TypeScript
       | compiler for my usecase.
       | 
       | Its two biggest shortcomings are:
       | 
       | 1. It can't compile const enums (TypeScript feature)
       | 
       | 2. It can't compile down to ES5 (with some exceptions)
       | 
       | So I still need to run TypeScript + esbuild side-by-side.
       | TypeScript compiles to ES5 and esbuild bundles the ES5 files.
       | 
       | Anyway, it is a massive improvement over TypeScript + webpack.
        
         | e12e wrote:
         | Curious to how you set this up without going crazy (and CI
         | working)? Just a line in package.json that runs tsc, then
         | another one that runs esbuild on the output?
        
         | duderific wrote:
         | We really need it to support top level await, and the author
         | doesn't seem to be that interested in supporting it at the
         | moment. Hopefully he will come around soon.
        
           | constexpr wrote:
           | I'm the author of esbuild. Rest assured that I am very
           | interested in supporting it and am actively working on it.
           | It's just unfortunately very complicated to correctly,
           | especially without affecting any of the other existing
           | features. There are some recent updates at the bottom of this
           | thread: https://github.com/evanw/esbuild/issues/253.
        
           | dbbk wrote:
           | Interesting, what is your use case for that?
        
             | ratww wrote:
             | The use case is not needing to wrap your code in an IIFE
             | [1] when you would have a top-level await statement. It is
             | useful in entry point of apps where you might need anything
             | that uses async. It's also useful for having async modules.
             | [2]
             | 
             | They're also very helpful for debugging. Using _await
             | something_ in the console is way more convenient than
             | _something.then()_.
             | 
             | [1] https://developer.mozilla.org/en-US/docs/Glossary/IIFE
             | 
             | [2] https://github.com/tc39/proposal-top-level-
             | await/blob/HEAD/R...
        
             | thitcanh wrote:
             | The use case is that it exists: It's already been vetted
             | and it's part of the language. Not supporting it means you
             | don't support the entire language.
        
               | sknowieowl wrote:
               | It's part of the language, but not so much thoroughly
               | vetted. The Chrome/V8 implementation has bugs.
               | 
               | https://github.com/evanw/esbuild/issues/253#issuecomment-
               | 773...
        
       | The_rationalist wrote:
       | _Go has shared memory between threads while JavaScript has to
       | serialize data between threads. Both Go and JavaScript have
       | parallel garbage collectors, but Go 's heap is shared between all
       | threads while JavaScript has a separate heap per JavaScript
       | thread._ Untrue when using sharedArrayBuffer
        
       | sknowieowl wrote:
       | I can confirm that esbuild is very fast - easily bundling my code
       | a hundred times faster than webpack or rollup. And the minified
       | esbuild bundles are only around 10% larger than what is produced
       | by the JS-based bundlers. Considering it saves 30 seconds per
       | build, this is more than an acceptable tradeoff.
       | 
       | It's good that this tool is shaking up the JS development
       | ecosystem. It was getting stagnant (babel) and overly complicated
       | (webpack). We can probably expect more tooling to migrate to
       | golang and rust. I think the esbuild author accomplished his
       | goal.
        
       ___________________________________________________________________
       (page generated 2021-02-16 23:00 UTC)