Is there an existing issue for this?
This issue exists in the latest npm version
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.
- if
files in package.json specifies "lib", lib content is included in the published pack
- if
.npmignore says to ignore "lib/**/*.test.*, they still are included. (unexpected)
- 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
- Create project with lib folder containing foo.js and foo.test.js
- Edit package.json to have a
files list containing lib
- Edit
.npmignore to have lib/**/*.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
Is there an existing issue for this?
This issue exists in the latest npm version
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.
filesinpackage.jsonspecifies"lib",libcontent is included in the published pack.npmignoresays to ignore"lib/**/*.test.*, they still are included. (unexpected).npmignoreis added to thefileslist, it's still including the test filesThe only way we've found to easily exclude test code from the lib folder is to include the
.npmignorefile 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
.npmignoreat root to pick off the matches resulting from the thefilesallow list. It does not. There's a wiki reference here which states:But that only seems to be true with nested non-root
.npmignorefiles. 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:
.npmignore. (backwards compatible)filescan continue being an allow-list array (backwards compatible)filescan also be an object with explicitincludeandexcludearrays(and include would have precedence over exclude.)
This makes things far more obvious, you don't have to muck with
.npmignorebeing yet another config file that needs to live in a specific place, everything is contained in onepackage.jsondefinition, 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
.npmignoreusage 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
fileslist containinglib.npmignoreto havelib/**/*.test.*exclusionnpm pack --dry-runExpected: no test file in list
Resulted: test file in list
Environment