Meteor.js: How do you require or link one javascript file in another on the client and the server?

1) In node on the backend to link one javascript file to another we use the require statement and module.exports. This allows us to create modules of code and link them together.

How do the same thing in Meteor?

2) On the front end, in Meteor is I want to access a code from another front end javascript file, I have to use globals. Is there a better way to do this, so I can require one javascript file in another file? I think something like browserify does this but I am not sure how to integrate this with Meteor.

Basically if on the client I have one file

browserifyTest.coffee

test = () ->    
  alert 'Hello'

I want to be able to access this test function in another file

test.coffee

Template.profileEdit.rendered = ->
  $ ->
    setPaddingIfMenuOpen()
    test()

How can I do this in Meteor without using globals?

  1. Meteor wraps all the code in a module (function(){...your code...})() for every file we create. If you want to export something out of your js file (module), make it a global. i.e don't use var with the variable name you want to export and it'll be accessible in all files which get included after this module. Keep in mind the order in which meteor includes js files http://docs.meteor.com/#structuringyourapp

  2. I don't think you can do this without using globals. Meteor wraps code in js files in SEF (self executing function) expressions, and exports api is available for packages only. What problem do you exactly have with globals? I've worked with fairly large Meteor projects and while using a global object to keep my global helpers namespaces, I never had any issues with this approach of accessing functions/data from one file in other files.

You can use a local package, which is just like a normal Meteor package but used only in your app. If the package proves to be useful in other apps, you may even publish it on atmosphere.

I suggest you read the WIP section "Writing Packages" of the Meteor docs, but expect breaking changes in coming weeks as Meteor 0.9 will include the final Package API, which is going to be slightly different. http://docs.meteor.com/#writingpackages

Basically, you need to create a package directory (my-package) and put it under /packages.

Then you need a package description file which needs to be named package.js at the root of your package.

/packages/my-package/package.js

Package.describe({
  summary:"Provides test"
});

Package.on_use(function(api){
  api.use(["underscore","jquery"],"client");
  api.add_files("client/lib/test.js","client");
  // api.export is what you've been looking for all along !
  api.export("Test","client");
});

Usually I try to mimic the Meteor application structure in my package so that's why I'd put test.js under my-package/client/lib/test.js : it's a utility function residing in the client.

/packages/my-package/client/lib/test.js

Test={
  test:function(){
    alert("Hello !");
  }
};

Another package convention is to declare a package-global object containing everything public and then exporting this single object so the app can access it. The variables you export NEED to be package-global so don't forget to remove the var keyword when declaring them : package scope is just like regular meteor app scope.

Last but not least, don't forget to meteor add your package :

meteor add my-package

And you will be able to use Test.test in the client without polluting the global namespace.

EDIT due to second question posted in the comments.

Suppose now you want to use NPM modules in your package. I'll use momentjs as an example because it's simple yet interesting enough.

First you need to call Npm.depends in package.js, we'll depend on the latest version of momentjs :

/packages/my-moment-package/package.js

Package.describe({
  summary:"Yet another moment packaged for Meteor"
});

Npm.depends({
  "moment":"2.7.0"
});

Package.on_use(function(api){
  api.add_files("server/lib/moment.js");
  api.export("moment","server");
});

Then you can use Npm.require in your server side code just like this :

/packages/my-moment-package/server/moment.js

moment=Npm.require("moment");

A real moment package would also export moment in the client by loading the client side version of momentjs.

You can use the atmosphere npm package http://atmospherejs.com/package/npm which lets you use directly NPM packages in your server code without the need of wrapping them in a Meteor package first. Of course if a specific NPM package has been converted to Meteor and is well supported on atmosphere you should use it.