We have not merged hot reloading support yet but I noticed a very unfortunate issue: Chrome doesn't update sourcemaps.
See how the Hello
in browser Sources pane doesn't change.
Note that if we change Webpack devtool
setting from cheap-module-source-map
to eval
it will update on hot reloads:
It used to be broken too but at some point Chrome fixed it. I remember chatting with @paulirish about it in the past.
However we can't switch to eval
mode because we need the source mapping.
We should reach out to somebody at Chrome and figure out if this is fixable. We can live with the broken behavior for a while but if it鈥檚 not possible to fix later, then hot reloading experience would be confusing.
This looks like a related bug: https://bugs.chromium.org/p/chromium/issues/detail?id=438251
And this is a similar bug that was fixed for eval
case by @pavelfeldman and (if I鈥檓 not mistaken) @ak239:
https://bugs.chromium.org/p/chromium/issues/detail?id=492902
Related webpack discussion (closed in favor of Chromium bugs): https://github.com/webpack/webpack/issues/2478
I provided a detailed standalone repro case here: https://bugs.chromium.org/p/chromium/issues/detail?id=438251#c28
For the record, I'm suffering from the same issue in a completely different environment too for 2 years by now:
[org.clojure/clojurescript "1.9.562"]
[tailrecursion/boot-static "0.0.1-SNAPSHOT"]
[hoplon/ui "0.2.1-SNAPSHOT"]
The phenomena is present in both Chrome 61, Firefox 53, Safari 10 and Opera 45.
The alt-r
workaround recommended in the Chromium discussion doesn't work (again?) in Chrome Canary 61.0.3124.0 either.
Maybe worth mentioning the related issue here too:
https://github.com/gaearon/react-hot-loader/issues/180
Closing and re-opening the dev tools in Firefox will load the latest source code, but since it doesn't preserve the state of its windows, we have to re-open the desired source files again.
Using the :source-map-timestamp
option mitigates the problem slightly by making the latest original source code available in the browser under a timestamped name (eg. application.cljs?rel=1496943424545
), but it doesn't remove earlier versions, so it's still a bit confusing...
At least clicking on error references in the console brings us to the correct version of the original source code.
This commit https://github.com/webpack/webpack/commit/84b6554f982fd9bc130262cfe0a8003531d4bcb9 has now landed in Webpack, which enables setting a contentHash as a query-string suffix. This workaround should be sufficient to solve this problem.
Could you help me understand how it solves the problem? What's the developer experience like? Do we need to update our config?
@gaearon yeah, just change the Webpack config to include:
{
// ...
output: {
// ...
sourceMapFilename: "[file].map?[contenthash]"
}
}
This will use the workaround which makes the sourcemaps work in Chrome together with cheap-module-source-map
.
It still won't replace sourcemaps on edit, right? Will just add new copies of the file.
I believe the mapping should update too, since the code-paths will be different.
@niieani I can't reproduce that it fixes the issue. If I use module.hot.accept
calls, I still see old code on hot reload. Can you provide full instructions for me to see how this fixes it?
Hmm, the old code will still be visible (since we cannot unload sourcemaps), however new code should appear and be mappable, correctly.
What works for me is adding timestamps:
const now = Date.now()
map.sources = map.sources.map(source => source + (source.includes('?') ? '&' : '?') + now)
The full source map plugin we use:
const { RawSource, ConcatSource } = require('webpack-sources')
const path = require('path')
module.exports = function sourceMapPlugin() {
return {
apply: compiler => {
compiler.plugin("compilation", compilation => {
// make sure webpack stuff keeps their source maps
compilation.plugin("build-module", module => {
module.useSourceMap = true
})
// add source map assets for anything that still has one
compilation.plugin('after-optimize-assets', assets => {
Object.keys(assets).forEach(name => {
const asset = assets[name]
const map = asset.map()
if (map) {
// make sure sources in the source map are timestamped, this helps with hot reloading
const now = Date.now()
map.sources = map.sources.map(source => source + (source.includes('?') ? '&' : '?') + now)
const [startComment, endComment] = name.endsWith('.css') ? ['/*', ' */'] : ['//', '']
assets[name] = new ConcatSource(asset, `\n${startComment}# sourceMappingURL=${path.basename(name)}.map${endComment}\n`)
assets[name + '.map'] = new RawSource(JSON.stringify(map))
}
})
})
})
}
}
}
Excuse rant.
Could we potentially, in dev, not bundle everything? Maybe just bundling the deps, and providing a source map for them, then generate a slow source map for individual JavaScript that could then be cached (since most files don't change) then bundle them together at the end or just push heaps of small files.. How much slower would it be? Could a service worker help? Would not merging the files make hot loading certain libs that rely on symbols or object identity more reliable?
@gaearon : I know it's not a _build_ tool thing or even CRA specific, but if we could poke the browser devtools developers to finally implement this, it would be a huge win for the JS ecosystem...
We did poke them a few times. I think the issue even got a patch and it has a milestone. So I鈥檓 hopeful 馃檪
Is there a corresponding Firefox DevTools issue?
I think so, mabye.
The fix for crbug.com/438251
has landed and will be available on tomorrow's Canary.
馃槏 馃槏
I'm a big fan of HMR and I see it's been several weeks since the Canary fix landed.
Apologies if I'm missing something but it seems like this still needs to be verified, right?
Is there a recommended way to do so? I use Canary and would be happy to take the necessary steps.
@onpaws : fwiw, I can verify that a copy of Chrome 66 correctly updates sourcemaps on hot reloading in my own non-CRA app.
Hello, is there any progress?
Latest chrome 65, no source map reload.
Doing Alt+R manually to reload devtools is too slow.
Is there a solution?
update chrome Version 67.0.3370.0 (Official Build) canary (64-bit)) , the bug has fixed ,according the bug issues: https://bugs.chromium.org/p/chromium/issues/detail?id=438251
update chrome Version 66.0.3359.117(64-bit) , the bug has fixed. 馃檪
Most helpful comment
The fix for
crbug.com/438251
has landed and will be available on tomorrow's Canary.