-
-
Notifications
You must be signed in to change notification settings - Fork 832
Allow Modal to be used with async-loaded components #618
Conversation
Add Modal.createDialogAsync, which can be used to display asynchronously-loaded React components. Also make EncryptedEventDialog use it as a handy demonstration.
702e1b1
to
ac22803
Compare
(relates to element-hq/element-web#2498) |
element-hq/element-web#2961 is a step on the way to solving that. |
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) => { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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);
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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.
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 called1.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.