Oprea.Rocks Logo

ES6 dynamic import and Webpack memory leaks

es6-dynamic-import-webpack-memory-leaks

Last week while working on a client project, I hit some serious dead end. A memory leak! It's been a while since I saw one of those.

After 10 minutes of chewing on the code, Webpack decided to throw up and leave me with nothing more than this V8 heap dump. See the dump in this GitHub gist.

es6-dynamic-imports-and-webpack-memory-leaks-wat

It hit me like a hammer in the head. What the hell was I doing wrong? After some digging, I realised my dynamic imports were causing this. But how?

The code was fairly simple.

// [...]
const components = Object.keys(config);
const imports = components.map(c => import(`${config[c].path`));
// [...]

So I have a fully computed path, which I'm reading from a config object. I would then pass that path to import(). What's wrong with that?

This went on for a day or two. I tried everything I knew. Went through GitHub issues, blog posts, and most importantly, the official dynamic import documentation / proposal here and here.

I finally found it

Once you're desperate enough to read comments on blog posts, you will find the solution to your problem.

Then I went through blog posts again, this time reading through the comments. I found this neat article from Dr. Axel Rauschmaier which I've read multiple times before.

While looking at the comments I saw one asking about using import with Array.map and it caught my attention. The only difference between my code and the one in the comment was the file extension which was concatenated directly in the import() function call. Weird.

That led me to look for specific dynamic import issues with computed module specifiers. And that's when I found these two issues which ultimately yielded the solution for my case:

Dynamic expressions for import() are broken #4292

Dymatic import() not working for computed module specifiers #2830

The bottom line

So, bottom line. If you have issues with Webpack not compiling your dynamic imports. Ask the following questions.

Q: Am I using computed module specifiers and just passing a variable to import()?

A: If so, please just concatenate an empty string at the import() statement level.

import('' + computedModulePath)

Q: Are my module names too long?

A: Can't prove anything here but I remember this problem being reported multiple times. Make your paths / names shorter.

Don't use empty paths and only variables. They don't work. Webpack can't know how to understand that. It is something you have to deal with.