Create an angular library

Creating the project

First we will setup the project using the angular cli.

Library

ng new my-library-name --no-create-application

Then inside the directory we can create the library.

ng generate library my-lib

Documentation / showcase application

I want to also create a application that will display the components, and also allow me to test the library while developing it.

ng generate application doc

I also cleaned the doc application by removing all the default html inside the app.component.html file.

Configuring scss for the library

By default, the components inside the library will use the css file. If you want to use scss, you will need to configure it.

You can do this by adding the following lines (schematics section) to the angular.json file in the “my-lib” section.

{
  "my-lib": {
    "projectType": "library",
    "schematics": {
      "@schematics/angular:component": {
        "style": "scss"
      }
    }
  }
}

Creating the first component

Cleaning module library

When the project was generated, a component was created inside the library. We will remove it, and remove the references inside the my-lib.module.ts file.

Here is the list of deleted files:

  • projects/my-lib/src/lib/my-lib.component.ts
  • projects/my-lib/src/lib/my-lib.component.spec.ts
  • projects/my-lib/src/lib/my-lib.service.ts
  • projects/my-lib/src/lib/my-lib.service.spec.ts

The service and the components were also inside the public-api.ts file, so we will remove them.

Component creation

I will create a button component inside the library, to show how to create a component and then use it inside the doc application.

ng g c my-button --project=my-lib

I will add some html and css to the component to make it look like a button.

<button>My example button</button>
button{
  background-color: rgba(51, 51, 51, 0.05);
  border-radius: 8px;
  border-width: 0;
  color: #333333;
  cursor: pointer;
  display: inline-block;
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  list-style: none;
  margin: 0;
  padding: 10px 12px;
  text-align: center;
}

To make you component available, you will need to export it inside the module.

@NgModule({
  declarations: [
    MyButtonComponent
  ],
  imports: [
  ],
  exports: [
    MyButtonComponent,
  ]
})
export class MyLibModule { }

You also need to export the module inside the public-api.ts file.

export * from './lib/my-button/my-button.component';
export * from './lib/my-lib.module';

Then inside the doc application, you can import the module and use the component.

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    MyLibModule, // <-- import the module
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Then inside the app.component.html file, you can use the component.

<lib-my-button></lib-my-button>

Publishing the library

Tu publish the library I am using github action. I followed this tutorial and adapted the workflow for angular.

Here is the workflow file:

name: Release package
on:
  workflow_dispatch:
    inputs:
      release-type:
        description: 'Release type (one of): patch, minor, major, prepatch, preminor, premajor, prerelease'
        required: true
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      # Checkout project repository
      - name: Checkout
        uses: actions/[email protected]

      # Setup Node.js environment
      - name: Setup Node.js
        uses: actions/setup-node@v2
        with:
          registry-url: https://registry.npmjs.org/
          node-version: '18'

      - name: Install angular cli
        run: npm install -g @angular/cli@latest

      - name: Install dependencies
        run: npm install


      # Configure Git
      - name: Git configuration
        run: |
          git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
          git config --global user.name "GitHub Actions"          

      # Bump package version
      # Use tag latest
      - name: Bump release version
        working-directory: ./projects/my-lib
        if: startsWith(github.event.inputs.release-type, 'pre') != true
        run: |
          echo "NEW_VERSION=$(npm --no-git-tag-version version $RELEASE_TYPE)" >> $GITHUB_ENV
          echo "RELEASE_TAG=latest" >> $GITHUB_ENV          
        env:
          RELEASE_TYPE: ${{ github.event.inputs.release-type }}

      # Bump package pre-release version
      # Use tag beta for pre-release versions
      - name: Bump pre-release version
        working-directory: ./projects/my-lib
        if: startsWith(github.event.inputs.release-type, 'pre')
        run: |
          echo "NEW_VERSION=$(npm --no-git-tag-version --preid=beta version $RELEASE_TYPE)" >> $GITHUB_ENV
          echo "RELEASE_TAG=beta" >> $GITHUB_ENV          
        env:
          RELEASE_TYPE: ${{ github.event.inputs.release-type }}


      - name: Build library
        working-directory: ./projects/my-lib
        run: ng build

      # Update changelog unreleased section with new version
      - name: Update changelog
        uses: superfaceai/release-changelog-action@v1
        with:
          path-to-changelog: CHANGELOG.md
          version: ${{ env.NEW_VERSION }}
          operation: release

      # Commit changes
      - name: Commit CHANGELOG.md and package.json changes and create tag
        run: |
          git add "projects/my-lib/package.json"
          git add "CHANGELOG.md"
          git commit -m "chore: release ${{ env.NEW_VERSION }}"
          git tag ${{ env.NEW_VERSION }}          

      # Publish version to public repository
      - name: Publish
        working-directory: ./dist/my-lib
        run: npm publish --verbose --access public --tag ${{ env.RELEASE_TAG }}
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPMJS_ACCESS_TOKEN }}

      # Push repository changes
      - name: Push changes to repository
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          git push origin && git push --tags          

      # Read version changelog
      - id: get-changelog
        name: Get version changelog
        uses: superfaceai/release-changelog-action@v1
        with:
          path-to-changelog: CHANGELOG.md
          version: ${{ env.NEW_VERSION }}
          operation: read

      # Update GitHub release with changelog
      - name: Update GitHub release documentation
        uses: softprops/action-gh-release@v1
        with:
          tag_name: ${{ env.NEW_VERSION }}
          body: ${{ steps.get-changelog.outputs.changelog }}
          prerelease: ${{ startsWith(github.event.inputs.release-type, 'pre') }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          

You will need to add a CHANGELOG.md file at the root of the project.

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

To make this workflow work you will need to create a secret inside your repository. The secret will be used to publish the library on npm.

Fist you need to go to npmjs.com in the token section to create a classic token for automation.

Then in the github repository, in the settings -> Secrets -> Actions you can create a new secret named NPMJS_ACCESS_TOKEN and paste the token you just created.

Before running the workflow, you will need to allow the github action to write on the repository. To do this, you need to go to the settings -> Actions -> General and at the bottom of the page there is Workflow permissions, chose Read and write permissions

Publishing the first version

In the action tab of your repository, you can run the workflow. You will need to enter the release type. I will enter prepatch to publish the first version.

Locally testing the library

You can test your component inside the doc application, but you also can test it in another project.

I create an app to test the library.

ng new app-test-list

Fist you need to go inside the library directory and run a command to link it.

npm link

Then inside the app-test-list directory, you can run the following command to link the library.

npm link my-lib

Github

The sources are available on github