Sharing Ionic 2 Code Between Projects

April 7th 2017 Ionic 2/3 Angular Git

Ionic 2 includes many components and native wrappers out of the box. However, you will probably want to share some of your own code between projects if you are working on more than one of them and they are at least remotely similar. Since Ionic 2 builds on top of Angular, shared modules are the right tool for the job.

Using NPM Packages

Although the official template for creating Ionic 2 modules isn't regularly maintained, it's still not difficult to get it running using the instructions from the repository. The following hints might help you expedite the process even more:

  • If you're using Windows, replace rm -rf in build script with its Node based cross-platform equivalent rimraf. Install the package first with npm install rimraf --save-dev, then change the script in package.json to:

      "build": "rimraf aot dist && npm run ngc"
    
  • To test the package locally before publishing it to npm, use npm pack instead of npm publish. You can install generated package in your application by passing its relative path to npm: npm install ../module/ionic-module-template-0.0.12.tgz --save.

  • To avoid issues in the future, you should update the module package dependencies to match the versions of their counterparts in your application. You can simply change the versions in module's package.json and run npm install afterwards.

While the approach works from the technical standpoint, I can't say the same for the development process it imposes. I don't like how it doesn't support putting the component template into a separate file, but I could live with that. The main problem is the long feedback loop for any changes to the module. Live reload doesn't work. The shared package needs to be rebuilt and reinstalled. For a mostly stable module that's not a problem, but if you plan to develop it in parallel with the app, it's going to slow you down a lot. Using npm link might help, but I had problems getting the sample to work and found it quite complex to set up reliably for the typical scenario with individual applications and the shared module in separate repositories.

Using Git Submodules

In the end, I decided for a less formal alternative approach, using git submodules. I abandoned the separate build process for the module in favor of directly including the sources in each application:

  • In the shared module repository, there are only files from the src folder of the official module template.
  • In each application's src folder I added a modules subfolder and initialized the shared module repository as a git submodule there: git submodule add https://bitbucket.org/damirarh/ionic-common-module.git src/modules/common.

This way, the shared module will be compiled together with the rest of the application code and live reload will work as intended. Any shared module unit tests will be run together with each application's unit tests, as well. To reference the module from the application code, path to its source must now be specified:

import { MyModule } from '../modules/common';

The setup allows me to transparently develop the module in parallel to the application(s). Using the many git submodules operations, I can decide how to handle and potentially branch the changes in the module, and which version (i.e. commit) of the module I want to reference in each application at any point in time.

There are also disadvantages to this approach:

  • There is no standalone build and test process for the module. Its correctness can only be evaluated when it is used from within another application.
  • The module has no package.json file to track external dependencies. They must be installed into each individual application, or the build will fail. However failed import statements usually give a very good hint about the missing package that needs to be installed.

Yes, the solution isn't perfect, but I can live with it and I like it better than any of the alternatives I tried.

Get notified when a new blog post is published (usually every Friday):

Copyright
Creative Commons License