Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hot Module Replacement #26

Closed
sokra opened this issue Oct 22, 2012 · 9 comments
Closed

Hot Module Replacement #26

sokra opened this issue Oct 22, 2012 · 9 comments

Comments

@sokra
Copy link
Member

sokra commented Oct 22, 2012

Reloading the whole page on bundle update is ok, but a far time goal is to replace modules on runtime. (Idea from #25)

It's a far time goal, but it may be good to start discussion early...

Steps:

  1. Find a syntax.
  2. Check how to implement it in webpack.
  3. Implement it.

Goals:

  • Don't interrupt other modules
  • Let the developer use it for the whole or only parts of an application
  • Module authors should be able to implement it for their modules. App devs shouldn't need to care.
  • App devs should be able to implement hot module reloading for modules. Even if module authors don't care.
  • It should be usable in production, if you want to. If not it should not make your bundle bigger.
  • It should work with CommonJS and AMD modules.
  • Opt-in for fallback to complete reload.
  • Only transfer updated modules.
  • There should be also a node.js version working with the same syntax

Problems:

  • Side-Effects in modules. It must be a opt-in feature.
  • Not possible for every module.
  • A module may support it, but the author hasn't opt-in.
  • When to check if new code is availible?
  • Implentation
    • Module/Chunk Ids have to stay
  • ...
@sokra
Copy link
Member Author

sokra commented Oct 22, 2012

@rdrey
Copy link
Contributor

rdrey commented Nov 7, 2012

Interesting. I am using the LiveReload app, which does full page refresh operations a lot, but that doesn't bother me.

I am also using yeoman and angular.js, which can LiveReload my client, but I haven't patched-in my custom Express server yet. I also haven't experimented with your grunt task to automate my webpack step, yet.

Problems:

  • When to check?

    Most other livereload-like frameworks & tools bundle a websocket server, just to emit events when source changes. That seems like a pretty big dependency to add to Webpack, but polling for changes seems like an outdated solution. What do you think? You said you have a prototype version, how did you implement it there?

@sokra
Copy link
Member Author

sokra commented Nov 7, 2012

The "prototype" is enhanced-require@0.4.x and only work on node.js, where I offer FileWatchers (watch: true) or manual checking (.check(cb)).

For webpack I plan to offer polling (every 10 minutes in production should be not problem, an update is not so important) and manual checking (so you could send a event if you have already some kind of bidirectional connection).

The grunt task does nothing special. It just runs webpack. (grunt's watch task is worse than webpack's)

Full page refreshing is already availible through the webpack-dev-server.


The impl plan is to emit special update files to the output directory, which contain all info regarding the update. There will be one main update file <old-hash>.update.js and updates for the chunks <x>.<old-hash>.update.js. Only modules that were updated are contained in these packages and the main file contains info about the new hash and existing update chunks.

The client can check existance of the main update file and download it. Than it can download the needed update chunks. When this is finished an update is availible and can be applied. If it can't be applied the app may display some info to do a whole page refresh.

To create these update files webpack need to know old module ids, old content hashes and the old bundle hash. So we need to use a hot reploading file which stores the info (--hot <file>, { hot: <file> }).

@sokra sokra closed this as completed in 8b23010 Jun 19, 2013
@jhnns
Copy link
Member

jhnns commented Jun 19, 2013

This feature is really crazy ^^

sokra added a commit that referenced this issue Jun 19, 2013
sokra added a commit that referenced this issue Jun 19, 2013
@sokra
Copy link
Member Author

sokra commented Jun 20, 2013

Yes it's crazy...

Here is more explanation:

All goals above have been reached.

Only modules (or module chains) which have opt-it (using the module API) can be replaced. An update will abort if any updated module havn't opt-in.

One can use the management API to start an update: module.hot.check(function(err, renewedModules) { /* ... */ });

If no update found renewedModules === null.

Elsewise it will download hot update chunks for each loaded chunk. After the update have been downloaded, the hot replacement code will determine modules that will be renewed. Then:

  • the old modules are disposed,
  • the new code is installed,
  • the accept handlers are called, and
  • the self accepted modules are required.

API: https://github.com/webpack/docs/wiki/hot-code-replacement

It must be globally enabled with --hot / options.hot = true.

If one don't write own management api code, one can use prepared code in the webpack/hot folder:

webpack/hot/dev-server for the webpack-dev-server.

webpack/hot/poll uses polling to find a update. (poll?10000 to specify a interval in ms)

Simple add it as entry:

module.exports = {
  entry: ["webpack/hot/poll?600000", "./entry.js"]
  // ...
};
webpack "webpack/hot/poll?600000" ./entry.js bundle.js --hot --records-path records.json

The style-loader and mocha-loader automatically generate hot-replaceable code.

So a stylesheet can be changed without a full page refresh and tests with changed dependencies rerun.


TODOs:

  • do not download empty update chunks

sokra added a commit that referenced this issue Jun 20, 2013
@sokra
Copy link
Member Author

sokra commented Jun 20, 2013

so integrated in my app at the page router with 10 LOC... App can update itself without full page refresh...

Thanks to @Phoscur for proposing the best feature ever! 😄

@sokra
Copy link
Member Author

sokra commented Jun 23, 2013

added a demo to http://webpack.github.io/example-app/

there are 2 updates.... you can apply them with the two buttons on the right.

@sokra
Copy link
Member Author

sokra commented Jul 4, 2013

Here is a graphical example:

Compile time

Left: first compilation
module 4 changed: async require to module 10 removed
module 9 changed: normal require to module 12 added
Right: second compilation including Hot Update Chunks

HMR

Runtime

Assuming module 4 accepts itself and module 2 accepts module 3.

  • Disposing modules: 3, 4, 5, 6, 8, 9, 10, 11
  • Calling accept handler in module 2 (accepting module 3)
  • Require self-accepted module 4

@gaearon
Copy link
Contributor

gaearon commented May 22, 2015

Thank you for doing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants