Skip to main content

Fixing node: prefixed requires/imports in Browserify

If you're running into issues with Browserify and prefixed module names (like in require("node:fs")), and you cannot change the imports because eg. they exist within a third-party module, then this workaround will fix that.

This doesn't work for newer core modules like node:test, which are only possible to require using the prefix; it only works for core modules that allow importing both with and without the prefix.

You can use browserify-replace to automatically replace every occurrence of the prefix in every module; you need to ensure that this comes before any other transform, including before things like Babel.

For example:

	app.use("/bundle.js", watchifyMiddleware(browserify("src/ui/index.jsx", {
		basedir: __dirname,
		debug: true,
		cache: {},
		extensions: [".jsx"],
		transform: [
			["browserify-replace", {
				global: true,
				replace: [
					{ from: '"node:([a-z_-]+)"', to: '"$1"' },
					{ from: "'node:([a-z_-]+)'", to: "'$1'" },
				]
			}],
			["babelify", {
				presets: ["@babel/preset-env", "@babel/preset-react"],
			}],
		]
	})));

The browserify-replace transform is what makes it work; the global flag is what makes it work for everything within node_modules too. The rest of the example is not relevant to make it work, this code is just taken from a project of mine.

What it does is do a string-replace to strip the prefix off everything that it finds. Because it's a string replace, it doesn't need to go through any (language-aware) processing steps that might stumble over the unsupported import path, so this should work for eg. JSX and Typescript as well.

It's still a hack and it'll match any string that has this format, so I wouldn't recommend relying on this in the long term, and I'd suggest looking into a better-maintained bundler like Parcel nowadays. But to keep things running in the short term, this should suffice.