【总结】1252- 导入 ES Modules 的新姿势!
共 2134字,需浏览 5分钟
·
2022-03-08 00:29
现代浏览器支持了ES Modules[1],也就是浏览器原生支持的 JavaScript 模块化方案。虽然考虑兼容性,我们还很少能够把 ES Modules 用于生产环境,但是在开发、测试、学习的场景中,ES Modules 发挥了越来越大的作用,比如构建工具Vite[2],就利用 ES Modules 来快速提供开发调试环境。React 和 Vue 框架的学习中,也都可以利用 ES Modules 不用安装本地构建工具,直接在浏览器上体验这些现代框架。
不过 ES Modules 有个局限性,就是它在浏览器里能够 import 指定 URL 的模块化 JS 代码,但是不能 import 自身 HTML 文件里的模块,比如:
<script type="module">
import {createApp} from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
script>
我们没有办法做到下面这种:
<script type="module" id="foo">
export default {foo: 'foo'};
script>
<script type="module" id="bar">
import foo from '#foo'; // 我想在这里引用上面的script标签里export的对象
script>
但是如果能实现这种 inline-import,其实还挺有用的,这就意味着我们可以在像 CodePen 这样简单的 Playground 环境中使用多个 JavaScript 模块,而不用把它们先发布成在线的 JS 文件再 import。
不过要实现 inline-import,也不是那么容易。
思路上,我们可以借助Blob[3]对象来实现,Blob 对象有一些神奇的能力,我在前端冷知识系列中分享过一篇文章《超好用的 Blob 对象!》[4],有兴趣的同学可以去看一下。
言归正传,我们可以实现一个函数,将一段 JavaScript 文本创建成 Blob 对象,并返回 Blob 对象的 URL。
function getBlobURL(module) {
const jsCode = module.innerHTML;
const blob = new Blob([jsCode], {type: 'text/javascript'});
const blobURL = URL.createObjectURL(blob);
return blobURL;
}
接着我们实现一个 inlineImport 函数:
// https://github.com/WICG/import-maps
const map = {imports: {}, scopes: {}};
window.inlineImport = async (moduleID) => {
const {imports} = map;
let blobURL = null;
if(moduleID in imports) blobURL = imports[moduleID];
else {
const module = document.querySelector(`script[type="inline-module"]${moduleID}`);
if(module) {
blobURL = getBlobURL(module);
imports[moduleID] = blobURL;
}
}
if(blobURL) {
const result = await import(blobURL);
return result;
}
return null;
};
上面这段代码不复杂,结合 getBlobURL,其核心就是从标签这段必须出现在所有的
type="inline-module"
的 script 标签之后,所有type="module"
的 script 标签之前。这样,我们就可以愉快地使用 inline-module 啦~有需要使用的同学,可以直接使用稀土掘金开源的 GitHub 仓库代码:github.com/xitu/inline…[5]有任何问题欢迎反馈~
参考资料
ES Modules: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Modules
[2]Vite: https://vitejs.dev/
[3]Blob: https://developer.mozilla.org/zh-CN/docs/Web/API/Blob
[4]《超好用的Blob对象!》: https://github.com/akira-cn/FE_You_dont_know/issues/12
[5]github.com/xitu/inline…: https://github.com/xitu/inline-module