gadicc:hot-build

v0.0.14Published 8 years ago

This package has not had recent updates. Please investigate it's current state before committing to using it in your project.

meteor-hmr

Hot-module-replacement 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.

  • 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.

screencast

Copyright (c) 2016 by Gadi Cohen <meteor@gadi.cc>, 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.

More info

Given that:

  1. Webpack has react hotload support and it's awesome.
  2. Meteor build process has become painfully slow

(but is improving)

  1. Meteor has no plans to integrate webpack (for

good reasons)

  1. MDG want more time to plan best way to do hot module replacement (as above).

Let's:

  1. Implement a less-than-ideal solution to get react hot loading NOW, until

something better/official comes along.

Discussion: https://forums.meteor.com/t/help-test-react-hotloading-in-native-meteor-i-e-no-webpack/17523/

Current status (2016-04-01): Fix for broken deploys. (04-02): SSR working.

Current release: There's no more need to specify the version in your packages file; remove it and meteor update for the latest stable version.

How to Use

If upgrading from an earlier version, please see Upgrading.

Hotloading is provided on a per-build-plugin basis. We provide a replacement ecmascript-hot loader to hotload your *.js and *.jsx files:

  1. Edit your .meteor/packages and replace ecmascript with gadicc:ecmascript-hot

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.

Notes:

  1. 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.

  1. 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.

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)

Not relevant for newer versions. Please remove this section.

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.

Troubleshooting

Is this even working?

On a save, you should see the following on the client console:

[gadicc:hot] Connected and ready.
[gadicc:hot] Updating ["/client/colors.js"]
[gadicc:hot] Skipping HCP after successful HMR

If you're not seeing that, probably we're not picking up the save. The biggest reason for this currently is atomic writes ("safe writes"), which we're working to fix. You can track the progress in #53.

Otherwise see further down about DEBUG LOGGING.

No hot.accept() in /client/non-hot-update.js > /client/index.jsx

Previously: /client/main.js is not hot and nothing requires it

For hot-updating to work, either the file you changed must be able to self accept, or we'll climb the import chain looking for a file that can accept the change (i.e. it knows how to handle an update to a specific import).

If you're trying to get React Hotloading working, see the React Hotloading docs. If you're trying to get something else working, check the docs for the build plugin you think should be HMR-aware, or the Handling Updates docs to get HMR working for other parts of your app.

For anything else, this is probably the correct message, and Meteor's regular Hot Code Push (HCP) will come through and reload the page. Hotloading only works for hotloading-aware code. Changes to any other code has to restart the page to work correctly.

You may find some other helpful info in #65.

Disable HCP on fail for debugging

If you want to report an error with meteor-hmr, but Meteor's HCP kicks in before you can see the error, you can disable HCP until the next page reload by typing the following line in your browser console:

1Reload._onMigrate(function() { return false; });

Debug Logging

You can set the environment variable HOT_DEBUG=1 for more server-side info. Actually, you can do HOT_DEBUG=2 or HOT_DEBUG=3 for even more verbose debug logging, up to HOT_DEBUG=5, but things get kind of crazy around there :)

A typical save with HOT_DEBUG=1 should look like this:

[gadicc:hot] Accelerator (Pof): gadicc:ecmascript-hot/compile-ecmascript-hot.processFilesForTarget(client/colors.js)
[gadicc:hot] Accelerator (Pof): Creating a bundle for 1 changed file(s)...

You may find other info which helps you work out the nature of your problem, so you can solve it or report it on github.

How this works

Brace yourself for reading this and recall the project goals.

  1. Build plugins that use gadicc:hot-build (like gadicc: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.

  2. 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() and api.export().

  3. 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).

  1. 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.

  1. 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).