Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/Septh/rollup-plugin-node-externals

A Rollup/Vite plugin that automatically declares NodeJS built-in modules and npm dependencies as 'external'
https://github.com/Septh/rollup-plugin-node-externals

external module node plugin rollup

Last synced: about 1 month ago
JSON representation

A Rollup/Vite plugin that automatically declares NodeJS built-in modules and npm dependencies as 'external'

Awesome Lists containing this project

README

        

# rollup-plugin-node-externals
A Rollup/Vite plugin that automatically declares NodeJS built-in modules as `external`. Also handles npm dependencies, devDependencies, peerDependencies and optionalDependencies.

Works in npm/yarn/pnpm/lerna monorepos too!

## Why you need this
(click to read)

By default, Rollup doesn't know a thing about NodeJS, so trying to bundle simple things like `import path from 'node:path'` in your code generates an `Unresolved dependencies` warning.

The solution here is quite simple: you must tell Rollup that the `node:path` module is in fact _external_. This way, Rollup won't try to bundle it in and rather leave the `import` statement as is (or translate it to a `require()` call if bundling for CommonJS).

However, this must be done for each and every NodeJS built-in you happen to use in your program: `node:path`, `node:os`, `node:fs`, `node:url`, etc., which can quickly become cumbersome when done manually.

So the primary goal of this plugin is simply to automatically declare all NodeJS built-in modules as external.

As an added bonus, this plugin will also allow you to declare your dependencies (as per your local or monorepo `package.json` file(s)) as external.

## Installation
Use your favorite package manager. Mine is [npm](https://www.npmjs.com).

```sh
npm install --save-dev rollup-plugin-node-externals
```

## Usage

### Import
The plugin is available both as the default export and as a named export:

```js
import nodeExternals from 'rollup-plugin-node-externals'
```

and

```js
import { nodeExternals } from 'rollup-plugin-node-externals'
```

will both work.

### Options
You generally want to have your **runtime dependencies** (those that will be imported/required at runtime) listed under `dependencies` in `package.json`, and your **development dependencies** (those that should be bundled in by Rollup) listed under `devDependencies`.

If you follow this simple rule, then the default settings are just what you need:

```js
// rollup.config.js

export default {
...
plugins: [
nodeExternals(),
]
}
```

This will bundle your `devDependencies` in while leaving your `dependencies`, `peerDependencies` and `optionalDependencies` external.

Should the defaults not suit your case, here is the full list of options.

```typescript
import nodeExternals from 'rollup-plugin-node-externals'

export default {
...
plugins: [
nodeExternals({

// Make node builtins external. Default: true.
builtins?: boolean

// node: prefix handing for importing Node builtins. Default: 'add'.
builtinsPrefix?: 'add' | 'strip' | 'ignore'

// The path(s) to your package.json. See below for default.
packagePath?: string | string[]

// Make pkg.dependencies external. Default: true.
deps?: boolean

// Make pkg.devDependencies external. Default: false.
devDeps?: boolean

// Make pkg.peerDependencies external. Default: true.
peerDeps?: boolean

// Make pkg.optionalDependencies external. Default: true.
optDeps?: boolean

// Modules to force include in externals. Default: [].
include?: string | RegExp | (string | RegExp)[]

// Modules to force exclude from externals. Default: [].
exclude?: string | RegExp | (string | RegExp)[]
})
]
}
```

#### builtins?: boolean = true
Set the `builtins` option to `false` if you'd like to use some shims/polyfills for those. You'll most certainly need [an other plugin](https://github.com/ionic-team/rollup-plugin-node-polyfills) as well.

#### builtinsPrefix?: 'add' | 'strip' | 'ignore' = 'add'
How to handle the `node:` scheme used in recent versions of Node (i.e., `import path from 'node:path'`).
- If `add` (the default, recommended), the `node:` scheme is always added. In effect, this dedupes your imports of Node builtins by homogenizing their names to their schemed version.
- If `strip`, the scheme is always removed. In effect, this dedupes your imports of Node builtins by homogenizing their names to their unschemed version. Schemed-only builtins like `node:test` are not stripped.
- `ignore` will simply leave all builtins imports as written in your code.
> _Note that scheme handling is always applied, regardless of the `builtins` options being enabled or not._

#### packagePath?: string | string[] = []
If you're working with monorepos, the `packagePath` option is made for you. It can take a path, or an array of paths, to your package.json file(s). If not specified, the default is to start with the current directory's package.json then go up scan for all `package.json` files in parent directories recursively until either the root git directory is reached, the root of the monorepo is reached, or no other `package.json` can be found.

#### deps?: boolean = true
devDeps?: boolean = false
peerDeps?: boolean = true
optDeps?: boolean = true
Set the `deps`, `devDeps`, `peerDeps` and `optDeps` options to `false` to prevent the corresponding dependencies from being externalized, therefore letting Rollup bundle them with your code.

#### include?: string | RegExp | (string | RegExp)[] = []
Use the `include` option to force certain dependencies into the list of externals, regardless of other settings:

```js
nodeExternals({
deps: false, // Deps will be bundled in
include: 'fsevents' // Except for fsevents
})
```

#### exclude?: string | RegExp | (string | RegExp)[] = []
Conversely, use the `exclude` option to remove certain dependencies from the list of externals, regardless of other settings:

```js
nodeExternals({
deps: true, // Keep deps external
exclude: 'electron-reload' // Yet we want `electron-reload` bundled in
})
```

## Notes

### 1/ This plugin is smart
- Falsy values in `include` and `exclude` are silently ignored. This allows for conditional constructs like `exclude: process.env.NODE_ENV === 'production' && 'my-prod-only-dep'`.
- Subpath imports are supported with regexes, meaning that `include: /^lodash/` will externalize `lodash` and also `lodash/map`, `lodash/merge`, etc.

### 2/ This plugin is not _that_ smart
It uses an exact match against your imports _as written in your code_. No resolving of path aliases or substitutions is made:

```js
// In your code, say '@/lib' is an alias for source/deep/path/to/some/lib:
import something from '@/lib'
```

If you don't want `lib` bundled in, then write:

```js
// In rollup.config.js:
nodeExternals({
include: '@/lib'
})
```

### 3/ Order matters
If you're also using [`@rollup/plugin-node-resolve`](https://github.com/rollup/plugins/tree/master/packages/node-resolve/#readme), make sure this plugin comes _before_ it in the `plugins` array:

```js
import nodeExternals from 'rollup-plugin-node-externals'
import nodeResolve from '@rollup/plugin-node-resolve'

export default {
...
plugins: [
nodeExternals(),
nodeResolve(),
]
}
```

Note that as of version 7, this plugin's `resolveId` hook has a `order: 'pre'` property that will make Rollup call it very early in the module resolution process. Nevertheless, it is best to always make this plugin the first one in the `plugins` array.

### 4/ Rollup rules
Rollup's own `external` configuration option always takes precedence over this plugin. This is intentional.

### 5/ Using with Vite
While this plugin has always been compatible with Vite, it was previously necessary to use the following `vite.config.js` to make it work reliably in every situation:

```js
import { defineConfig } from 'vite'
import nodeExternals from 'rollup-plugin-node-externals'

export default defineConfig({
...
plugins: [
{ enforce: 'pre', ...nodeExternals() },
// other plugins follow
]
})
```

Since version 7.1, this is no longer necessary and you can use the normal syntax instead. You still want to keep this plugin early in the `plugins` array, though.

```js
import { defineConfig } from 'vite'
import nodeExternals from 'rollup-plugin-node-externals'

export default defineConfig({
...
plugins: [
nodeExternals()
// other plugins follow
]
})
```

## Breaking changes

### Breaking changes in version 7
- This package now only supports the [Maintenance, LTS and Current versions](https://github.com/nodejs/Release#release-schedule) of Node.js.
- The previously undocumented `externals` named export has been removed.

### Breaking changes in previous versions
Previous versions -- click to expand

#### Breaking changes in version 6
- This package is now esm-only and requires NodeJS v16+.
*If you need CommonJS or older NodeJS support, please stick to v5.*
- This plugin now has a **peer-dependency** on Rollup `^3.0.0 || ^4.0.0`.
*If you need Rollup 2 support, please stick to v5.*

#### Breaking changes in version 5
- In previous versions, the `devDeps` option defaulted to `true`.
This was practical, but often wrong: devDependencies are meant just for that: being used when developping. Therefore, the `devDeps` option now defaults to `false`, meaning Rollup will include them in your bundle.
- As anticipated since v4, the `builtinsPrefix` option now defaults to `'add'`.
- The deprecated `prefixedBuiltins` option has been removed. Use `builtinsPrefix` instead.
- `rollup-plugin-node-externals` no longer depends on the Find-Up package (while this is not a breaking change per se, it can be in some edge situations).
- The plugin now has a _peer dependency_ on `rollup ^2.60.0 || ^3.0.0`.

#### Breaking changes in version 4
- In previous versions, the `deps` option defaulted to `false`.
This was practical, but often wrong: when bundling for distribution, you want your own dependencies to be installed by the package manager alongside your package, so they should not be bundled in the code. Therefore, the `deps` option now defaults to `true`.
- Now requires Node 14 (up from Node 12 for previous versions).
- Now has a _peer dependency_ on `rollup ^2.60.0`.

## Licence
MIT