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

Add template helper for loading a bundle. #56

Open
rwjblue opened this issue Aug 11, 2017 · 18 comments

Comments

Projects
None yet
7 participants
@rwjblue
Copy link
Member

commented Aug 11, 2017

A template helper like this would allow folks to use lazy routeless engines with a nice(ish) syntax:

{{mount (load-engine 'engine-name-here')}}

Example implementation (thanks to @mike183):

import Ember from 'ember';

const { Helper, inject, getOwner } = Ember;

export default Helper.extend({

  assetLoader: inject.service("asset-loader"),

  compute: function([ engineName ]) {
    // Return engineName if engine is loaded
    if (this._engineName !== undefined && this._engineName === engineName) { 
      this._engineName = engineName; 
      return this._engineName;
    }

    // need to expose the ability to introspect a bundle's state (loaded, unloaded, etc)
    if (this.get('assetLoader').isLoaded(engineName)) {
      this._engineName = engineName;
      return this._engineName;
    }

    // Load unloaded engine
    this.get("assetLoader").loadBundle(engineName).then(() => {
      // Update this._engineName
      this._engineName = engineName;

      // Trigger recompution of helper
      this.recompute();
    });

    // Returning null ensures nothing is rendered
    return null;
  }
});
@rwjblue

This comment has been minimized.

Copy link
Member Author

commented Aug 11, 2017

@mike183

This comment has been minimized.

Copy link
Contributor

commented Aug 13, 2017

I had always figured that this helper would live in the ember-engines repo itself, and ember-asset-loader would simply provide some helper methods (i.e. isLoaded()) in order to simplify its implementation.

I can't imagine the helper being very useful outside of ember-engines, though maybe someone else can think of a use case in which it would be?

@rwjblue

This comment has been minimized.

Copy link
Member Author

commented Aug 13, 2017

I think my thought was that this addon and its main service is what is responsible for loading bundles, so it is the thing that should provide the helper. Though it's helper should likely be load-asset-bundle or something, because it's not 100% engine focused...

Am I on the wrong track?

@mike183

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2017

Wouldn't the helper also need to actually register the engine after it had finished downloading the bundle?

@rwjblue

This comment has been minimized.

Copy link
Member Author

commented Aug 14, 2017

Hmm. What do you mean? Loading the bundle would mean that the modules that the {{mount keyword looks for would be present, right?

Note: I haven't ran the code I pasted above in the description. So perhaps I'm missing something obvious...

@mike183

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2017

Its entirely possible that I am actually missing something obvious, but I would have thought that the helper would need to register the engine with the application after successfully downloading its bundle.

So essentially, the call to loadBundle() would look something like:

// Load un-registered engine
this.get("assetLoader").loadBundle(engineName).then(() => {
  // Get engine
  const engine = window.require(`${engineName}/engine`).default;
  // Register engine with application
  owner.register(`engine:${engineName}`, engine);
  // Update this._engineName
  this._engineName = engineName;
  // Trigger recompution of helper
  this.recompute();
});
@rwjblue

This comment has been minimized.

Copy link
Member Author

commented Aug 14, 2017

Ya, I just think that manual registration shouldn't be needed. Once the bundle is loaded, the engine-name/engine module will be present in the module registry so that when the owner.lookup('engine:engine-name-here') happens, this code in the resolver would return the proper value.

@mike183

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2017

Ah I see, if thats the case and it works then keeping the helper in the asset-loader repo sounds good to me.

@trentmwillis

This comment has been minimized.

Copy link
Member

commented Aug 15, 2017

Overall, this seems like a reasonable addition to this addon.

Though it's helper should likely be load-asset-bundle or something, because it's not 100% engine focused...

Agreed. Either load-bundle or load-asset-bundle seems good for consistency with the terminology used elsewhere by this addon.

Once the bundle is loaded, the engine-name/engine module will be present in the module registry so that when the owner.lookup('engine:engine-name-here') happens, this code in the resolver would return the proper value.

This is correct, and essentially what we do for routable engines.

@scalvert

This comment has been minimized.

Copy link

commented Aug 17, 2017

Yep, this sounds good.

@buschtoens

This comment has been minimized.

Copy link

commented Jun 17, 2018

The most recent Ember.js times newsletter had a reference to this, that reminded me about this addon I once wrote: ember-lazy-mount

I guess this is not really relevant, since it uses a component instead of a template helper, but maybe you still find it useful. ✌️

@GCheung55

This comment has been minimized.

Copy link

commented Oct 24, 2018

@buschtoens your addon covers an important usecase - loading state. Probably should also cover error state?

How would that be handled in the load-bundle or load-asset-bundle helper?

@buschtoens

This comment has been minimized.

Copy link

commented Oct 24, 2018

Glad that you like it :)

In fact it does cover error states as well. I've updated the docs to reflect that.

{{#lazy-mount engineName model=optionalDataForTheEngine as |engine|}}
  {{#if engine.isLoading}}
    🕑 The engine is loading...
  {{else if engine.error}}
    😨 There was an error loading the engine:
    <code>{{engine.error}}</code>
  {{/if}}
{{/lazy-mount}}
@villander

This comment has been minimized.

Copy link
Member

commented Dec 28, 2018

@rwjblue @dgeb @stefanpenner what you think about make ember-lazy-mount as our solution to lazy loading route-less engines?

makes sense when looking at engines RFC

@buschtoens

This comment has been minimized.

Copy link

commented Dec 28, 2018

I know this might come up, so I'll address it right away: I have no problem with stripping out ember-concurrency(-decorators) and ember-decorators to reduce the bundle size for consumers that don't use these addons.

@villander

This comment has been minimized.

Copy link
Member

commented Dec 28, 2018

yup @buschtoens and as asset-loader was written in ES6, we would have to remove the typescript as well.

@buschtoens

This comment has been minimized.

Copy link

commented Jan 10, 2019

I've defactored ember-lazy-mount in buschtoens/ember-lazy-mount#4 to not use any dependencies except babel and htmlbars in order to decrease bundle size and also reverted back to the Ember Object Model, to make it possible to merge this code into ember-asset-loader and / or ember-engines.

@villander

This comment has been minimized.

Copy link
Member

commented Jun 18, 2019

Now that we know that Lazy Loading on ember-engines will work more friendly replacing ember-asset-loader with embroider. I think that we can make ember-asset-loader complete, following the RFC and Roadmap 1.0 and add ember-lay-mount solution here.

what you think guys?

cc: @rwjblue @dgeb @stefanpenner

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.