Reputation: 28611
Is there a Babel plugin or a polyfill, which will transform the dynamic import calls, so the following code will work in browsers:
const namespace = await import('https://example.com/bundle.js');
console.log(namespace.exportedSymbol);
If not, maybe it could be converted to SystemJS imports instead, so the SystemJS loader could be used in runtime to load the external bundle?
// transformed code:
import System from 'systemjs';
const namespace = await System.import('https://example.com/bundle.js');
console.log(namespace.exportedSymbol);
I don't want to implement the dynamic loading myself with XHR/Fetch and I want the source code to be as close to where EcmaScript is going as possible (future compatibility).
Upvotes: 2
Views: 4548
Reputation: 717
I am looking to implement the above approach and wants to dynamically load the chunk by url. So the url would be external something like http://example.com/some-library/lib.chunk.js
. I am using webpack and can't use any other builder like rollup. Also apart from new import the old import should also work as it is.Any idea how we can replace the import to new Import so that when i try something like import('http://example.com/some-library/lib.chunk.j').then(result => console.log(result))
. I also tried to add webpackIgnore: true for import as i read that dynamic import is available in Webpack v.2+ (I have v4.6) but it didn't work out.
Upvotes: 0
Reputation: 28611
The first thing I should mention is that import
is a special keyword in EcmaScript, so there is no possibility to polyfill it transparently.
The only option is to call another function, which will detect if dynamic imports are supported natively and switch the implementation accordingly.
The good news is that Rollup has an option output.dynamicImportFunction
, which allows to rename the dynamic imports during compilation, so you could have a standard imports in your source code.
So, if you are using SystemJS you could set it to:
{
output: {
dynamicImportFunction: 'System.import',
},
}
Webpack has a built-in mechanism for transforming dynamic imports, but it's more tailored for the code splitting use case and doesn't work with external imports. I believe you could tell Webpack to ignore such imports using the import(/* webpackIgnore: true */ 'https://example.com/bundle.js');
construct, but you will also need to replace import
function name with something else using text replacement plugin or something along the lines.
Looks like the best polyfill for dynamic imports is the dynamic-import-polyfill by GoogleChromeLabs.
You can initialize it like this in your entry point:
import dynamicImportPolyfill from 'dynamic-import-polyfill';
dynamicImportPolyfill.initialize();
You could also pass a base URL from which relative URLs will be resolved and the name of the function that should be polyfilled (it's __import__()
) by default.
In order to use it with Rollup you will need the following config:
{
output: {
dynamicImportFunction: '__import__',
},
}
Or you will need to replace import()
with __import__()
in Webpack using a replacement plugin.
The drawback of this polyfill is that it's relying on some ESM features, which are not supported in legacy browsers, so it won't work in Internet Explorer 11 for example.
Also, it's using dynamically created scripts with code content passed as a blob src. If you are using CSP policies, you should update them to allow usage of the blob:
URLs.
Upvotes: 1