Skip to content

Support for getUnsupportedUserAgentRegex() #1558

Open
@oprypkhantc

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';
}

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions