Esbuild: Flow support

Created on 29 Apr 2020  路  9Comments  路  Source: evanw/esbuild

Hello, are you also considering Flow support or will this only support TypeScript?

Most helpful comment

I'm not currently considering Flow support. I've never used Flow myself and I had the (perhaps incorrect) impression that the web development community was gradually moving away from Flow to TypeScript. My goal for esbuild is to build a bundler that solves for a sweet spot of common use cases, not to build a bundler that works for any codebase.

That said, I could consider it. To get an idea of the scope of work that this would require (since I'm completely unfamiliar with Flow):

  • Does Flow ever use types to change how code is emitted? Or is it possible to convert Flow to JavaScript just by "deleting the types"?
  • Does Flow add any extra syntax to JavaScript like TypeScript does (enum and namespace) that would need to be converted to JavaScript?
  • Is there a good comprehensive public suite of test files that, if they are parsed correctly, could give reasonable confidence that the parser will work on real-world code?

All 9 comments

I'm not currently considering Flow support. I've never used Flow myself and I had the (perhaps incorrect) impression that the web development community was gradually moving away from Flow to TypeScript. My goal for esbuild is to build a bundler that solves for a sweet spot of common use cases, not to build a bundler that works for any codebase.

That said, I could consider it. To get an idea of the scope of work that this would require (since I'm completely unfamiliar with Flow):

  • Does Flow ever use types to change how code is emitted? Or is it possible to convert Flow to JavaScript just by "deleting the types"?
  • Does Flow add any extra syntax to JavaScript like TypeScript does (enum and namespace) that would need to be converted to JavaScript?
  • Is there a good comprehensive public suite of test files that, if they are parsed correctly, could give reasonable confidence that the parser will work on real-world code?
  1. Flow is purely type annotations for JavaScript, so conversion to JS merely involves removing the annotations. This is what the Flow Babel plugin does.
  2. Flow adds special syntax for type annotations, but does not introduce any additional language features that need to be converted to JS. As stated before, you just need to remove the annotations.
  3. There might be a test suite somewhere, but at the very least, there are number of large projects using Flow (Parcel for example) that might be good candidates.

As @rtsao says, Flow does not add any new language constructs. All Flow syntax can simply be stripped to get working JS code.

The Flow project contains multiple packages, one of which is the flow-remove-types package with a test file featuring all the added syntax and multiple possible outputs which are valid JS.

Please look at this material to see if it can help. The package itself (published on NPM as flow-remove-types) could be used directly. (It is not written in Go though.)

Thanks for the pointers! That's very helpful. I'm currently focused on building some other features first (code splitting and tree shaking) but I would like to do this at some point.

I'd like to see this as well. The flow syntax is extremely similar to TypeScript, really just a handful of differences. So hopefully this wouldn't be very hard to add.

I've scraped relevant test cases from from https://github.com/facebook/flow/tree/master/src/parser/test/flow/types and https://github.com/babel/babel/tree/main/packages/babel-parser/test/fixtures/flow and generated esbuild unit test cases.

In doing this, I learned that Flow actually supports enum syntax, which isn't really documented anywhere. Support for parsing Flow enums was also added to Babel, but interestingly it appears Babel does not transform them to anything when using @babel/plugin-strip-flow-types. It's worth noting enums are gated behind configuration with both Flow and Babel. It might not be worth supporting in esbuild at all since it doesn't seem clear how they get converted to standard JS. Or I guess esbuild could just passthrough like Babel does.

Unfortunately, no special file extension is used for Flow syntax, so there's no way to know if a .js file uses Flow syntax.

https://github.com/evanw/esbuild/blob/5f6aac00dc8a3d296db534b1360a8c95e274057a/internal/bundler/bundler.go#L607-L608

I can think of two ways of handling this:

  1. Just add Flow parsing to the standard JS parser, but disable it if options.TS.Parse = true.
  2. Enforce the use of // @flow or /* @flow */ pragma.

I think Flow pragma comments aren't strictly required, but I imagine the first option could introduce some overhead.

I need to clean up the test cases a bit more, but at some point I'd be interested in working on Flow support. My initial thought would be something like this:

  • Update the lexer to handle Flow-specific syntax.
  • Duplicate parser_ts.go into parser_flow.go and make adjustments as needed. There'd be a lot of overlap, but I'm not sure it'd be worth trying to DRY things up (at least initially).

Some quick thoughts:

  • If this is to be integrated into esbuild itself, it should be off by default and only enabled with --loader=flow since Flow is not JavaScript.

  • It looks like Flow perhaps doesn't support enums? There's an open issue debating the addition of enums here and the AST generated on https://flow.org/try for enum foo {} indicates that it's parsed as enum; foo; {} and generates the parse error Unexpected token `{`, expected the end of an expression statement (`;`). It's a deliberate decision for esbuild to not support work-in-progress syntax proposals, so this probably shouldn't be included.

  • Heads up that I'm currently working on getting a CSS parser working and integrating it into esbuild. I'm about to refactor the JavaScript-related code as I'm adding support for a second fundamental data type, which could potentially introduce a lot of merge conflicts for code that touches JavaScript language support. So now isn't the best time to be adding Flow support.

Makes sense, thanks for the heads up. Right now, I'm mainly tinkering around to better understand the differences between TS and Flow syntax and see how difficult it would be to add Flow support.

At the very least, I'm merely hoping to produce a suite of test cases that will prove useful no matter what kind of refactoring happens.

Regarding enums, they have to be explicitly enabled by adding experimental.enums=true to .flowconfig. Agreed it probably doesn't make sense for esbuild to support them yet.

The refactoring I have in mind is mainly renaming files and packages, so it should be straightforward to carry any modifications to the JavaScript parser forward. It鈥檒l just potentially be a lot of conflicts.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aelbore picture aelbore  路  4Comments

Gotterbild picture Gotterbild  路  3Comments

tonyhb picture tonyhb  路  3Comments

vforsh picture vforsh  路  3Comments

frandiox picture frandiox  路  3Comments