Lazy load a in-repo-addon

Hi all! I work in a big Ember app. My team manages an engine and now we’re looking forward to extend some of the functionalities beyond this engine (reuse them in other engines). I know that the solution for this is creating a in-repo-addon, move the shared code there and then import it in every engine where we want to use (by adding it to the destination engine’s package.json).

But… In some of the engines we would like to have that code downloaded on-demand. I mean, downloading that in-repo-addon only if it’s requested (let’s say: if the user clicks in one button). I know this is easily achievable with a full engine (by setting it to lazyLoading: true) but don’t know if it’s possible with an in-repo-addon.

Thanks in advance!

Hi abelespana! I’ve got a few thoughts for you but this might be a little more than you bargained for :sweat_smile:. A lot of this is centered around Embroider, Ember’s next-gen build system, and if you’re not familiar with that yet definitely check it out (some of the EmberConf talks about it from the last 2 years are really helpful). Part of what makes this so complicated to answer is that we’re in the middle of a big migration as an ecosystem so there’s some nuance to the answers and the different paths you can take.

in repo addons

First, I’d recommend not investing in in-repo addons (engines or “regular”). In short because they were sort of a weird Ember construct and while they worked well for a while (our team used them very successfully until recently) they probably(?) won’t work into the future. At least I’m not aware of any efforts to support them in Embroider etc. My recommendation would be using a monorepo with a good package manager (pnpm specifically). This allows you to use as many apps and addons as you want in the same repo but treat them as “real” packages.

Our team just migrated to a pnpm monorepo. We used to have an app with 5 (lazy) in-repo engines and 2 in-repo addons, then we split one addon out as a separate “real” addon, developed a 6th engine as a standalone “real” engine, then migrated the app to a monorepo, pulled the engine and addon back in, and then migrated the in-repo engines to “real” addon packages that just participate in the monorepo like the others.

This has been smoother for us with dependency management and it’s going to be more forwards compatible with Embroider and v2 addons (at least I assume, i doubt in-repo addons will be carried forward). The major downside is that tracking test coverage becomes more difficult as you have to break out your tests and test coverage instrumentation becomes more granular. CI/CD config also becomes slightly more complicated.

Lazy loaded dependencies

So in Embroider/v2 addon world this will be a first class feature as you’ll get route-based code splitting and lazy loaded dependencies. And indeed it already is with ember-auto-import. That said to leverage this feature of auto-import for an Ember Addon I think you’d need your addon to be “v2” ready and as far as i know there’s no way to lazy load v1 addon dependencies.

Conclusion

I’m not super confident in my understanding here but a TLDR would be:

  • you probably don’t want to start using in-repo addons now, I don’t think they have a long-term future I think at best there will be support long enough for people to move off them (not 100% on this though)
  • you probably want to invest time/effort into a decent monorepo setup for a number of reasons and so this seems like a good time to start even though it’s a bigger lift
  • you can probably lazy load an addon (or even a small part of one) in the way that you want pre-embroider by using ember-auto-import but to do that you probably need a v2 addon (though you may want a second opinion on that).

I’d ask here or in Discord about the specifics of any of that or for second opinions from someone on the core team.

I’d also be happy to elaborate on our experience with pnpm/monorepo config if you’d like.