@re2tools/re2-wasm
v1.0.2
Published
Lightweight WebAssembly wrapper around Google RE2. ESM-only, works in Node, browser, React, Angular, Storybook.
Maintainers
Readme
@re2tools/re2-wasm
Lightweight WebAssembly wrapper around Google RE2. ESM-only; works in Node.js 18+, browser, React 16+, Angular 14+, and Storybook 7+.
- No top-level await — call
RE2.initialize()once, then use sync API - Singleton WASM — HMR-safe, no double instantiation
- Small target — WASM < 600KB (vs re2js ~3.34MB)
- No catastrophic backtracking — RE2 guarantees linear time
Installation
npm install @re2tools/re2-wasmQuick start
Node.js (18+)
import RE2 from '@re2tools/re2-wasm';
await RE2.initialize();
const re = new RE2('\\d+');
console.log(re.test('hello42')); // true
console.log(re.exec('hello42')); // [ '42', index: 5, input: 'hello42' ]
console.log(re.replace('a1b2', 'X')); // 'aXbX' (with g flag)Browser
<script type="module">
import RE2 from 'https://cdn.example.com/@re2tools/re2-wasm/dist/index.js';
await RE2.initialize('/wasm/re2.wasm');
const re = new RE2('world');
console.log(re.test('hello world')); // true
</script>See docs/node.md, docs/browser.md, docs/react.md, docs/angular.md, docs/storybook.md for framework-specific setup.
API (sync after initialize())
| Method | Description |
|--------|-------------|
| RE2.initialize(urlOrPath?) | Async. Load WASM once. Call before any other use. |
| new RE2(pattern, flags?) | Constructor. pattern can be string or RegExp. |
| RE2.compile(pattern, flags?) | Same as new RE2(...). |
| re.test(input) | Returns true if pattern matches. |
| re.exec(input) | Returns match array or null (like RegExp.prototype.exec). |
| re.match(input) | Like String.prototype.match. |
| re.replace(input, replacement) | Like String.prototype.replace. |
| re.split(input, limit?) | Like String.prototype.split. |
Properties: source, flags, global, ignoreCase, multiline, dotAll, unicode, lastIndex.
WASM hosting
- Node: WASM is resolved from the package
wasm/directory next to the built JS. - Browser / Vite / Webpack: Copy or serve
node_modules/@re2tools/re2-wasm/wasm/re2.wasmand pass its URL toRE2.initialize(url)if the default resolution fails.
See docs/browser.md for Vite/Webpack and CDN notes.
Common errors and fixes
| Error | Fix |
|-------|-----|
| "RE2 not initialized" | Call await RE2.initialize() before using any RE2 API. |
| "Failed to load WASM" | Ensure re2.wasm is present in wasm/ and (in browser) served with correct MIME or path. |
| Node ESM path error | Use "type": "module" and import from the package name; avoid __dirname in user code. |
See docs/troubleshooting.md for more.
Performance
- Target WASM size < 600KB.
- No catastrophic backtracking (unlike JS
RegExpon certain patterns). - Stable under heavy loops; no async in hot paths after
initialize().
Differences from JS RegExp
- RE2 syntax — Some PCRE/JS features (e.g. lookbehind, backreferences) are not supported; see RE2 syntax.
- One async step — Only
RE2.initialize()is async; all instance methods are synchronous after that. - Singleton — One WASM instance per process/page; safe with HMR.
Build (WASM from source)
Prerequisites: Emscripten SDK, Google RE2 (include + lib).
# Set RE2 paths if needed
export RE2_INC=/usr/local/include RE2_LIB=/usr/local/lib
npm run build:wasmThis produces wasm/re2.wasm. The script runs the following (see scripts/build-wasm.sh):
emcc -Os -flto -fno-exceptions -fno-rtti \
-s WASM=1 -s ENVIRONMENT=web,node -s FILESYSTEM=0 \
-s ALLOW_MEMORY_GROWTH=1 -s ASSERTIONS=0 -s SAFE_HEAP=0 \
-s STACK_OVERFLOW_CHECK=0 -s MINIMAL_RUNTIME=1 \
-s EXPORTED_FUNCTIONS='["_re2_test","_re2_exec","_malloc","_free"]' \
-s EXPORTED_RUNTIME_METHODS='[]' \
-I "$RE2_INC" cpp/re2_wrapper.cc -L "$RE2_LIB" -lre2 -o build/re2.jsEmscripten outputs re2.js and re2.wasm; the package uses only re2.wasm with WebAssembly.instantiate. Target WASM size is under 600KB.
License
Apache-2.0
