I am writing a Polymer 2 application. The default is to transpile ES6 to ES5 so that you can use ES6 syntax and be sure it will just work.
The problem with this is that everybody (even supporting browsers) get to receive transpiled code.
Two questions:
Is it just too crazy to say "no" to legacy browsers, and just stop transpiling?
Is there an easy-ish way to redirect specific browsers to a non-transpiled version of the app?
It really depends on the audience of the app you want to create. As for my own projects, I can see in my Google Analytics that there are still some people who are accessing it via Safari 8, 9 and even IE 11. I cannot just tell them to use a different browser because of several reasons... mostly financial reason (either personal or corporate)
Because of that, it is still a default for me to just transpile back to ES5 (given that I am using Webpack for now while waiting for the script type="module" to stabilize).
As for easiest way, they say if you use Polymer-CLI's serve function, it autotranspiles your code depending on the browser's capabilities.
Or you can have a simple javascript code that tries to check an ES6 method, then if it works, it loads the ES6 version of the bundled code... if not, it loads the ES5 version of the bundled code + the custom-elements-es5-adapter. But this one takes some performance hit because of the wait to parse the initial JS script to check before loading the necessary files instead of loading them right away (I haven't tested this though)
Or you can check in the server what type of browser is calling and then heuristically guess what type of version code you want to send.
As for performance for the overhead of the transpiled code, it's a bit miniscule, given that if you are just using Polymer.Element, you can get at least 12KB of code... then you'll have like 30+KB left to show content, which is more than enough to have a PRPL+50
The simple answer isL use prpl-server-node which does exactly what I was talking about, and more.
Specifically:
Differential Serving
Modern browsers offer great features that improve performance, but most applications need to support older browsers too. prpl-server can serve different versions of your application to different browsers by detecting browser capabilities using the user-agent header.
Builds
prpl-server understands the notion of a build, a variant of your application optimized for a particular set of browser capabilities.
Related
How to check the ECMAScript standard version that the currently installed JS on the system is using, is there any special command to know or we need to check the JS version and then Google it to know on which ES standard version it is based up on.
Environments do not run "a particular version of the standard." Rather, environments implement features from different years of the specification piecemeal. For example, it may be that in June 2022, a particular browser has implemented, say, 7 of 9 specification additions or tweaks from the prior year - and a different browser will implement those things on a different schedule.
Even if something is in the standard, there's no absolute guarantee that environments will support it, unfortunately. Usually they will, and often in a reasonably timely manner, but not always. For example, proper tail calls, from ES6, still have not been implemented in V8 or SpiderMonkey.
So, to figure out what is supported in a given environment, you'll have to test all the properties/features you're looking for individually. (eg window.hasOwnProperty('Promise'))
Often, rather than script-writers trying to detect what a browser currently supports, and working around that, script-writers will simply use a polyfill service (example) that adds all necessary missing features - that way you can get on with the main logic of your application and simply not worry about it.
Vanilla JS does not have any version as of Jquery,Angular, Reactjs, etc which are build using vanilla JS. It depends whether the current browser update supports upto which version of ECMA Script. You can use any version syntax as long as you can compile your code to ES5 syntax if your browser does not understand higher version of JS.
I have a first generation iPad mini. It's a about 8 years old and although it displays my page correctly some functionalities that require JavaScript doesn't seem to work. If I understood correctly I need to load Babel or something like that. Is that true? But what's the best way to load Babel? should I just use a script tag like so:
<script src="https://unpkg.com/#babel/standalone/babel.min.js"></script>
Is that enough?
TL;DR: don't load Babel in the browser in a production env
It depends on what exactly doesn't work. If it's simply syntax and some ES6 classes/functions, that's probably solved by Babel which transforms syntax and has some polyfills. You can transpile your JS server-side if you're concerned about load times (which makes sense for older devices). If you can't do it on the server, you can just deploy a JS file you transpiled on your workstation. Also, if you go here and click on "In the browser", you'll see this:
Compiling in the browser has a fairly limited use case, so if you are working on a production site you should be precompiling your scripts server-side.
You should probably also have a look at CanIUse. Then you can decide how much time you want to invest in the first place. const for example is supported by 99.8% of users globally.
However, it can be that your page uses JS to do some complex interaction that depends on pointers, touch events and such. In that case you probably need to rewrite a lot of it. This does not apply to your situation, but generally may impact someone's decision on what browsers to support.
I've recently bumped into users that use old devices and whose browsers (mainly Safari 9) raise JS errors because they do not implement the const keyword that we use in our modern SPA app*.
I suppose a fix would be to let Babel recompile the whole app with regular var keywords, but I'm afraid of the speed loss of the website by doing so. Do you have any ideas/experience ith this ?
If we decide to support such broswers, is there a way to maybe compile a version of the website just for those browsers ? I've heard it was possible to use media queries for javascript files. Is it convenient ?
*We are hosting a ReactJS app at https://www.myjobglasses.com that comes from an ejected create_react_app
Use Babel to transpile the website code before uploading it. From my experience, it should not slow down your app significantly, even when targeting a bit older browsers.
Babel has a great tool to transpile code for particular browsers, called babel-preset-env:
https://babeljs.io/docs/en/babel-preset-env
As it uses this: https://github.com/browserslist/browserslist for checking, you can define different rules that your transpiling will follow, hence - you'll always have working code as a result, e.g. (taken from preset-env documentation):
{
"targets": "> 0.25%, not dead"
}
{
"targets": {
"chrome": "58",
"safari": "9"
}
}
Another idea - if you want to delve deeper, you can actually prepare two bundles and load them conditionally, based on browser version (so, essentially, for this specific case of Safari).
That would require you to somehow detect browser when connecting to the server (e.g. by User-Agent) and serve different bundles, but it's doable ;)
What about using a package like Modernizr? You could check if the client's browser supports certain feature that is well known to fail in Safari, and include it in you Modernizr support. It is pretty straight forward, I think. Check out Modernizr here
Also, this answer could be useful: https://stackoverflow.com/a/13480430/7868769
I implemented CKEditor on a project and I was surprised to discover, either in the interface or in the source code, that it's written in ECMA 6, using all its modern features such as the short function notation (arrow functions).
Given these features are not widely supported as the ECMA 5 version is (not yet as of today, July 2018), I ask why the developers made this strategic choice: are they not interested in a wide browser compatibility? Or is CKEditor so well spread to allow them to dictate a precise direction towards modern browser versions, risking to lose a portion of users?
Browsers are not a problem
Let's be clear here:
CKEditor 5 can be run in all browsers which it supports without any transpilation. All browsers which it supports have a sufficient level of ES6 support.
Why would you need ES5?
The only reason why you might want to transpile CKEditor 5 from ES6 to ES5 are:
Legacy browsers which it doesn't support (at least at the moment).
Existing setups which use ES6-incompatible JS minifiers (UglifyJS). It may be a bit inconvenient to include CKEditor 5 in such applications but, as it was commented already, we explain how to transpile CKEditor 5 to ES5.
Development environments for frameworks like React (create-react-app) or Angular (angular-cli) which didn't catch up yet and still require that libs kept in your node_modules/ are in ES5.
The last case is indeed a bigger problem because you don't have that much control over this environments as on your own projects. As I commented on Twitter:
3 years ago we decided that CKEditor 5 will be released in ES6 because all browsers which we planned to support should have a sufficient ES6 support by our ETA.
We were right – it worked great... in the browsers.
It turned out that the problem is in the build environments (create-react-app, angular-cli) which did not catch up.
We'll need to introduce ES5 builds just to satisfy these envs ;/
To clarify – I'm not criticising authors of these tools. It's more of an observation that we've been always worried about browser support while today the tools stop us.
And, as I mentioned in the other tweet, the problem is broad (e.g. finding a supported, stable, ES6+ compatible and fast minifier – see e.g. https://github.com/webpack-contrib/uglifyjs-webpack-plugin/issues/262 …).
Fortunately, the situation is improving:
#mtrebizan:
I think CRA 2.0 will be shipping non-transpiled code,just don't know how far release is. cc #dan_abramov
#dan_abramov:
There’s alphas you can try. Other than that the ETA is when the community makes it happen 🙂 there’s active work and you can help too
I know there was work in angular-cli on improving this situation too. So, in a relatively short time, all should work smoothly too.
Time aspect
The difference (in terms of features) between ES6 and ES5 is huge. Back in 2014, when we've been starting CKEditor 5 development, we chose ES5. ES6 wasn't standardised yet.
However, the situation changed in 2015. ES6 got published and our tests proved that all features we looked to (classes, generators, iterators, weak sets, weak maps, and more) were already available in Chrome. We decided to go for it and see.
About 1.5 year later CKEditor 5 worked natively (without any transpilation) in all modern browsers (with the exception of Safari which had a nasty bug). At the same time, babel-minify became usable so we didn't have to transpile CKEditor 5 to ES5 even for production.
It's 2018 and the number of obstacles was reduced even more. There's a chance that still this year you won't have to transpile CKEditor 5 to ES5 unless your project is supposed to be ES5 because of browser support (but then, why would you include CKEditor 5? it's not going to work in those browsers anyway).
Looking at the history of CKEditor 3-4, CKEditor 5 will stay with us for the next 8+ years. So, we're talking here about 2026+. This means that for the vast majority of its lifetime ES6 will not be a problem.
CKEditor supports vanilla javascript (ES5) and ES6 as well. The issue is not the editor, it just supports it, doesn't care about compatibility because it doesn't know where your code is going to run but only how to highlight and give you tools to develop it.
The thing is that, by the time, the ECMA standard is under heavy development, improving in every version, so there's a lot going on, there are a lot of proposals being added every month, some passes and makes their way into the standard, which later gets into cool features we can use like arrow function.
All of that makes it harder for browsers to catch on the new updates. Even so, there are a lot that supports the new features now (you may track the updates in that page).
Anyway, besides from all of that, you may use a code compiler like Babel (which compiles ES6/ES7... down to code the browsers can understand such as ES5). It's widely adopted, and recommended for the thing it does: Make your life easier. Many big companies adopted it, such as Facebook which uses react (and made it) using Babel to compile not only ES6 but JSX (check this).
Side note: Why should I use ES6 if I need a compiler?
https://itnext.io/why-you-should-use-es6-56bd12f7ae09
I want to use ES6 features in my script, and having all browsers support it. How can I do that, and can I?
I've been thinking about using some tool that will convert my code to ES5 automatically on git pulling it on the server, and create the second file out of it. And then in the browser I could use one of those scripts, depending on the browser and its version.
Is this possible?
It would however create some problems:
Converted code would have the same performance as writing the code
in ES5 natively.
I would have to write some kind of if in the HTML, and I want to
include just one script, without anything else.
What's the best way to do this?
Until more browsers support ES2015 (aka ES6) features, using transpilers and polyfills will be the only way to go. Checkout the ES6 compatibility table to determine what features you can use today for the browsers your site supports.
Keep in mind that there are two main parts to ES6:
new language features
new native API features
Until all the browsers your site supports have support for the new ES6 language features, you won't be able to use them in your scripts without first transpiling them to an ES5 equivalent. I've used babel and it has worked great. The ES5 equivalent code that is generated has performed just fine. It also beats me trying to write equivalent ES5 code manually. The code generated by babel has been thoroughly tested by babel's test suite and has been used by thousands of developers around the world. Also, writing your code with ES6 is shorter and easier to maintain. This saves a lot of developer time. When the day comes that when all the browsers your site supports have support for all the ES6 features, then you can turn off the transpiling step in your build and you'll get the full benefit of native browser performance without having to manually convert your manually written ES5 code to ES6.
Many of the new native API features can be used today by providing a polyfill. The polyfill is only needed when you want to use an ES6 feature AND you need to support older browsers. With a polyfill, only the older browsers may have slower performance compared to the native implementation. Since most of the modern browsers already support many of the native ES6 API features, many of your users will get the full performance of the browser's native implementation. From my experience with polyfills, I have not noticed any significant performance implications.
If you are concerned about modern browsers unnecessarily downloading and running the polyfill all for naught, then there are techniques you can to do minimize the impact:
On the server-side, you can detect the browser making the request and determine whether to bother sending the polyfill script tag in the response.
You can properly version the polyfill and make sure the web server's caching is set so the browser will rarely make a request for the polyfill after the initial download.
babel used to be able to transpile the ES6 code in your html files, but that feature has been removed. You can just move your embedded code to a separate external JavaScript file. If you don't like the idea of incurring another request to get this external JavaScript file, then you can do the following:
Write your ES6 code in a separate file.
Run this file through babel
Use your server-side scripting language to include the transpiled content directly in your HTML.
#DannyHurlburt's answer was correct at the time of posting it, but now, you can use TypeScript language (with .ts file extension) to work around this. TypeScript is a strict superset of JavaScript, so any ES6 code you have is also lexically valid TypeScript. TS compiles to old versions of JavaScript as old as ES3.