How to dynamically load modules in Babel and Webpack?
Asked Answered
S

1

8

I'm trying to use the dynamic module loading feature in ES6 and it seems that it's not actually implemented yet. But there are substitutes like ES6 Module Loader Polyfill which supposedly should do the trick for the time being.

So I have a ES6 project transpiled to ES5 using Babel and Webpack, and it works fine on its own. But all of my code is merged into one bundle.js file which I would like to split into modules. And when I tried the mentioned Polyfill, it throws some error from within and the project won't even start.

index.js:6 Uncaught TypeError: Cannot read property 'match' of undefined

And line 6 reads:

var filePrefix = 'file:' + (process.platform.match(/^win/) ? '/' : '') + '//';

Here's my package.js file:

{
  "dependencies": {
    "es6-module-loader": "^0.17.11",
    "events": "^1.1.0",
    "flux": "^2.1.1",
    "fs": "0.0.2",
    "react": "^15.0.2",
    "react-addons-css-transition-group": "^15.0.2",
    "react-dom": "^15.0.2",
    "react-router": "^2.4.0",
    "react-tap-event-plugin": "^1.0.0",
  },
  "devDependencies": {
    "babel-core": "^6.8.0",
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.6.0",
    "babel-preset-react": "^6.5.0",
    "html-webpack-plugin": "^2.16.1",
    "react-hot-loader": "^1.3.0",
    "transfer-webpack-plugin": "^0.1.4",
    "webpack": "^1.13.0",
  }
}

Can someone please point me to a working example of dynamic module loading with Webpack and Babel?

Subternatural answered 13/5, 2016 at 22:47 Comment(2)
You might be talking about require.ensure - here is a working exampleChesney
@Chesney I think that's a different technology but it's good to know. Thanks.Subternatural
N
5

There's really three things at play here... dynamic importing, lazy loading, and code splitting/bundling. The System.import method, poly-filled with ES6 Module Loader will allow dynamic imports but not dynamic code splitting:

However, most transpilers do not support converting System.load calls to require.ensure so you have to do that directly if you want to make use of dynamic code splitting.

Dynamic code splitting is when you create child bundles within an entry point, which you can then dynamically lazy load. For this I would recommend using the promise-loader which is a bit more friendly than require.ensure:

import LoadEditor from 'promise?global,[name]!./editor.js';

...

if (page === 'editor') {
  LoadEditor().then(Editor => {
    // Use the Editor bundle...
  })
} 

Webpack will now break the editor.js module and all of it's dependencies into a separate bundle which can be loaded immediately or dynamically (as shown above). Lastly, depending on the size of the app, I think you should also consider splitting the vendor code out.

UPDATE

System.import was removed from the spec and replace by just import(). The new webpack docs have a page that discusses dynamic imports in webpack and the limitations of them.

Nepali answered 14/5, 2016 at 5:46 Comment(5)
Is there any way I can omit the editor.js and not name it in my code? I need to write a code which loads a file without having any prior knowledge about it. In all of the examples that I see, the module to be loaded is explicitly named in the same file as it is going to be dynamically loaded! It doesn't sound very dynamic to me.Subternatural
@Subternatural As mentioned in the linked answers, dynamic can refer to a lot of things but usually means some code needs to run to determine whether or not to load the module. You want to use a variable name or something to import it? Are you trying to iterate through and load a bunch of files?Nepali
Exactly, I have a collection of file paths which I want to load based on user events. And the iteration code has no idea what they are. It just gets them in a variable. There are even cases that the collection is populated at runtime!Subternatural
In that case, the ES6 Module Loader (System.load) is what you'd want. I think you might be slightly confused how this works with Webpack though. I haven't used it before but it's actually seems to be an alternative to Webpack in a sense. The point of Webpack is to create transpiled ES5 bundles before runtime. Looking through the documentation, the module loader actually transforms ES6 to ES5 during runtime. This is probably why it's been hard to find a working example with both...Nepali
In other words, with the ES6 Module Loader you wouldn't transpile and bundle your code with Webpack before hand. You would have raw ES6 in your web directory that gets loaded and transpiled at runtime.Nepali

© 2022 - 2024 — McMap. All rights reserved.