NPM packages and ES6 Modules (CJS/AMD too!) for Meteor, on the client and server.
DEPRECATED, in favor of Meteor 1.3 modules. I am no longer working on this. If you really want to use Webpack (which is what this is built on) check out webpack:webpack.
meteor update --release 1.2-rc.7
meteor add rocket:module
Note, a manual update to the release candidate of Meteor (version 1.2-rc.7 or greater) is required until 1.2 is officialy released.
Many useful React components and React-related modules are available on NPM,
and can be bundled for the client or the server with rocket:module
.
rocket:module
also allows you to write CommonJS, AMD, or ES6 modules.
rocket:module
can be used for packages too, not just apps, and it will share
(as much as possible) NPM dependencies across packages in an app (and the app
itself).
You can use rocket:module
to load NPM modules on the client or the server. Here's how:
meteor update --release 1.2-rc.7
meteor add rocket:module
Note that the update command is only temporary until Meteor 1.2 is released.
Create an npm.json
file in your app or package that specifies the
dependencies you'd like from NPM. In most cases, you should leave the carrot
(^
) in front of the version number to ensure that the most compatible
versions of your dependencies can be found. If you need more control of the
versions in your package for whatever reason, you can (but try to avoid)
plucking the carrot.
If you're making a package, be sure to add your npm.json
file via
api.addFiles()
.
/path/to/your/app/npm.json
{ "react": "^0.13.1", "famous": "^0.7.0", "async": "^1.4.0" }
rocket:module
handles all the JavaScript files in your app. JavaScript files
that end with .entry.js
or are entirely named "entry.js"
are entry points
into your application. You'll need at least one entrypoint file. In each
entrypoint you can begin importing whatever you need, like in the following ES6
examples:
/path/to/your/app/entry.js
import React from 'react' import Node from 'famous/core/Node' import async from 'async' ...
or
/path/to/your/app/main.entry.js
import React from 'react' import Node from 'famous/core/Node' import async from 'async' ...
Note, these last two entry point examples would run on boths sides, the client and the server.
Use CommonJS module syntax if you feel more comfortable with that:
/path/to/your/app/server/entry.js
let React = require('react') let Node = require('famous/core/Node') let async = require('async') ...
Heck. If you really like AMD, use it:
/path/to/your/app/server/entry.js
define([ 'react', 'famous/core/Node', 'async', ], function( React, Node, async, ) { ... })
You've just imported React, Famous, and async from NPM.
Note, rocket:module
works on both sides, client and server! The last two
entry point examples run on the server because they're in a server
folder.
Now that's something to feel good about.
You can also import local files!
/path/to/your/app/client/entry.js
import somethingLocal from './path/to/local/file' ...
Note, this last one loads on the client only because it's in a client
folder.
That's basically it! See the example
app for an actual
example. See the example
package to learn how
to use rocket:module
in a Meteor package.
All your entrypoint files load in the same order as normal files would, based on Meteor's load order rules.
Note that Meteor's load order rules don't apply to any files that you've ever
import
ed or require
d into any other file. In this case, the order is
defined by you, and loading starts from your entrypoint files. Imported or
required files are completely ignored by Meteor's load order mechanism.
Files that are not entrypoint files and that are never imported into any other
file are ignored by rocket:module
. Those files are handled exclusively by
Meteor's load order mechanism, not by rocket:module
.
If you make a change to npm.json
, the server will reload as expected, but
will fail to update your NPM dependencies. This will be fixed in
rocket:module
v1.0.0. For now, there are two ways you can work around this (choose one):
- Relative to your app, run
npm install
inside of both./meteor/local/rocket-module/platform-builds/web.browser
and./meteor/local/rocket-module/platform-builds/os
. - Stop your Meteor server, remove
.meteor/local/rocket-module
relative to your app, restart Meteor. This option is easier to do, but takes longer becauserocket:module
will have to re-install all NPM dependencies again.
You may experience a build delay (sometimes around a minute long) due to a possible bug in the release candidate of Meteor. I hope we can get to the bottom of it soon. See meteor/meteor#5067.
Added inrocket:module
will have a cache before reaching 1.0.0. Until then, your app may take a long time to build if you've got lots of files.rocket:module
v0.8.1.- Some more speed improvements around NPM package handling.
- Version 1.0.0 of
rocket:module
will handle source maps. - Fix npm.json live reload.
- Cross-package imports/exports (ES6, CommonJS, or AMD).
These steps are mostly in the order that they'll be developed. Semver rules apply starting from v0.2.0.
- Register a new compiler with Plugin.registerCompiler.
- Redo everything but with the files handed to rocket:module by Meteor, thus eliminating the two previous month's worth of work. (:
- Switch to npm CLI instead of programmatic usage to see if that fixes random NPM bugs that don't happen when I try from CLI.
- Ensure that files that aren't handled by Webpack (for applications) are given back to Meteor so they can be executed.
- Let users specify rocket:module configs in rocket-module.json of the app.
- Allow an
aliases
config option that works like that of Webpack'sresolve.alias
config option.
- Allow an
- Only read npm.json at the root level of a package or app, and same with rocket-module.js of an app.
- Use Webpack's caching feature so that only modified files are rebuilt.
Make sure to write the replacement of
window
byRocketModule
to the built files if Webpack's cache reads the built files. - Make sure that files that are no longer in the project are also not present in rocket:module build cache.
- Does Meteor tell you which files have changed? If so, update only those files on the disk, leaving other files unchanged.
- Add sub-node_modules folders to the resolve/resolveLoader root option if there are any (it happens with dependency forks, but most of the time the first level node_modules folder will be flat because we're using NPM v3).
- Add useful Webpack loaders: babel, coffeescript, typescript, jsx, glslify,
css, less, sass, and stylus.
- babel
- coffeescript
- typescript
- jsx (via babel)
- glslify
- css
- less
- sass
- stylus
- PNG/JPEG
- Get code splitting working (webpack/webpack issue #1296). Currently each entry point is having duplicate code, which is the same as Meteor's dependency handling.
- Handle source maps.
- Use
npm outdated
to detect if we need to runnpm update
. We'll need to run the update command when dependencies listed in npm.json files have changed in order to update the local packages. - Make a
enforceModules
option that, when true, doesn't handle files unused by Webpack back to Meteor. This makes it so that files are only in your project if they are explicitly required or imported into another file, otherwise their code is completely ignored. - Don't hand files in a
modules
folder back to Meteor. This can be used similarly to theenforceModules
option to tell rocket:module that these files are meant only to be required or imported into other files, and if they are not, they won't be handed back to Meteor. - Test in Windows.
- Report file-specific Webpack errors using corresponding InputFile.error() calls.
- Finish commented TODOs that are left in rocket:module.
- Update README with usage and configuration documentation.
- Describe how to use npm dependencies.
- Describe client/server file naming.
- Celebrate! Wooooo!
- Install Webpack locally instead of using
rocket:webpack
, which will prevent architecture-specific builds ofrocket:module
. - Add support for browserify transforms.