URLPattern Polyfill
The `urlpattern-polyfill` package provides a robust and standards-compliant polyfill for the emerging URLPattern Web API, designed to bring powerful URL matching capabilities to environments lacking native support. Currently at version 10.1.0, this project is actively maintained, with releases typically following updates to the URLPattern specification and bug fixes. A key differentiator is its rigorous adherence to the official web platform test suite, ensuring functional parity with native browser implementations. This enables developers to utilize `URLPattern` for complex routing logic in web applications, service workers, and Node.js backend services without concerns about environment fragmentation. The polyfill integrates intelligently, only applying itself to `globalThis` if `URLPattern` is not already defined, preventing conflicts and ensuring efficient resource usage.
Common errors
-
Property 'URLPattern' does not exist on type 'typeof globalThis'.
cause TypeScript compiler cannot find the `URLPattern` type on `globalThis` before the polyfill's types are globally applied, particularly within conditional `if` statements that check for its existence.fixAdd `// @ts-ignore: Property 'URLPattern' does not exist on type 'typeof globalThis'.` above the line where `globalThis.URLPattern` is accessed for the conditional check.
Warnings
- gotcha When conditionally loading the polyfill (`if (!globalThis.URLPattern) { await import("urlpattern-polyfill"); }`), TypeScript might flag `globalThis.URLPattern` as an unknown property because the polyfill hasn't loaded yet and the type definitions aren't globally applied at compile-time.
- breaking While `urlpattern-polyfill` aims for spec compliance, relying on polyfills for core web platform features always carries a risk of subtle behavioral differences or performance implications compared to native implementations, especially as the standard evolves. This is inherent to polyfilling a rapidly developing specification.
- gotcha The polyfill is designed to load conditionally, only activating if `globalThis.URLPattern` is undefined. If another polyfill has already been loaded, or if a browser's native implementation is present but potentially buggy or non-compliant, this polyfill will not overwrite it by default.
Install
-
npm install urlpattern-polyfill -
yarn add urlpattern-polyfill -
pnpm add urlpattern-polyfill
Imports
- URLPattern (global)
import URLPattern from 'urlpattern-polyfill';
if (!globalThis.URLPattern) { await import("urlpattern-polyfill"); } - URLPattern (named export)
import * as URLPattern from 'urlpattern-polyfill';
import { URLPattern } from 'urlpattern-polyfill'; - URLPattern (global, CJS)
const URLPattern = require('urlpattern-polyfill');if (!globalThis.URLPattern) { require("urlpattern-polyfill"); } - URLPattern (destructured, CJS)
const URLPattern = require('urlpattern-polyfill').URLPattern;const { URLPattern } = require('urlpattern-polyfill');
Quickstart
// First, ensure the polyfill is loaded if native URLPattern is absent.
// @ts-ignore: Property 'URLPattern' does not exist on type 'typeof globalThis'.
if (!globalThis.URLPattern) {
// Using dynamic import for conditional loading, works in ESM contexts.
await import("urlpattern-polyfill");
}
// Basic example: Matching a simple path with a named group.
// Ensure URLPattern is available after the conditional import.
let p1 = new URLPattern({ pathname: '/foo/:name' });
let r1 = p1.exec('https://example.com/foo/bar');
console.log('--- Basic Example ---');
console.log(`Input: ${r1?.pathname?.input}`); // Expected: "/foo/bar"
console.log(`Named group 'name': ${r1?.pathname?.groups?.name}`); // Expected: "bar"
console.log('\n');
// More advanced example: Matching specific file types with a base URL.
const p2 = new URLPattern({
pathname: '/*.:filetype(jpg|png)',
baseURL: 'https://example.com' // Explicit baseURL for clarity, mimicking self.location
});
const urlsToTest = [
'https://example.com/images/photo.jpg',
'https://example.com/docs/report.pdf',
'https://example.com/assets/icon.png',
'https://anothersite.com/image.jpg' // This will not match due to baseURL
];
console.log('--- Filetype Matching Example ---');
urlsToTest.forEach(url => {
const r2 = p2.exec(url);
if (r2) {
console.log(`Match for ${url}:`);
console.log(` Filetype: ${r2.pathname.groups['filetype']}`);
if (r2.pathname.groups['filetype'] === 'jpg') {
console.log(' -> Process as JPG');
} else if (r2.pathname.groups['filetype'] === 'png') {
console.log(' -> Process as PNG');
} else {
console.log(' -> Unknown image type');
}
} else {
console.log(`No match for ${url}`);
}
});