Leverage the power of Meteor with any client-side framework

Introduction to Meteor-Client-Bundler

Urigo
Meteor Blog

--

Meteor Javascript Client bundle can run on any frontend app

Meteor was first released back in 2011, and since then it’s been one of the most powerful platforms for web developers. It brought many new concepts to the table — one of the more powerful ones is where the client, server and the database can share code, almost the same API and code snippets, which really accelerated the development process.

This has been a very big advantage that’s proven itself to be worthy, but has also created a misconception that Meteor is a monolith that can’t be broken down to smaller parts. But in fact, when you build a Meteor app for deployment to Galaxy or any other hosting platform, Meteor essentially generates a stand-alone Node application that you can run anywhere Node is installed. This built application can be easily consumed by a wide variety other tools that work with Node and Javascript apps.

In this post, I will show how you can use your existing React, Angular, or WebPack front-end app (or break up your existing Meteor front-end app away from the Meteor CLI) while still using Meteor’s benefits like Meteor Collections, Minimongo, real time updates and DDP, accounts packages and more…

Introducing Meteor Client Bundler

Two example scenarios could be: a) We want to use React Native’s CLI to build our client, since it provides us with native mobile components, and a configurable bundler; or b) We want to use WebPack and the great create-react-app.

Because we’re using Meteor, you might think we’re obligated to use the Meteor CLI, leaving WebPack’s great tools impractical to use. We can therefore ask the following question: “Is there a way to use WebPack, or any other similar tool, to create our client, and Meteor as our backend?” Well folks, the answer is — YES!

I present you — Meteor Client Bundler (it’s a long name, so we’re gonna refer it as MCB).

MCB, as we can infer, is a module-bundler which will take a bunch of Meteor packages and bundle them into a single script, based on a specified configuration. This means we can load Meteor’s core client-script, along with other desired packages, like mys:accounts-phone, jalik:ufs, matb33:collection-hooks etc into any front-end app!

This will give us the ability to create two separate projects: one is made with WebPack CLI (the client) and other is made with Meteor’s CLI (the server). Furthermore, with a little help from bundling tools like Webpack, we can even achieve the effect of shared code snippets between the two apps, which will be shown further in this article.

Some of the advantages of such a strategy are:

  • Applications which are not based on Meteor can use the DDP client to fetch data from a Meteor-service
  • We can gradually migrate outdated front-end applications into Meteor
  • We can use other CLI tools besides Meteor’s like WebPack, Angular and Ionic CLIs and more and not be locked in on a single CLI
  • Use Meteor when and where it excels and where it fits your needs

I believe that through practical example you can get the hang of it and understand exactly what I’m talking about, by simply fulfilling the scenario described in the second paragraph.

How it works

Let’s dive in! We will begin with creating our client using create-react-app, by running the following command:

$ create-react-app my-frontend-app

Then, we will create a web API service using Meteor’s CLI by typing the following command:

$ meteor create api

Now that they are both created, Let’s connect them to each other, so the React client will know how to use Meteor collections and retrieve data from them using MCB.

First, you’ll need to install MCB globally using NPM using the following command:

$ npm install -g meteor-client-bundler

This will make MCB available globally as a CLI under the name meteor-client:

$ meteor-client — help

Thanks to MCB, we can create a Meteor client with all the necessary dependencies in it using the bundle command. The bundle command takes a configuration file and can be operated differently. The easiest and fastest solution would be providing it the path where the Meteor server is at, using the -s, — source <dirpath> option:

$ meteor-client bundle — source=api

This will create a new file called meteor-client.js under the directory node_modules, which can easily be loaded anywhere in the project like so:

import “meteor-client”;

If you want, you can change the output destination by providing a -d, — destination <filepath> option:

$ meteor-client bundle — destination=dist/meteor-client.bundle.js

Moreover, you don’t necessarily have to have the client and server on the same machine. The server can be hosted on a completely different computer, yet we can generate its appropriate client. This can be achieved by providing the -c, — config <configpath> option:

$ meteor-client bundle — config=meteor-client.config.json

Here’s an example config:

{
“runtime”: {
“DDP_DEFAULT_CONNECTION_URL”: “http://127.0.0.1:8100
},
“import”: [
“meteor-base@1.0.4”,
“mongo@1.1.14”,
“reactive-var@1.0.11”,
“jquery@1.11.10”,
“tracker@1.1.1”,
“standard-minifier-css@1.3.2”,
“standard-minifier-js@1.2.1”,
“es5-shim@4.6.15”,
“ecmascript@0.6.1”,
“shell-server@0.2.1”
]
}

Each field in the configuration file represents the following:

  • runtime — Meteor’s runtime config. Most commonly used to set the URL of the Meteor server we would like to interface with.
  • import — A list of packages we would like to include in our bundle. The bundle will also take care of loading them in the right order and with the required dependencies

You can also specify the server’s URL explicitly using the — url <urlpath> option:

$ meteor-client bundle — url=http://127.0.0.1:8100

How MCB works under the hood

Basically, MCB takes a list of Meteor packages we would like to load in our client. Based on these, it builds a temporary Meteor application and composes a unified file from the fetched packages, with a focus in their chronological loading order.

Still sharing Client and Server code

If you’re using any sort of a configurable module bundler like Webpack, you can recreate one of Meteor’s greatest behaviors where we can load the same script on both client and server with a single definition. This will require you to add an alias for the server’s directory path, and define a special handler for imported Meteor packages. In the case of Webpack, the config extension should look like so:

module.exports = {
// …
resolve: {
alias: [
api: “path/to/meteor/server”
]
},
externals: function (context, request, callback) {
var match = request.match(/^meteor\/(.+)$/);
var pack = match && match[1];
if (pack) {
callback(null, ‘Package[“‘ + pack + ‘“]’);
}
}
// …
};

This should achieve the following result on the client:

Import { FooCollection, BarCollection } from “api/collections”;
Import { Accounts } from “meteor/accounts-base”;

And at the same time, we can use almost identical importations on the server:

Import { FooCollection, BarCollection } from “./collections”;
Import { Accounts } from “meteor/accounts-base”;

In conclusion

These were the key-concepts of Meteor Client Bundler. If you want to build an app while using the Meteor platform for all your stack, or you want to interact with a Meteor server and use any other front-end library or setup, MCB got everything you need, and will get you on the right track.

For a simple example of using MBC, check out this React-Meteor Todo app remake and for a more full-scale app check out the Ionic CLI WhatsApp clone project.

More information regards MCB can be found in its official Github repository over here: https://github.com/Urigo/meteor-client-bundler

I want to thank Eytan Manor for helping me make this library!

--

--