browserslist-useragent-regexp
Compile a Browserslist query into a RegExp that tests a browser's user agent string.
Repository Health
Technical Analysis
browserslist-useragent-regexp turns a Browserslist query (the same syntax used by Autoprefixer, Babel, and PostCSS) into a compiled RegExp that can be tested directly against navigator.userAgent on the client. That means the decision of which browsers are supported can move out of a server-side lookup table and into a single regex shipped with the bundle, avoiding a round trip or a dependency on server logic to decide which bundle a visitor should receive.
Under the hood it merges browser version ranges from Browserslist, generates per-family user-agent regex fragments, applies semver-aware version constraints (ignoring patch/minor differences as configured), and optimizes the combined regex so it stays compact even for broad queries like “last 2 versions, not dead”. It ships both a programmatic API (getUserAgentRegex/getUserAgentRegexes) and a CLI (browserslist-useragent-regexp / bluare) for generating the regex as part of a build script.
What You Get
getUserAgentRegex(options)— compiles a Browserslist query into a single combined RegExpgetUserAgentRegexes(options)— compiles per-browser-family regex info objects (family, min/max version, source and versioned regex)- A CLI (
browserslist-useragent-regexp, aliasedbluare) for generating the regex as a build step and writing it to a file - Full TypeScript typings and semver-aware options (
ignorePatch,ignoreMinor,allowHigherVersions,allowZeroSubversions) for tuning how strictly versions must match - A
--verboseCLI mode that prints a readable breakdown of the resolved browser list and each compiled regex for debugging
Common Use Cases
- Generating a client-side supported-browsers check to gate legacy-bundle warnings or upgrade prompts
- Implementing differential script loading (serve modern vs. legacy bundles) purely from a build-time generated regex, no server logic required
- Feature-detection fallback: testing the user agent as a secondary signal alongside
navigatorfeature checks - CI/build-time generation of a
supportedBrowsers.jsconstant from the project’s existing.browserslistrcconfig
Under The Hood
Architecture
The library is organized as a small pipeline of independent, single-purpose modules under src/: browsers/ resolves and merges Browserslist query results into per-family version ranges, useragent/ maps each browser family to its raw user-agent regex fragment (sourced from ua-regexes-lite), versions/ applies the resolved version ranges onto those fragments, regex/ optimizes and compiles the final combined pattern (via regexp-tree), and semver//numbers/ provide the version-comparison and range-arithmetic primitives the other layers depend on. src/useragentRegex/useragentRegex.ts is the orchestration point — getPreUserAgentRegexes chains getBrowsersList → mergeBrowserVersions → getRegexesForBrowsers → applyVersionsToRegexes, and getUserAgentRegex(es) wrap that with final compilation. src/cli.ts is a thin presentation layer over the same exported API, adding argument parsing (argue-cli) and table-formatted verbose output (easy-table, picocolors). If the core browser-to-regex mapping changed, every downstream module (versions, regex compilation, CLI output) would need to follow, but the layered exports (index.ts per folder) keep that blast radius explicit and typed.
Tech Stack
Written in TypeScript (ESM-only, type: module) targeting Node >=14, built with Rollup plus rollup-plugin-swc3 for transpilation and tsc --emitDeclarationOnly for .d.ts output. Runtime dependencies are minimal and single-purpose: browserslist (peer dependency) for query resolution, ua-regexes-lite for the raw per-browser user-agent regex fragments, regexp-tree for regex AST manipulation/optimization, plus argue-cli, easy-table, and picocolors for the CLI. Testing runs on Vitest with @vitest/coverage-v8; linting uses ESLint 9 via @trigen/eslint-config; commit messages are enforced with commitlint/commitizen and hooks via simple-git-hooks/nano-staged. Bundle size is tracked in CI with size-limit.
Code Quality
Tests are colocated with source as *.spec.ts files across nearly every module (browsers, numbers, regex, semver, useragent, useragentRegex, versions, utils) and run through Vitest with coverage collection, indicating deliberate unit-level coverage of each pipeline stage rather than only integration tests. Public functions carry JSDoc comments describing parameters and return types, and the whole codebase is strict TypeScript with exported types for every options/result shape (e.g. UserAgentRegexOptions, SemverCompareOptions). CI (.github/workflows/tests.yml, checks.yml) runs linting, the size-limit check, package.json linting, and editorconfig checks on every PR, plus a separate commitlint workflow — indicating a maintained, gated contribution process despite the project’s low commit cadence.
What Makes It Unique
Rather than parsing a user agent string at request time against a large signature database (the approach used by libraries like browserslist-useragent’s matchesUA), this project precompiles the entire Browserslist query into one optimized RegExp at build time. That shifts all the matching cost to a single client-side regex test — measurably faster than repeated string/version parsing — and removes the need for any server-side logic to decide which bundle to serve, which is the specific niche it occupies relative to adjacent Browserslist tooling.