A plugin to resolve ECMAScript module bare/url import specifiers at build-time for browsers which don't support import-maps, mostly based on WICG's import-maps reference implementation.
This plugin plays a role of polyfill for browsers but is used at build-time rather than at run-time. If some day (maybe in 2023) all major browsers support import-maps then this plugin can be retired.
Contents:
npm install --save-dev rollup-plugin-import-mapsedit rollup.config.js, import and use the plugin
import { importMapsPlugin } from 'rollup-plugin-import-maps';
// import { readFileSync } from 'fs';
export default {
input: './src/index.js',
plugins: [
importMapsPlugin({
srcPath: './index.importmap',
// srcText: readFileSync('./index.importmap', { encoding: 'utf8' }),
// srcObject: JSON.parse(readFileSync('./index.importmap', { encoding: 'utf8' })),
}),
],
output: [
{
file: './dist/index.js',
format: 'es'
}
]
};-
srcPath:string optionalfile path to importmap
-
srcText:string optionalplain text of importmap
-
srcObject:Object optionalparsed object of importmap
Note: One of
srcObject,srcText,srcPathshould be specified, if multiple of them specified, then precedence order is: srcObject, srcText, srcPath. -
baseDir: string defaultprocess.cwd()baseDir to calculate scope paths in order to match scopes defined in importmap
-
transformingReport:string defaultundefinedset a file path to save transforming report as a JSON file, will output to Console if value set to
"-" -
noTransforming:boolean defaultfalseif value set to
true, then the plugin will mark specifiers defined in importmap as external, and won't transform those specifiers. useful if you want to build for browsers which already support import-maps and "set external list" with importmap. -
exclude:string|RegExp|Function defaultundefinedskip bare/url specifiers from resolving / transforming according to importmap.
e.g.
.json,.wasm,.css,/\.(json|wasm|css)$/,(source, importer)=> /\.(json|wasm|css)$/.test(source)
-
This plugin doesn't yet support transforming module specifiers defined in data url. example data url:
import {foo, bar} from "data:application/javascript;charset=utf-8,import%20%7Bdefault%20as%20foo%7D%20from%20'foo'%3B%0Aexport%20%7Bfoo%7D%3B%0Aexport%20%7Bdefault%20as%20bar%7D%20from%20'bar'%3B";
which can be decoded as
import {default as foo} from 'foo'; export {foo}; export {default as bar} from 'bar';
-
When tansforming specifiers in dynamic imports, only string literal can be transformed. example specifiers:
import('foo/locales/en/messages.js') // Yes import("foo/locales/en/messages.js") // Yes let lang = 'en'; import('foo/locales/'+lang+'/messages.js') // No let modulePath = 'foo/locales/en/messages.js' import(modulePath) // No import(`foo/locales/en/messages.js`) // No
importmap
{
"imports": {
"three": "/node_modules/three/build/three.module.js",
"three/": "/node_modules/three/",
"underscore": "data:application/javascript;charset=utf-8,export%20default%20window._%3B",
"~/": "//mysite.com/packages/myapp/"
}
}input code
import * as THREE from 'three';
import GLTFLoader from 'three/examples/jsm/loaders/GLTFLoader.js';
import _ from 'underscore';
import '~/polyfills/navigator.userAgentData.js';
console.log(THREE, GLTFLoader, _);output code
import * as THREE from '/node_modules/three/build/three.module.js';
import GLTFLoader from '/node_modules/three/examples/jsm/loaders/GLTFLoader.js';
import _ from 'data:application/javascript;charset=utf-8,export%20default%20window._%3B';
import '//mysite.com/packages/myapp/polyfills/navigator.userAgentData.js';
console.log(THREE, GLTFLoader, _);importmap
{
"imports": {
"https://unpkg.com/three@0.141.0/build/three.module.js": "/node_modules/three/build/three.module.js",
"node-modules:/": "/node_modules/",
"data:application/javascript;charset=utf-8,export%20default%20window._%3B": "/underscore/underscore-esm-min.js",
"app-home:/": "//mysite.com/packages/myapp/"
}
}input code
import * as THREE from 'https://unpkg.com/three@0.141.0/build/three.module.js';
import GLTFLoader from 'node-modules:/three/examples/jsm/loaders/GLTFLoader.js';
import _ from 'data:application/javascript;charset=utf-8,export%20default%20window._%3B';
import 'app-home:/polyfills/navigator.userAgentData.js';
console.log(THREE, GLTFLoader, _);output code
import * as THREE from '/node_modules/three/build/three.module.js';
import GLTFLoader from '/node_modules/three/examples/jsm/loaders/GLTFLoader.js';
import _ from '/underscore/underscore-esm-min.js';
import '//mysite.com/packages/myapp/polyfills/navigator.userAgentData.js';
console.log(THREE, GLTFLoader, _);You may use rollup to build two distributions, for browsers with or without import-maps support, and load corresponding distribution conditionally. e.g.
// rollup.config.js
export default [
{
input: './src/index.js',
plugins: [
importMapsPlugin({
srcPath: './index.importmap',
transformingReport: '-',
}),
],
output: [
{
file: './dist/index.js',
format: 'es'
}
]
},
{
input: './src/index.js',
plugins: [
importMapsPlugin({
srcPath: './index.importmap',
noTransforming: true,
}),
],
output: [
{
file: './dist/index-experimental.js',
format: 'es'
}
]
}
];<script type="importmap">
put content of ./index.importmap here
</script>
<script type="module">
if (HTMLScriptElement.supports && HTMLScriptElement.supports('importmap')) {
console.log('Your browser supports import maps.');
import('/dist/index-experimental.js');
}else{
console.log('Your browser doesn\'t support import maps.');
import('/dist/index.js');
}
</script>- import-maps - Reference implementation playground for import maps proposal
Other licenses of dependencies
- import-maps: W3C Software and Document License and W3C CLA