/generator-ngx-library

Yeoman generator to bootstrap :rocket: your Angular library creation and publication.

Primary LanguageJavaScriptMIT LicenseMIT

generator-ngx-library - Yeoman generator to bootstrap your Angular library creation and publication

npm version Build Status Build status Coverage Status dependencies Status devDependency Status Greenkeeper Badge Join the chat at https://gitter.im/generator-ngx-library/Lobby

Demo

Here are live examples of some Angular libraries developed with the generator:

These are some that i know of. Want your project listed here ? Drop me a line.

Features

These are the main features of the generator:

  • Ahead Of Time(AOT) Compilation, Flattened ES Modules(FESM), [Minified] UMD Bundles, Closure Compiler support (follows Angular Package Format)
  • Universal (Server Side Rendering) support
  • Code Linting based on codelyzer rules
  • Styles and Templates Inlining in components
  • SASS/SCSS to CSS compilation
  • Integrated demo app built with angular-cli and ng-bootstrap
  • Project Documentation built with compodoc and published along with demo app 📚
  • Continuous Integration with Travis CI
  • Testing Environment with Karma and Webpack or Jest
  • Code Coverage with Coveralls.io
  • Real-time Monitoring and Automatic Updates of npm dependencies with Greenkeeper 🌴
  • Enforcing of Angular Git Commit Message Guideline with Commitplease 💬
  • Publication to npm registry
  • Releasing to Github :octocat:
  • Support for scoped packages (eg: @mycompany/mylibrary)
  • Support for Angular from 2.x.x all the way up to 6.x.x!
  • and so much more out-of-the-box 📦!

TL; DR :)

If you find next sections way too long, here is a quick summary for you:

  • Setup:
    • Dependencies: npm install -g yo gulp-cli @angular/cli
    • Installation: npm install -g generator-ngx-library
    • Usage: yo ngx-library [project-folder]
  • Library main tasks:
    • Testing Library: gulp test
    • Building Library: gulp build
    • Watching source files and auto-rebuilding Library: gulp build:watch
    • Watching source files and auto-rebuilding Library (without running tests): gulp build:watch-fast
    • Releasing Library: gulp release --version=[major|minor|patch]
  • Demo app main tasks:
    • Serving demo app: gulp serve:demo
    • Serving demo app with Hot Module Replacement (HMR): gulp serve:demo-hmr
    • Serving demo app with Server (Universal): gulp serve:demo-ssr
    • Building demo app for Prod: gulp build:demo
    • Building demo app for Prod with Server (Universal): gulp build:demo-ssr

Table of contents

Installation & Usage

Requirements

You should already have the following dependencies installed: Node.js(npm), Yeoman , Gulp and Angular CLI. if not:

  • Install Node.js. This will also install npm, which is the node package manager we are using in the next commands.
  • Install Yeoman: npm install -g yo
  • Install Gulp: npm install -g gulp-cli
  • Install Angular CLI: npm install -g @angular/cli

Otherwise, install directly the generator via:

$ npm install -g generator-ngx-library

Usage

Once installed, simply run the following command:

$ yo ngx-library [project-folder]

Notice that you can optionally provide the folder where to generate files into, otherwise current one is used.

And answer the questions you are prompted to.

generator-ngx-library in action!

Options

The following options can be passed to customize the generator. The syntax is:

$ yo ngx-library [project-folder] --<option-name>
Name Purpose
skip-install skips the automatic installation of project dependencies at the end of the generator
skip-checks skips the checks of required tools (yarn, angular-cli) prior to generation
skip-cache forces the regeneration on an exising project (ignore previous answers)
skip-demo skips the generation of the demo application
skip-styles skips the generation of style inlining related code (in case you don't use styles)
skip-sample skips the generation of the sample library
skip-travis skips the integration with Travis CI
skip-coveralls skips the integration with Coveralls (code coverage)
skip-gh-releasing skips the releasing of the library on Github
del-excluded-files deletes excluded files that have been found in the file system (from previous generation for example)
npm forces usage of npm to install dependencies

Overall Directory Structure

At a high level, the generated structure looks exactly like this:

my-ngx-library/
  |- .git/
  |- src/
  |  |	|- component/
  |  |	|  |- lib.component.html
  |  |	|  |- lib.component.scss
  |  |	|  |- lib.component.spec.ts
  |  |	|  |- lib.component.ts
  |  |	|- component/
  |  |	|  |- lib.service.spec.ts
  |  |	|  |- lib.service.ts
  |  |	|- index.ts
  |  |	|- lib.module.ts
  |  |	|- tsconfig.lib.es5.ts      # if targeting Angular v4.x.x
  |  |	|- tsconfig.lib.json
  |  |	|- tsconfig.spec.json
  |- config/
  |  |	|- helpers.js
  |  |	|- karma-test-shim.js
  |  |	|- karma.conf.js
  |  |	|- webpack.test.js
  |- demo/
  |  |- # <angular-cli files> + <following additional files>:
  |  |- src/
  |  |	|- app/
  |  |	|  |- getting-started/
  |  |	|  |  |- getting-started-routing.module.ts
  |  |	|  |  |- getting-started.component.html
  |  |	|  |  |- getting-started.component.scss
  |  |	|  |  |- getting-started.component.ts
  |  |	|  |  |- getting-started.component.spec.ts
  |  |	|  |  |- getting-started.module.ts
  |  |	|  |- home/
  |  |	|  |  |- home-routing.module.ts
  |  |	|  |  |- home.component.html
  |  |	|  |  |- home.component.scss
  |  |	|  |  |- home.component.ts
  |  |	|  |  |- home.component.spec.ts
  |  |	|  |  |- home.module.ts
  |  |	|  |- shared/
  |  |	|  |- app-rooting.module.ts
  |  |	|- assets/
  |  |	|  |- logo.svg
  |  |	|- testing/
  |  |	|  |- index.ts
  |  |	|  |- router-stubs.ts
  |  |	|- tsconfig.server.json           # for universal (server side rendering)
  |  |- prerender.ts                      # for universal (server side rendering)
  |  |- server.ts                         # for universal (server side rendering)
  |  |- webpack.server.config.js          # for universal (server side rendering)
  |- .editorconfig
  |- .gitignore
  |- .travis.yml
  |- CHANGELOG.md
  |- gulpfile.js
  |- karma.conf.js
  |- LICENSE
  |- package.json
  |- tsconfig.json
  |- tslint.json
  |- webpack.config.js

Here are the main files and folders:

File / Folder Purpose
gulpfile.js The gulp configuration file to manage the whole project build lifecycle (from testing to releasing)
tslint.json This file contains rules to lint your library based on codelyzer
tsconfig.json The typescript configuration file used for editors (VSCode, ...)
src/tsconfig.lib.es5.json The typescript configuration file used to compile your library in an AoT compatible way, as ESM/ES5 module (only available when targeting Angular v4.x.x)
src/tsconfig.lib.json The typescript configuration file used to compile your library in an AoT compatible way, either as ESM/ES2015 module (when targeting Angular v4.x.x) or as ESM/ES5 module (when targeting Angular v2.x.x)
src/tsconfig.spec.json The typescript configuration file used for tests
src/ This folder will contain all the files of your library
config/ This folder contains the configuration files for tools used to test your lib (Webpack & Karma or Jest)
demo/ This folder contains an integrated demo application, to showcase your library. The demo app is built with angular-cli, so everything you know about the CLI is applicable inside this folder.
dist/ (generated) This generated folder contains everything that will be published as part of your package to npm registry. It contains only necessary files and is built via gulp buildcommand

Note : The demo app has a dependency on your local package, that is post-installed via npm link <YOUR_PACKAGE_NAME> and point to the generated dist/ folder (from project root). This way, you can be sure you are using the library as final users will, without having to publish it first.

Besides, any changes to the files in the dist/ folder will immediately affect the global <YOUR_PACKAGE_NAME> package, allowing you to quickly test any changes you make to your library.

npm link is very similar to npm install -g except that instead of downloading the package from the repo, the just built dist/ folder becomes the global package.

Overall Distributed Package Structure

Depending on the minimal version of Angular your library targets (2.x.x or 4.x.x), the distributed package files are different, but both are AOT compatible:

For Angular >=v4.x.x

The published package follows the official Angular Package Format v4.0

dist/
	|- bundles/                           # Directory that contains all bundles (UMD/ES5)
	|  |- my-ngx-library.umd.js           # UMD bundle
	|  |- my-ngx-library.umd.js.map       # UMD bundle sourcemap
	|  |- my-ngx-library.umd.min.js       # Minified UMD bundle
	|  |- my-ngx-library.umd.min.js.map   # Minified UMD bundle sourcemap
	|- module/                            # 
	|  |- component/                      #
	|  |  |- lib.component.d.ts           # Type definitions
	|  |- service/                        #
	|  |  |- lib.service.d.ts             # Type definitions
	|- CHANGELOG.md                       #
	|- my-ngx-library.d.ts                # Type definitions
	|- my-ngx-library.metadata.json       # Metadata used by AOT compiler
  |- [esm5]/                            # Optional Directory containing ESM5 files (for ng >=v5 only)
	|  |- my-ngx-library.es5.js           # ESM+ES5 flat module (FESM5)
	|  |- my-ngx-library.es5.js.map       # ESM+ES5 flat module (FESM5) sourcemap
  |- [esm2015]/                         # Optional Directory containing ESM2015 files (for ng >=v5 only)
	|  |- my-ngx-library.js              # ESM+ES2015 flat module (FESM15)
	|  |- my-ngx-library.js.map          # ESM+ES2015 flat module (FESM15) sourcemap
	|- LICENSE                            #
	|- lib.module.d.ts                    # Type definitions
	|- package.json                       # Package.json, with just the right dependencies & peerDependencies
	|- README.md                          #

For Angular v2.x.x

The published package also follows the format of Angular core packages (prior to v4.0.0), but contrary to v4, there is no official(or publicly available) documentation about that format.

dist/
	|- bundles/                           # Directory that contains all bundles (UMD/ES5)
	|  |- my-ngx-library.umd.js           # UMD bundle
	|  |- my-ngx-library.umd.js.map       # UMD bundle sourcemap
	|  |- my-ngx-library.umd.min.js       # Minified UMD bundle
	|  |- my-ngx-library.umd.min.js.map   # Minified UMD bundle sourcemap
	|- module/                            # 
	|  |- component/                      #
	|  |  |- lib.component.d.ts           # Type definitions
	|  |  |- lib.component.js             # ES5 file
	|  |  |- lib.component.js.map         # ES5 sourcemap
	|  |  |- lib.component.metadata.json  # Metadata used by AOT compiler
	|  |- service/                        #
	|  |  |- lib.service.d.ts             # Type definitions
	|  |  |- lib.service.js               # ES5 file
	|  |  |- lib.service.js.map           # ES5 sourcemap
	|  |  |- lib.service.metadata.json    # Metadata used by AOT compiler
	|- CHANGELOG.md                       #
	|- index.d.ts                         # Type definitions
	|- index.js                           # ES5 entrypoint
	|- index.js.map                       # ES5 sourcemap
	|- index.metadata.json                #
	|- LICENSE                            #
	|- lib.module.d.ts                    # Type definitions
	|- lib.module.metadata.json           # Metadata used by AOT compiler
	|- package.json                       # Package.json, with just the right dependencies & peerDependencies
	|- README.md                          #

Development

It's now up to you to write your kick-ass Angular library by adding your components, directives, pipes, services... and tests in src/.

It doesn't matter how you organize files inside the folder, but it is important to keep the index.ts at the root, and to export every file that must be publicly available in your package.

Here are the most important gulp tasks to use during your development workflow:

Task Purpose
gulp build Builds and packages your library under the dist/ folder.
gulp build:watch Watches the source files (*.ts, *.html and *.scss) and re-builds your library upon changes (useful for live refresh of demo app during development).
gulp build:watch-fast Watches the source files (*.ts, *.html and *.scss) and re-builds your library upon changes (without running tests).
gulp test Launches the tests (*.spec.ts) you wrote in src/ and run code coverage on them. The coverage report can be found in coverage/ folder
gulp test:watch Launches tests in watch mode. Every changes in *.spec.ts
gulp test:watch-no-cc Same as gulp test:watch but files do not get instrumented for code coverage (useful for debugging)
gulp test:demo1 Launches demo application tests(same as running ng test from demo/).
gulp build:demo1 Builds demo application for production.
gulp build:demo-ssr1 Builds demo application for universal (server side rendering) testing.
gulp serve:demo1 Serves demo application (same as running ng serve from demo/).
gulp serve:demo-hmr1 Serves demo application with HMR (hot module replacement)
gulp serve:demo-ssr1 Serves demo application for universal (server side rendering) testing.
gulp serve:doc2 Serves the generated compodoc documentation (from dist/doc folder) at https://localhost:8080.

Note About consuming locally linked library :

In case you encounter the following : 'Error: Unexpected value '[object Object]' imported by the module 'AppModule'. Please add a @NgModule annotation', try adding --preserve-symlinks to your launch command (eg: ng serve --preserve-symlinks, for Angular CLI projects). In fact, this flag is needed to consume locally built/linked libraries (via npm link) with peerDependencies. See this post for more information.

Note About compodoc and demo application :

compodoc documentation is only available if you chose to use compodoc during generator setup.

When serving demo app (via gulp serve:demo), in order to access documenation files (which are available at URL /doc/), be sure to also serve compodoc's generated documentation files (via gulp serve:doc).

In development, the url /doc/ is proxied to redirect to that locally running server for compodoc files (at https://localhost:8080)

In production, the generated documentations files are deployed along with the demo application and are available at same url (/doc/) from root index.html

1 = This task is only available if you chose not to skip demo app generation during generator setup

2 = This task is only available if you chose to use compodoc during generator setup

Recipes 🍯

Some useful recipes to help you during the development process can be found here

Updating

When a new version of the generator is available, you can take advantage of the new features/bug fixes it brings by updating your globally installed version and by re-running it again (from your project root folder).

$ npm install -g generator-ngx-library
$ yo ngx-library

Please make sure to read CHANGELOG first, to take all necessary actions for a seamless upgrade.

Enforcing angular-style commit messages

The generator can enforce (via Commitplease) that all your commit messages follow Angular guidelines.

validating commit messages!

This convention helps making your git mesages more readable and meaningful, in addtion of keeping each commit simple and well focused on a certain scope.

The generator also takes full advantage of the convention to autogenerate project's CHANGELOG.md and Github release notes from Git metadata. Only relevant commit messages are considered (commits about new features, fixes, performance, and breaking changes).

You can tweak or deactivate (:scream:) the convention by editing the "commitplease" section in package.json. See here.

Pre-Releasing 🏁

A set of checks is automatically performed for you prior to releasing (during gulp release), to ensure that you are indeed ready for it. Right now, we check that:

  • Travis build on master branch is passing
  • User is currently on master branch
  • User is currently logged in to NPM
  • Option --version has been provided to gulp release task, with value: major, minor or patch
  • Option --ghToken has been provided or env variable CONVENTIONAL_GITHUB_RELEASER_TOKEN is set

pre release checks

You can also run the gulp pre-release task alone, to solely perform these checks without actually releasing anything.

Note: if you provided --skip-travis option (resp. --skip-gh-releasing) when running the generator, the Travis build (resp. releasing on Github) will be ignored/skipped.

Releasing

Once your killer library is done, then it is time unleash the beast!

Nothing is simpler 😛

$ gulp release --version=[major|minor|patch] [--ghToken=YOUR_GITHUB_TOKEN]

As you can see above, the releasing task can take 2 parameters:

  • version (mandatory): Version of the library to release, following semantic versioning. Possible values are: patch, minor, and major
  • ghToken (optional): Github Token to use to release on Github. if no token is provided, default to environment variable CONVENTIONAL_GITHUB_RELEASER_TOKEN.

How to setup Github Token : Go to create a new token and set your environment variable CONVENTIONAL_GITHUB_RELEASER_TOKEN to the token you just created. You can google How to set environment variable. The scopes for the token you need is public_repo or repo (if you need to access private repos). More details.

Running this task will (in that order) :

  1. check if ready for release (see Pre-Releasing above) and abort if not
  2. bump the version of your library in package.json
  3. update the CHANGELOG.md file based on your commit messages (provided they follow the angular git message convention)
  4. commit on master branch
  5. create and push a new tag matching the new version
  6. create a new release on Github :octocat: (using the provided token or environment variable CONVENTIONAL_GITHUB_RELEASER_TOKEN)
  7. publish the package 📦 on npm registry (you must be logged in to npm)
  8. build and deploy 🚀 the demo application in demo/dist to gh-pages branch

The demo application will be available at : https://USERNAME.github.io/REPO_NAME/ (provided you chose to generate one).

The documentation will be available at : https://USERNAME.github.io/REPO_NAME/doc/ (provided you chose to generate one) or at https://USERNAME.github.io/REPO_NAME/, if you chose to skip demo application generation.

Troubleshooting

See most common problems, and how to solve them here.

Support

Having trouble using the generator? Want to discuss about new features to add? Come and join the project's Gitter to chat about it!

License

Copyright (c) 2018 Tine Kondo. Licensed under the MIT License (MIT)