I have a project that include a gulp task for building and packaging the sources and release in a directory called dist
. My goal is publish it as a npm package,
option 1: Navigate to the folder and execute "npm publish ." command
option 2: Run npm publish /path/directory
If you are (and I recommend) using semantic-release, add the pkgRoot
option in the .releaserc.json
file:
{
"pkgRoot": "dist",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/npm",
[
"@semantic-release/exec",
{
"prepareCmd": "npx rjp package.json version nextRelease.version"
}
],
[
"@semantic-release/git",
{
"assets": ["package.json"]
}
],
],
}
That'll take care of the problem. Just make sure your dist
folder contains a package.json
file. You can easily do that by adding a cp
to your postbuild
script. Also install rjp
I highly recommend you to use .npmignore
instead of moving or copying things around, specially if you are using a CI for deployments, and just add there the files you don't want to publish.
https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package
Example:
#tests
test
coverage
#build tools
.travis.yml
.jenkins.yml
.codeclimate.yml
#linters
.jscsrc
.jshintrc
.eslintrc*
#editor settings
.idea
.editorconfig
If you want to split your code, into different npm packages using the same repo, I bumped into this project recently: Lerna and looks really good.
Maybe you should take a look
This works fine for me.
cd TMPDIR; npm pack
/path/to/package.json
Tarball will create inside the TMPDIR directory.
I have a similar problem to the original poster (@robsonrosa). In my case I use typecript which compiles to a dist
directory. While I could make typescript compile to the root directory I think the best solution is to generate a separate package.json
file in the dist directory.
This is similar to @scvnc suggestion of copying the package.json
but with a twist:
As part of the packaging process you should generate a package.json
for the package which is based on but distinct from the main package.json
file in the root directory
The rationale:
package.json
file is the development file. It may contain scripts or development dependencies that are of no use to the package user, but may pose security concerns for you. Your packaging procedure may include code that strips that information from the production package.json
.--- EDIT ---
I was asked for a solution in the comments. So here is some code I am using. This should be considered as an example it is not meant to be generic and is specific to my projects.
My setup:
package.json - main package.json with dev dependencies and useful scripts.
.npmignore - files to ignore; copied to 'dist' directory as part of the setup.
/src - directory where my typescript code resides.
/src/SetupPackage.ts - bit of code used to setup the package.
/dist - destination directory for the compiled javascript files.
I want to package only the dist
directory and the directory should be the root directory in the package.
The file SetupPackage.ts
in my src
directory will be compiled to SetupPackage.js
in the dist
directory by typescript:
import fs from "fs";
// DO NOT DELETE THIS FILE
// This file is used by build system to build a clean npm package with the compiled js files in the root of the package.
// It will not be included in the npm package.
function main() {
const source = fs.readFileSync(__dirname + "/../package.json").toString('utf-8');
const sourceObj = JSON.parse(source);
sourceObj.scripts = {};
sourceObj.devDependencies = {};
if (sourceObj.main.startsWith("dist/")) {
sourceObj.main = sourceObj.main.slice(5);
}
fs.writeFileSync(__dirname + "/package.json", Buffer.from(JSON.stringify(sourceObj, null, 2), "utf-8") );
fs.writeFileSync(__dirname + "/version.txt", Buffer.from(sourceObj.version, "utf-8") );
fs.copyFileSync(__dirname + "/../.npmignore", __dirname + "/.npmignore");
}
main();
This file:
package.json
but removes the scripts and dev dependencies which are not needed in the package. It also fixes the main entry point to the package.package.json
to a file called version.txt
..npmignore
package from the root.The .npmignore content is:
*.map
*.spec.*
SetupPackage.*
version.txt
I.e. unit tests (spec files) and typescript map files are ignored as well as the SetupPackage.js
file and the version.txt
file it creates. This leaves a clean package.
Finally the main package.json
file has the following scripts for use by the build system (assumes sh
is used as the shell).
"scripts": {
"compile": "tsc",
"clean": "rm -rf dist",
"prebuildpackage": "npm run clean && npm run compile && node dist/SetupPackage.js",
"buildpackage": "cd dist && npm pack"
},
To build the package the build system clones the repo, does npm install
and then runs npm run buildpackage
which in turn:
dist
directory ensuring a clean compile.SetupPackage.js
file which prepares dist
for packaging.dist
directory and builds the package there.I use the version.txt
file as an easy way to get the version in package.json and to tag my repo. There are countless other ways to do this or you may want to auto-increment the version. Remove this from SetupPackage.ts
and .npmignore
if it is not useful to you.
dist
folderThe natural way to achieve that, according to the npm approach, is to publish the folder which is to be the root. There are several ways to do that, depends on the final environment you want to work with:
npm publish dist
.npm install relative/path/to/dist
node_modules
in another project in case you'd like to have the changes in your original package reflected instantly in other project. In your case you first cd dist
and run npm link
and then go to the other project and run npm link robsonrosa-ui-alert
.Prerequisite: in any case above, prior to the publish/install/link, you have to put in your dist
folder at least a proper package.json
file. In your case, you have to have the package name defined in your package.json file as "name": "robsonrosa-ui-alert"
. Typically, you'll want there also some other files like README.md or LICENSE.
Automation example
You can automate the publishing process using the prepare script, combined with build
script. Additionally, you can protect your package against an accidental publishing of the package root folder with "private": true field put in the package.json, located in the root directory of your package repo. Here is an example:
"private": true,
"scripts": {
"build": "rm -rf dist && gulp build && cat ./package.json | grep -v '\"private\":' > dist/package.json",
"prepare": "npm run build"
},
This way you won't publish the root folder and get the package built and package.json copied to the dist
folder automatically, within the publishing process.