-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
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
distdirectory) - copy package.json, license and readme to the
distdirectory - do some package.json cleanups in the
distdirectory (delete devDepedencies, move dependencies to peerDependencies, remove scripts...) - npm publish from the
distdirectory.
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_modulesnot 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
distas part of the pathimport { something } from 'my-package/dist/something. but once you publish fromdistfolder directly, you should somehow fix the pass by removing thedistduring 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:
- The dist folder must exists with a package.json inplace before the
lerna bootstrapprocess symlink the folders. - 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:
- we can use a preinstall script to create the folder and a simple package.json file (with at least 'id','name').
- the build scripts should clear the folder content instead of
rm -rfthe 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 |