Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Allow Modal to be used with async-loaded components #618

Merged
merged 1 commit into from
Jan 19, 2017

Conversation

richvdh
Copy link
Member

@richvdh richvdh commented Jan 16, 2017

Here's a vaguely interesting hack: with very few lines of code, it's possible to delay loading of bits of riot-web until they are actually needed. Here is a demonstration of how we might do it for modal dialogs (which seem to be obvious candidates for factoring out in this way).

However, this will break existing users when we deploy a new version (they might be looking for 1.6bfef606b3e11954030e.js, but the new file could be called 1.af6f5457910a37776515.js, so they'll get a 404). The only plausible way to make this work would be to keep old versions of the submodules available.

... so this PR isn't ready to land until we solve that problem.

Add Modal.createDialogAsync, which can be used to display asynchronously-loaded
React components. Also make EncryptedEventDialog use it as a handy
demonstration.
@richvdh
Copy link
Member Author

richvdh commented Jan 16, 2017

(relates to element-hq/element-web#2498)

@richvdh
Copy link
Member Author

richvdh commented Jan 16, 2017

element-hq/element-web#2961 is a step on the way to solving that.

@richvdh
Copy link
Member Author

richvdh commented Jan 17, 2017

element-hq/element-web#2969 was another part of the puzzle. We still need a new script for updating riot.im/app, but that seems to work in principle. Which means this PR is viable after all.


componentWillMount: function() {
this._unmounted = false;
this.props.loader((e) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for callbacks rather than promises here, ooi?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just that require (or require.ensure, for that matter) takes a callback, rather than returning a promise. We can't easily wrap require with something that returns a promise, because that breaks webpack's static analysis. So if loader was expected to be a Promise, we would have to add some nasty boilerplate everywhere we loaded a component asynchronously.

IOW: currently we can do:

createDialogAsync((cb) => {require(['foo'], cb)});

If instead we had to pass a promise, this would become:

d = q.defer(); 
require(['foo'], (m) => {d.resolve(m)});
createDialogAsync(d.promise);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, if it makes it simpler then callbacks ftw.

var event = this.props.mxEvent;

Modal.createDialog(EncryptedEventDialog, {
Modal.createDialogAsync((cb) => {
require(['../../../async-components/views/dialogs/EncryptedEventDialog'], cb)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether it would be better to use the CommonJS require.ensure here, as we've used CommonJS elsewhere, rather than introducing AMD syntax (https://webpack.github.io/docs/code-splitting.html) (also require.ensure seems to me a little more obvious what it might be doing, rather than calling require with an array and a callback versus a string).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed, though where have we used commonjs elsewhere? (And it's the callback that makes the difference between the two types of require, rather than the arrayness, but yes)

will make it so

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, except that conflicts with my previous point: using the CommonJS syntax would be considerably more verbose, as there is no longer a simple way to pass the component into createDialogAsync.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we use straight 'require' which is CommonJS, although of course now we're moving to ES6 import syntax, but webpack doesn't support this for async loading. And yeah, it does seem to make it quite a chunk more verbose.

@dbkr dbkr assigned richvdh and unassigned dbkr Jan 18, 2017
@richvdh richvdh merged commit ba2460a into develop Jan 19, 2017
@richvdh richvdh deleted the rav/async_dialog branch January 23, 2017 10:31
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants