229

I would like to publish a npm package that contains my source as well as distribution files. My GitHub repository contains src folder which contains JavaScript source files. The build process generates dist folder that contains the distribution files. Of course, the dist folder is not checked into the GitHub repository.

How do I publish a npm package in a way that when someone does npm install, they get src as well as dist folder? Currently when I run npm publish from my Git repository, it results in only the src folder being published.

My package.json file looks like this:

{
  "name": "join-js",
  "version": "0.0.1",
  "homepage": "https://github.com/archfirst/joinjs",
  "repository": {
    "type": "git",
    "url": "https://github.com/archfirst/joinjs.git"
  },
  "main": "dist/index.js",
  "scripts": {
    "test": "gulp",
    "build": "gulp build",
    "prepublish": "npm run build"
  },
  "dependencies": {
    ...
  },
  "devDependencies": {
    ...
  }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Naresh
  • 23,937
  • 33
  • 132
  • 204

4 Answers4

276

When you npm publish, if you don't have an .npmignore file, npm will use your .gitignore file (in your case you excluded the dist folder).

To solve your problem, create a .npmignore file based on your .gitignore file, without ignoring the dist folder.

Source: Keeping files out of your Package

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
topheman
  • 7,422
  • 4
  • 24
  • 33
  • 1
    This answer saved my day, since I was already using `"files": [ "dist" ]` in my `package.json` but for some reason it was still not being published to NPM. Keeping `dist` in `.gitignore` while having a `.npmignore` without `dist` did the job. – Erick Petrucelli Mar 23 '23 at 16:47
179

Take a look at the "files" field of package.json file: package.json, files

From the documentation:

The "files" field is an array of files to include in your project. If you name a folder in the array, then it will also include the files inside that folder. (Unless they would be ignored by another rule.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Eugene Nezhuta
  • 2,017
  • 1
  • 10
  • 7
  • 5
    I'm curious to know if the "files" field overrides `.gitignore` or `.npmignore` (it seems like it doesn't as I read the doc) - @Naresh please tell us which way worked fine. – topheman Jul 26 '15 at 22:41
  • 17
    "files" indeed is ignoring .gitignore. I have "dist" in my .gitignore, but included in "files" and the folder is being published to npm. "files" seems to be how several popular packages like expess and bluebird are publishing (while there are other packages that use the .npmignore method). For now, I am going with "files" because it seems to be a more direct way of saying what to publish. But thanks to both of you for increasing my knowledge about npm at least by twice today! – Naresh Jul 27 '15 at 02:07
  • 7
    It's worth noting that if "files" is specified then *only* those files are the only ones that are included in your project (other than the can't-be-excluded files like package.json, etc.) – bmacnaughton Sep 05 '17 at 15:13
1

just don't mention src and dist inside the .npmignore file to get the scr and dist inside the node_modules ... that's it

Another point is if there is a .gitignore file, and .npmignore is missing, .gitignore's contents will be used instead.

Md Joynul Abedin
  • 164
  • 1
  • 11
0

Minimal example of how to use data files from a script

Another common use case is to have data files that your scripts need to use.

This can be done easily by using the techniques mentioned at: How can I get the path of a module I have loaded via require that is *not* mine (i.e. in some node_module)

The full example can be found at:

With this setup, the file mydata.txt gets put into node_modules/cirosantilli-data-files/mydata.txt after installation, because we added it to our files: entry of package.json.

Our function myfunc can then find that file and use its contents by using require.resolve. It also just works on the executable ./cirosantilli-data-files of course.

package.json

{
  "bin": {
    "cirosantilli-data-files": "cirosantilli-data-files"
  },
  "license": "MIT",
  "files":  [
    "cirosantilli-data-files",
    "mydata.txt",
    "index.js"
  ],
  "name": "cirosantilli-data-files",
  "repository": "cirosantilli/linux-kernel-module-cheat",
  "version": "0.1.0"
}

mydata.txt

hello world

index.js

const fs = require('fs');
const path = require('path');

function myfunc() {
  const package_path = path.dirname(require.resolve(
    path.join('cirosantilli-data-files', 'package.json')));
  return fs.readFileSync(path.join(package_path, 'mydata.txt'), 'utf-8');
}
exports.myfunc = myfunc;

cirosantilli-data-files

#!/usr/bin/env node
const cirosantilli_data_files = require('cirosantilli-data-files');
console.log(cirosantilli_data_files.myfunc());

The is-installed-globally package is then useful if you want to generate relative paths to the distributed files depending if they are installed locally or globally: How to tell if an npm package was installed globally or locally

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • The questioner wants to make a folder to be published even though it is ignored, so he only needs to specify `files: ["dist"]`. I doubt that he needs all this overcomplicated staff. – FrameMuse Jan 07 '23 at 16:58
  • 1
    This is really great! Any chance you can share ideas on how to adopt this to typescript/ES modules (e.g. import instead of `require`)? – zaitsman Sep 01 '23 at 23:08
  • @zaitsman sorry, don't know it immediately and lazy to try it out now, if you find a good example (ideally minimally modifying mine, or not) let's edit it in or link to it – Ciro Santilli OurBigBook.com Sep 02 '23 at 09:29