meteor-hmr
This project is no longer maintained
Interested in taking it over? See Info for potential maintainers. I regret that I simply do not have the resources to continue this project at this point in time.
Past Info
Hot Module Replacement (HMR) for Meteor
NB: This README refers to the upcoming release. Although it's experimental, you're encouraged to try it out, since that's the direction we're going in. More details in #51. Otherwise, you can find the old README here.
gadicc:[email protected]
is the last release for Meteor 1.3.2.4; later releases and the 2.0.0 final will target Meteor 1.3.3, using Meteor's new official babelrc support, and no longer includes our own babel-compiler-babelrc
which we no longer support.
Since Meteor 1.3.3 we use Meteor's native babelrc support. You should npm rm --save-dev babel-preset-meteor
and remove the meteor
preset from your .babelrc
.
- Edit your react components and see changes instantly, while maintaining state.
- Catch react
render()
errors and show on your screen rather than crashing your app. - Add your own
.babelrc
plugins and presets, like jsx-control-statements.
Copyright (c) 2016 by Gadi Cohen <[email protected]>, released under the MIT License. Note: this code includes / republishes additions to core Meteor packages that are Copyright MDG and released under the same license.
Discussion: https://forums.meteor.com/t/help-test-react-hotloading-in-native-meteor-i-e-no-webpack/17523/
How to Use
If upgrading from an earlier version, please see Upgrading.
What follows are step-by-step instructions to add meteor-hmr to an existing project. You can also see the Boilerplates & Examples section of the docs.
Hotloading is provided on a per-build-plugin basis. We provide a replacement
ecmascript-hot
loader to hotload your *.js
and *.jsx
files:
meteor remove ecmascript
meteor add gadicc:ecmascript-hot
If you're trying a non-stable release, you need to explicitly provide the @version
(or @=version
if it's not picked up correctly) in the second step.
Note, your code needs to be hot-module-replacement (HMR) aware. For instuctions on how to add hot loading for React, please see the React Hotloading docs. For general instructions, see the Handling Updates. If you're a build-plugin author, see the Build Plugin docs. Other build plugins HMR support are list below:
Other Notes:
-
We use an extra port for communication with the client. By default this is Meteor's port + 2 (i.e., right after mongo), but you can override it with the
HOT_PORT
environment variable. -
For Mantra style apps, skim over the React Hotloading docs above and then read this diff for an example on how to add hotloading to the
mantra-sample-blog-app
(or just clone the repo). You may also find more info in #60.
List of HMR-aware Build Plugins
gadicc:ecmascript-hot
-.js
and.jsx
files (core, part of this project)gadicc:node-modules-hot
- compilation & hot updates of local node-modules (core, see docs)
Build plugin authors, please submit a PR to add your HMR-aware build plugin to this list. For more info, see the Build Plugin docs.
Where this works and doesn't work
Hot Module Replacement (HMR) only works with "pure" modules that use import
and export
. Any reliance on Meteor's old method of api.use()
,
api.export()
and globals will absolutely not work properly, ever.
Forced Refresh
Just do a browser refresh like normal (ctrl-R, etc).
If you experience the need to do this frequently, please report on GitHub.
Note, errors thrown in your app can break Meteor's HCP system, requiring a browser refresh regardless... we can't help with that.
Settings (in package.json)
Hotloading is disabled by default for packages that can be hot loaded, unless the package explicitly forces hotloading, like ecmascript-hot
and node-modules-hot
which should simply be removed to disable hotloading. You can enable hotloading for other packages as follows:
{
// Besides for "-hot" packages which are always enabled,
// enable hotloading for all other packages that support it.
"enabled": true
// Or, we can specify an array of names
"enabled": [ "author:packageName", "etc" ]
}
Please note that the old ecmascript-hot
section is no longer used and should be removed.
Packages
If you replace the api.use('ecmascript')
in the package.js
file with the
gadicc:ecmascript-hot@<currentVersion>
, you'll be able to use the hotloading
while developing local packages, with one caveat:
This only works for "new style" 1.3 module packages. That means any reference
inside of a file should refer to the local scope only, i.e. any dependencies
should be imported via the import X from Y;
syntax, and your code should not
expect them to "just be available" because of Meteor's linker code.
Note, at time of writing (2016-05-07), Meteor doesn't allow for the
hot.accept()
check to flow from packages back down to the app, so you need
to do this per package. BUT, we have a PR open for this in
meteor#6391.
Troubleshooting
Please see the Troubleshooting docs. The first entry there is called Is this even working?. Otherwise, see if anyone else has experienced your problem by searching in issues and if not, please open a new one.
How this works
Brace yourself for reading this and recall the project goals.
-
Build plugins that use
gadicc:hot-build
(likegadicc:ecmascript-hot
) will be loaded a 2nd time in a forked process. They will watch all the same files, and on update, will recompile only changed files and send this update directly to the client. -
This above bundle resembles Meteor's linker output but also bypasses it, so this will only work with "pure" modules that use import/export and don't rely at all on Meteor's old method of
api.use()
andapi.export()
. -
The accelerator also runs an http server (to serve bundles) and a websocket server (to notify the client of new bundles ids). The client requests said bundles by inserting a script tag into the HEAD (so it will be loaded in the correct context).
-
We patch meteorInstall's root, delete previous exports, climb the tree, and reevaluate. This happens before the HCP, so if everything succeeded, we skip the next HCP.
-
We skip HCPs by wrapping autoupdate's observe()'s
changed
callback, to not fire the original callback in cases we want to skip.
Changes from original core packages
The bases for babel-compiler
and ecmascript
began from 1.3-modules-beta.5
and are upgraded as necessary, in their own commits (look out for commit messages
update package bases to 1.3-beta.11 (<SHA>)
etc).