Node.js module resolution algorithm with browser field support for handling browser-specific module mappings
npx @tessl/cli install tessl/npm-browser-resolve@2.0.0Browser Resolve is a Node.js module resolution algorithm with browser field support. It extends the standard Node.js require.resolve() to handle browser-specific module mappings defined in package.json files through the 'browser' field specification, enabling proper module resolution for browser environments.
npm install browser-resolveCommonJS (primary format):
const resolve = require('browser-resolve');ES modules (when using Node.js with ESM or bundlers):
import resolve from 'browser-resolve';const resolve = require('browser-resolve');
// Async resolution
resolve('../some-module', { filename: __filename }, function(err, path) {
if (err) throw err;
console.log('Resolved to:', path);
});
// Sync resolution
try {
const resolvedPath = resolve.sync('../some-module', { filename: __filename });
console.log('Resolved to:', resolvedPath);
} catch (err) {
console.error('Resolution failed:', err);
}
// Browser field resolution
resolve('./main.js', {
basedir: '/path/to/package',
browser: 'browser' // use browser field from package.json
}, function(err, path) {
console.log('Browser-specific path:', path);
});
// Core module shimming
const shims = {
http: '/path/to/browser-http.js',
fs: false // exclude fs module
};
resolve('http', { modules: shims }, function(err, path) {
console.log('Shimmed path:', path);
});Resolves a module path asynchronously with browser field support and calls a callback with the result.
/**
* Resolve a module path and call cb(err, path [, pkg])
* @param {string} id - Module identifier to resolve
* @param {ResolveOptions} opts - Resolution options
* @param {function} cb - Callback function (err, path, pkg) => void
*/
function resolve(id, opts, cb);Resolves a module path synchronously with browser field support and returns the resolved path.
/**
* Synchronously resolve a module path
* @param {string} id - Module identifier to resolve
* @param {ResolveOptions} opts - Resolution options
* @returns {string} - Resolved path
* @throws {Error} - If resolution fails
*/
resolve.sync = function(id, opts);All resolution functions accept an options object with the following properties:
interface ResolveOptions {
/** Directory to begin resolving from */
basedir?: string;
/** The package.json property to use for browser mappings (defaults to 'browser') */
browser?: string;
/** The calling filename where require() originated */
filename?: string;
/** Module id/name -> path mappings for core modules */
modules?: { [key: string]: string | false };
/** Transform parsed package.json contents before looking at main field */
packageFilter?: (pkg: any, pkgdir: string) => any;
/** require.paths array for additional search paths */
paths?: string[];
/** Filter resolved paths during resolution */
pathFilter?: (pkg: any, path: string, relativePath: string) => string;
}The library supports various browser field formats in package.json:
{
"main": "index.js",
"browser": "browser.js"
}{
"browser": {
"./server.js": "./client.js",
"./lib/fs.js": false
}
}{
"browser": {
"fs": false,
"crypto": false
}
}{
"browser": { "./main.js": "browser.js" },
"chromeapp": { "./main.js": "chromeapp.js" }
}// Use custom browser field
resolve('./main.js', { browser: 'chromeapp' }, callback);Browser Resolve provides flexible core module handling:
// Define custom core module mappings
const modules = {
'http': '/path/to/browser-http.js',
'fs': '/path/to/browser-fs.js',
'crypto': false // exclude crypto module
};
resolve('http', { modules: modules }, function(err, path) {
// path will be '/path/to/browser-http.js'
});
resolve('crypto', { modules: modules }, function(err, path) {
// path will be the empty module (exclusion)
});When a browser field maps a module to false, it resolves to an empty module:
// If package.json has: { "browser": { "fs": false } }
resolve('fs', { basedir: '/path/to/package' }, function(err, path) {
// path will be '/path/to/browser-resolve/empty.js'
});The library handles various error conditions gracefully:
// Async error handling
resolve('non-existent-module', opts, function(err, path) {
if (err) {
console.error('Resolution failed:', err.message);
return;
}
console.log('Resolved:', path);
});
// Sync error handling
try {
const path = resolve.sync('non-existent-module', opts);
console.log('Resolved:', path);
} catch (err) {
console.error('Resolution failed:', err.message);
}Browser Resolve depends on:
The library maintains backward compatibility:
browserify field if browser field is not present