353 lines
14 KiB
Markdown
353 lines
14 KiB
Markdown
|
# node-stdlib-browser
|
|||
|
|
|||
|
[![Build Status][ci-img]][ci]
|
|||
|
|
|||
|
[Node standard library](https://nodejs.org/docs/latest/api/) for browser.
|
|||
|
|
|||
|
Features:
|
|||
|
|
|||
|
- Based on [`node-libs-browser`](https://github.com/webpack/node-libs-browser)
|
|||
|
for Webpack
|
|||
|
- Maintained with newer versions and modern implementations
|
|||
|
- Works with Webpack, Rollup, Vite, esbuild and Browserify, but should also
|
|||
|
work with other bundlers
|
|||
|
- Exports implementation with [`node:` protocol][node-protocol-imports] which
|
|||
|
allows for builtin modules to be referenced by valid absolute URL strings
|
|||
|
|
|||
|
Check [example](/example) to see how modules work in browser environment.
|
|||
|
|
|||
|
## Install
|
|||
|
|
|||
|
```sh
|
|||
|
npm install node-stdlib-browser --save-dev
|
|||
|
```
|
|||
|
|
|||
|
## Usage
|
|||
|
|
|||
|
### Webpack
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary>Show me</summary>
|
|||
|
|
|||
|
As of Webpack 5, aliases and globals provider need to be explicitly configured.
|
|||
|
If you want to handle [`node:` protocol][node-protocol-imports] imports, you
|
|||
|
need to provide helper plugin.
|
|||
|
|
|||
|
```js
|
|||
|
// webpack.config.js
|
|||
|
const stdLibBrowser = require('node-stdlib-browser');
|
|||
|
const {
|
|||
|
NodeProtocolUrlPlugin
|
|||
|
} = require('node-stdlib-browser/helpers/webpack/plugin');
|
|||
|
const webpack = require('webpack');
|
|||
|
|
|||
|
module.exports = {
|
|||
|
// ...
|
|||
|
resolve: {
|
|||
|
alias: stdLibBrowser
|
|||
|
},
|
|||
|
plugins: [
|
|||
|
new NodeProtocolUrlPlugin(),
|
|||
|
new webpack.ProvidePlugin({
|
|||
|
process: stdLibBrowser.process,
|
|||
|
Buffer: [stdLibBrowser.buffer, 'Buffer']
|
|||
|
})
|
|||
|
]
|
|||
|
};
|
|||
|
```
|
|||
|
|
|||
|
If you’re using ESM config, additional configuration is needed to handle
|
|||
|
unspecified extensions:
|
|||
|
|
|||
|
```js
|
|||
|
// webpack.config.js
|
|||
|
module.exports = {
|
|||
|
// ...
|
|||
|
module: {
|
|||
|
rules: [
|
|||
|
{
|
|||
|
test: /\.m?js$/,
|
|||
|
resolve: {
|
|||
|
fullySpecified: false
|
|||
|
}
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
};
|
|||
|
```
|
|||
|
|
|||
|
</details>
|
|||
|
|
|||
|
### Rollup
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary>Show me</summary>
|
|||
|
|
|||
|
Since many packages expose only CommonJS implementation, you need to apply
|
|||
|
plugins to handle CommonJS exports. Those packages could have dependencies
|
|||
|
installed with npm so they need to be properly resolved (taking into account
|
|||
|
browser-specific implementations).
|
|||
|
|
|||
|
Some dependencies can have circular dependencies and Rollup will warn you about
|
|||
|
that. You can ignore these warnings with helper function
|
|||
|
([reference](<(https://github.com/rollup/rollup/issues/1089#issuecomment-635564942)>)).
|
|||
|
|
|||
|
```js
|
|||
|
// rollup.config.js
|
|||
|
const stdLibBrowser = require('node-stdlib-browser');
|
|||
|
const {
|
|||
|
handleCircularDependancyWarning
|
|||
|
} = require('node-stdlib-browser/helpers/rollup/plugin');
|
|||
|
const { default: resolve } = require('@rollup/plugin-node-resolve');
|
|||
|
const commonjs = require('@rollup/plugin-commonjs');
|
|||
|
const json = require('@rollup/plugin-json');
|
|||
|
const alias = require('@rollup/plugin-alias');
|
|||
|
const inject = require('@rollup/plugin-inject');
|
|||
|
|
|||
|
module.exports = {
|
|||
|
// ...
|
|||
|
plugins: [
|
|||
|
alias({
|
|||
|
entries: stdLibBrowser
|
|||
|
}),
|
|||
|
resolve({
|
|||
|
browser: true
|
|||
|
}),
|
|||
|
commonjs(),
|
|||
|
json(),
|
|||
|
inject({
|
|||
|
process: stdLibBrowser.process,
|
|||
|
Buffer: [stdLibBrowser.buffer, 'Buffer']
|
|||
|
})
|
|||
|
],
|
|||
|
onwarn: (warning, rollupWarn) => {
|
|||
|
handleCircularDependancyWarning(warning, rollupWarn);
|
|||
|
}
|
|||
|
};
|
|||
|
```
|
|||
|
|
|||
|
</details>
|
|||
|
|
|||
|
### Vite
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary>Show me</summary>
|
|||
|
|
|||
|
Vite config uses combination of Rollup and esbuild plugins. It’s **important**
|
|||
|
to use dynamic import when using CommonJS configuration so ESM version of
|
|||
|
modules is picked up. This allows Vite bundling to use our mocking
|
|||
|
implementation and implement heuristics such as proper tree-shaking and dead
|
|||
|
code removal marking.
|
|||
|
|
|||
|
```js
|
|||
|
const inject = require('@rollup/plugin-inject');
|
|||
|
|
|||
|
const esbuildShim = require.resolve('node-stdlib-browser/helpers/esbuild/shim');
|
|||
|
|
|||
|
module.exports = async () => {
|
|||
|
const { default: stdLibBrowser } = await import('node-stdlib-browser');
|
|||
|
return {
|
|||
|
resolve: {
|
|||
|
alias: stdLibBrowser
|
|||
|
},
|
|||
|
optimizeDeps: {
|
|||
|
include: ['buffer', 'process']
|
|||
|
},
|
|||
|
plugins: [
|
|||
|
{
|
|||
|
...inject({
|
|||
|
global: [esbuildShim, 'global'],
|
|||
|
process: [esbuildShim, 'process'],
|
|||
|
Buffer: [esbuildShim, 'Buffer']
|
|||
|
}),
|
|||
|
enforce: 'post'
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
};
|
|||
|
```
|
|||
|
|
|||
|
#### Vite plugins
|
|||
|
|
|||
|
If you wish to use simpler configuration, you can use one of the available Vite
|
|||
|
plugins which use this package under the hood:
|
|||
|
|
|||
|
- https://github.com/sodatea/vite-plugin-node-stdlib-browser
|
|||
|
- https://github.com/davidmyersdev/vite-plugin-node-polyfills
|
|||
|
|
|||
|
</details>
|
|||
|
|
|||
|
### esbuild
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary>Show me</summary>
|
|||
|
|
|||
|
Using esbuild requires you to use helper utilities and plugins.
|
|||
|
|
|||
|
```js
|
|||
|
const path = require('path');
|
|||
|
const esbuild = require('esbuild');
|
|||
|
const plugin = require('node-stdlib-browser/helpers/esbuild/plugin');
|
|||
|
const stdLibBrowser = require('node-stdlib-browser');
|
|||
|
|
|||
|
(async () => {
|
|||
|
await esbuild.build({
|
|||
|
// ...
|
|||
|
inject: [require.resolve('node-stdlib-browser/helpers/esbuild/shim')],
|
|||
|
define: {
|
|||
|
global: 'global',
|
|||
|
process: 'process',
|
|||
|
Buffer: 'Buffer'
|
|||
|
},
|
|||
|
plugins: [plugin(stdLibBrowser)]
|
|||
|
});
|
|||
|
})();
|
|||
|
```
|
|||
|
|
|||
|
</details>
|
|||
|
|
|||
|
### Browserify
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary>Show me</summary>
|
|||
|
|
|||
|
Bundling ES modules is currently not supported natively in Browserify, but you
|
|||
|
can try using [esmify](https://github.com/mattdesl/esmify) or
|
|||
|
[babelify](https://github.com/babel/babelify) for transforming to CommonJS
|
|||
|
first.
|
|||
|
|
|||
|
```js
|
|||
|
const fs = require('fs');
|
|||
|
const path = require('path');
|
|||
|
const browserify = require('browserify');
|
|||
|
const aliasify = require('aliasify');
|
|||
|
const stdLibBrowser = require('node-stdlib-browser');
|
|||
|
|
|||
|
const b = browserify(
|
|||
|
[
|
|||
|
/* ... */
|
|||
|
],
|
|||
|
{
|
|||
|
// ...
|
|||
|
transform: [[aliasify, { aliases: stdLibBrowser }]],
|
|||
|
insertGlobalVars: {
|
|||
|
process: () => {
|
|||
|
return `require('${stdLibBrowser.process}')`;
|
|||
|
},
|
|||
|
Buffer: () => {
|
|||
|
return `require('${stdLibBrowser.buffer}').Buffer`;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
);
|
|||
|
```
|
|||
|
|
|||
|
</details>
|
|||
|
|
|||
|
## Package contents
|
|||
|
|
|||
|
| Module | Browser implementation | Mock implementation | Notes |
|
|||
|
| --------------------- | --------------------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|||
|
| `assert` | [assert](https://github.com/browserify/commonjs-assert) | |
|
|||
|
| `buffer` | [buffer](https://github.com/feross/buffer) | [buffer](mock/buffer.js) | `buffer@5` for IE 11 support |
|
|||
|
| `child_process` | | |
|
|||
|
| `cluster` | | |
|
|||
|
| `console` | [console-browserify](https://github.com/browserify/console-browserify) | [console](mock/console.js) |
|
|||
|
| `constants` | [constants-browserify](https://github.com/juliangruber/constants-browserify) | |
|
|||
|
| `crypto` | [crypto-browserify](https://github.com/crypto-browserify/crypto-browserify) | |
|
|||
|
| `dgram` | | |
|
|||
|
| `dns` | | [dns](mock/dns.js) |
|
|||
|
| `domain` | [domain-browser](https://github.com/bevry/domain-browser) | |
|
|||
|
| `events` | [events](https://github.com/browserify/events) | |
|
|||
|
| `fs` | | | [Mocking `fs`](#mocking-fs) |
|
|||
|
| `http` | [stream-http](https://github.com/jhiesey/stream-http) | |
|
|||
|
| `https` | [https-browserify](https://github.com/substack/https-browserify) | |
|
|||
|
| `module` | | |
|
|||
|
| `net` | | [net](mock/net.js) |
|
|||
|
| `os` | [os-browserify](https://github.com/CoderPuppy/os-browserify) | |
|
|||
|
| `path` | [path-browserify](https://github.com/browserify/path-browserify) | |
|
|||
|
| `process` | [process](https://github.com/defunctzombie/node-process) | [process](mock/process.js) | Contains additional exports from newer Node |
|
|||
|
| `punycode` | [punycode](https://github.com/bestiejs/punycode.js) | | `punycode@1` for browser support |
|
|||
|
| `querystring` | [querystring-es3](https://github.com/mike-spainhower/querystring) | | Contains additional exports from newer Node versions |
|
|||
|
| `readline` | | |
|
|||
|
| `repl` | | |
|
|||
|
| `stream` | [stream-browserify](https://github.com/browserify/stream-browserify) | |
|
|||
|
| `string_decoder` | [string_decoder](https://github.com/nodejs/string_decoder) | |
|
|||
|
| `sys` | [util](https://github.com/browserify/node-util) | |
|
|||
|
| `timers` | [timers-browserify](https://github.com/browserify/timers-browserify) | |
|
|||
|
| `timers/promises` | [isomorphic-timers-promises](https://github.com/niksy/isomorphic-timers-promises) | |
|
|||
|
| `tls` | | [tls](mock/tls.js) |
|
|||
|
| `tty` | [tty-browserify](https://github.com/browserify/tty-browserify) | [tty](mock/tty.js) |
|
|||
|
| `url` | [node-url](https://github.com/defunctzombie/node-url) | | Contains additional exports from newer Node versions (`URL` and `URLSearchParams` are not polyfilled) |
|
|||
|
| `util` | [util](https://github.com/browserify/node-util) | |
|
|||
|
| `vm` | [vm-browserify](https://github.com/browserify/vm-browserify) | |
|
|||
|
| `zlib` | [browserify-zlib](https://github.com/browserify/browserify-zlib) | |
|
|||
|
| `_stream_duplex` | [readable-stream](https://github.com/nodejs/readable-stream) | |
|
|||
|
| `_stream_passthrough` | [readable-stream](https://github.com/nodejs/readable-stream) | |
|
|||
|
| `_stream_readable` | [readable-stream](https://github.com/nodejs/readable-stream) | |
|
|||
|
| `_stream_transform` | [readable-stream](https://github.com/nodejs/readable-stream) | |
|
|||
|
| `_stream_writable` | [readable-stream](https://github.com/nodejs/readable-stream) | |
|
|||
|
|
|||
|
## API
|
|||
|
|
|||
|
### packages
|
|||
|
|
|||
|
Returns: `object`
|
|||
|
|
|||
|
Exports absolute paths to each module directory (where `package.json` is
|
|||
|
located), keyed by module names. Modules without browser replacements return
|
|||
|
module with default export `null`.
|
|||
|
|
|||
|
Some modules have mocks in the mock directory. These are replacements with
|
|||
|
minimal functionality.
|
|||
|
|
|||
|
## Tips
|
|||
|
|
|||
|
### Mocking `fs`
|
|||
|
|
|||
|
`fs` package doesn’t return anything since there are many different ways you can
|
|||
|
implement file system functionality in browser.
|
|||
|
|
|||
|
Examples of implementations:
|
|||
|
|
|||
|
- [`BrowserFS`](https://github.com/jvilk/BrowserFS)
|
|||
|
- [`fs-web`](https://github.com/matthewp/fs)
|
|||
|
- [`browserify-fs`](https://github.com/mafintosh/browserify-fs)
|
|||
|
- [`mock-fs`](https://github.com/tschaub/mock-fs)
|
|||
|
- [`memfs`](https://github.com/streamich/memfs)
|
|||
|
|
|||
|
## Node support
|
|||
|
|
|||
|
Minimum supported version should be Node 10.
|
|||
|
|
|||
|
If you’re using ESM in Node < 12.20, note that
|
|||
|
[subpath patterns](https://nodejs.org/api/packages.html#packages_subpath_patterns)
|
|||
|
are not supported so mocks can’t be handled. In that case, it’s recommended to
|
|||
|
use CommonJS implementation.
|
|||
|
|
|||
|
## Browser support
|
|||
|
|
|||
|
Minimum supported version should be Internet Explorer 11, but most modules
|
|||
|
support even Internet Explorer 9.
|
|||
|
|
|||
|
## Types
|
|||
|
|
|||
|
You can use default `@types/node` types.
|
|||
|
|
|||
|
## License
|
|||
|
|
|||
|
MIT © [Ivan Nikolić](http://ivannikolic.com)
|
|||
|
|
|||
|
<!-- prettier-ignore-start -->
|
|||
|
|
|||
|
[ci]: https://github.com/niksy/node-stdlib-browser/actions?query=workflow%3ACI
|
|||
|
[ci-img]: https://github.com/niksy/node-stdlib-browser/workflows/CI/badge.svg?branch=master
|
|||
|
[node-protocol-imports]: https://nodejs.org/api/esm.html#node-imports
|
|||
|
|
|||
|
<!-- prettier-ignore-end -->
|