shirakaba / react-nativescript

React renderer for NativeScript
https://react-nativescript.netlify.com
MIT License
280 stars 14 forks source link

HMR broken (issue is actually with Webpack configuration, not RNS itself) #65

Closed shirakaba closed 3 years ago

shirakaba commented 3 years ago

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

1) Install the last-known working version of CopyWebpackPlugin:

npm install -D "copy-webpack-plugin@4.6.0"

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

mykone commented 3 years ago

@shirakaba is this for React NativeScript only? I tried editing the generated webpack.config.js in Nativescript-Vue but this technique didn't work. Where do I find the webpack.typescript.js?.

shirakaba commented 3 years ago

@mykone for NativeScript Vue, the corresponding section is instead found in webpack.config.js:

            new CopyWebpackPlugin({
              patterns: [
                { from: 'assets/**', noErrorOnMissing: true, globOptions: { dot: false, ...copyIgnore } },
                { from: 'fonts/**', noErrorOnMissing: true, globOptions: { dot: false, ...copyIgnore } },
                { from: '**/*.+(jpg|png)', noErrorOnMissing: true, globOptions: { dot: false, ...copyIgnore } }
              ],
            }),

So again, just replace it with this:

      new CopyWebpackPlugin([
        { from: { glob: 'assets/**', dot: false } },
        { from: { glob: 'fonts/**', dot: false } },
        { from: { glob: '**/*.jpg', dot: false } },
        { from: { glob: '**/*.png', dot: false } },
      ], copyIgnore),

... and run:

npm install -D "copy-webpack-plugin@4.6.0"

mykone commented 3 years ago

@shirakaba what version of the {NS} Core did you try your regression on? After I run the tns debug android command, the app runs fine. But when I make a changes in the