esModule内联代码的导入导出实现

2024年 5月 7日 47.1k 0

背景

浏览器层面的esModule在设计的时候不太完美,只能import外部JS,如果某个<script type="module">是通过内联代码直接写在HTML里面的反而没法导入:

<script type="module">export default 123;</script>
<script type="module">
// 无法导入上面的模块代码
</script>

只能改成下面这样:

// test.js
export default 123;

然后再导入单独的JS文件:

<script type="module">
import test from './test.js';
console.log(test);
</script>

hack

虽然这么做没啥实际意义,但我就偏不信这个邪,非得试试,实现之后可以比较方便写一些简单测试代码。既然浏览器只能导入外部JS文件,那我们就给它生成外部文件就好了:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>测试内联代码导入导出</title>
<script>
// 预编译带 text/babel 的script标签,处理 import
function preCompileInlineModuleScript() {
const srcMap = {}; // 存储所有内联模块的blob src地址
[...document.querySelectorAll('script[type="text/module"]')]
.map((script, idx) => {
// 如果未通过 data-module 指定模块名,生成类似 module0 的默认名称
const moduleName = script.dataset?.module || `module${idx}`;
const url = URL.createObjectURL(new Blob([script.textContent], { type: 'text/javascript' }));
srcMap[moduleName] = url;
return script;
})
.forEach(script => {
const { src, textContent, dataset } = script;
if (!textContent) {
return;
}
// 自动检索类似 `import Demo from 'demo'` 这样的代码
const newContent = textContent.replace(/(?<=import .+['"])(.+)(?=['"][;\n])/g, (m, src) => srcMap[src] || src);
const ele = document.createElement('script');
ele.textContent = newContent;
ele.type = 'module';
script.parentNode.insertBefore(ele, script); // 依次插在原script前面
script.remove();
});
}

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论