[BUG] "files" and root ".npmignore" don't work as expected.
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 10.1k
- Forks
- 4.7k
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 19
Description
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 https://github.com/npm/npm/pull/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.
- if
filesinpackage.jsonspecifies"lib",libcontent is included in the published pack - if
.npmignoresays to ignore"lib/**/*.test.*, they still are included. (unexpected) - even if
.npmignoreis added to thefileslist, 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) filescan continue being an allow-list array (backwards compatible)filescan also be an object with explicitincludeandexcludearrays
"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
- Create project with lib folder containing foo.js and foo.test.js
- Edit package.json to have a
fileslist containinglib - Edit
.npmignoreto havelib/**/*.test.*exclusion - 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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the behavior with a package.json files allow-list, a root .npmignore, and npm pack --dry-run as described. Start by tracing npm CLI package-file inclusion and ignore handling; done means matching test files are absent from the dry-run package listing without requiring a nested .npmignore.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100