
Security News
Feross on TBPN: How North Korea Hijacked Axios
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.
@tubular/browser-check
Advanced tools
As a web developer you likely know the pain of wanting to take advantage of useful new web browser features, but feeling like you have to hold back until very few users will be inconvenienced or excluded by browser incompatibilities which might arise from using the latest and greatest features that browsers have to offer.
Fortunately these days a majority of web users have switched to “evergreen” browsers which frequently self-update, allowing you to employ new features of JavaScript, HTML, and CSS with reasonable confidence.
There are still, however, people clinging to Windows 7 and IE. There are users with old desktops and mobile devices with limited capacity for updates and upgrades. Ideally, instead of leaving such users out in the cold, you selectively downgrade the capabilities of your websites a little, still providing most of the desired experience on older browsers — perhaps a little less stylishly, without all the bells and whistles.
There are times, however, when only relatively up-to-date web browsers will do. There need to be some cut-off points, below which you have to say to your users (much more diplomatically, of course) they are 💩 out of luck trying to get by with an older web browser.
Preferably this message of misfortune will be conveyed gracefully, not left to the user to deduce by way of frozen screens, confusing error messages, endlessly spinning spinners, jumbled page layouts, and other assorted technical failures. A polite, friendly, human-readable message explaining the problem, and perhaps even how to remedy the issue, is a much better way to go.
This is where @tubular/browser-check comes in.
This is a script written in lowest-common-denominator JavaScript (requiring nothing that cannot be done when constrained by the ancient standard of ES3) for assessing what a web browser is or is not capable of, providing an opportunity to redirect to an incompatibility message page when needed.
Using @tubular/browser-check, you can specify a minimum ES level (6/2015, 2016, 2017, etc.), particular features required (such as grid layout or WebGL), and/or minimum version numbers for popular web browsers. You can also rule out some web browsers (such as Internet Explorer and pre-Chromium Legacy Edge) entirely.
@tubular/browser-check should be invoked via a <script> tag, before any other (possibly incompatible) JavaScript has a chance to run. This likely means being the first, or close to the first, script in the <head> section of a web page.
npm i -D @tubular/browser-check
Since this code is meant to run as a pre-check process, and not to be a bundled part of a web application itself, it makes the most sense to install it under devDependencies, not dependencies, then copy either browser-check.js or browser-check.min.js from node_modules as part of your build process. For example, here is how I’m using the script in an Angular project, as seen in a snippet from my angular.json file:
{
// ...
"assets": [
"src/favicon.ico",
"src/assets",
{
"glob": "browser-check.min.js*",
"input": "./node_modules/@tubular/browser-check/dist/",
"output": "./assets/"
}
],
// ...
}
The script is pulled into the <head> section of the project’s index.html like this:
<script src="assets/browser-check.min.js" type="text/javascript"
id="tb-browser-check"
data-bc-vers="0,79,79,13.1,605" data-bc-min-es="2017"
data-bc-fail-url="assets/incompatible.html"></script>
The id is important so that very old browsers which don’t support querySelector can locate the script tag using getElementById. An alternative id value is "tubular-browser-check".
<script src="https://unpkg.com/@tubular/browser-check/dist/browser-check.min.js" type="text/javascript"
id="tb-browser-check"
data-bc-vers="0,79,79,13.1,605" data-bc-min-es="2017"
data-bc-fail-url="assets/incompatible.html"></script>
As always, the unpkg.com URL can include a specific npm package version if desired.
Older versions of IE can be buggy handling <base href=...> tags. As a result, it’s possible either the loading of this script, or the loading of your redirect page, might fail. The following code, placed after the <base> tag, and before the <script> tag, can fix that issue:
<!--[if IE]><script type="text/javascript">
(function() { // Fix for IE ignoring relative base tags.
var baseTag = document.getElementsByTagName('base')[0];
baseTag.href = baseTag.href + '';
})();
</script><![endif]-->
Options are passed to @tubular/browser-check via various data-bc- attributes of the <script> tag.
data-bc-fail-urlThis is the URL to which the user will be forwarded if the browser check fails. If this setting is omitted, @tubular/browser-check merely gathers information about a browser without taking any action.
In the event of a failed browser check, this URL will be appended with the parameter msg, containing a URL-encoded explanation of the reason why the browser check failed.
data-bc-min-esThis is the minimum acceptable ES compliance level. Nothing earlier than ES3 will be reported or detected. (Very few browsers should rate lower than ES2009 (ES5) these days.)
When set to a specific ES version (for example, 2018), @tubular/browser-check will stop checking for higher ES levels as soon as 2018 compliance is determined (although individual higher-level features can still be checked). If data-bc-min-es is set to 0, no ES level checking will be performed. If data-bc-min-es is set to -1, @tubular/browser-check will seek the highest level of support.
Not every ES feature is tested, of course, only a representative sample sufficient to determine the level of support with reasonable certainty.
| ES2009 (ES5) tests | |
|---|---|
array2009 | Array methods forEach, map, filter,
reduce, and sort |
object2009 | Object methods create, freeze, and keys |
| ES2015 (ES6) tests | |
array2015 | Array methods Array.from, keys, find, and findIndex |
arrow | Arrow functions |
class | class declarations |
def_params | Default function parameter values, e.g. function foo(a = 5) |
destructuring | Destructuring, e.g. let [a, b, c] = [1, 2, 3] |
for_of | for/of loops |
let_const | let and const keywords |
map_set | Map and Set classes |
promise | Native Promise |
regex2015 | Unicode-aware regular expressions, with the u flag |
rest_param | Rest function parameters, e.g. function foo(a, ...b) |
string2015 | String methods includes, startsWith, and endsWith |
symbol | Symbol objects are available |
template | Template strings, marked with back ticks, e.g. `You have ${count} cats.` |
| ES2016 tests | |
array2016 | The array includes method |
exp_op | The ** exponentiation operator |
| ES2017 tests | |
async | async/await support |
object2017 | Object.entries and Object.values |
string2017 | String methods padStart and padEnd |
| ES2018 tests | |
for_await | for/await loops |
promise_finally | Promise finally method |
regex2018 | Support for look-behind, Unicode character classes, and the dot-all flag, e.g. /(?<=f)\p{L}+./su |
rest_prop | Rest syntax for object properties, e.g. let objClone = { ...obj } |
| ES2019 tests | |
array2019 | Array flat and flapMap methods |
catch_unbound | catch clause in try/catch doesn’t need to be bound to a variable |
object2019 | Object.fromEntries method |
string2019 | String trimStart and trimEnd methods |
| ES2020 tests | |
all_settled | Promise.allSettled method |
bigint | Native big integers, e.g. 12345678901234567890n |
global_this | globalThis is defined |
null_ops | Support for ?. optional chaining and ?? null-coalescing operators |
| ES2021 tests | |
logical_assigns | Support for &&=, ||=, and ??= assignment operators |
promise_any | Promise.any method |
underscores | Underscores allowed in numeric constants, such as 86_400_000 |
| ES2022 tests | |
private_fields | Classes can have private fields, marked by # |
private_accessors | Classes can have private accessors, marked by # |
static_fields | Classes can have static fields |
static_methods | Classes can have static methods |
static_init | Classes can have static initializers |
array_at | Array at(index) function available |
error_cause | Error class can be initialized with a cause |
has_own | Object.hasOwn() function available |
regex2022 | Regular expression d flag, providing start and end positions for matched groups |
data-bc-featuresA comma-delimited list of browser features that you want to check and require. They can be any of the above ES feature tests, or from the list of other browser features below. Use the test other to compile a full list of all the features listed below that a browser supports.
audio | Basic audio playback and processing |
av_input | Audio/video input, such as access to microphone and camera |
canvas | 2-D canvas drawing |
canvas_text | 2-D canvas drawing with text rendering |
flex | CSS flex layout |
geo | Geolocation services |
grid | CSS grid layout |
local_storage | Local storage support |
video | Video playback via HTML5 <video> tag |
webgl | Canvas WebGL support |
webgl2 | Canvas WebGL 2.0 support |
workers | Support for Web Workers |
data-bc-versYou can set this attribute to a comma-delimited list of minimum-supported browser version numbers, with the list of numbers being in this fixed order:
You can use 0 as the version number for any browser you wish to completely disallow, and -1 for any browser you do not wish to check at all. (Any unspecified versions are treated as -1). Version numbers can include multiple dot-delimited version fields, such as 13.1 or 101.0.4951.64. Qualifiers such as -beta are not handled.
Ideally you can test for browser support without identifying particular browsers, using ES level and other feature checks alone. But sometimes particular browser quirks and bugs must be considered.
I fully support, for example, data-bc-vers="0,0" as a common starting point, completely giving up on supporting Internet Explorer and all the pre-Chromium versions of Microsoft’s Edge browser.
Many browsers, such as Opera, Samsung, and the latest versions of Microsoft Edge, are based on the same Chromium core engine as Google Chrome. These browsers are treated as variants of Chrome, and their Chrome version is what will matter, not their various browser-specific version numbers.
Please note: @tubular/browser-check does not employ a highly sophisticated browser identification system. Browser identification is an inexact science. The most accurate identification systems are much bigger and more elaborate than the quick-and-dirty classification scheme provided here. You might need to employ other means in addition to, or instead of, @tubular/browser-check if your needs for browser identification are more demanding.
data-bc-globalsSet this attribute to true (or simply add the attribute as a flag attribute with no value at all) if you would like to have @tubular/browser-check save its results in the global variable window.tb_bc_info. The information provided is, for example, as follows:
{
browser: "Chrome", // Name or description of browser, possibly "Unrecognized"
version: "101.0.4951.64", // Browser version, if determined
es: 2021, // ES specification passed. 0 if never checked, minimum value of 3 if checked
otherFeatures: "audio, av_input... workers", // Any tests successfully passed beyond the ES level check tests.
msg: "" // If any tests have failed, the message describing that failure.
}
data-bc-googlebotBy default, this option is A(lways), allowing Googlebot access all the time. Option (N)ever turns Googlebot away in all circumstances. Option (I)gnore makes Googlebot immaterial, so that all other tests function as normal.
Add the parameter tb-bc-skip=true to a URL to skip over browser checking when a web page loads.
FAQs
Check for compatibility of browser versions and features
We found that @tubular/browser-check demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.

Security News
OpenSSF has issued a high-severity advisory warning open source developers of an active Slack-based campaign using impersonation to deliver malware.

Research
/Security News
Malicious packages published to npm, PyPI, Go Modules, crates.io, and Packagist impersonate developer tooling to fetch staged malware, steal credentials and wallets, and enable remote access.