找回密码
 会员注册
查看: 18|回复: 0

实现在浏览器中import内联JS模块_UTF_8

[复制链接]

9

主题

0

回帖

28

积分

新手上路

积分
28
发表于 2024-10-1 08:19:35 | 显示全部楼层 |阅读模式
现代浏览器支持了ES Modules[1],也就是浏览器原生支持的 JavaScript 模块化方案。虽然考虑兼容性,我们还很少能够把 ES Modules 用于生产环境,但是在开发、测试、学习的场景中,ES Modules 发挥了越来越大的作用,比如构建工具Vite[2],就利用 ES Modules 来快速提供开发调试环境。React 和 Vue 框架的学习中,也都可以利用 ES Modules 不用安装本地构建工具,直接在浏览器上体验这些现代框架。不过 ES Modules 有个局限性,就是它在浏览器里能够 import 指定 URL 的模块化 JS 代码,但是不能 import 自身 HTML 文件里的模块,比如:我们没有办法做到下面这种:但是如果能实现这种 inline-import,其实还挺有用的,这就意味着我们可以在像 CodePen 这样简单的 Playground 环境中使用多个 JavaScript 模块,而不用把它们先发布成在线的 JS 文件再 import。不过要实现 inline-import,也不是那么容易。思路上,我们可以借助Blob[3]对象来实现,Blob 对象有一些神奇的能力,我在前端冷知识系列中分享过一篇文章《超好用的 Blob 对象!》[4],有兴趣的同学可以去看一下。言归正传,我们可以实现一个函数,将一段 JavaScript 文本创建成 Blob 对象,并返回 Blob 对象的 URL。functiongetBlobURL(module){constjsCode=module.innerHTML;constblob=newBlob([jsCode],{type:'text/javascript'});constblobURL=URL.createObjectURL(blob);returnblobURL;}接着我们实现一个 inlineImport 函数://https://github.com/WICG/import-mapsconstmap={imports:{},scopes:{}};window.inlineImport=async(moduleID)=>{const{imports}=map;letblobURL=null;if(moduleIDinimports)blobURL=imports[moduleID];else{constmodule=document.querySelector(`script[type="inline-module"]${moduleID}`);if(module){blobURL=getBlobURL(module);imports[moduleID]=blobURL;}}if(blobURL){constresult=awaitimport(blobURL);returnresult;}returnnull;};上面这段代码不复杂,结合 getBlobURL,其核心就是从标签这样实现可以解决大部分问题,但是用起来还是不爽,因为这样只能动态 import。事实上,我们希望也能够以静态的方式 import,比如const foo = (await inlineImport('#foo')).default;可以写成import foo from '#foo';实际上这个也是可以实现的,要用到现代浏览器的另一个特性,importmap。importmap 本来是为了解决 ES Modules 引入模块的别名问题,比如我们觉得下面的代码写得不爽,因为 import 的 URL 太长了。可以改成:也就是在前面加一个给要 import 的模块 URL 加一个别名就行了。不过要注意,importmap 使用有限制,首先页面上只能有一个type="importmap"的 Script 标签,多个是不支持的,另外 importmap 的位置要在所有或者要用到自定义的 importmap 的时候可以这么写:只是需要注意的是,这段必须出现在所有的type="inline-module"的 script 标签之后,所有type="module"的 script 标签之前。这样,我们就可以愉快地使用 inline-module 啦~有需要使用的同学,可以直接使用稀土掘金开源的 GitHub 仓库代码:github.com/xitu/inline…[5]有任何问题欢迎反馈~参考资料[1]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
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-13 10:35 , Processed in 0.820590 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表