Three.js: Starting from r109 three.module.js contain non transpiled classes

Created on 26 Nov 2019  Â·  17Comments  Â·  Source: mrdoob/three.js

r109 introduced the usage of ES6 which is a good thing.

Reading the PR #17276 that made this change states that the classes get transpiled to ES5 syntax in three.js and three.min.js which is not sufficient.
three.modle.js needs to have ES5 syntax too.

In fact other NPM modules depend on three.js such as Photo Sphere Viewer that got affected by this change.

We use this module on production and it caused our website to crash on IE 11.

Duplicate

Most helpful comment

the ask here is that Three.js follows suit on many established standards in the open source community...

Are there references you could share explaining this standard? All npm packages should be published as ES5? They aren't always, as a rule, but I'm certainly open to any guidelines we can find.

Out of the box, the library should work against the lowest common denominator runtime.

Developers using threejs may be writing applications whose final build output targets different ECMA features, from ES3 up to ES6+. By transpiling the library down to older JS versions we may also force some costs (code size, performance) onto developers who are targeting modern browsers. three.js is an unusually performance-sensitive library, and there has historically been some aversion to adding new build steps that mutate optimized code.

I don't know whether those costs outweigh those you describe; perhaps not. But it would be nice to have input from authors of the bundling/transpiling tools here.

All 17 comments

This is intentional. See #17919

IE11 doesn't support ES6 so it needs to be transpiled anyway. We recommend you do that as part of the bundle for your project.

I understand why now.

Thank you for the clarification and the advice

@mrdoob The better fix that avoids all this issue entirely would be to provide three.module.js which should be plain ES5 with modules, and three.es6.js which would contain all the ES6 features you like to use.

three.module.js should not use class. It is not okay to expect module users to transpile the library themselves to support IE11.

This may be my personal opinion, but it seems to be the generally accepted view of most JS libraries I've encountered. I've never needed to transpile a modern third-party library myself to make it work with IE11. YMMV.

IE11 doesn't support modules either.

@mrdoob you are correct, and that's why users of three.module.js must use a module bundler like webpack, rollup, or parcel.

The idea is that three.module.js should be usable with webpack (or other bundler) without also bringing in babel or typescript to transpile Three.

@mrdoob in case it isn't obvious, webpack and other bundlers can and do replace import/export syntax with IE compatible ES5 code

Devs aiming to street IE11 can use three.min.js or if they use webpack they can bundle and transpile three.module.js. What am I missing?

@mrdoob The point is not having to transpile three.module.js and also have the benefits of modern ES6 module syntax and webpack tree shaking.

Every other library I've ever used does this properly.

With the current architecture, we can't have tree shaking without classes.

It would still be nice to have just modules so that it can be used in a webpack project without having to setup an ES6 transpiler. Oh well, I tried. At least you are fully aware of the issue now, even if three.js continues to be a pain to use.

Once you've already got a bundler running (Rollup, Parcel, Webpack) adding Babel is not that hard, so I don't see what all the fuss is here.

@mrdoob @looeee the ask here is that Three.js follows suit on many established standards in the open source community to enable wide consumption of the library on all platforms. It is known across the community that not all browsers follow the ES6 conventions out of the box, the main offender used by a substantial set of web consumers being IE11.

By asking developers to manually transpile the final build of the library as a runtime, you are asking developers to provide an extra configuration that is entirely self-composed in order for their application to be able to consume it. From a pure practical sense in the context of Three.js, this is a perfectly valid ask, but from the perspective of developers working on larger scale projects, Three.js in all likelihood not the only library being pulled into the project. Imagine if every library on github started adopting this mentality. Every developer would need to provide a compatible configuration, often times a very fragile and high-maintenance project-level configuration, based on the ECMA standard of the sum of all libraries required, to correctly transpile. The number of libraries can get into the tens, hundreds, and this is only for direct dependencies. Furthermore, they would be required to check, update, and change every time each individual library updates in a breaking way. When transitive dependencies start coming into the equation, it gets even worse. What this amounts to is a maintenance task that should be entirely avoided, as the minimal configuration for any library to correctly work as ECMA evolves over time will absolutely vary between projects and dependencies.

In addition to all of this, each time a library provided a breaking update, a developer would not only need to anticipate that it updated, but the developer would also need to spend time understanding how those updates affect their existing configuration. This isn't a matter of understanding Babel at this point, it's a matter of maintenance over time for every library that follows this avoidance mentality, forcing consumers to understand what the project needs to work correctly, and then playing referee for the sum of all dependencies, some which might actually have locked in a version of Babel until a subsequent release (Vue's CLI and testing tools are a perfect example), which could actually trap them into pulling in multiple versions of Babel with multiple configurations. Out of the box, the library should work against the lowest common denominator runtime. Playing referee in this regard does not scale from a maintenance, time, and overall cost perspective, especially for small teams working on a limited budget who may rely on large numbers of libraries in order to be successful.

In an even mostly ideal world, the onus is on the developer of the library to provide some form of configuration that is guaranteed to work without requiring developers to spend time figuring out which Babel versions, configurations, and plugins are required for this specific project. Taking the responsibility as the browser ecosystem matures, you are able to alleviate, mathematically, potentially hundreds of hours at a time around domain-specific requirements that (may not yet, but will) exist for the library to ultimately work as you increment the version and adopt newer ECMA features, and you are able to guarantee that it will work the same way every time, since it will have worked prior to being pulled in to the consuming project. At the moment, you haven't even established which versions of any of the above you will need to configure (are you ES2015, 2017? etc). Given the long list of available standards, https://en.wikipedia.org/wiki/ECMAScript, any developer will need to start off by guessing what features you are consuming.

I hope you reconsider because of how widely Three.js is used. This is not an exhaustive list, but please understand that the open source community does in fact typically provide the common reduced library runtimes for a very good set of reasons.

the ask here is that Three.js follows suit on many established standards in the open source community...

Are there references you could share explaining this standard? All npm packages should be published as ES5? They aren't always, as a rule, but I'm certainly open to any guidelines we can find.

Out of the box, the library should work against the lowest common denominator runtime.

Developers using threejs may be writing applications whose final build output targets different ECMA features, from ES3 up to ES6+. By transpiling the library down to older JS versions we may also force some costs (code size, performance) onto developers who are targeting modern browsers. three.js is an unusually performance-sensitive library, and there has historically been some aversion to adding new build steps that mutate optimized code.

I don't know whether those costs outweigh those you describe; perhaps not. But it would be nice to have input from authors of the bundling/transpiling tools here.

So the ask is to provide a three.module.es5.js build so people can do tree shacking and we are responsible for the transpiling? Would a three.umd.js work too?

I think the ask would be that both our pkg.main (CommonJS or UMD) and pkg.module (ES6 Modules) entries contain only ES5 code, excluding the ES6 import/export statements in the latter. If we wanted to also publish the original ES6 code, in this situation, it would have to be a separate npm package, like npm install --save three-es6.

EDIT: Although just putting a three.module.es5.js version into the published build/ folder — not in pkg.module — is definitely not a standard practice, that might work as well if that's what you're suggesting?

EDIT: Although just putting a three.module.es5.js version into the published build/ folder — not in pkg.module — is definitely not a standard practice, that might work as well if that's what you're suggesting?

Yes, that's what I meant.

Was this page helpful?
0 / 5 - 0 ratings