-
-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ability to import UMD modules #18
Comments
I can't answer for @guybedford but my guess it is out of scope for this shim. What you can do is bundle the UMD into an ESM. There are a few tools you can use, maybe rollup. |
That was my first guess too. But I thought maybe if you guys went ahead and added support for import maps, then UMD would be a nice addition too. The thing is I’m not in control how NPM packages are published, and above mentioned React case is totally out of my influence, moreover it’s a long going discussion there. I was experimenting with React and for now I created a super dirty solution https://github.com/kirill-konshin/pure-react-with-dynamic-imports/blob/master/public/sw.js#L19 - use a Service Worker to patch the react sources on the go. The problem with their UMD dist is that global (this) is not defined when UMD is imported, so the entire file is useless. |
i would not really expect ideally i think our goal should be to drag legacy packages, kicking and screaming, into the future of esm ;) @kirill-konshin, there might be three interesting branches on the tree of solutions here
considering limited time and resources, i think you should consider grabbing rollup and going that way — unless you want to donate time to the community and/or use react with es-module-shims, in which case you might opt to do the forking — otherwise we can pray for luck that guy bedford will take the third option because maybe he's already done similar work in systemjs, and is a wizard from what i can tell food for thought.. what do you think? cheers! 👋 |
@chase-moskal a very nice overview of the space :) Yes the goal of this project is exactly to be entirely polyfill-like, ideally such that you can develop in modern browsers, and ship this as a shim for older browsers. We're still a ways off that sort of mode, but any work in these directions is always welcome. UMD does fall outside of those goals, although if there is an easy way to support it as an addon (see how SystemJS does extras), or if you want to fork this project and explore the space, please feel free. For the (2) case, this is exactly what jspm 2.0 does in converting CJS to ESM on install from npm, and ideas to improve the experience there are very welcome. Yes handling the conversion layer at the package layer would be ideal, but while packages still need to support legacy environments, building direct ESM ecosystems remains the other approach here, sort of like what Pika is doing. How we convert packages to be directly ESM will be a tough process at first, but will be a lot easier once it is the default to support modules in Node.js 12 and enough users have moved over to that. |
I do agree that conversion may not be the focus of this package. But I strongly disagree that custom package or custom install converter is a good idea. The whole point is to eliminate as many build steps as possible, so like I showed in my example, I already spent some time and found a viable solution (Service Worker). It just has to become more generic than straightforward replace. And it could be done as a plug-in, yep. Can you give me some information how to make a plug-in for the shim? |
@kirill-konshin perhaps we could add a |
Here's the other way, also via Service Worker, quite elegant. The idea is to inject UMD as-is into the page and then // this is needed to activate the worker immediately without reload
//@see https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle
self.addEventListener('activate', event => clients.claim());
const globalMap = {
'react': 'React',
'react-dom': 'ReactDOM'
};
const getGlobalByUrl = (url) => Object.keys(globalMap).reduce((res, key) => {
if (res) return res;
if (matchUrl(url, key)) return globalMap[key];
return res;
}, null);
const matchUrl = (url, key) => url.includes(`/${key}/`);
self.addEventListener('fetch', (event) => {
const {request: {url}} = event;
console.log('Req', url);
if (Object.keys(globalMap).some(key => matchUrl(url, key))) {
event.respondWith(
fetch(url)
.then(response => response.text())
.then(body => new Response(removeSpaces(`
const head = document.getElementsByTagName('head')[0];
const script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.appendChild(document.createTextNode(${JSON.stringify(body)}));
head.appendChild(script);
export default window.${getGlobalByUrl(url)};
`), {
headers: new Headers({
'Content-Type': 'application/javascript'
})
})
)
)
}
}); Here's what I've done here:
The code above makes sure that it's executed as a regular script, so we won't have issues with sudden strict mode when the original package was not designed for it. |
I think wrapper approaches like the above make a lot of sense, and would be preferable to trying to include it in this project since they would also in theory work with native ES modules. |
Currently UMD modules (like
react
orreact-dom
) cannot be imported directly.I was exploring the current state and found out that, for example, React is published only as UMD, they have a ticket to add ES6 modules to the published versions. But it's a long awaited feature and there's no conclusion on how to export.
Maybe it is possible to address this feature in this library then? It would be a nice step forward.
Some other useful links:
The text was updated successfully, but these errors were encountered: