tko
tko copied to clipboard
Fix backwards ES3/6/IE9 compat + polyfills
To be backwards compatible the TKO library needs to be polyfilled. Examples of ES6 features that need polyfill:
- Generators
- Object.entries/Object.assign
- Backticks
-
=>
functions - Spreads
Here are some things needed to polyfill:
- WeakMap (?)
- Object.assign / entries
- Promise
- Generators
- Map + Set
- Node.remove
- Symbol, Symbol.interator / observable
- String::startsWith
Everything in TKO should be polyfillable (i.e. no WeakSet), but my attempts to make it work, using the config below (among many variants), never worked quite right.
An example of the Babel attempt, removed in 7dbec4cab30259e87c5c9f03f7a8137b1c9c8057, is:
I'm interested in helping out with this one.
If I may, I'd like to suggest using Typescript instead of Babel for transpilation. At this point, there is very little that babel can do that tsc can't, and it's faster. If necessary, it's trivial to add babel to cover what TypeScript can't.
The coolest part about TS in my opinion is the incremental adoption. The build process can utilize the tsc without any further buy-in. Also has the upside of making publishing typings trivial.
EDIT:
Ideally I think, if it's possible, the Typescript definitions ought to be in the leaves.
That way, when someone decides to mix-and-match with other packages that follow the "tko formula" the definitions will be automatically included in the build project.
We'll probably have to come up with a way to build the descriptions from all the leafs (tko.utils, tko.observable, etc.) into one description for the end-result (tko or ko), but I think this is the correct long-term design.
... I'm not sure if or how that's possible, but I thought to mention it.
I want to point out that this is exactly the pattern I have in mind. Each package would have it's own build process and declarations, as well as one for the root tko
.
The root tko
package would need only export those modules, and their declarations will be included in it its build. This would allow modular, or wholesale consumption of tko and types would just work.
TS is fine. I have no idea how it works, but so long as it does, I'm good with that. :)
I'd +1 the Typescript too.
@caseyWebb I've gotten testing working, but I had to make some changes to the packages, per 67ec170b6a2d573b6ee013474d3ef38cee90d087 and c07a2d192beebff07dac931fb38d83493ab2652f – do you see anything breaking from these?
Notable changes:
- I changed the
module
in allpackages/*/package.json
tosrc/index.js
, which is needed otherwise during testing the dependencies get duplicate imports all over the place - I disabled uglify b/c it broke with a parsing error on tko.js
- I removed
postinstall
frompackage.json
because it was causing an infinite yarn -> lerna -> yarn loop
If it looks like everything is compiling, we might be off to the races here.
There are some more implications of pointing module
to src/
, namely
- webpack/rollup consumers will get ES6, when they may expect ES3/5. Most people omit
node_modules
from babel/typescript transpilation, so we'd have to note that those must still be transpiled. -
src
needs to be added topackage.json => files
so they are published to NPM. Because of the previous though, I think this is going to take some more thinking.
Uglify breaking on ES2015 modules is expected, I'm not sure why those were being minified in the first place as it doesn't really make sense to publish minified modules
Thanks @caseyWebb
-
On the Typescript issue, I got a great answer here: https://blog.mariusschulz.com/2017/06/30/typescript-2-3-downlevel-iteration-for-es3-es5
-
On the
module
consumers, it's a great point. It might be preferable to rewrite the test imports from thespec/*
, if that's possible, and revert the transpilation. -
We're producing four versions now .es6, .es6.min, .js, and .min.js; there's no need for .es6.min, yes?
Will be looking into this.
Re. modules, going to go on what Rich Harris said here: https://github.com/rollup/rollup/wiki/pkg.module -
Wait, it just means import and export – not other future JavaScript features?
Yes. If you're using things like arrow functions and classes (or more exotic features like decorators and object spread), you should transpile them if you want your library to work in environments that don't support those features. Otherwise, whoever uses your library will have to transpile it themselves, including configuring their transpiler to handle your code, which might involve esoteric transforms and conflicting versions of Babel.
It's a frequent source of frustration. Be a responsible library author and ship code that actually runs in the environments you support!
So I'll point module
to dist/X.js
and see what I have to do to make the tests work again.
Just to report, we're hung up on https://stackoverflow.com/questions/47210133. Then it's just a matter of adding the polyfills. Fingers crossed.
Hi All,
I was wondering if anyone had thoughts on the best way to add polyfills?
In the worst case, I was going to add a "polyfills"
property to packages/*/package.json
to add the respective polyfills needed for each package. It occurred to me that there might be a simpler and easier way — thoughts?
Thanks
We may be able to intuit the required polyfills with the tsconfig.json lib
property and prepend the matching core-js imports. This would take a bit of investigation to see how feasible it is.
In Typescript accessors on the object itself are not supported in ES3. This is not suprising, as accessors cannot be polyfilled in ES6.
Take this for instance, in tko/utils/options
:
Object.defineProperty(options, '$', {
get: function () { return options.jQuery }
})
This will fail in IE7 and below, which do not support Object.defineProperty
. In this case an property accessor is not strictly necessary, but I can imagine there are other instances in the code base where there is.
I am curious:
- What is the current market share of es3 browsers?
- In what year did any of them last receive a security patch?
Every feature, including backwards compatibility, has a tangible opportunity cost. I can't help but wonder what the cost-benefit analysis for ES3 support looks like.
There are still a huge number of internal Intranet systems that use IE, so public numbers may not be the ideal indicator. However, a lot of those internal systems are unlikely to be updating to KO4.
That being said, I think we can realistically include IE8, since that's still testable on e.g. SauceLabs, we've got the tests for the edge cases we get with IE8. The one unknown is what issues crop up with the Typescript transpilation.
The one unknown is what issues crop up with the Typescript transpilation.
As long as we're targeting ES3 I expect no issues. However, I believe we can safely target ES5 with Typescript as it primarily uses the new methods on Object
like defineProperty
, which happens to be supported in IE8 and calls to it are already present in the current codebase.
But given the both the market share, security state, and likeliness legacy enterprise apps will upgrade to tko we should really question how much effort we want to put in supporting IE8 compared to a much modern browser (in comparison) like IE9.
I have been thinking about this this week, and I think I've changed my mind slightly.
Re:
RyanCavanaugh commented on Nov 27, 2017
Long story short - after five years of not having this and people surviving despite it, it seems like ES6 adoption is catching up fast enough that the narrow window of people who target ES5 (rather than 3 for maximum compat or 6 for smallest emit delta) is closing to the point where we don't want to accept a big chunk of helper emit at this point. Open to data otherwise but it just doesn't seem common enough to warrant a big change in the emitter. https://github.com/Microsoft/TypeScript/issues/338
If we are going to use TypeScript as our transpiler and Microsoft's position is that people either want to target ES3 or ES6, then I think t/ko should build es3 and es6 distributables.
Yeah, tko could implement the kludge buried in that github issue, but then 18 months from now, how many other unofficial patches buried in how many other github issues or stack overflow answers will be required to maintain an es5 codebase? I think that it would ultimately result in needless technical debt.
Hi Brian - hope all is well.
There was an issue in Gitter wrt Symbols in IE11. I suggested using this polyfill, which I'm taking it was enough to get TKO running in IE.
Hi @avickers Sorry I missed this — the ideal eventually will be to have a polyfilled version with the basics from core.js, which could (and I think should) include the IE11 polyfills (e.g. Symbol).
Why not drop this one partially? In 2021 no one uses IE9 and will not even maybe use IE11. Even Microsoft is dropping support to IE11