[no longer an issue] Strange behaviour in Safari (OSX and iOS)

Just wondering if anyone else has experienced any issues with Safari (either OSX or iOS) since 1.3?

My app has been working perfectly in 1.3, up until today really.

It looks like it is hanging, waiting on a subscription. I get stuck at the loading screen, strange thing is sometimes it will get through that and display the page. Sometimes it happens straight away sometimes after a long wait. 90% of the time it just sits on the loading screen doesn’t progress at all.

I am using React and have the standard pattern with getMeteorData returning !collection.ready() to move past the loading screen.

In chrome under the exact same circumstances it works fine without delay or issue… so strange!
There are no errors in the console, either chrome and safari, and the collection data is all there when interrogated via console… so not sure why it thinks it’s still loading.

Here is the other thing. I am not able to replicate this on my local dev machine, only on the deployed server. On my dev machine everything works fine with Safari.


Happy to share code or whatever, but kind of more interested to see if anyone has seen this before.
Also, if anyone has any code I could throw on the server to do some debugging on the deployed server…

Something similar. Just started looking at the OSX iOS version of my app ( 1.3, react, using the Guides createContainer recommendation.

It runs fine on FF, IE and Chrome, but incredibly slow on Safari. Still investigating, but the first thing I noticed is that Safari does a lot of rerenders compared to the others with subscriptions:

I have multiple subscriptions in the container object like

workers: Meteor.users.find({'profile.function':'worker'},{sort: {'profile.firstname': 1}}).fetch()

I disabled all loading screens, and dumped the page immediately( and put a console.log in the component. Firefox rerenders 1 times, Chrome 3, Safari 40 (!) times. If I disable one or more of the subscriptions, it drops to 3.

1 Like

Some progress. ( although I’m not sure it’s related to your problem. I’ll post it anyway for others, because the react createContainer method is quit new for most ( certainly for me).

My createContainer used to be something like

const Report = createContainer(() => {
  let reportId = FlowRouter.getParam('reportId')
  let handle = Meteor.subscribe("reports", reportId )
  Meteor.subscribe("users.workers")

  return {
    dataLoading: !handle.ready(),
    report: ReportsCollection.findOne({_id:reportId}),
    workers: Meteor.users.find().fetch(),
  }
}, container)

I only looked at the main subscripton’s handle, for displaying a dataLoading component. All other elements ( the workers) would load quitly.

This works fine in FireFox and Chrome,… but triggers a lot of rerenders on Safari ( iOs, OSX). So I tried putting a handle on all subscriptions, and return an empty object or array if not ready. Now, my rerenders in Safari dropped from 50 to 3, and the speed increase is incredible:

const Report = createContainer(() => {
  let reportId = FlowRouter.getParam('reportId')
  let report = Meteor.subscribe("reports", reportId )
  let workers = Meteor.subscribe("users.workers")

  return {
    dataLoading: !report.ready(),
    report: report.ready() ? ReportsCollection.findOne({_id:reportId}) : {},
    workers: workers.ready() ? Meteor.users.find().fetch() : [],
  }
}, container)

It took me a while to find what was causing the delay in Safari. By putting a console.log(‘render’) in one of my components, I noticed it got logged alot. Whatever I did, it kept logging 40-50 times, even on an empty component. Until I disabled the subscriptions themselves.

Probably each rerender in Safari is triggered as a chunk of data arrives from the server. Other browsers seem to be optimised for this.

eleventy

1 Like

I did the same thing and it works fine in Safari now - however not iOS… (not working in either still)
Where do we even report this as an issue?
Do you think this is a browser quirk or an issue with the getMeteorData process?

@sashko any ideas?

I’ve done my own tests and yeah I can’t seem to get the subscription to ready up in Safari…

Very weird!!!

I thought perhaps Subs Manager might have had something to do with it - but after converting my subscription calls back to the vanilla way, the problem still persisted. There was one less attempt at running the render function in react. However the subscription still never readied up, only in Safari (OSX and iOS)…

Chrome console:

Safari console:

Code:

render() {

    console.log('## Rendering ##', this.data.subsLoading);

    if (this.data.subsLoading) {
      return(
        <Loading />
      )
    }else{
    ... actual page here

This is back with subs manager, two attempts to render while not-ready:

Chrome:

Safari:

After a solid 10 minutes of loading screen and it worked itself out eventually…

The subscription it was waiting on is the Stocks subscription.
You can see that all the data is present, and it attempts to re-render a bunch of times.

I can only describe what works for me( I’m also still getting my head wrap around the whole new 1.3 concept).

  • I don’t use subsmanager at the moment
  • I converted getMeteorData to the createContainer method described in the guide( the container object wraps your Component, and injects your subscriptions as reactive props).
  • Until the main subscription becomes ready, I show a dataloading element. As soon as the main sub is ready, I display the page( the report-sub in the example above).
  • Other (helper)subscriptions may or may not be ready at that point ( in the example above, the workers-sub to fill something like a dropdown on a form).
  • Each time a chunk of data arrives on the workers-sub, it triggers a rerender. If the sub is relatively large, this means a lot of rerenders.
  • I changed the helper-subs to return an empty array until that subscription was ready( example above). This way, I only get one extra rerender per helper-sub. My rerenders dropped from 40 to 3 or 4 in safari.
  • you could wait for all helper-subs to get ready, before releasing them onto the component, but 3 or 4 at the moment is quite ok for me.

The above example with the wrapped component:

class container extends Component {
  constructor(props) {
    super(props)
    this.state = {
    }
  render() {
    props = {
      report: this.props.report,
      workers: this.props.workers,
    }
    return (
      <div>
          {this.props.dataLoading
            ? <DataLoading />
            : <ReportForm {...props}/>
          }
        </div>
      )
    }
  }

container.propTypes = {
  report: PropTypes.object,
  workers: PropTypes.array,
  dataLoading: PropTypes.bool
}

const Report = createContainer(() => {
  let reportId = FlowRouter.getParam('reportId')
  let report = Meteor.subscribe("reports", reportId )
  let workers = Meteor.subscribe("users.workers")

  return {
    dataLoading: !report.ready(),
    report: report.ready() ? ReportsCollection.findOne({_id:reportId}) : {},
    workers: workers.ready() ? Meteor.users.find().fetch() : [],
  }
}, container)

1 Like

Thanks for running me through what you’ve done - so has it been fixed for your app?

I am not keen on doing a whole re-write at the moment.
Just want to understand what is going wrong.

Just wondering if anyone else has seen something similar with their deployed apps?

I am finding that this is not only an issue with subscriptions, but also with web-sockets in general.
Safari won’t respond to Meteor.call() either once it gets caught up with the subscription.
However this could just be because the subscription call breaks something on the client in Safari because if I do a refresh on a page without that bigger subscription call there are no issues with the app hanging.

No errors anywhere in the console on client or server.

Just a final update, this issue seems to have resolved itself with the 1.3.1
Without knowing exactly what was wrong, I can’t be sure if it was the update that fixed things.