Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flow support #79

Closed
jankuca opened this issue Apr 29, 2020 · 12 comments
Closed

Flow support #79

jankuca opened this issue Apr 29, 2020 · 12 comments

Comments

@jankuca
Copy link

jankuca commented Apr 29, 2020

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

@evanw
Copy link
Owner

evanw commented Apr 30, 2020

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?

@rtsao
Copy link
Contributor

rtsao commented May 6, 2020

  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.

@jankuca
Copy link
Author

jankuca commented May 6, 2020

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.)

@evanw
Copy link
Owner

evanw commented May 10, 2020

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.

@murrayju
Copy link

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.

@rtsao
Copy link
Contributor

rtsao commented Sep 11, 2020

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.

".ts": config.LoaderTS,
".tsx": config.LoaderTSX,

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).

@evanw
Copy link
Owner

evanw commented Sep 12, 2020

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.

@rtsao
Copy link
Contributor

rtsao commented Sep 12, 2020

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.

@evanw
Copy link
Owner

evanw commented Sep 13, 2020

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’ll just potentially be a lot of conflicts.

@andrioid
Copy link

I'm currently trying to use esbuild for "react-native-web", but many of the libraries I use have flow in the code. So, just adding the use-case of react-native libraries to this thread. No to rush in any way. Thanks.

@dalcib
Copy link

dalcib commented Dec 5, 2020

You can try esbuild-plugin-flow.

@evanw
Copy link
Owner

evanw commented May 26, 2021

The Flow team just announced that they are going to diverge from the JavaScript language and no longer be just JavaScript with types: https://medium.com/flow-type/clarity-on-flows-direction-and-open-source-engagement-e721a4eb4d8b. Given that, I don’t think it makes sense to include this in esbuild itself. You can of course still do this with a plugin.

@evanw evanw closed this as completed May 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants