Search code examples
javascriptwebpackwebpack-dev-serverwebpack-hmrhot-module-replacement

Webpack importing files without extension outputs changes incorrectly in HMR(Hot Module Replacement)


I follow this guide and write code like that guide. Everything is Ok! But when I change import printMe from './print.js' to import printMe from './print', HMR doesn't output changes correctly!

When I change like following in print.js:

   export default function printMe() {
 -   console.log('I get called from print.js!');
 +   console.log('Updating print.js...')
   }

Console should output: Updating print.js...

But it outputs: I get called from print.js!

When I sencond change 'Updating print.js...' to 'Updating print.js again...', it doesn't out changes.

The following is my snapshot:

console output

However, Module Resolution says:

  • If the path has a file extension, then the file is bundled straightaway.
  • Otherwise, the file extension is resolved using the resolve.extensions option, which tells the resolver which extensions (eg - .js, .jsx) are acceptable for resolution.

and resolve-extensions also says:

Automatically resolve certain extensions. This defaults to:

extensions: [".js", ".json"]

So, my question is: Can't webpack resolve the path without extension like what it says above? Is this a bug or what I am doing wrong? What I have done is just changing import printMe from './print.js' to import printMe from './print'.

My environment:

  • node v7.4.0
  • npm 4.0.5
  • webpack 3.4.1
  • webpack-dev-server 2.6.1
  • macOS Sierra 10.12

Thanks a lot!!


Solution

  • I suppose I know why it works incorrectly.

    What I do is:

    src/index.js

    import _ from 'lodash';
    import printMe from './print';
    
    // ...
    
    if(module.hot) {
      module.hot.accept('./print.js', function() {
        console.log('Accepting the updated printMe module!');
        printMe();
      });
    }
    

    But you should always make the name of import and the first param of module.hot.accept be the same:

    src/index.js

    import _ from 'lodash';
    import printMe from './print';
    
    // ...
    
    if(module.hot) {
      module.hot.accept('./print', function() {
        console.log('Accepting the updated printMe module!');
        printMe();
      });
    }
    

    OR:

    src/index.js

    import _ from 'lodash';
    import printMe from './print.js';
    
    // ...
    
    if(module.hot) {
      module.hot.accept('./print.js', function() {
        console.log('Accepting the updated printMe module!');
        printMe();
      });
    }
    

    These two situations all work. It may be the expected behaviour of authors of webpack. But from my points of view they three situations should all have worked. :(