-
Notifications
You must be signed in to change notification settings - Fork 241
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
Move to TypeScript / TSDX #51
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was such a deep problem 🤯
scripts/build.sh
Outdated
# This is an awful solution to a problem that couldn’t get solved in any | ||
# other way (as of 2020-08-07). WalletConnect uses CommonJS with | ||
# the `__esModule: true` property, indicating that the CJS module can be | ||
# transformed into ESM. Unfortunately, it ends up being exported | ||
# as `export default { default: value }` rather than `export default value`, | ||
# in several bundlers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐉 such a rabbit hole...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a couple of small notes, but I'm not entirely sold on esbuild if it introduces this much complexity to the build tooling (and surely, there must be a nice tool out there so we don't have to specify all the flags??).
Is there no other way to support consuming use-wallet
with snowpack?
@@ -3,7 +3,7 @@ | |||
[ | |||
"@babel/preset-env", | |||
{ | |||
"targets": "> 2%, not dead, not ie > 0", | |||
"targets": "> 2%, supports es6-module", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh interesting, but this is assuming no post-bundler, right? Just if you deployed the code snowpack generated by itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it could be nice to start removing not ie > 0
and not dead
as they are both included in > 2%
now, and to add supports es6-module
to be explicit in this SnowPack demo, because we are using native ESM. But it’s not really needed as > 2%
already only includes ESM-enable browsers.
No, SnowPack only works with ES modules. It can handle CJS modules through a transform, but it comes with compatibility issues.
Having flags rather than a config file is a design decision I think, personally I like it haha. Otherwise, I described the different attempts here: esbuild is the only one getting close, all the other approaches have issues. IMO the main issue with esbuild is that the project is young, but I personally find everything else superior to the others. No config file, plugins, presets, etc.: just one command to run and that’s it. After this, the plan is to open issues on every library that we are using here, to ask them to support ESM exports, and target browser environments first (rather than Node). A good reason to do so would be to be compatible with tools like SnowPack, Vite or even Webpack 5, which will ship without Node.js polyfills. Note: an easy solution to these problems would be to only provide CJS exports in use-wallet. That could be a compromise until our dependencies start to export in ESM, but would prevent us to use useWallet() with SnowPack or Vite. We are also discussing about moving useWallet() to TypeScript, which might solve the issue if tsc provides a better support for these modules, especially since some of them are generated by tsc already. |
To add to the discussion:
The problem is that, as Pierre says, the approaches used by the other libs, have compatibility issues, and in general it's a hard problem. Pretty much a legacy compatibility mess.
Indeed, and personally, it's a solution I wouldn't take... It would feel like a step backwards, and we've already committed to using new projects as test beds for these new tools, which have proved to be better overall. I'd push for ESM adoption and just poke everyone about catching up. Webpack 5 is definitely pushing for that direction.
I'm definitely the complete opposite on this: I hate not having a config file! But at the same time, as I played with esbuild during the week it has this "no frills" feeling to it, for just doing what it's supposed to do very well and very fast, and that's what I really like. :) |
This is interesting, and perhaps worth a shot! This would require the end project to use tsc, not just |
Yes, trying this now!
tsc can export in ESM and CJS, so the end project can use any bundler if we export both (e.g. that’s what Connect does). The only thing would be to ensure that the dependencies get transformed properly, this is what doesn’t work so well at the moment. But since tsc is the compiler that generated the two dependencies we have having issues with (exporting in “CJS-with- |
Hey guys, if you need me to ship an ESM bundle. Let me know! We could work on this under the WalletConnect monorepo instead of having to hack on top of it |
@pedrouid It would help a lot! Let me know if I can help. I don’t think there is any way to make tsc export in two formats at the same time, so for Connect, we build twice. |
I've dived into CJS, ESM and UMD earlier this year and it's a world in itself. I found it useful to stick to the simplest setup by having TSC handle the CJS transpilling and then webpack would take that CJS bundle and output a UMD bundle TSDX is a library that supposedly does all of this out-of-the-box very for all bundles. However there were some caveats and discrepancies so I went with the simpler approach. What I will attempt instead is to have TSDX build the ESM straight from source and see how it works out. I can follow up in a couple of days with an update |
Sounds good! TSDX is what I am using to convert this project in TS, it seems to export in CJS + ESM by default now. |
The first issue I hit right away is that TSDX throws me an error for not finding the plugin |
@pedrouid Do you have a .babelrc declaring it? Otherwise I can have a look at your files, let me know! 🙂 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was also wondering if it could be a good idea to have a use-wallet/esm-only export.
Yes, I think we should do this, even with the default export (do we really need to have all of those connectors available by default?). It anyway seems like a user concern, e.g. "you can't use provider X with snowpack yet; go ask them to fix it."
I also opened this PR on web3-react, which will allow us to not transform any of the connectors, and let the app bundlers deal with them directly.
Wasn't sure what this means; it wouldn't really change anything right (since snowpack would ultimately be that app bundler anyway? Or could we have it such that the development build only enables X providers but the production build done via another bundler enables all providers?)?
import { Account, EthereumProvider } from './types' | ||
|
||
const KNOWN_CHAINS = new Map<number, string>([ | ||
[1, 'Mainnet'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we would be interested in using the names in https://chainid.network/ instead, or if it'd be too verbose?
Do we need to use the names in this library (I would treat this somewhat as a user concern, since it's up to them how they'd like to define the UI per network)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to use the names in this library (I would treat this somewhat as a user concern, since it's up to them how they'd like to define the UI per network)
Yes I agree, let’s remove them and networkName
👍 (I’ll do this in a separate PR).
I do agree; having an ESM export would be amazing! It's a bummer that Snowpack will need more time, and we should definitely bug library authors to catch on. |
With previous versions, we were bundling the external dependencies, with the library e.g. Fortmatic was here: https://unpkg.com/browse/[email protected]/dist/fortmatic-083107e5.js This makes the connectors more compatible, since all these dependencies are exporting in different ways and converting them was having the effect of making them all provide the same export formats. But an issue with this strategy is that the conversion vary a lot from a connector to another, and we had to disable some of them for this reason. Another approach is to not bundle them at all, and let app bundlers do this work. I now think it might be a better strategy, so that app authors can decide themselves to discard a connector that doesn’t work well (by not using it / tree shaking it). But a problem preventing this to work is that web3-react is doing
I’m not sure I understand this, do you mean having a different set of providers based on |
I would agree.
But regardless, we can't get past the current bundling issue even if we drop most of our default connectors?
Yes, sort of. I was thinking that during development with a tool like snowpack, you're using ESM modules and don't really need that many connectors anyway (during development, you're likely to only need the injected one unless you're specifically testing the others). So at a later step, if you use another bundler, e.g. parcel, to build the production site, you can enable the other non-ESM friendly connectors and don't have to worry about it being in ESM. |
It would fix the issue yes, but it would mean dropping these connectors: Uniswap/web3-react#115 I just hope this PR could get merged soon in web3-react, so we can keep using some of these connectors in the light (ESM only) version. If if this other PR gets merged, we could also support Magic, which now exports in ESM as well (Fortmatic was only exporting in CJS).
I see, I think we should detect the ESM / CJS mode rather than development / production if we do anything like that, but I don’t see how it could be done 🤔 Toggling connectors using Also I think it could be a bit odd to tell users that the connectors available is not only affected by I see two approaches at the moment (both requiring Uniswap/web3-react#115):
I think the latter one would be ideal if it works as expected! |
I merged the PR: the ESM / CJS issues are fixed, the only problem now is that several dependencies are relying on Node.js polyfills, making it difficult to use in SnowPack: this will be addressed separately. |
Requires Uniswap/web3-react#115
This is an attempt to fix the different issues we have with some connectors that expect a CJS or even Node.js environment.
Changes: