Description
Would you like to work on this feature?
- Check this if you would like to implement a PR, we are more than happy to help you go through the process.
What problem are you trying to solve?
Hey.
Currently the generated regex by getUserAgentRegex
outputs a RegExp to match a browser that is supported. This works for build/automation tools - they can use that information to avoid unnecessary transformations when features are natively supported.
However, this works poorly to match a browser that is not supported. Suppose we have this example .browserlistrc
:
chrome >= 85
firefox >= 76
safari >= 14.1
not ie
If we then simply take the result of the browserslist-useragent-regexp --allowHigherVersions
and do this:
import supportedBrowsers from './supportedBrowsers.js';
if (navigator.userAgent && !supportedBrowsers.test(navigator.userAgent)) {
window.location.href = '/old-browser.html';
}
then indeed Chrome < 85, Firefox < 76 and Safari < 14.1 will be redirected to /old-browser.html
. The problem with this approach is that any other browser, say latest Opera or any new (unknown to Browserslist) browser, will also be redirected to /old-browser.html
, even though it may indeed be working and fully functional.
Describe the solution you'd like
A new getUnsupportedUserAgentRegex()
function that returns a RegExp matching all browsers that were specified in .browserslistrc
, but whose version does not match, including negated ones (not ie
).
Basically, the same .browserslistrc
from above:
chrome >= 85
firefox >= 76
safari >= 14.1
not ie
would match Chrome < 85, Firefox < 76, Safari <14.1 and Internet Explorer, but NOT any other browser that wasn't explicitly specified in .browserslistrc
. So Chrome >= 85, Firefox >= 76, Safari >= 14.1, Opera >= 0, Baidu >= 0 etc.
I would work on the PR for this, but I'm not sure how to approach this since browserslist()
function doesn't even return Internet Explorer
as one of the browser in this case. It seems that this must first be implemented on browserslist
side by negating each expression separately, transforming the original file:
not chrome >= 85
not firefox >= 76
not safari >= 14.1
not not ie
Which would then give us basically what I want:
chrome < 85
firefox < 76
safari < 14.1
ie
Describe alternatives you've considered
I've considered using two RegExps:
import { getUserAgentRegexes } from 'browserslist-useragent-regexp';
const browserRegexes = getUserAgentRegexes({
allowHigherVersions: true,
});
// Browsers that were explicitly specified in the config, e.g. Firefox, Chrome and Safari
const knownBrowsers = new RegExp(browserRegexes.map(({ sourceRegex}) => sourceRegex.source).join('|'));
// Same browsers, but also with version constraints
const supportedBrowsers = new RegExp(browserRegexes.map(({ regex}) => regex.source).join('|'));
if (navigator.userAgent && knownBrowsers.test(navigator.userAgent) && !supportedBrowsers.test(navigator.userAgent)) {
window.location.href = '/old-browser.html';
}
This does fix the problem of unknown browsers - those not explicitly specified (e.g. Opera from the example above) in the config will not be redirected anymore.
But now explicitly NOT supported browsers will not be redirected to, because not ie
is completely ignored and isn't present in any of the RegExps. So even though IE is explicitly specified as not supported, it won't be redirected.
Documentation, Adoption, Migration Strategy
Users can switch the function to a new one, or use a new CLI flag (browserslist-useragent-regexp --unsupported
).
// browserslist-useragent-regexp --allowHigherVersions --unsupported
import unsupportedBrowsers from './unsupportedBrowsers.js';
if (navigator.userAgent && unsupportedBrowsers.test(navigator.userAgent)) {
window.location.href = '/old-browser.html';
}