Closed dangviettuan closed 3 months ago
@nartc is this being considered for angular packages as well?
+1
Hi all, Nx 15 will come with an experimental feature that allows
@nrwl/js
to achieve this. Keep an eye out for the release blog post and give it a try. This is a tricky feature to get right so we're definitely looking for a lot of feedback.
Any update if this is available yet?
Think this should be an essential feature, adding a comment to keep the dream alive!
Hoping we can turn on that experimental feature to try it out soon, this is definitely important for us
Big agree, this feels largely essential. Let's keep this train moving ๐
did you find any solution for the this ?
Greetings colleagues.
I had the same task, but only for deploying cloud functions. I made a plugin for Nx. It embeds dependencies like local files.
The plugin uses itself to inject its local dependencies for publishing to npm.
While it is in alpha version and I will be glad someone will write about the bugs found.
If you have any questions, I can answer.
https://github.com/arthurgubaidullin/embed-dependencies#readme
Ran into this as well. I expected internal libs to get bundled just as they do with apps. I'll keep the train going!
I'm also running into this issue.
It turns out publishing the shared libs is not necessarily enough:
apps/
โโ angular-app
libs/
โโ lib1 - depends on shared lib, @angular/material
โโ lib2 - depends on shared lib, @angular/material
โโ shared_lib - no dependencies
โโ composed_lib - packages lib1, lib2, and shared together into a single module
If I run the default builder for composed_lib, lib1 and lib2 will be listed as peer dependencies. This is not what I want, as I am now forcing the consumer to install 4 libraries instead of just 1.
If I add "buildableProjectDepsInPackageJsonType": "dependencies"
to composed_lib, then lib1 and lib2 get listed as dependencies, which is great, but shared lib doesn't get listed as either a dependency or peer dependency, likely because it's listed as a peer dependency of lib1 and lib2.
Now, if I add "buildableProjectDepsInPackageJsonType": "dependencies"
to lib1 and lib2, shared_lib will get listed as a dependency, but @angular/material will be as well. I obviously don't want to ship an extra version of material to my consumer.
Is there any way to reconcile this?
It turns out publishing the shared libs is not necessarily enough:
apps/ โโ angular-app libs/ โโ lib1 - depends on shared lib, @angular/material โโ lib2 - depends on shared lib, @angular/material โโ shared_lib - no dependencies โโ composed_lib - packages lib1, lib2, and shared together into a single module
If I run the default builder for composed_lib, lib1 and lib2 will be listed as peer dependencies. This is not what I want, as I am now forcing the consumer to install 4 libraries instead of just 1.
If I add
"buildableProjectDepsInPackageJsonType": "dependencies"
to composed_lib, then lib1 and lib2 get listed as dependencies, which is great, but shared lib doesn't get listed as either a dependency or peer dependency, likely because it's listed as a peer dependency of lib1 and lib2.Now, if I add
"buildableProjectDepsInPackageJsonType": "dependencies"
to lib1 and lib2, shared_lib will get listed as a dependency, but @angular/material will be as well. I obviously don't want to ship an extra version of material to my consumer.Is there any way to reconcile this?
What if you use "peerDependency" for material?
It turns out publishing the shared libs is not necessarily enough:
apps/ โโ angular-app libs/ โโ lib1 - depends on shared lib, @angular/material โโ lib2 - depends on shared lib, @angular/material โโ shared_lib - no dependencies โโ composed_lib - packages lib1, lib2, and shared together into a single module
If I run the default builder for composed_lib, lib1 and lib2 will be listed as peer dependencies. This is not what I want, as I am now forcing the consumer to install 4 libraries instead of just 1. If I add
"buildableProjectDepsInPackageJsonType": "dependencies"
to composed_lib, then lib1 and lib2 get listed as dependencies, which is great, but shared lib doesn't get listed as either a dependency or peer dependency, likely because it's listed as a peer dependency of lib1 and lib2. Now, if I add"buildableProjectDepsInPackageJsonType": "dependencies"
to lib1 and lib2, shared_lib will get listed as a dependency, but @angular/material will be as well. I obviously don't want to ship an extra version of material to my consumer. Is there any way to reconcile this?What if you use "peerDependency" for material?
It is actually listed as a peerDependency. buildableProjectDepsInPackageJsonType
seems to pull in external peer dependencies as well. I could sed
and alter the build output, I suppose, but that doesn't feel so great.
@nartc is it safe to assume the experimental feature referred to in https://github.com/nrwl/nx/issues/4620#issuecomment-1274027580 is https://nx.dev/packages/js/executors/swc#external ?
The "Examples" section mentions:
@nrwl/js:swc
can also inline buildable libraries by setting external: 'none'
Is there any news on this? This feature would be a big help for us!
I agree, it would be a great help!
Bump! ๐
I've also hit this issue - my scenario is ~2 new applications (building in monorepo) and an old app. I would like to build a new feature in new apps and bundle it into an importable feature to the old one. It uses some of the other libraries which do not need to be built except with the new Mono repo and the 1 buildable library.
Will make all the libraries buildable for now, but would prefer a cleaner (ideally out of box) solution.
@benmoses-equineregister, for such a use case, I'd propose, instead of bundling it as a package considering the Webpack module federation approach. https://webpack.js.org/concepts/module-federation/
Hey, I'm using "nx": "15.7.2" how can I use it ?
Same question, how is this possible in the current 15 version?? @nartc
Using the "external": "none"
option will inline all buildable libraries into the final project. Seems to be an experimental feature as of now. More on it here
An issue I'm still having is the fact the NX still includes all internal buildable libs as peerDependencies in the final package.json file. No sure this is the intended result since NX shouldn't include those buildable libs already inlined in the project.
The worst things I see about this implementation is that we would have inline each buildable library as well which causes a bit of duplication as lib-a and lib-b depend on lib-c so now we'll have lib-c in both lib-a and lib-c. Perhaps I'm doing something wrong, but I feel that handling this kind of issue to avoid such duplications is a must?
I've spent quite some time to solve this issue, and looks like for now the best option is to simply use tsc
builder directly, and what I also noticed is if you add one more level in project structure - all of required packages will be placed inside target path.
After a week try many solutions I found a way to publish a library with all dependencies.
- All dependencies must be buildable projects. We can convert non-buildable projects by update
workspace.json
"build": { "builder": "@nrwl/web:package", "outputs": ["{options.outputPath}"], "options": { "outputPath": "dist/libs/<YOUR LIB IMPORT PATH>", "tsConfig": "libs/<YOUR PACKAGE DIRECTORY>/tsconfig.lib.json", "project": "libs/<YOUR PACKAGE DIRECTORY>/package.json", "entryFile": "libs/<YOUR PACKAGE DIRECTORY>/src/index.ts", "external": [<IF YOU HAVE ANY EXTERAL LIBS WANT TO IGNORE FROM BUNDLE (react, react-dom)>], "babelConfig": "@nrwl/react/plugins/bundle-babel", (Optional: If you lib is React Lib) "rollupConfig": "@nrwl/react/plugins/bundle-rollup", (Optional: If you lib is React Lib) "assets": [ { "glob": "README.md", "input": ".", "output": "." } ] } },```
- Update
paths
intsconfig.base.json
file same with . Example: YOUR LIB IMPORT PATH = @myorg/my-awesome-lib"paths": { "@myorg/my-awesome-lib": ["libs/ui/awsome-button/src/index.ts"], ..... },
- Build your library with
--with-deps
flag.Rebuild you library with custom rollup config
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); const builtins = require('rollup-plugin-node-builtins'); const resolve = require('@rollup/plugin-node-resolve'); const fileExtensions = ['.js', '.jsx', '.ts', '.tsx']; function getRollupOptions(options) { const extraGlobals = { // <YOUR EXTRAGLOBALS NAMES> // Example: 'react-dom': 'ReactDOM', 'styled-components': 'styled', '@emotion/core': 'emotionCore', }; if (Array.isArray(options.output)) { options.output.forEach((o) => { o.globals = Object.assign(Object.assign({}, o.globals), extraGlobals); }); } else { options.output.globals = Object.assign( Object.assign({}, options.output.globals), extraGlobals ); } options.plugins.push( resolve.nodeResolve({ preferBuiltins: true, extensions: fileExtensions, moduleDirectories: ['dist/libs', 'node_modules'], // IMPORTANT }) ); options.plugins.push(builtins()); options.external = [ // YOUR EXTERNAL LIBS (Libs you don't want to bundle) // Example: 'react', 'react-is' ]; return options; } module.exports = getRollupOptions;
- NX will automatically add dependencies and buildable libraries to
dependencies
orpeerDependencies
. You can select by add flagbuildableProjectDepsInPackageJsonType=
dependencies
orpeerDependencies
to buid command.- Go to the library and manually remove your buildable libraries from package.json because after publishing to NPM you can not download them.
- Publish your Package to NPM PS: You should test your package before publishing to NPM to make sure it works properly. I faced 3 problems.
- CSS not extract. To fix it just add the flag
--no-extractCss
to the build command. I don't know why my buildable library exported to 2 CSS files but when bundle my publishable library CSS files not included. So embed CSS inside JS is my choice.- NX missing some dependencies in package.json. After build my publish library I found that some dependencies is missing and I have to manually add them to package.json before publish to NPM.
- Typescript module augmentation: In my project, I use
module augmentation
to override a third-party interface. After the bundle, an error occurred because ofundefined
property. To fix it I remove third-party library from theexternal
list to bundle it with my library.
@dangviettuan Thank you, can you please share a repo with the workaround solution? I tried to implement your solution but it didn't worked.
Don't know if this will solve all of the requirements exposed in this page, but I have created a custom executor to address my specific use case (described here). Hopefully it could help you too!
Here's the link to the npm package: https://www.npmjs.com/package/@altack/nx-bundlefy And the source code: https://github.com/altack/nx-bundlefy
If anyone is using pnpm and is experiencing dependencies not being written correctly to package.json please replace them with yarn or npm !!!
Most of the dependency lookup requires the createProjectGraphAsync
provided by nx, which doesn't seem to work correctly in pnpm at the moment.
Don't know if this will solve all of the requirements exposed in this page, but I have created a custom executor to address my specific use case (described here). Hopefully it could help you too!
Here's the link to the npm package: https://www.npmjs.com/package/@altack/nx-bundlefy And the source code: https://github.com/altack/nx-bundlefy
Thanks for your package.
I have been reading your code and have a couple of questions:
Do I need to explicitly write the bundledDependencies
entry in the package.json
?
All my buildable packages are automatically scoped by NX. Is this a problem?
- Do I need to explicitly write the
bundledDependencies
entry in thepackage.json
?- All my buildable packages are automatically scoped by NX. Is this a problem?
Hi @bommox,
bundledDependencies
entry is created for you automatically. This is how we ensure that required dependencies are bundled within your lib.--importPath
https://nx.dev/more-concepts/buildable-and-publishable-librariesHope it helps!
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! ๐
Keep active please
Bumped into this as well and specifying "external": "none"
in the builder of the project that I want to publish has solved the issue for me. The shared libraries that are used in the published project get correctly bundled without having to publish the libs or specify the libs in the package.json
file of the published project.
External does appear to work but if you want to bundle only some of your workspace libs while maintaining others as independently published, it requires you to list all those "external" libs manually. I would have expected there to be a setting like "external: 'buildable'"
that just automatically externalizes libs that are buildable
This should be automated based on your lib's package.json
:
cc @jaysoo
How does that interact with the externals setting then? Do you just not set it in that case? Or do you have to list the same packages ?
The "external" setting does seem to successfully produce a working output with certain packages inlined, but it has a bunch of bugs when interacting with other parts of Nx. I filed a few yesterday:
https://github.com/nrwl/nx/issues/20019 https://github.com/nrwl/nx/issues/20016 https://github.com/nrwl/nx/issues/20015 https://github.com/nrwl/nx/issues/20014 https://github.com/nrwl/nx/issues/20033
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! ๐
not stale
would be very nice to have this for latest NX version!
In @nx/js:tsc
executor that is used in build
step for ts projects, adding "external": "none"
to options as per https://nx.dev/nx-api/js/executors/tsc seems to almost solve the issue, but not entirely. It still includes aliased imports even when all my libs are "external": "none"
Assigning @jaysoo since he was working on this functionality
any update?
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs. If we missed this issue please reply to keep it active. Thanks for being a part of the Nx community! ๐
please unstale
This has been addressed with our new Nx release command: https://nx.dev/features/manage-releases
Please check that out and let us know what you think!
@FrozenPandaz can you provide an example of how the release command addresses the concern here? It doesn't seem to have anything to do with bundling libraries inside of other libraries
The last time I was told to use the nx release
command, it was doing something entirely different. It's either bugged out or has completely separate scope since, at the least, January 8th: https://discord.com/channels/1143497901675401286/1193795596235063356/1193795596235063356
Ah, sorry. I've reopened the issue. :+1:
Thanks to everyone who has commented. As someone who just spent ~13 hours going slowly mad thinking he had forgotten or was crazy or didn't survive his last plane trip because this scenario just wasn't working...
This sure would be nice to have! It's not obvious/spelled out at all that you can't have a normal nx library that is imported by other published libraries. And attempting to do so causes the 'rootDir' is expected to contain all source files.
errors which don't make a lot of sense.
I can confirm that external: "none"
works although if you want to limit the scope of what is inlined in your package to just the specific shared library you are using in your project.json
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"external": ["@my-project/lib/shared"],
where "@my-project/lib/shared"
is whatever shared library or libraries you need. That will inline them into the package and cause the error to go away. Unfortuantely this feature is marked deprecated and scheduled for removal in nx 20 which means this solution, while it works, means you can never upgrade your project. Not great!
Anway +1 and thanks to all the folks who have commented here and helped.
First most, I am not that experienced with monorepo
& nx
. I am getting similar error and best to my knowledge I tried all possible options shared on this thread as well as whatever answer I got on google, but none of them worked for me. May I am doing it completely wrong or my expectation itself is wrong!
What I am expecting is, during the build
first-package
package will be published as separate package, so it will be referenced in the second-package
- this works fineutility
package code should become part of the second-package
so it can be published as a single package with name second-package
I am yet to figure out on how to change symbolic link of
first-package
insecond-package
package.json
file with exact version during publishing.
Here is my repo and attached screenshot of the error I am getting.
Also, seem like external: "none"
only bundle packages inside nx workspace, it does not bundle outside package like dayjs, moment, ...
I would like to create a package that not dependent to any other packages instead.
There is very basic example where this is required for us and I'm surprised that no one mentioned it.
We have about 10 logically distinct libraries which we use to create very thin lambdas. Whole NX affected
approach is very beneficial as only some lambdas are packaged and deployed when changes in libraries occur - no problem at this level.
However, we also have utility methods across those libraries which we want to share with other teams.
One could say just pull all of the utility methods into single library, but then affected
becomes way less useful - affected
doesn't operate at method level, so updating single utility method will cause all lambdas to rebuild though only couple are using updated method.
external: "none"
sort of works, however it is not compatible with @nx/dependency-checks
eslint plugin which is shouting about missing local libraries, even though everything works fine both locally and in published package. The only way to stop this is to list all of libraries used within in ignoredDependencies
in .eslintrc.json
and it doesn't seem like there is way to use regex or specify just scope.
And like someone else said external: "none"
is getting removed in nx 20
๐คทโโ๏ธ
I got an error while trying to publish my library. Here is example source code: https://github.com/dangviettuan/nx-publishable I have:
Originally posted by @dangviettuan in https://github.com/nrwl/nx/issues/3602#issuecomment-768173108