Angular CLI: 6.0.0
Node: 8.9.1
OS: win32 x64
Angular: 6.0.0
... animations, cli, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router
Package Version
------------------------------------------------------------
@angular-devkit/architect 0.6.0
@angular-devkit/build-angular 0.6.0
@angular-devkit/build-ng-packagr 0.6.0
@angular-devkit/build-optimizer 0.6.0
@angular-devkit/core 0.6.0
@angular-devkit/schematics 0.6.0
@ngtools/json-schema 1.1.0
@ngtools/webpack 6.0.0
@schematics/angular 0.6.0
@schematics/update 0.6.0
ng-packagr 3.0.0-rc.3
rxjs 6.1.0
typescript 2.7.2
webpack 4.6.0
With the release of Angular 6, the CLI now supports the concept of creating Angular 6+ libraries. However, the workflow imposed by the CLI does not line up with a typical npm module development workflow:
dist
directory, complete with its own package.json
. As a result, publishing the module requires the developer to run npm publish
from within the dist
folder, rather than at the root of the project.npm link
command to be run from within the dist
folder.package.json
, it's unclear where library dependencies should be installed. If dependencies are installed into the root package.json
, the dependencies don't get included in the package published to npm. However, if the dependencies are instead installed into the library's package.json
(i.e. ./projects/my-module/package.json
), an error is thrown when ng build my-module
is run (BUILD ERROR: Dependency XXX must be explicitly whitelisted
)../package.json
./projects/package.json
./projects/ng-package.json
./projects/ng-package.prod.json
./dist/my-module/package.json
The Angular 6+ library development experience should match that of developing a typical npm module:
package.json
).npm publish
and npm link
commands should be able to be run from the root of the project.@nfriend, I'm not sure if you consider the fact that people build Angular libraries that are used by multiple Angular projects and are published to NPM as separate packages. So, it would be nice to support the generation of Angular libraries without creating an app first, but I don't see how the other 2 points make sense.
Also, you can try using "devDependencies" combined with "peerDependencies" when building a library.
Totally agree with maxtacco. We should be able to build the ng 6 libraries independently and import them as npm dependencies in any app.
I just want to point out that the "entirely separate module in dist" makes sense when you have a mono-repo style setup with several libraries in the same Angular project, each building to their own folder, to be deployed from there.
In that case, the default, root-level app becomes somewhat redundant. I have simply deleted it, though it wouldn't be unreasonable to use it as a demo/documentation app for the project's libraries.
But I agree that the structure doesn't serve the "simple project for single library" use case all that well.
I think it would also be nice to create a namespaced library e.g @namespace/library
. Tried to do that by running ng generate library @namespace/library
but when importing I had to use import { Stuff } from library
. It seemed to ignore the namespace bit. I cannot do import { Stuff } from @namespace/library
, the same way we import { Component } from @angular/core
I view the app at the base as a great place to create a "sample" app for the library - ensuring that as set up the library created under it can be consumed.
However, ng build
on the base app actually kills the dist
folder - which destroys the as-built library.
@mcaden, I experienced the same issue. I updated "dest" property in ng-package.json of my library to output to a different folder as a fix for now.
Totally agree.
The Angular guys are greating a great job but please: stop monopolizing all the workflow, and sorry to say it this way.
Angular itself uses npm ecosystem. Why cannot we just make
ng library whatever
, which would create a basic project structure ready to be linked by a cli app ? Similar to
https://github.com/jvandemo/generator-angular2-library
Ng-packagr is great, but I really think big angular applications need the flexibility of npm, and not a strict schema where you cannot watch changes or attach sass files to the dist.
Best regards.
I like the @nfriend mentioned about the dependencies part.
It's really confusing how to deal with library dependencies today. It was expected that now, when angular has finally reached the library features, is to make them much simpler to develop.
It would been great to have something like
npm i some-awesome-dependency --project=my-awesome-library --peer=true --dev=false
@joashmusyoka , I have it working fine. Just remember to add:
"paths": {
"@namespace/library": ["dist/namespace/library"]
}
in your tsconfig file.
Hope it helps.
Thanks, I will try this
On Thu, 7 Jun 2018 12:46 pm Sergio Correa, notifications@github.com wrote:
@joashmusyoka https://github.com/joashmusyoka , I have it working fine.
Just remember to add:"paths": {
"@namespace/library": ["dist/namespace/library"]
}in your tsconfig file.
Hope it helps.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/angular/angular-cli/issues/10751#issuecomment-395360446,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AJthgTdSfmU_GjAIVbIgBoFvTnRQXBl9ks5t6PZigaJpZM4T4XUL
.
I'm really hoping that addressing the "library" workflow and features becomes a priority to angular cli team. It's critical to enable the ecosystem. Think of all the angularjs libraries that are just dormant now! If we truly want angular to flourish, library creation and publishing should be a no brainer! Simply put we need simplified workflow and dependency control/flexibility.
A positive thing about the default app and library(s) in the same Workspace is that if you are building out a new app and re-usable libraries at the same time you can build and debug the libraries as part of your app development -- your app is actually the "sample" app. At some point as the app and libraries become more mature, the Library projects can be shared/published as NPM packages.
It's all about the dist
getting deleted on the build. Here's my workaround
Creating a library
ng generate library tvmaze --prefix=tv
Go to path/to/your/app/tsconfig.json
and delete
"tvmaze/*": [ "projects/tvmaze/dist/*"]
and now change the path for the tvmaze
from projects/tvmaze/dist
to ../distPack/tvmaze
"tvmaze": [ "../distPack/tvmaze"]
NOTE: you can also add a namespace to be nice, just change to @supername/tvmaze
Go to projects/tvmaze/ng-package.json
and change the dist
to distPack
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../distPack/tvmaze",
"deleteDestPath": false,
"lib": {
"entryFile": "src/public_api.ts"
}
}
Now just use it
import {TvmazeModule} from '@supername/tvmaze';
I altered the projects folder to src and make src folder as demo/playground as my library source. That structure makes sense to me. I agree that angular-cli should create a library without a workspace. However, for some monorepo, multiple package.json to maintain dependencies seems necessary.
Can someone please clarify for me?:
Is the official method for creating a git repo for a npm angular 6 library is to create an _entire_ angular 6 application with a projects
folder and then your actual library in that folder? If that is the case that seems to me a bit bizarre to have your library published to github with all this app code around it.
What if you want to move your library into its own git repo? Is the best practice to create a git submodule in your products
folder of your top level app?
@jcroll In my experience, there is no such thing as "official method" yet. It all depends on the situation you are in and what you are willing to sacrifice.
For the situation @jcroll mentions, I'd lean towards having the library in the projects
folder and using the root project for demonstration and documentation. I don't find it bizarre to have the app code around it; on the contrary, I'd find it a help to see how library could/should be used in an actual app.
It sort of feels like the actual "payload"; the library itself, is rather hidden in a "random subfolder" this way, but for an Angular developer, it is a recognizable structure.
But as @jSchez says, I think we're currently all feeling our way around, trying to figure out the best practices.
In terms of the issue of having to create an app as well as a lib, is it not beneficial to have a sample app paired alongside your library so you can demonstrate usage as well as test?
Is it also such that a library must be a single module?
I'm taking a library written on an earlier version of the Angular CLI and ripping the modules out and adding them to the library "project". I've been able to export them all through the public_api.ts
file using barrel files. However, building in prod mode, using AOT, I get a host of errors either in building the library portion or when trying to import modules in the "containing app".
I liken the current approach used by the CLI as somewhat similar to how VisualStudio works. It creates a "solution". The solution is your demo application. You can add more "projects" from the various things that can be done through the schematics.
It just seems frustrating that after the all the work that has been done and touted in the version 6 release that there are still these basic tooling issues. Look at other large or "production grade" type libraries. For example angular material. They support Angular 6 and even the CLI, but you'll be quick to notice that their project is not using the CLI itself.
@mikejr83
However, building in prod mode, using AOT, I get a host of errors either in building the library portion or when trying to import modules in the "containing app".
Ensure your prod build also creates valid .metadata.json.
Btw: Importing from directories ('/') will cause ng-packagr to Not emit Metadata, sometimes even without throwing compile errors. You need to directly import from ('/index')
@joashmusyoka , I have it working fine. Just remember to add:
"paths": { "@namespace/library": ["dist/namespace/library"] }
in your tsconfig file.
Hope it helps.
However, in the angular schema @
is not allowed for projects, see https://github.com/angular/angular-cli/blob/4718de4dae9bbdf25882091610dfc0afc54341b0/packages/angular/cli/lib/config/schema.json#L30
would it be possible to have one library but group it inside so then I can do:
import { SomeService } from '@myOrg/lib/services';
import { SomeEntity } from '@myOrg/lib/model'
a bit side question I still think is related
It would be great to have some documentation on best practice or a part 3 to the very useful: Angular in depth library series
I wanted to be able to use my library as an unpublished private npm package installed via git.
so I decided to go for the postinstall approach mentioned above, so like this:
package.json
"scripts"
...
"postinstall": "npm i node_modules/my-ui-library/dist/my-lib/my-lib-0.0.1.tgz"
},
"dependencies": {
...
"my-ui-library": "git+https://[email protected]/my-lib.git",
npm adds an entry for my-lib
which is confusing but with the --no-save
flag you can get around this, still feels like a workaround though.
Thanks everyone for participating in this conversation, however as any long outstanding issue the discussion is going off topic. Before closing, I'll try to answer and clarify as many points as I can.
An Angular 6+ library should be able to be generated without first creating an app.
This is possible via ng new --no-create-application
, See: https://angular.io/cli/new
Building an Angular library should not create a new module (e.g. a new package.json)
We follow the mono-repo model, similar to other tools, such as Lerna and Bazel. Where the dependencies in the root level package.json are shared among all projects of the workspace. Hence the root level package.json, is not reserved to any project in the workspace.
The
npm publish
andnpm link
commands should be able to be run from the root of the project.
I think changing this now would be more confusing and overall I think that having a dist
package is cleaner and more intuitive (What you see if what you get sort of thing). Over the years, I experienced multiple times that libraries using the publish from the root causes accident breakages. Because either they missed to update the .npmignore
or the files
option in package.json
. Not to mention that this approach does require more maintenance and is not as straightforward to publish from a dedicated distributable folder
Also, this is rather limiting and you will not be able to do certain transitions on files such as package.json
as it will override the source package.json. Apart from that it's would be rather messy to write the transpilled .js
file next to the .ts
sourcefiles.
Confusing library dependencies and root level dependencies
In many cases a library should not any dependencies, most of the dependencies used in the library should be declared as peer dependencies. See: https://github.com/ng-packagr/ng-packagr/blob/master/docs/dependencies.md
In the same vein, linking an Angular library for local development requires the npm link command to be run from within the dist folder.
Indeed although for a better DX we recommend using a mono repo instead of npm link
.
After a library is built, a total of five package-related files exist in the project directory. This has the potential to be very confusing.
Those files have now been reduced and they all serve different purposes.
Most helpful comment
@nfriend, I'm not sure if you consider the fact that people build Angular libraries that are used by multiple Angular projects and are published to NPM as separate packages. So, it would be nice to support the generation of Angular libraries without creating an app first, but I don't see how the other 2 points make sense.
Also, you can try using "devDependencies" combined with "peerDependencies" when building a library.