diff --git a/packages/node-resolve/README.md b/packages/node-resolve/README.md index ea195a06e..5993f3089 100755 --- a/packages/node-resolve/README.md +++ b/packages/node-resolve/README.md @@ -157,6 +157,10 @@ Specifies the root directory from which to resolve modules. Typically used when rootDir: path.join(process.cwd(), '..') ``` +## `ignoreSideEffectsForRoot` + +If you use the `sideEffects` property in the package.json, by default this is respected for files in the root package. Set to `true` to ignore the `sideEffects` configuration for the root package. + ## Preserving symlinks This plugin honours the rollup [`preserveSymlinks`](https://rollupjs.org/guide/en/#preservesymlinks) option. diff --git a/packages/node-resolve/src/index.js b/packages/node-resolve/src/index.js index 481fa8a60..a1861864b 100644 --- a/packages/node-resolve/src/index.js +++ b/packages/node-resolve/src/index.js @@ -34,7 +34,8 @@ const defaults = { // which deploy both ESM .mjs and CommonJS .js files as ESM. extensions: ['.mjs', '.js', '.json', '.node'], resolveOnly: [], - moduleDirectories: ['node_modules'] + moduleDirectories: ['node_modules'], + ignoreSideEffectsForRoot: false }; export const DEFAULTS = deepFreeze(deepMerge({}, defaults)); @@ -42,7 +43,7 @@ export function nodeResolve(opts = {}) { const { warnings } = handleDeprecatedOptions(opts); const options = { ...defaults, ...opts }; - const { extensions, jail, moduleDirectories } = options; + const { extensions, jail, moduleDirectories, ignoreSideEffectsForRoot } = options; const conditionsEsm = [...baseConditionsEsm, ...(options.exportConditions || [])]; const conditionsCjs = [...baseConditionsCjs, ...(options.exportConditions || [])]; const packageInfoCache = new Map(); @@ -51,7 +52,7 @@ export function nodeResolve(opts = {}) { const useBrowserOverrides = mainFields.indexOf('browser') !== -1; const isPreferBuiltinsSet = options.preferBuiltins === true || options.preferBuiltins === false; const preferBuiltins = isPreferBuiltinsSet ? options.preferBuiltins : true; - const rootDir = options.rootDir || process.cwd(); + const rootDir = resolve(options.rootDir || process.cwd()); let { dedupe } = options; let rollupOptions; @@ -200,7 +201,9 @@ export function nodeResolve(opts = {}) { preserveSymlinks, useBrowserOverrides, baseDir, - moduleDirectories + moduleDirectories, + rootDir, + ignoreSideEffectsForRoot }); const resolved = diff --git a/packages/node-resolve/src/resolveImportSpecifiers.js b/packages/node-resolve/src/resolveImportSpecifiers.js index 391e533f7..6c0904bf8 100644 --- a/packages/node-resolve/src/resolveImportSpecifiers.js +++ b/packages/node-resolve/src/resolveImportSpecifiers.js @@ -43,7 +43,9 @@ async function resolveId({ preserveSymlinks, useBrowserOverrides, baseDir, - moduleDirectories + moduleDirectories, + rootDir, + ignoreSideEffectsForRoot }) { let hasModuleSideEffects = () => null; let hasPackageEntry = true; @@ -58,7 +60,9 @@ async function resolveId({ pkgPath, mainFields, preserveSymlinks, - useBrowserOverrides + useBrowserOverrides, + rootDir, + ignoreSideEffectsForRoot }); ({ packageInfo, hasModuleSideEffects, hasPackageEntry, packageBrowserField } = info); @@ -180,7 +184,9 @@ export default async function resolveImportSpecifiers({ preserveSymlinks, useBrowserOverrides, baseDir, - moduleDirectories + moduleDirectories, + rootDir, + ignoreSideEffectsForRoot }) { let lastResolveError; @@ -197,7 +203,9 @@ export default async function resolveImportSpecifiers({ preserveSymlinks, useBrowserOverrides, baseDir, - moduleDirectories + moduleDirectories, + rootDir, + ignoreSideEffectsForRoot }); if (result instanceof ResolveError) { diff --git a/packages/node-resolve/src/util.js b/packages/node-resolve/src/util.js index b261b40f5..7b21d250a 100644 --- a/packages/node-resolve/src/util.js +++ b/packages/node-resolve/src/util.js @@ -40,7 +40,16 @@ export function getMainFields(options) { } export function getPackageInfo(options) { - const { cache, extensions, pkg, mainFields, preserveSymlinks, useBrowserOverrides } = options; + const { + cache, + extensions, + pkg, + mainFields, + preserveSymlinks, + useBrowserOverrides, + rootDir, + ignoreSideEffectsForRoot + } = options; let { pkgPath } = options; if (cache.has(pkgPath)) { @@ -130,13 +139,15 @@ export function getPackageInfo(options) { packageInfo.browserMappedMain = false; } - const packageSideEffects = pkg.sideEffects; - if (typeof packageSideEffects === 'boolean') { - internalPackageInfo.hasModuleSideEffects = () => packageSideEffects; - } else if (Array.isArray(packageSideEffects)) { - internalPackageInfo.hasModuleSideEffects = createFilter(packageSideEffects, null, { - resolve: pkgRoot - }); + if (!ignoreSideEffectsForRoot || rootDir !== pkgRoot) { + const packageSideEffects = pkg.sideEffects; + if (typeof packageSideEffects === 'boolean') { + internalPackageInfo.hasModuleSideEffects = () => packageSideEffects; + } else if (Array.isArray(packageSideEffects)) { + internalPackageInfo.hasModuleSideEffects = createFilter(packageSideEffects, null, { + resolve: pkgRoot + }); + } } cache.set(pkgPath, internalPackageInfo); diff --git a/packages/node-resolve/test/fixtures/root-package-side-effect/index.js b/packages/node-resolve/test/fixtures/root-package-side-effect/index.js new file mode 100644 index 000000000..3425e6f0f --- /dev/null +++ b/packages/node-resolve/test/fixtures/root-package-side-effect/index.js @@ -0,0 +1 @@ +import './side-effect.js'; diff --git a/packages/node-resolve/test/fixtures/root-package-side-effect/package.json b/packages/node-resolve/test/fixtures/root-package-side-effect/package.json new file mode 100644 index 000000000..dca881437 --- /dev/null +++ b/packages/node-resolve/test/fixtures/root-package-side-effect/package.json @@ -0,0 +1,4 @@ +{ + "main": "./index.js", + "sideEffects": false +} diff --git a/packages/node-resolve/test/fixtures/root-package-side-effect/side-effect.js b/packages/node-resolve/test/fixtures/root-package-side-effect/side-effect.js new file mode 100644 index 000000000..75bb07d82 --- /dev/null +++ b/packages/node-resolve/test/fixtures/root-package-side-effect/side-effect.js @@ -0,0 +1 @@ +console.log('side effect'); diff --git a/packages/node-resolve/test/snapshots/test.js.md b/packages/node-resolve/test/snapshots/test.js.md index 5a676b49b..eb686f717 100644 --- a/packages/node-resolve/test/snapshots/test.js.md +++ b/packages/node-resolve/test/snapshots/test.js.md @@ -47,6 +47,23 @@ Generated by [AVA](https://avajs.dev). }, ] +## ignores the package.json sideEffects property for files in root package with "ignoreSideEffectsForRoot" option + +> Snapshot 1 + + `'use strict';␊ + ␊ + console.log('side effect');␊ + ` + +## respects the package.json sideEffects property for files in root package by default + +> Snapshot 1 + + `'use strict';␊ + ␊ + ` + ## throws error for removed customResolveOptions.basedir option > Snapshot 1 diff --git a/packages/node-resolve/test/snapshots/test.js.snap b/packages/node-resolve/test/snapshots/test.js.snap index 385df660d..5998414a5 100644 Binary files a/packages/node-resolve/test/snapshots/test.js.snap and b/packages/node-resolve/test/snapshots/test.js.snap differ diff --git a/packages/node-resolve/test/test.js b/packages/node-resolve/test/test.js index 3124b764f..7a279a467 100755 --- a/packages/node-resolve/test/test.js +++ b/packages/node-resolve/test/test.js @@ -246,6 +246,37 @@ test('resolves dynamic imports', async (t) => { t.is(result.default, 42); }); +test('respects the package.json sideEffects property for files in root package by default', async (t) => { + const bundle = await rollup({ + input: 'root-package-side-effect/index.js', + plugins: [ + nodeResolve({ + rootDir: 'root-package-side-effect' + }) + ] + }); + + const code = await getCode(bundle); + t.false(code.includes('side effect')); + t.snapshot(code); +}); + +test('ignores the package.json sideEffects property for files in root package with "ignoreSideEffectsForRoot" option', async (t) => { + const bundle = await rollup({ + input: 'root-package-side-effect/index.js', + plugins: [ + nodeResolve({ + rootDir: 'root-package-side-effect', + ignoreSideEffectsForRoot: true + }) + ] + }); + + const code = await getCode(bundle); + t.true(code.includes('side effect')); + t.snapshot(code); +}); + test('handles package side-effects', async (t) => { const bundle = await rollup({ input: 'side-effects.js',