webpack: Webpack 2 Dynamic Import degrades build performance (slow) compared to static imports.
Do you want to request a feature or report a bug? I would like to report a bug.
What is the current behavior? When converting my project’s components to dynamically import components instead of using static import statements, the build time increases by 10x and incremental builds by about the same.
The dynamic import functionality has reduced my bundle size astronomically by breaking all of my react components into separate chunks that get loaded into the app on-demand. I used a react-loader setup to replace most of my component static imports with dynamic imports.
If the current behavior is a bug, please provide the steps to reproduce.
- Create a large number static imports in your project.
- Convert those imports into dynamic imports.
- Run webpack-dev-server with hot-reloading for both and compare the build time.
//Static Example: index.js
import ComponentA from './component-a';
import ComponentB from './component-b';
export { ComponentA, ComponentB }
//Dynamic Example: index.js
import Loadable from 'react-loadable';
const LoadingComponent = f => {
return (
<div style={{textAlign:'center'}}><i className="fa fa-spinner fa-spin fa-2x"></i></div>
)
}
const LoadableComponent = opts => {
return Loadable({
delay: 300,
LoadingComponent,
...opts,
})
}
const ImportLoadable = (loader) => {
const Component = LoadableComponent({
loader
});
return Component;
}
const ComponentA = ImportLoadable(f => import('./component-a'));
const ComponentB = ImportLoadable(f => import('./component-b'));
export { ComponentA, ComponentB }
What is the expected behavior? I expect the dynamic import build time to be the same as a static import build time.
If this is a feature request, what is motivation or use case for changing the behavior? It seems that even though the dynamic import automatically chunks your bundle into multiple files, that when changing the underlying code for one of those chunks, webpack should be able to detect which file that was and only rebuild that file and hot-reload it.
Please mention other relevant information such as the browser version, Node.js version, webpack version and Operating System. Webpack 2.3.2 Webpack-Dev-Server 2.4.2
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 10
- Comments: 19 (6 by maintainers)
@gaearon, this makes quite a bit of sense. My though for a solution is to have an option that allows us to disable dynamic
import
andrequire.ensure
in development. The main reason I use import and require.ensure are to chunk in production.We are willing to have a longer build time for pushing to production, but it is debilitating for development.
From a brief chat with @sokra, my impression that https://github.com/webpack/webpack/issues/4636#issuecomment-301830807 does not actually demonstrate a perf regression, but rather the difference in how
require.ensure()
andimport()
work. (Correct me if I’m wrong.)With
require.ensure()
, anything yourequire()
in the block becomes a part of one chunk. So this example puts all the “dynamic” modules (which we have a lot if we use dynamic expressions) in one JS chunk. This seems worse for the app performance, as, for example, if you load locale files based on current language with a statement like this, you’re going to load all of them in one file. But it’s faster to process at build time. This behavior seems optimal if bundles contain a lot of common code, and so it’s not a big deal to combine them together.With
import()
, however, every single possible match gets its own chunk. This seems better for the app performance, and it maps more intuitively to how you’d expect it to work, but is worse for the build performance because of all those chunks. This behavior seems optimal if bundles are different enough and contain little common code (of if you rarely need to switch them).So
require.ensure()
default behavior seems to work better for things like component trees, butimport()
default behavior seems to work better for things like locales.Frankly, I don’t know what the intended solution is here, but I’d love to hear more from Webpack folks on how this feature should be used, and what the intended performance is.Apparently the
import()
default behavior is different fromrequire.ensure()
default behavior, but you will be able to customize it with hints to theimport()
call: https://github.com/webpack/webpack/issues/4807#issuecomment-300443876.I’ve created a small repo to help reproduce the problem here.
Just clone and
npm install
, then you can run two commands:npm run import
: run the web server using dynamicimport
s;npm run require
: run the web server usingrequire.ensure
syntaxThe repo and the files included are very small so the difference is not that big but if you modify a random file it’s usually taking ~300/400ms to rebuild with
require.ensure
versus ~700/800ms withimport
(the problem is way more evident in real apps).Also if you edit a file with
require.ensure
here’s the output:versus this using
import
:is this applicable for latest versions as well ? I am using webpack 3.5.x and recently modified implementation for Dynamic Import using react-loadable and feel that build time has been increased.
Please suggest better solution to do so
@NomadGraphix I was referring specifically to
require.ensure
but the same general technique (with a different plugin) could be used for the dynamic import syntax that you specified.