HTML中不能直接使用import语句,必须通过type="module"声明模块脚本且仅限顶层作用域;import为静态声明,import()为动态函数调用并返回Promise;ESM需配合import.meta.url、自定义元素、constructable stylesheets等实现真正HTML模块化,并注意兼容性与路径解析。

HTML里不能直接用import
浏览器原生不支持在普通<script>标签里写import语句——哪怕加了type="module",也只允许在模块脚本中使用import,且必须是顶层作用域。直接写<script>import { foo } from './utils.js'</script>会报Uncaught SyntaxError: Cannot use import statement outside a module。
常见错误场景:
- 把
import写在内联<script>里(没加type="module"或加了但路径不对) - 试图在非ESM上下文(比如传统
<script src="..."></script>加载的脚本)中调用import()动态导入,却忘了它返回的是Promise - 用
import加载CSS或HTML文件——原生ESM只认JS,其他类型需额外处理(如import.meta.url配合fetch)
import和import()不是一回事
import是静态声明,必须写在模块顶层,编译期解析依赖;import()是动态函数调用,返回Promise,可在任意位置执行,适合按需加载。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 静态导入写法:
import { render } from './ui.js';—— 适用于启动即需、确定依赖的模块 - 动态导入写法:
const { default: Chart } = await import('./chart.js');—— 适合路由切换、用户操作触发的模块加载 - 动态导入不支持裸specifier(如
import('lodash')),必须是相对/绝对路径或完整URL(import('./node_modules/lodash/index.js')) - 打包工具(如Vite、Webpack)会对
import()自动做代码分割,但原生环境不会——要自己确保路径可访问
HTML模块化 ≠ 把JS拆开就完事
真正在HTML层面做模块化,核心是让组件、样式、逻辑能被声明式复用,而不仅是JS文件拆分。ESM只是其中一环,还需配合:
-
<script type="module">标记:所有模块脚本默认defer,且有独立作用域,不会污染window -
import.meta.url:获取当前模块路径,用于相对资源定位(比如fetch(new URL('./template.html', import.meta.url))) - 自定义元素(Custom Elements):把
import来的类注册为customElements.define('my-card', Card),才能在HTML中写<my-card></my-card> - CSS模块化要靠
constructable stylesheets(new CSSStyleSheet())+adoptedStyleSheets,否则import './style.css'根本不会生效
ESM在HTML中的兼容性陷阱
Chrome 61+/Firefox 60+/Safari 11.1+ 支持原生ESM,但IE全系、老Android WebView、部分微信内置浏览器仍不支持。不是“加个type="module"就万事大吉”。
关键判断点:
- 用
<script nomodule src="fallback.js"></script>兜底传统脚本(注意:nomodule只对不支持ESM的浏览器生效) - 动态
import()在旧浏览器中会直接报import is not a function,需提前检测:if (typeof import === 'function') { ... } - 模块路径必须是有效URL:相对路径基于
import.meta.url,不是HTML文档URL;服务器需正确返回Content-Type: text/javascript,否则Chrome会拒绝执行 - Vite等开发服务器默认支持
.html作为入口,但生产环境部署时,若用hash路由或子路径,import的相对路径容易404——得配base或用import.meta.env.BASE_URL
模块化真正卡住人的地方,往往不是语法,而是路径解析时机、资源加载顺序、以及浏览器对“模块”的定义比开发者想象中更严格。



















