Meteor + Webpack: ES6 modules, hot-code-patching, fixes load order & more

In an normal app that gets it data via AJAX than the answer should be yes as there is nowhere else to put it. However Meteor has it’s own cache (minimongo) so we could use that instead. We’ll just have data in two places… Redux state tree for local non persistent data, and minimongo for persistent data. This is the same with Relay/GraphQL, you still use Redux for local state and Relay handles the db data.

On the other hand, data (such as meteor collections) changes over time (data is created, updated, deleted), and by saving the data directly into the state, it is no longer possible to determine the UI. Shouldn’t instead store the queries that retrieve the data, instead of the actual data?

So if you sync the minimongo cache (that’s all it really is) with your Redux cache, then you’ll have an exact copy of both at any given point in time. The flux helper I use will detect a change, ask for all the data in the collection and replace it with the new data.

However, this isn’t as memory efficient, though most apps won’t be a problem. The other con is that this is more complicated that slapping the meteor mixin in the component.

It is then the job of the components (or the routes) to use this information to retrieve the actual data.

That’s possible but I think it would be easier to just call the database in the component. Also IMHO making the view responsible for any data handling is making it less maintainable.

I believe time travel would still work, though it wouldn’t change the DB data, just the cache.

OK I see what you are saying. I was thinking more in the way of taking a snapshot of the state and (theoretically) replicating the UI in multiple clients. Or serializing the state in localstorage for showing the exact same UI when the user closes and reopens the app.

For instance, here it could be something like:

this.state = {
  players: function() {
     // Return a finder, in this case:
     Player.findLeaders();
  },
  selectedId: '',
  selectedPlayerName: ''
};

Storing functions may not be the solution, but what I’m trying to say is that storing the actual data isn’t needed, you just need to store what data should be retrieved. This also avoids having the data in two places. A better implementation of the above might be:

this.state = {
  players: 'SHOW_ALL_ORDERED_BY_SCORE',
  selectedId: '',
  selectedPlayerName: ''
};

And use the value of state.players to call the right finder to retrieve the data.

That’s exactly what I’m thinking, how to reflect undo/redo actions on DB data.

1 Like

did you all guys tried to user meteor run ios-devices on app code base?

I haven’t tried yet but it should work. I’m using React Native so i haven’t had the chance.

@SkinnyGeek1010 you are right that it is more appropriate to store the data into the Redux store. In this way, on data change react-reduxconnect handles updating the component.

What I’m doing: each (smart) component specifies its required subscriptions, a HOC handles starting/stopping the subscriptions on mounting/unmounting, and data is synced on the redux store using meteor-immutable-observer.

Some issues with component-based subscriptions:

  • Unnecessary start/stop subscriptions. For example, two sibling routes require the same publication A. When switching routes, A will stop and start again.
  • A parent and child component require the same publication B. In order to avoid duplicate subscriptions, the B requirement is specified only on the parent. This creates a tight coupling between components, which hurts reusability and maintainability.

I think handling subscriptions should live at a higher level than inside the components. The components declare only the needed data, and a higher-level mediator translates these requirements into publication methods. Which I think is this declarative approach that GraphQL provides, among other things, but I’m not sure how GraphQL would fit with the ad-hoc nature of Meteor pubSub system.

Hi everyone, since some of you may know I’m working on “official” support for ES2015 and CommonJS modules in Meteor 1.3, I just wanted to say I’ve been following this thread carefully, and I really appreciate all the work that’s going on here, especially because it helps me understand what features of Meteor you’d be willing to do without in order to reap the benefits of Webpack.

Since it’s only natural to wonder why Meteor 1.3 wouldn’t just use Webpack, I wrote up a longer discussion on that topic over here.

7 Likes

@SkinnyGeek1010 watched the video and the looked through this boilerplate. Wow. I really want to transition my Meteor app to this project setup-- NPM is treated as a first-class citizen, and I still retain the Meteor packages I have been using. As my app has grown, I’ve hit initial page performance walls due to Meteor’s build process, making this approach very appealing. It’s particularly interesting when compared to kickstart-simple, in that your approach feels like a conventional node application.

However, I’m pretty new to webpack and react. How future-proof do you see this skeleton being, as meteor, webpack, and react evolve?

1 Like

@peterm I think it’s pretty future proof, as long as webpack stays maintained. If you really boil it down, you’re creating a normal JS project that assumes some globals will be available at runtime (Meteor, package vars, etc.). This is also why I love it!

This means that at any time if you need to swap out Meteor for a different Node based framework you can do so really easily. If you would switch to a non-node app then you could ditch the serverside code which would clean up the configs as well.

It’s really improved my Meteor experience and honestly it has kept me from ditching Meteor. Now I can build a JavaScript app and use Meteor’s core features where it makes sense. I also tend to not use very many atmosphere packages at all because there are so many good (better) ones in NPM.

Also, i’ve found that if you really want to understand Webpack the only way is to find a tutorial that starts out with a 5 line config, and slowly builds up the features you need (loaders, dev/prod configs, dev-server, etc…). At it’s core webpack is simple but covering every edge case makes it bloat into an unwieldy config :smiley:

5 Likes

To anyone new to Webpack, I watched this and found it to be a fantastic primer.

From 1.3 modules Release Notes:

If you would like a module to be evaluated lazily (in other words: on demand, the first time you import it, just like Node does it), then you should put that module in an imports/ directory (anywhere in your app, not just the root directory), and include that directory when you import the module: import {stuff} from “./imports/lazy”. Note: files contained by node_modules/ directories will also be evaluated lazily (more on that below).

Lazy evaluation will very likely become the default behavior in a future version of Meteor, but if you want to embrace it as fully as possible in the meantime, we recommend putting all your modules inside either client/imports/ or server/imports/ directories, with just a single entry point for each architecture: client/main.js and server/main.js. The main.js files will be evaluated eagerly, giving your application a chance to import modules from the imports/ directories.

If I started using 1.3 today, do I really need webpack? Sure there would be no HMR, but lazy loading is what I needed to improve my application’s performance.

1 Like

The main benefit to webpack vs 1.3 is hot code reloading and code splitting for large projects.

Lazy loading is done at compile time so you wouldn’t get any performance benifit there, perhaps you’re referring to code splitting? Which is the feature that lets you send down chunks of JS to the client as they’re needed.

Lazy loading just means that the script won’t get executed until it’s required, which solves the load order problem.

1 Like

I don´t see any benefit from 1.3 vs webpack https://github.com/jedwards1211/meteor-webpack-react. What you thinks of this?

Thanks for clarifying that distinction. For some reason, lazy loading in my mind implied code splitting, although as we see that’s not the case.

+1 for webpack.

1 Like

1.3 is probably more newbie friendly than webpack.
Best of both worlds would have been for MDG to implement Meteor Legacy Build System on top of Webpack, to make it zero configuration / zero frightening messages for newbies.
But that’s not the road they choose since they reinvented the wheel again.
I wonder if in the end, they won’t have to do it anyway with webpack, with another uncompatible upgrade once again.

2 Likes

I think the Webpack integration would benefit from the new Meteor 1.3 feature of being able to import symbols exported by Meteor packages such as import { Match, check } from 'check';.

I opened an issue about that 2 months ago but it was closed by @benoitt. Should we re-consider it now that we have an actual implementation of imports/exports with Meteor packages?

1 Like

For those using a lot of Meteor package, it is quite unconvinient to write every externals. I’ll re-open your issue and take a look at that.

I’m trying to figure how add local npm packages like we did on ‘packages’ folder.
Any advice ??

Until Meteor 1.3 you will need to use a webpack.package.json like this.

@vjau will you talk more about what MDG has done in this space to help me understand?

Done :slight_smile: You can update to webpack 0.4.0.

When a package export something like: ReactRouterSSR, it will be available through:

import ReactRouterSSR from 'ReactRouterSSR';
// or
import ReactRouterSSR from 'react-router-ssr';
3 Likes

Love it, great work!