react-nativescript: HMR broken (issue is actually with Webpack configuration, not RNS itself)
Why is HMR broken?
HMR has been broken since the migration to NativeScript 7 because @nativescript/webpack depends on copy-webpack-plugin@~6.0.2, which – to the understanding of @rigor789 – has broken HMR most likely due to this outstanding issue.
The last known working version was copy-webpack-plugin@4.6.0. It’s possible that the latest major in-between version, 5.1.1, or one of the 6.x.x series may lack this bug, but I don’t have time to dig into it. At the very least, I know how to correctly invoke the plugin for version 4.6.0. So it’s clear that we can roll back to that version.
How can we roll back to copy-webpack-plugin@4.6.0?
Annoyingly, we cannot achieve this by a change to the RNS-owned webpack.config.js; the moment we evaluate const baseConfig = webpackConfig(env); it evaluates the array of plugins, and unfortunately, that API has changed so much since version 4.6.0 that the build throws an error on that line.
So instead, our easiest option is to patch webpack.typescript.js. This is incovenient because it’s not technically a file owned by the RNS project; it’s really supposed to remain common to all NativeScript flavours, unchanged by users and library maintainers, and not kept under version control (if I recall, it’s generated by a hook). Hence why I’m hesitant about patching it in the RNS template, as they might get blown away anyway.
Regardless, here’s how to do it, and it’s how I’ve set up sample in this repo on master.
Steps to patch webpack.typescript.js
- Install the last-known working version of CopyWebpackPlugin:
npm install -D "copy-webpack-plugin@4.6.0"
- Replace the following in the NativeScript Core common webpack config,
webpack.typescript.ts:
new CopyWebpackPlugin({
patterns: [
{ from: 'assets/**', noErrorOnMissing: true, globOptions: { dot: false, ...copyIgnore } },
{ from: 'fonts/**', noErrorOnMissing: true, globOptions: { dot: false, ...copyIgnore } },
{ from: '**/*.jpg', noErrorOnMissing: true, globOptions: { dot: false, ...copyIgnore } },
{ from: '**/*.png', noErrorOnMissing: true, globOptions: { dot: false, ...copyIgnore } },
],
}),
… with the necessary construction arguments for this older version of CopyWebpackPlugin (v6 takes an object instead of an array):
new CopyWebpackPlugin([
{ from: { glob: 'assets/**', dot: false } },
{ from: { glob: 'fonts/**', dot: false } },
{ from: { glob: '**/*.jpg', dot: false } },
{ from: { glob: '**/*.png', dot: false } },
], copyIgnore),
See CopyWebpackPlugin’s Changelog for version differences.
Hopefully they fix whatever issue is causing the regression, and we can eventually use the latest CopyWebpackPlugin without obstacle. It’s required for adopting Webpack 5, for example.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 4
- Comments: 20 (2 by maintainers)
So with a little help from your suggestion @ChrisSchneiider, I basically add the following code which is the function in that file. 😃 Man, you rock…
It’s Working thank you …
Thanks for the suggestion @ChrisSchneiider, but it’s not an ideal solution. For developing locally and testing, probably yes. But if I put my app through a CI/CD it’s a clean build directory and when
npm installget run it’s the new files. Maybe, I can override that function somehow.I also came across this problem. I spent the whole day hunting for a solution and that was the only one that worked! Good job.
@shirakaba what version of the {NS} Core did you try your regression on? After I run the
tns debug androidcommand, the app runs fine. But when I make a changes in the <style/> block of theApp.vue, I get an exception. What stands out is this line:System.err: TypeError: webpack_require(…).getCssFileName is not a function
Console Out with error