Skip to content
This repository was archived by the owner on Jan 1, 2025. It is now read-only.

ES6 code in production build breaks IE11 #238

Closed
pgrippi opened this issue Jun 2, 2020 · 10 comments · May be fixed by #467
Closed

ES6 code in production build breaks IE11 #238

pgrippi opened this issue Jun 2, 2020 · 10 comments · May be fixed by #467
Assignees
Labels
build / infra enhancement New feature or request

Comments

@pgrippi
Copy link

pgrippi commented Jun 2, 2020

I was hoping to give Recoil a try in one of my projects, but it looks like ES6 code is not being transpiled away in the production build:

const next=new Set(set);
class AbstractRecoilValue{constructor(newKey)

We sadly have to support IE11, would it be possible to update the rollup config to output ES5 code instead?

@drarmstr drarmstr added the enhancement New feature or request label Jun 2, 2020
@drarmstr
Copy link
Contributor

drarmstr commented Jun 2, 2020

Would it make sense to have different build targets? cc @mondaychen

Does the ES5 output polyfill for Symbol support?

@pgrippi
Copy link
Author

pgrippi commented Jun 3, 2020

Does the ES5 output polyfill for Symbol support?

I don't think that would be needed, we use react-app-polyfill which already includes one for Symbol. I think all we'd need is the consts and classes transpiled to es5

@JeremyRH
Copy link

@pgrippi IE11 supports const and let. The only issue being const in for-in loops.

Ideally, libraries shouldn't be concerned with the environment. The consumers build process should take care of transpiling and adding any necessary runtime code. That being said, this complicates things for the consumer and would affect build times (e.g. having to transpile node_modules).

Multiple outputs is a good solution for this but how would you pick which output you needed? It could be explicit like changing the import/require specifier: import { atom } from 'recoil/es5'; or the library's entry point could use an environment variable like React does. But what environment variable would it use? There is no standard USE_ES5 environment variable.

I personally would recommend using are-you-es5 to only transpile the packages that need it. As time goes on, you will probably run into more packages that don't output ES5 so this might be the best option for you.

@drarmstr
Copy link
Contributor

Closing this for now as hopefully transpiling is a workable solution for those needing ES5 support.

@Brianzchen
Copy link
Contributor

I think it would be a simple fix of updating the .babelrc to have something like the following:

"presets": [
  [
    "@babel/preset-env",
    {
      "targets": { "browsers": ["last 2 versions", "safari >= 7"] },
    },
  ],
  // ... other
],
"plugins": [
  "@babel/plugin-transform-modules-commonjs",
  // ... other
],
// ... other

@drarmstr thoughts?

@drarmstr
Copy link
Contributor

drarmstr commented Jul 6, 2020

cc @mondaychen

@JeremyRH
Copy link

JeremyRH commented Jul 7, 2020

It looks like there are four outputs right now:

  • Production ES Modules
  • Production CommonJS
  • Development ES Modules
  • Development CommonJS

ES Modules & CommonJS

Most bundlers automatically handle which module format to use. Recoil controls the options through the "main" and "module" fields in package.json. Using the "module" field is not standardized by NPM but it's used by many popular NPM packages and bundlers will likely support this for a while. Recoil's current ES module output will probably fail when using native modules in Node 14 because the "module" file is entirely CommonJS. Not really a problem now but it would be nice to find a solution that is future compatible.

Development and Production

The NODE_ENV environment variable is used to determine the stage of the environment: Production or Development. The environment variable is configured by the consumer's build and Recoil provides the options through this entry point. This is a very common solution to providing dev and prod outputs and works pretty well in my opinion. One problem with this is you need CommonJS for synchronously importing in an if else statement.


Let's say we make all outputs ES5:
What about consumers who don't need ES5? Some of them might argue that their bundle sizes increase with unnecessary syntax transformations. According to debugbear, it seems like syntax transformations are not very costly and babel transformations often have an option for "loose" mode, saving additional bytes.

What if Recoil offered two more outputs, ES5 and ES{current}?:
A new way of choosing between these outputs would have to be introduced.
There would now be eight outputs because the existing four would need both ES5 and ES{current}.

In my opinion, I would just transform the outputs to ES5 and use the "loose" option babel provides. It would be pretty cool if NPM or another package manager handled generating the output the consumer needed but I doubt a feature like that is even on their radar.

@mondaychen
Copy link
Contributor

Hey @JeremyRH thanks for your input! Does #433 look good to you?

@Brianzchen
Copy link
Contributor

@mondaychen I've checked out on my local and linked to my app. Seems to all work as expected without any random import errors that I had before.

But it's still not transpiled down to es5. That would simple just to add @babel/preset-env, should we add it to #433 or have a separate PR?

@mondaychen
Copy link
Contributor

Let's add ES5 transpiling in a separate PR (after #433 merged) so that we can test the impact on file size there.

Some thoughts on the options we have:

About loose mode: IMO we should NOT use babel loose mode because this is a library and we should not risk getting problems when switching to non-transpiled version in the future.

About providing multiple outputs: if we do see a relatively significant size impact in the output transpiled down to es5, we can consider providing one single ES-current uncompressed output, so that people who care about size a lot have the option to pick target browsers themselves.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
build / infra enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants