vazco / universe-modules

Use ES6 / ES2015 modules in Meteor with SystemJS
https://atmospherejs.com/universe/modules
MIT License
52 stars 7 forks source link

Issues in Safari? #27

Closed olivermack closed 9 years ago

olivermack commented 9 years ago

Just came across this. Checked out the demo app at http://universe-modules-demo.meteor.com/ and it seems to work fine in Chrome (45.0.2454.93) but not in Safari (7.1.8 (9537.85.17.9.1)).

Safari complains about There is no route for the path: /

I had this issue while playing around locally with a fresh app and thought I did something wrong, but obviously there is an issue. Maybe it's not directly related to the loader but rather to the router, I don't know, but actually it is also broken in your demo.

Cheers

MacRusher commented 9 years ago

Thanks for reporting. It's probably related to this issue: https://github.com/kadirahq/flow-router/issues/310 and it's more about FlowRouter itself then our modules, but of course we need to make sure that our modules play nicely with all routers :)

My guess is that because modules are executed asynchronously, there is small chance that FlowRouter.route('/', {...}) will be called too late. It's classic race condition, FlowRouter performs navigation before the route was registered, causing this error. For unknown for me reason, this happens much more often on Safari then on other browsers.

There are IMHO two ways to solve this.

First, you can make use of FlowRouter.wait() and then call FlowRouter.initialize() on the end of loaded module, once you register your routes.

// main.js //
FlowRouter.wait();
System.import('router');

// router.import.js //
FlowRouter.route('/', {
  action() {
    //code
  }
});
FlowRouter.initialize();

Second option is to move routes out from modules back to "main thread" and load modules inside action handler.

E.g. instead of

// main.js //
System.import('router');

// router.import.js //
FlowRouter.route('/', {
  action() {
    //code
  }
});

you can make:

// router.js - its a normal .js file //
FlowRouter.route('/', {
  action() {
    System.import('myModule').then(myModule => {
      //code
    })
  }
});

The latter is more boilerplate, but has one advantage. We will release lazy loading of modules soon, and using the second syntax will allow you to not load all modules at startup, but instead fetch them when user navigates to particular routes (e.g. admin panel).

Let me know if one of these solves your issue.

olivermack commented 9 years ago

Hi @MacRusher, thanks for the blazing fast feedback - amazing! :)

Indeed, the first suggested approach solved the issue and works fine. I'll give the second one also a try as soon as I find some time.

Cheers & thanks again!