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
Related
In my Vue.js app, I have the following in package.json
"browserslist": [
"> 1%",
"last 2 versions"
]
I believe this is used by Babel to customise the JavaScript that is generated (other build tools may also use it). Is it possible for me to leverage this list of supported browsers to show an error if the user attempts to load the app in an unsupported browser?
I could write some JavaScript that detects the user agent and shows an error if the browser is not supported, but this would likely require me to maintain the list of supported browsers in 2 places, which I'd rather avoid.
First and foremost I want to mention that it might be a bad idea to do this. Browsers are update at quite a fast pace and users might not be able to update often due to for example some company policy. A better approach would be to use feature detection, where you check if a specific feature is supported by the browser. This might be a bit more work, but gives an actual reason to tell people that their browser is not supported.
You can use the browserslist-useragent-regexp package to generate a regular expression from your browserslist configuration. You can write this regular expression to a file and use it to test if navigator.userAgent is supported by your configuration. The README file in the browserslist-useragent-regexp repository contains an example setup.
Another options is to use the browserslist-useragent package, you can give this tool a user-agent and a browserslist configuration to check if a specific user-agent matches the browserslist configuration. This option might need some more research as it seems to be aimed first at Node.js applications.
This option seems to be abandoned and has some dependencies which are no longer maintained, so proceed at your own risk. obsolete-webpack-plugin can also be used which requires less setup if you're already using Webpack 4 in your project. It can be used with HtmlWebpackPlugin and it creates a new chunk which will insert an HTML snippet in your page when a browser is not supported.
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'm using Number.prototype.toLocaleString() to get rounding and thousands separators working nicely with world currencies in my first React Native app.
It works great in the iOS but not on Android. I guess the different JS engines have differing support for toLocaleString.
I understand that BabelJS has support for polyfills but don't understand fully what it does and does not cover and cannot find information on this function in particular.
Is there a way I can get it to work in RN using Babl to polyfill it?
Looking up a polyfill for Number#toLocaleString(), I found this module, and it does not require babel to use. In order to activate it in your code, put this line somewhere before you need it :
// recommended
require('number-tolocalestring-polyfill')()
If you need to force the polyfill to load, even if it detects that the environment already supports Number#toLocaleString() you can do this:
// probably for debug purposes only
require('number-tolocalestring-polyfill')(true)
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.
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.