The npm publish
command creates a tarball (with src dir) and publish it to registry.
is there a way to exclude the src dir avoiding use of .npmignore ?
npm provides no other built-in feature to achieve that, so a custom solution is required.
If you really don't want to use .npmignore to keep the src directory out of your published package, then consider utilizing pre and post hooks in your npm scripts instead.
The pertinent hooks are:
prepublishOnly: Run BEFORE the package is prepared and packed, ONLY on npm publish ...
postpublish: Run AFTER the package is published.
For *nix platforms
Add a prepublishOnly script to the scripts section of your package.json that moves the src directory to another location outside of your project directory prior to publishing.
Also, add a postpublish script that moves the src directory back to the project directory when publishing has completed.
Run npm publish (as per normal) to publish your package.
For instance:
package.json
...
"scripts": {
"prepublishOnly": "mv src/ ../",
"postpublish": "mv ../src .",
...
},
...
Note: You'll need to ensure that no other src folder/directory exists at the path location you choose to temporarily move the src directory to via your prepublish script.
Cross platform:
For a cross-platform solution consider utilizing shx. This package includes a portable mv command. In which case, configure your prepublish and postpublish scripts something like the following instead:
package.json
...
"scripts": {
"prepublishOnly": "shx mv src/ ../",
"postpublish": "shx mv ../src .",
...
},
...
You can use the files property in your package.json to explicitly include the files you want to publish.
{
"files": [
"dist",
"index.js"
]
}
As #RobC answer, there is no other way then a custom solution for avoid using .npmignore.
Since I’m using the publish command in a Jenkins pipeline, a solution is to create a temporary .npmignore while the publish step directly in the Jenkinsfile:
echo "src/" >> .npmignore
echo "*.js" >> .npmignore
echo "*.json" >> .npmignore
echo "Jenkinsfile" >> .npmignore
curl --insecure -u ${USERPASS} 'https://my-repo/api/npm/auth' >> /home/jenkins/.npmrc
npm publish --registry https:// my-repo/api/npm/npm-local/
Related
We have a self-hosted GitLab (15.5.4) and I've configured everything we needed for publishing npm packages.
A CI/CD pipeline that properly creates the entry in the Package Registry.
The problem is that when I pull the package [npm i #scope/lib] (It doesn't change if I cast the auth token in the package.json or I pass through an environment variable as suggested in the documentation) the unwanted result is that the #scope/lib doesn't have the dist/ folder in it!! [node_module/#scope/lib/].
If I browse to the Package Registry and manually download the .tgz file I can see that the dist/ folder is present.
I've played around a bit with the .npmignore and "prepublish" script but I had no success and literally have no glue why this is happening.
Any tips would be very appreciated
To clarify:
The proper way is to tell npm to keep the dist/ folder, bypassing the .gitignore file (instead of defining an .npmignore article here ) is to define a files entry in the package.json :
{
"files": [
"dist",
"build",
...
]
}
Another unproper way to do get the result I needed is to use a postinstall command. But it is clearly an anti-pattern. Given that I am writing a typescript library, that is tested and then compiled by the CI, there's no need to recompile it within the postinstall command. But it could be an hacky solution when needed.
{
"scripts": {
"postinstall": "tsc src/index.ts"
}
}
To sum up, I think it was only an npm cache issue or more probably a server-side cache issue, because I've run npm cache clean --force different times.
Hope this helps.
EDIT: Not sure what happened in the initial test, but .gitignore and .npmignore are now working to exclude the bin files as desired.
I have a simple NPM package which just installs a binary by downloading it from GitHub. My goal is to leave the binary out of the published package and just let the script install it. My thinking is that the install script may need to install different binaries depending on the host platform, and secondarily, there's no need to bloat the package size with the binaries.
The problem is that I can't seem to get NPM to ignore the 'bin' files. I've tried using .gitignore, .npmignore and the package.json 'files' attribute as well as placing the bin files in a folder other than bin, and it seems that NPM insists on including the 'bin' files. The relevant package.json is basically:
{
"bin": {
"my-bin": "./bin/my-bin"
},
"files": [ "bin-install.sh" ],
"scripts": {
"preinstall": "./bin-install.sh"
},
}
As a workaround, I can juggle the 'bin' directory existence like:
"scripts": {
"preinstall": "./bin-install.sh",
"prepublishOnly": "! [[ -d bin ]] || mv bin tmp",
"prepack": "npm run prepublishOnly",
"postpublish": "! [[ -d tmp ]] || mv tmp bin",
"postpack": "npm run postpublish"
}
This works, but looks ugly and makes me think I'm missing something that's leading me to go against the grain.
Is there a cleaner approach to achieve what I'm trying to do?
.npmignore should work, here are the docs. You haven't shown how exactly you've attempted to set up ignore, but it sounds like you has been trying to ignore all files inside bin/ so this is what you needed:
# inside .npmignore
bin/
We have within a package.json build script a copy command (no we cant quickly change that).
Is there any solution we can make this work multiplatform with the same syntax easily?
I looked in several npm copy packages, but they don't transpile from windows to unix paths.
We basically need something like:
"build": "doStuff && cp -r ../folder/ /dist/"
working for windows.
Any ideas?
For a cross-platform solution consider utilizing the shx package.
Firstly cd to your project directory and run the following command to install it:
npm i -D shx
Then redefine your build script in the scripts section of your package.json as follows:
"scripts": {
"build": "doStuff && shx cp -r ../folder/ ./dist/"
}
I've got continuous deployment setup with Netlify and a git repo but so far no matter what I do, Netlify isn't npm-installing anything. There's no node_modules folder when I download a zip of the deploy, my site can't access node_modules, it's just not there. I've started with a random npm package (lodash) to try to get it to install but I've got nothing so far.
Netlify says that it automatically runs npm install. I've tried having no build commands and I've tried adding npm install as a build command with no results from either.
package.json:
{
"name": "netlify-test",
"version": "1.0.0",
"description": "stuff",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/electrovir/netlify-test.git"
},
"author": "electrovir",
"license": "MIT",
"bugs": {
"url": "https://github.com/electrovir/netlify-test/issues"
},
"homepage": "https://github.com/electrovir/netlify-test#readme",
"dependencies": {
"lodash": "^4.17.11"
}
}
HTML:
<!doctype html>
<html>
<head>
<title>
hi
</title>
<script src="node_modules/lodash/_apply.js"></script>
</head>
<body>
Why can't this find node_modules??
</body>
</html>
It took a while to figure this out but I discovered that Netlify does npm install into your repo root or Base directory when you have a package.json. This can be seen by changing the Build command to something like ls and reading the deploy console output (there will be a node_modules folder listed).
However, at some point after running the Build command and before deploying, this node_modules is deleted. Hence, if you use something similar to the following as a Build command, node_modules can be copied to your Publish directory:
rm -rf dist && mkdir dist && rsync -rv * dist --exclude ./dist
This copies the Base directory contents into dist, which I have set as my Publish directory, ignoring ./dist itself (it can't be copied into itself). It'd be even better if this were added as an npm script in package.json with npm run <script name> for your Build command.
Note that Base directory, Build command, and Publish directory are all under Deploys > Deploy settings or Settings > Build & deploy in Netlify.
Thanks to lastmjs for help with figuring this out.
It would be odd if node_modules WERE there. Netlify's continuous deployment does run npm install for you, if and only if there is a package.json in the root of your repository (or instead in the base directory if you set one in netlify.toml. However, it also uses a custom npm directory that is outside of the deployment directory (see how it is setup here: https://github.com/netlify/build-image/blob/master/run-build-functions.sh#L34), since deploying your node_modules shouldn't be needed for a static site at browse time - only at build time.
The intended path for a Netlify deploy is:
you have your dependency manager configuration checked into your git repo at the root of the repo (if no base directory is set in the UI or in the toml file) or in the base directory if set. This could be any/all of Gemfile.lock, package.json, yarn.lock, or requirements.txt as explained in this article about the build settings at Netlify
you do not store your node_modules in the repo. Many of those will be specific to the architecture of the build environment - and your local machine is almost certainly different than Netlify's. You'll want those generated at build time.
your build is intended to USE those modules DURING BUILD. So you use for instance dotenv to read your .env file while building, or you use gulp-cli to process your Gulpfile.js
your build completes, and you've used all the modules during build to generate standalone html/js/css/images, so you're done with them - your static html and other assets are generated in your publish directory, where the build process has intentionally not put your node modules, and thus they are not deployed. Your static website should not need the modules at runtime, so deploying the (thousands!) of files in there is not efficient or needed.
You could have a situation that requires some/one of them - e.g. a function or you could need a file from one of them even on your static site - and that's fine, feel free to copy it into the publish directory explicitly. But that is not the norm :)
How to streamline npm release when I want to include only specific path(s)?
I have ./src and ./dist files in my repository. I want to effectively publish only the contents of ./dist + ./package.json.
Using .npmignore to ignore ./src will simply ignore the ./src folder. I want to include only the contents of ./dist, i.e. now user would need to do require('my-package/dist/something'). I want to make it require('my-package/something'). ./something is contained in ./dist.
The way I have done it at the moment is, I have created a bash script:
npm run build
cp package.json ./dist
# or, if you need to have package.json "main" entry different,
# e.g. for being able to use `npm link`, you need to replace "main" value:
# sed 's#"main": "./dist/index.js"#"main": "./index.js"#' package.json > ./dist/package.json
cd ./dist
npm publish
For cross-platform compatibilty use shx:
npm run build
shx cp package.json ./dist
shx cd ./dist
npm publish