Skip to content

[BUG] "files" and root ".npmignore" don't work as expected. #6221

Description

@dzearing

Is there an existing issue for this?

  • I have searched the existing issues

This issue exists in the latest npm version

  • I am using the latest npm

Current Behavior

This seems related to npm/npm#11669 which was closed a while ago with no action. Could we re-evaluate .npmignore behavior? It is confusing, and either the wiki is wrong or there is a bug.

  1. if files in package.json specifies "lib", lib content is included in the published pack
  2. if .npmignore says to ignore "lib/**/*.test.*, they still are included. (unexpected)
  3. even if .npmignore is added to the files list, it's still including the test files

The only way we've found to easily exclude test code from the lib folder is to include the .npmignore file in a subfolder (lib), rather then at root. Apparently that has precedence over the files list and works as expected. If we want it located at the root with all the other config files, we have to have a hacky copy step run pre-publishing.

Expected Behavior

At minimum, I expected .npmignore at root to pick off the matches resulting from the the files allow list. It does not. There's a wiki reference here which states:

You can use ignore files, optionally in combination with a files array, in order to get more fine-tuned control over what gets included or excluded.

But that only seems to be true with nested non-root .npmignore files. So that's a bug, or the wiki is wrong.

But taking a step back, one way to improve the design to be more obvious while being backwards compatible:

  • deprecate .npmignore. (backwards compatible)
  • files can continue being an allow-list array (backwards compatible)
  • files can also be an object with explicit include and exclude arrays
"files": {
    "include":  [ "lib" ],
    "exclude": [ "*.test.*"]
}

(and include would have precedence over exclude.)

This makes things far more obvious, you don't have to muck with .npmignore being yet another config file that needs to live in a specific place, everything is contained in one package.json definition, tooling can recommend this usage, package lint tooling could even auto fix it.

The default behavior here is also desirable - having an allow list really should be the default recommended thing devs use to define what gets published. What we see in practice with .npmignore usage only is that over time tools are added without adding ignore exclusions, and things like config, logfiles, cache folders and unused build artifacts show up in the package undetected. So consumers end up downloading these things which at best ends up taking more disk space and network traffic, and at worst confuses their tooling (e.g. Typescript ends up parsing accidentally distributed source, which references dev dependencies that don't exist.)

Steps To Reproduce

  1. Create project with lib folder containing foo.js and foo.test.js
  2. Edit package.json to have a files list containing lib
  3. Edit .npmignore to have lib/**/*.test.* exclusion
  4. Run npm pack --dry-run

Expected: no test file in list
Resulted: test file in list

Environment

  • npm: 9.x
  • Node.js: 18
  • OS Name: Windows 11

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Bugthing that needs fixingNeeds Triageneeds review for next stepsRelease 9.xwork is associated with a specific npm 9 release

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions