Skip to content

[Feature] Allow custom publish subdirectory #901

@esakal

Description

@esakal

Many libraries in the Angular ecosystem publish to NPM from a subdirectory that was cooked during the build process. The process is usually as followed:

  • build the library in a subdirectory (i.e dist directory)
  • copy package.json, license and readme to the dist directory
  • do some package.json cleanups in the dist directory (delete devDepedencies, move dependencies to peerDependencies, remove scripts...)
  • npm publish from the dist directory.

I understand that it is not a common technique for node.js package developers but i think it is common for web package developers and my libraries uses the same technique..

While embedding lerna into our shared packages monorepo - kaltura-ng I read a lot of issues in lerna and googled about this topic. I read carefully the conversation of issue #91 and even used the same subject with my issue. Unless I missed new issues that address this feature it was marked as 'wontfix' with a recommendation to use the 'package.json:files' array instead.

The reasons for using this approach instead of package.json:files array are:

  • Many known libraries in the Angular ecosystem does it (angular/angular, ReactiveX/rxjs, cyclejs/cyclejs) so they must have a reason.
  • There is a lot of hoo-ha/complexity with the way node.js resolve modules for the web projects since during the bundling process you must refer to the same instance of the library. Unless the bundler (typescript, webpack etc...) provide a hack/workaround/solution to force the library to use its' own node_modules, it will not work. Publishing from sub-directory works just because the dist/node_modules not exists.
  • During development if the symlink is done against the root, when you import nested class which was not exported in the main index, you will need to refer to the dist as part of the path import { something } from 'my-package/dist/something. but once you publish from dist folder directly, you should somehow fix the pass by removing the dist during the tranpiling which is not a valid option.
  • The libraries being used as dependencies during development should be assigned as peerDependencies at runtime because you want the application to provide them.

so to recap, we cannot just publish the package with a dist folder, we need to publish from dist directly

There are some caveats that I could think about with my suggested approach:

  1. The dist folder must exists with a package.json inplace before the lerna bootstrap process symlink the folders.
  2. The build process should not delete the 'dist' folder, instead it should just clear its content otherwise the symlink of dependent libraries will be broken.

IMO those two caveats are manageable as:

  1. we can use a preinstall script to create the folder and a simple package.json file (with at least 'id','name').
  2. the build scripts should clear the folder content instead of rm -rf the folder itself.

Expected Behavior

when bootstrapping/publishing a package the package.json is being queried for the following config:

"config" : {
	"npmDistDirectory" : "dist"
},

if this config exists, it will symlink to that folder during bootstrap command and will publish from that folder during publish command

using the 'config' attribute allow using the same configuration both in lerna and in other node scripts.

I already modified the 'bootstrap' command in a fork esakal/lerna. I didn't create a PR yet because I'm missing the 'publish' command. I will be happy to continue my work if you are going to consider this feature.

You can see it in action in our repo - kaltura-ng :

$ git clone https://github.com/kaltura/kaltura-ng.git
$ yarn
$ npm run setup
$ cd kaltura-ui/node_modules/@kaltura-ng
$ ll # you should see a symlink to kaltura-common/dist and kaltura-client/dist

NOTE - your yarn version should be 0.24.6 and above

Current Behavior

n/a

Your Environment

Executable Version
lerna --version 2.0.0-rc.5
yarn --version v0.24.6
OS Version
macOS El Capitan 10.11.6

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions