Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

rollup-plugin-node-externals

Package Overview
Dependencies
Maintainers
1
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rollup-plugin-node-externals - npm Package Compare versions

Comparing version 7.0.1 to 7.1.0

53

dist/index.d.ts

@@ -5,65 +5,12 @@ import type { Plugin } from 'rollup';

export interface ExternalsOptions {
/**
* Mark node built-in modules like `path`, `fs`... as external.
*
* Defaults to `true`.
*/
builtins?: boolean;
/**
* node: prefix handing for importing Node builtins:
* - `'add'` turns `'path'` to `'node:path'`
* - `'strip'` turns `'node:path'` to `'path'`
* - `'ignore'` leaves Node builtin names as-is
*
* Defaults to `add`.
*/
builtinsPrefix?: 'add' | 'strip' | 'ignore';
/**
* Path/to/your/package.json file (or array of paths).
*
* Defaults to all package.json files found in parent directories recursively.
* Won't go outside of a git repository.
*/
packagePath?: string | string[];
/**
* Mark dependencies as external.
*
* Defaults to `true`.
*/
deps?: boolean;
/**
* Mark devDependencies as external.
*
* Defaults to `false`.
*/
devDeps?: boolean;
/**
* Mark peerDependencies as external.
*
* Defaults to `true`.
*/
peerDeps?: boolean;
/**
* Mark optionalDependencies as external.
*
* Defaults to `true`.
*/
optDeps?: boolean;
/**
* Force include these deps in the list of externals, regardless of other settings.
*
* Defaults to `[]` (force include nothing).
*/
include?: MaybeArray<MaybeFalsy<string | RegExp>>;
/**
* Force exclude these deps from the list of externals, regardless of other settings.
*
* Defaults to `[]` (force exclude nothing).
*/
exclude?: MaybeArray<MaybeFalsy<string | RegExp>>;
}
/**
* A Rollup plugin that automatically declares NodeJS built-in modules,
* and optionally npm dependencies, as 'external'.
*/
declare function nodeExternals(options?: ExternalsOptions): Plugin;

@@ -70,0 +17,0 @@ export default nodeExternals;

116

dist/index.js
import path from 'node:path';
import fs from 'node:fs/promises';
import { createRequire, isBuiltin } from 'node:module';
// Get our own version
const { version } = createRequire(import.meta.url)('../package.json');
// Prepare node built-in modules lists.
const nodePrefix = 'node:';
const nodePrefixRx = /^node:/;
// Files that mark the root of a workspace.
const { name, version } = createRequire(import.meta.url)('../package.json');
const workspaceRootFiles = new Set([
'pnpm-workspace.yaml', // pnpm
'lerna.json', // Lerna
// Note: is there any interest in the following?
// 'workspace.jsonc', // Bit
// 'nx.json', // Nx
// 'rush.json', // Rush
'pnpm-workspace.yaml',
'lerna.json',
]);

@@ -30,15 +21,10 @@ const defaults = {

const isString = (str) => typeof str === 'string' && str.length > 0;
/**
* A Rollup plugin that automatically declares NodeJS built-in modules,
* and optionally npm dependencies, as 'external'.
*/
function nodeExternals(options = {}) {
const config = { ...defaults, ...options };
let include, exclude;
const isIncluded = (id) => include.some(rx => rx.test(id)), isExcluded = (id) => exclude.some(rx => rx.test(id));
const isIncluded = (id) => include.length > 0 && include.some(rx => rx.test(id)), isExcluded = (id) => exclude.length > 0 && exclude.some(rx => rx.test(id));
return {
name: 'node-externals',
name: name.replace(/^rollup-plugin-/, ''),
version,
async buildStart() {
// Map the include and exclude options to arrays of regexes.
[include, exclude] = ['include', 'exclude'].map(option => []

@@ -55,5 +41,2 @@ .concat(config[option])

}, []));
// Populate the packagePath option if not given by getting all package.json files
// from cwd up to the root of the git repo, the root of the monorepo,
// or the root of the volume, whichever comes first.
const packagePaths = []

@@ -65,11 +48,12 @@ .concat(config.packagePath)

for (let current = process.cwd(), previous = undefined; previous !== current; previous = current, current = path.dirname(current)) {
const entries = await fs.readdir(current, { withFileTypes: true }).catch(() => null);
if (entries === null)
this.error(`Could not read contents of directory ${JSON.stringify(current)}.`);
// Gather package.json files.
const entries = await fs.readdir(current, { withFileTypes: true }).catch(({ code }) => code);
if (isString(entries) || !entries) {
return this.error({
message: `Could not read directory ${JSON.stringify(current)}, error: ${entries || 'UNKNOWN'}.`,
stack: undefined
});
}
if (entries.some(entry => entry.name === 'package.json' && entry.isFile()))
packagePaths.push(path.join(current, 'package.json'));
// Break early if this is a git repo root or there is a known workspace root file.
if (entries.some(entry => (entry.name === '.git' && entry.isDirectory())
|| (workspaceRootFiles.has(entry.name) && entry.isFile()))) {
if (entries.some(entry => (entry.name === '.git' && entry.isDirectory()) || (workspaceRootFiles.has(entry.name) && entry.isFile()))) {
break;

@@ -79,25 +63,21 @@ }

}
// Gather dependencies names.
const dependencies = {};
for (const packagePath of packagePaths) {
this.addWatchFile(packagePath);
const buffer = await fs.readFile(packagePath).catch(({ code }) => code);
if (isString(buffer) || !buffer) {
return this.error({
message: `Cannot read file ${JSON.stringify(packagePath)}, error: ${buffer || 'UNKNOWN'}.`,
stack: undefined
});
}
try {
const json = (await fs.readFile(packagePath)).toString();
try {
const pkg = JSON.parse(json);
Object.assign(dependencies, config.deps ? pkg.dependencies : undefined, config.devDeps ? pkg.devDependencies : undefined, config.peerDeps ? pkg.peerDependencies : undefined, config.optDeps ? pkg.optionalDependencies : undefined);
// Break early if this is a npm/yarn workspace root.
if ('workspaces' in pkg)
break;
}
catch {
this.error({
message: `File ${JSON.stringify(packagePath)} does not look like a valid package.json file.`,
stack: undefined
});
}
const pkg = JSON.parse(buffer.toString());
Object.assign(dependencies, config.deps ? pkg.dependencies : undefined, config.devDeps ? pkg.devDependencies : undefined, config.peerDeps ? pkg.peerDependencies : undefined, config.optDeps ? pkg.optionalDependencies : undefined);
this.addWatchFile(packagePath);
if (Array.isArray(pkg.workspaces) && pkg.workspaces.length > 0)
break;
}
catch {
this.error({
message: `Cannot read file ${JSON.stringify(packagePath)}`,
message: `File ${JSON.stringify(packagePath)} does not look like a valid package.json file.`,
stack: undefined

@@ -107,3 +87,2 @@ });

}
// Add all dependencies as an include RegEx.
const names = Object.keys(dependencies);

@@ -113,23 +92,26 @@ if (names.length > 0)

},
async resolveId(specifier) {
// Ignore absolute (already resolved) ids, relative imports and virtual modules.
if (/^(?:\0|\.{0,2}\/)/.test(specifier) || path.isAbsolute(specifier))
return null;
// Handle node builtins.
if (isBuiltin(specifier)) {
const stripped = specifier.replace(nodePrefixRx, '');
return {
id: config.builtinsPrefix === 'ignore'
? specifier
: config.builtinsPrefix === 'add' || (specifier.startsWith(nodePrefix) && !isBuiltin(stripped))
? nodePrefix + stripped
: stripped,
external: (config.builtins || isIncluded(specifier)) && !isExcluded(specifier),
moduleSideEffects: false
};
resolveId: {
order: 'pre',
async handler(specifier, importer, { isEntry }) {
if (isEntry
|| /^(?:\0|\.{1,2}\/)/.test(specifier)
|| path.isAbsolute(specifier)) {
return null;
}
if (isBuiltin(specifier)) {
const stripped = specifier.replace(/^node:/, '');
return {
id: config.builtinsPrefix === 'ignore'
? specifier
: config.builtinsPrefix === 'add' || !isBuiltin(stripped)
? 'node:' + stripped
: stripped,
external: (config.builtins || isIncluded(specifier)) && !isExcluded(specifier),
moduleSideEffects: false
};
}
return isIncluded(specifier) && !isExcluded(specifier)
? false
: null;
}
// Handle npm dependencies.
return isIncluded(specifier) && !isExcluded(specifier)
? false // external
: null; // normal handling
}

@@ -136,0 +118,0 @@ };

{
"name": "rollup-plugin-node-externals",
"version": "7.0.1",
"version": "7.1.0",
"description": "Automatically declare NodeJS built-in modules and npm dependencies as 'external' in Rollup config",

@@ -12,3 +12,6 @@ "author": "Stephan Schreiber <septh@sfr.fr>",

"rollup",
"vite",
"plugin",
"rollup-plugin",
"vite-plugin",
"external",

@@ -75,6 +78,3 @@ "externals",

]
},
"np": {
"yarn": false
}
}
# rollup-plugin-node-externals
A Rollup plugin that automatically declares NodeJS built-in modules as `external`. Also handles npm dependencies, devDependencies, peerDependencies and optionalDependencies.
A Rollup/Vite plugin that automatically declares NodeJS built-in modules as `external`. Also handles npm dependencies, devDependencies, peerDependencies and optionalDependencies.

@@ -8,3 +8,3 @@ Works in npm/yarn/pnpm/lerna monorepos too!

## Why you need this
<details><summary>(click to expand)</summary>
<details><summary>(click to read)</summary>

@@ -113,6 +113,6 @@ 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.

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:` prefix is always added. In effect, this homogenizes all your imports of Node builtins to their prefixed version.
- If `strip`, the prefix is always removed. In effect, this homogenizes all your imports of Node builtins to their unprefixed version.
- 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 prefix handling is always applied, regardless of the `builtins` options being enabled or not._
> _Note that scheme handling is always applied, regardless of the `builtins` options being enabled or not._

@@ -153,10 +153,10 @@ #### packagePath?: string | string[] = []

### 2/ This plugin is not _that_ smart
It uses an exact match against your imports _as written in your code_, so if your are using some kind of path substitution, eg.:
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 '@/' is mapped to some directory:
import something from '@/mylib'
// In your code, say '@/lib' is an alias for node_modules/deep/path/to/some/lib:
import something from '@/lib'
```
and you don't want `mylib` bundled in, then write:
If you don't want `lib` bundled in, then write:

@@ -186,3 +186,3 @@ ```js

As a general rule of thumb, you might want to always make this plugin the first one in the `plugins` array.
As a general rule of thumb, you will want to always make this plugin the first one in the `plugins` array.

@@ -192,8 +192,39 @@ ### 4/ Rollup rules

### 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 situations:
```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 supports the latest release of [any major version that is supported by Node.js itself](https://github.com/nodejs/Release#release-schedule).
- The undocumented `externals` named export has been removed.
- 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.

@@ -200,0 +231,0 @@ ### Breaking changes in previous versions

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc