`npm publish` ignoring new additions to .npmignore

1.3k views Asked by At

While building create-near-app, artifacts get created within the project tree. Some of these were added to a .npmignore file, but others were missed until I attempted to publish a new version and noticed that the npm package would be several hundred megabytes large (!!) due to Rust build artifacts. I added these to .npmignore, but npm publish is failing to notice.

I am able to work around this by removing the files, but such a workaround is error prone for an open source library which may be maintained and published by a growing & morphing team of contributors.

Does npm cache the .npmignore file somewhere? How do I make npm use the new settings?


Details & quick reference:

os: macOS 10.15.6
node version manager: asdf v0.7.6
node: v12.14.1
npm: v6.13.7

package.json:

-- snip --
"files": [
  "/common",
  "/templates"
],
-- snip --

.npmignore:

common/contracts/rust/target
common/contracts/out
templates/*/.cache
templates/*/assembly
-- snip --

output of npm pack --dryrun:

-- snip --
npm notice 293.2kB common/contracts/rust/target/debug/build/ryu-140fa0ad757694f9/build_script_build-140fa0ad757694f9                                                                           
npm notice 20.6kB  common/contracts/rust/target/debug/build/ryu-140fa0ad757694f9/build_script_build-140fa0ad757694f9.dSYM/Contents/Resources/DWARF/build_script_build-140fa0ad757694f9         
npm notice 297.4kB common/contracts/rust/target/debug/build/serde-3bef95b74f70906a/build_script_build-3bef95b74f70906a                                                                         
-- snip --

If you want to try it yourself:

  1. clone the repository
  2. cd common/contracts/rust
  3. cargo build (you will need to install Rust)
  4. cd ../../..
  5. npm pack --dryrun

Does it work for you? Is this an "only broken on my machine" thing?

1

There are 1 answers

1
RobC On

"Is this an "only broken on my machine" thing?"

No, this is (almost) expected behaviour given your projects current configuration(s) - and no npm doesn't cache the .npmignore file somewhere.

The reason I said "almost" previously is because in your last comment you said:

"So in this case, all paths in templates/* are ignored, but the paths in common/contracts are included in the package."

That should not be the case because according to npm's expected behaviour as stated in the docs, (see "Why is this happening?" section below), none of the patterns currently specified in your .npmignore file should be effective given your current package.json's files configuration.

What you're encountering is odd behaviour, i.e. some patterns are being respected whilst others are not, however hopefully by following either of the two proposed solutions/approaches (below) you'll get the correct desired result.


Why is this happening?

The docs for package.json's files field states the following which is pertinent to your issue:

Note: Bold emphasis added by me.

You can also provide a .npmignore file in the root of your package or in subdirectories, which will keep files from being included. At the root of your package it will not override the “files” field, but in subdirectories it will.

So, the reason why the patterns currently specified in your .npmignore file are NOT being ignored is because they are trying to override the inclusion patterns currently specified in your package.json's files field. Essentially, because your .npmignore file currently resides at the root of your package it will not override the “files" field.


Solutions

Here are a two different solutions/methods to consider (they're in no particular order):

  1. Omit the files entry from package.json and augment your current .npmignore file as necessary

    i.e. Delete this from package.json:

    "files": [
     "/common",
     "/templates"
    ],

    Then create additional patterns in your current .npmignore file for any other directories/files that should also be excluded from packing/publishing. In other words add any patterns to .npmignore for assets that do not reside somewhere in /common or /templates that should also be excluded.

    For example, after briefly looking at your repo, you'll need to add the pattern tests to .npmignore too.

    In summary, this first approach is a case of delete the files field and specify all patterns for assets to be ignored in one place - in the .npmignore file at the root of your project.

  2. Or, keep the files entry in package.json as-is and create additional .npmignore files in subdirectories

    Given the patterns currently specified in your .npmignore file are:

    common/contracts/rust/target
    common/contracts/out
    templates/*/.cache
    templates/*/assembly
    templates/*/contract
    templates/*/package.json
    templates/*/src/assets
    templates/*/src/config.js
    templates/*/src/global.css
    templates/*/src/utils.js
    

    and also given that the docs stated; "at the root of your package [.npmignore] will not override the “files” field, but in subdirectories it will" then you'll need to:

    1. Create a .npmignore file in the common/contracts/ directory containing the following patterns:

      rust/target
      out
      
    2. Create a .npmignore file in the templates/ directory containing the following patterns:

      */.cache
      */assembly
      */contract
      */package.json
      */src/assets
      */src/config.js
      */src/global.css
      */src/utils.js
      

    The .npmignore file currently residing at the root of your project directory (as-is) becomes redundant with this second method.


Note: Hopefully by following either of the two aforementioned solutions/methods, (which do closely adhere to npm's documented expectations), you'll get the desired result. However, if neither of those proposed solutions yield the desired result, then I suggest keeping one of the proposed solutions as a baseline starting point, then reading some of the answers in this SO thread. Yes, the question is the opposite of your issue, however you might gain further insight towards next steps particularly from this answer - it mentions "npm pack and publish respect any package.json files you have in the directory tree, not just at the root.".