Let's say our project is growing and we want to keep things separated. Sometimes we can split our angular project in two or three different projects, but then, we realize it will be repeated code from styles, components or any other resource.
As a first resume of what we want to do:
- Create a couple of Angular projects that will use the same custom library
- Create the custom components library (with Angular)
- Host that custom library in our base projects like a GIT submodule
- Build and access the library from our base projects like an angular package
- Profit :)
You can find nice posts with generic information that can help you to accomplish this task. Like this amazing summary about GIT submodules. Or the official documentation of ng-packagr about transpile a library to Angular Package Format.
But for this post, what a I want to do is a practical example with Angular (I need to practice to feel like I really understand, I'm sure some of you too!).
Create the example projects
Create three minimal Angular projects:
ng new HelloFoo --minimal
ng new HelloBar --minimal
ng generate library ComponentsLibrary
After a few tweaks, to help us differentiate both Hello projects, we could have something like this:
Prepare the custom library project
Pay attention to the shape of our components library. We have generated it as a library. Doing so, we don't need to delete non useful Angular configuration files, we only need to be able to export components/modules.
For this occasion, lets create a footer module in our new components library project.
We want to use this resource in both Hello projects and we want to be sure that it's going to keep consistency while avoiding DRY. (This is one of the main reasons of having a common submodule)
Pay attention to public-api.ts
file. It describes the access points that we'll need to import in the Hello Projects later on.
For the purposes of this tutorial, we can have these two projects in local, but we need to put the components library in a shared repository.
We use Github in this case, so we push this new components library into his repository. https://github.com/RadW2020/components_library_tutorial
Add the submodule to the projects
At this point, we want our two base projects stay aware of this new library. In order to do that we execute this command in the root folder of our Hello project:
git submodule add git@github.com:RadW2020/components_library_tutorial.git custom_lib
Execute this in our two Hello projects. This will add it as a submodule in the given folder. Please notice the new file GIT has created for us named .gitmodules
From now on, this shared library, that is a project on itself, is tied in our Hello projects as a submodule hosted in his own folder custom_lib.
Maintain the submodule updated
What happens if a change is pushed to the components library repository? We need to be aware and check it to keep our library updated.
This will be noticeable any time we use git status
in our Hello projects:
GIT is warning us about commits in lib's origin. We want to tell to our Hello project to point to the last commit of the components library repository. For that, we do:
git add .
git commit -m "update custom_lib to last reference"
This will update the submodule from the point of view of our Hello project. What we really are doing here is maintaining our Hello project custom_lib folder. This is done by holding a reference that points to a commit of the custom_lib GIT history, if it is not the last, the message (new commits) shows up.
Components library evolution
To finnish this mutation, we have to prepare our library to behave like that. A new configuration file has to be created, so ng-packagr will know how to handle it:
In ng-package.json
it is specified where will be located the build (dest), and how it will be accesible (entryFile).
Next steps
Let's tell to our Hello projects that this custom_lib is more than just a sub-folder synced with GIT. We have to specify a few things:
- How to compile custom_lib so it can be used like a regular dependency.
- Where it's located the library dependency. (We will leave it in dist folder next to the other installed dependencies)
- The compiled library needs to be listed in package.json.
Dev Dependencies
In devDependencies
, it is declared the ng-packagr and other dependencies needed to transpile the library to an Angular package format.
Time to execute npm install
to get those new dependencies.
Build lib
In scripts
, it is declared how to build the library.
This will build the project that we have to define in angular.json
Then execute npm run build-lib
. The console will show useful information.
In dependencies
, must be declared where to find the build.
The last step is to execute npm install
. With this final step we're installing the package as a regular dependency. In fact, you can find it inside node_modules folder.
Back to work
It's time to come back to our regular Angular workflow. This means, to import the FooterModule
and then use Footer component in the template.
Both Hello projects should look like this:
yai!
We got it :D
Test it
- Custom lib: Edit footer background.
- Custom lib: Commit and push changes.
- Hello projects:
git pull --recurse-submodules
- Hello projects: Serve and enjoy.
Salute!!
Top comments (1)
I see a mistake, the FooterModule is imported used directly in your example and not from the dist/ folder.
And there is also a issue where you need dependencies to build the submodule to have
yarn install
to succeed. Having file: depenecy will fail with not found as the build havent happen yet.