DEV Community 👩‍💻👨‍💻

tmhao2005
tmhao2005

Posted on

webpack compiles node_modules

I found out an interesting use case as we import a module (just call it foo) which supports both node and browser. But with the same import of foo, webpack would end up a different result in the browser. Let's have a look at the following example:

Firstly, assume to have a package foo like below:

- dist
-- index.js (cjs)
-- index.module.js (esm - mostly for browser)
Enter fullscreen mode Exit fullscreen mode

The content of foo would look like in both modules:

// dist/index.js 
// the content can be `cjs` or `umd`, for example:
module.exports = 1;

// dist/index.module.js
export default 1;
Enter fullscreen mode Exit fullscreen mode

Next, write a simple snippet to import foo in cjs style:

const foo = require('foo');

console.log(foo);
Enter fullscreen mode Exit fullscreen mode

Then run on Node:

const foo = require('foo');

// since above line of code ref to dist/index.js so will work as expected
console.log(foo); // 1
Enter fullscreen mode Exit fullscreen mode

Finally, run on browser via webpack after having been transformed:

// webpack auto select `esm` module by default
var foo = __webpack_require__("./node_modules/foo/index.module.js");

// __webpack_require__ will turn the foo object to be like: 
// { default: 1 }

// As a result of that, this code won't work as expected
console.log(foo); // undefined
Enter fullscreen mode Exit fullscreen mode

To sum up, we have to be careful with the package (foo) which supports running on node/browser to avoid unexpected result as above. As I know most of packages are now being implemented that way. If you write code in Typescript or Esnext style, you can enable the configuration { esModuleInterop: true } to import helper to sort out the issue in case of Typescript.

Thanks for reading!

Top comments (0)

Need a better mental model for async/await?

Check out this classic DEV post on the subject.

⭐️🎀 JavaScript Visualized: Promises & Async/Await

async await