Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: decide whether to align versioning with Angular's #993

Open
davidlj95 opened this issue Oct 24, 2024 · 0 comments
Open

build: decide whether to align versioning with Angular's #993

davidlj95 opened this issue Oct 24, 2024 · 0 comments

Comments

@davidlj95
Copy link
Owner

davidlj95 commented Oct 24, 2024

Maintaining compatibility with older versions of Angular is starting to be a challenge. See for instance:

So maybe versioning numbers alongside Angular releases can be a good idea. Like: 18.x to be compatible with Angular v18 and so on and so forth. This doesn't misalign with being compatible with all Angular actively supported versions. Because 18.x can support 16, 17 and 18. Then, in 19.x, support for v16 is dropped and support for v19 is added. Hence it supports v17, v18 and v19.

Otherwise, being compatible with really old Angular versions can be a maintenance burden. Plus we won't be able to use newer APIs.

The idea of supporting all versions was because setting <meta> elements needs very few APIs from Angular. Plus they're quite important APIs that haven't changed much. So could be possible.

However many things have changed over time and right now the library isn't compatible with v14 or below. Due to the following APIs mainly:

  • makeEnvironmentProviders: introduced in v15
  • inject() with inject options instead of flags. Options were introduced in v14.1 and flags deprecated at same time. Flags have been supported since inception of the function. However, at some point flags will be removed! Could be replaced by @Inject decorators in a service though. But then the ones needing those would need to be turned services hence increasing bundle size. Specifically metadata loader (to inject local registry) and metadata resolver (to inject optional route metadata strategy and optional defaults).
  • ENVIRONMENT_INITIALIZER: introduced in v14 after renaming. It was originally called INJECTOR_INITIALIZER. However, rename happened during the pre-releases of the version, so no breaking changes. It was actually introduced here. To add moar, it will be deprecated in v19, and replaced by a provideEnvironmentInitializer function.

Environment'ish APIs are regarding the standalone approach and then there's the inject thing. But anyway, seems that even those fundamental APIs may be subject to changes over time. So having a versioning aligned with Angular releases would help updating to newer APIs (like takeUntilDestroyed that could simplify router listener). With 3 releases of difference to provide more support time. But at least at some point in time.

Also Angular.dev recommends building apps using the same or greater version than the library was build with. So according to this, the library should be compiled with the oldest version that supports. Hence supporting older versions becomes more difficult. In few words, quoting the Angular.dev link:

Angular does not support using an earlier version for the application.

Another alternative is to go with regular sem ver, then publish a compatibility table of which versions are compatible with which ones. Just publish a breaking change when an API has been removed hence it doesn't work anymore. This will reduce the amount of breaking changes. As if aligning with Angular releases, a new version may include breaking changes. In the library, a part from the Angular-related APIs ones.

However, that approach implies yet another library to look for compatibilities when upgrading. Like: version X is compatible with Angular version Y. See https://github.com/FortAwesome/angular-fontawesome?tab=readme-ov-file#compatibility-table

Another thing to take into account is that maintaining support for many versions means more CI/CD minutes as for each major version we create an example app and run E2E tests against it to ensure everything goes fine.

We can take a look at several popular Angular libraries and see how they do it. So at least is not strange for developers:

  • Font Awesome: compatibility table.
  • NgRx: Angular versioning
  • Angular Material: Angular versioning
  • Angular ESLint: Angular versioning
  • PrimeNg: Angular versioning. However it goes one behind. Now the latest one is 18.2.8 but they're in 17.x still. Maybe due to that recommendation? As last release is quite recent.
  • NgBootstrap: Same as above
  • Angular Fire: Angular versioning
  • Ngxtension: regular semver, no compatibility table. Recent library done by Angular pros. Seems they are going same way as tried here 🤔
  • Angular three. Also baked by an Angular pro. Same as Ngxtension. However, it does view things. Hmmm.
  • CKEditor: compatibility table.
  • @sentry/angular: compatibility table.

It's quite normal that UI-related ones like Material, PrimeNg, NgBootstrap do the Angular versioning as many updates may happen in the view side of things. Regarding the linter, same but also taking into account way of doing things may switch in a major version hence the need to release along the major version release.

The ones going free as we tried here are quite new. Angular three 1.0.0 version is from Jan 2023. Ngxtension 1.0.0 is from Nov 2023. Though breaking changes releases are done properly

Here's a comparison table to recap

Aspect Angular-independent version Angular aligned version
Support Angular actively supported versions (last 3 majors)
Support Angular versions older than v15
Release schedule Only major changes when breaking changes Aligned with Angular. Major every 6 months rn
Needs compatibility table Yes 1 No
CI/CD Example apps to create 3+ 3
npm distribution tags 1: latest Ideal: n: 1 per major release. Like Angular's v{n}-lts. Can be just one too
Stability sentiment to consumers2 More stable than Angular's Aligned w/ Angular

However, maintaining a major version can imply many things:

  • A new branch for that version v{major}.x

Footnotes

  1. When a new major is released that drops support for older versions, it will be needed to know which versions are compatible with which ones.

  2. If we just do a major release every 1 year for instance, users will just experience breaking changes once per year. Breaking changes may be just dropping support for older Angular versions though (no code changes required if users update their Angular version frequently). Hence greater development experience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant