Creating a route/page that loads, then disconnects the user?

I’m working on an embeddable audio player for ReelCrafter. ReelCrafter subscribers will be able to embed one or more of these players on their websites, and people can listen to their music/sounds/etc.

This could potentially be thousands of concurrent users, so I’m trying to minimize the server load as much as possible. I had an idea to just load up the data, and then immediately disconnect DDP. I have the following:

import { Meteor } from 'meteor/meteor';
import { createContainer } from 'meteor/react-meteor-data';

import EmbedPage from './EmbedPage';
import { Reel } from '/imports/collections/reels';

export default createContainer(({ embedId }) => {
  const handle = Meteor.subscribe('embedReel', embedId);
  const reel = Reel.findOne({ embedId }, { reactive: false });

  if (reel) Meteor.disconnect();

  return {
    dataReady: handle.ready(),
    reel,
  }
}, EmbedPage);

Does this make sense? Is there another/better way?

It is not the connection that matters in the end (although marginally it does) but what the connection is used for.

In your case, it is a subscription which is evidentally the toughest load on a meteor server.

Why don’t you use a method call to fetch your data? Or perhaps even create a rest (or graphql) endpoint and call that to completely eliminate websockets?

1 Like

Create a server-side route (meteorhacks:picker) or whatever.
Use ReactDOM.renderToString() to render the template.

Problem solved.

1 Like

I would assume that the embeddable widget be distributed as a static asset, not a served page, though.

I also kind of assumed he would be switching out Meteor client for something like Asteroid (if he prefered methods/subscriptions) so that it is completely redistributable.

1 Like

Thanks! You guys have given me some ideas to think about.

Nice! I’m not quite sure what that would even look like. Something like this?

const getRoutes = Picker.filter((req) => {
  return req.method === 'GET';
});

getRoutes.route('/embed', function (params, req, res) {
  const component = ReactDOMServer.renderToString(<AudioPlayer embedId={params.id} theme="dark" />);

  res.write(component);
  res.statusCode = 200;
  res.end();
});

AudioPlayer is built for the client, and there’s a Meteor container in there too. Is there anything I’d have to change about its code or child components?

So, that was cool. The markup gets rendered out, but this audio player is interactive obviously, so I’m not sure how to get the JS code out to the client via server-side rendering. Is this trivial to do? Otherwise I might go with @serkandurusoy’s idea to use a Meteor method to fetch data rather than pub/sub.

@serkandurusoy Converting pub/sub to method worked out great, thanks! I’m still using Meteor.disconnect() so that code updates don’t force all the embeddable players to reload.

1 Like