前言
最近用Rails7 + hotwire + importmap 的技术站做了个AI站,下图中标黄的都是有较多异步交互的地方,项目中基本没有使用手动 Ajax 与 JSON 交互,仅使用 turbo_frame、turbo_stream 来完成交互。
这里重点说说最新的 importmap 的使用问题,也欢迎大家体验下 kittyai.cn
Importmap 的基本用法
-
importmap.rb 示例
下面是我的 config/imortmap.rb 部分内容,前面部分是脚手架生成的 hotwire 等库的配置。
这里 controller 目录里的文件是可以动态加载的,例如HTML中有某个 data-controller="message",才会加载 message_controller.js 文件。
额外引入了 highlight.js 的高亮配置,注意 importmap 是可以配置目录的。这里也发挥了其按需加载的优势,用到什么语言才加载什么语言的高亮代码。
# Pin npm packages by running ./bin/importmap
pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "https://ga.jspm.io/npm:@hotwired/stimulus@3.2.1/dist/stimulus.js"
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
pin_all_from "app/javascript/utils", under: "utils"
# For markdown preview
# https://jspm-packages.deno.dev/package/markdown-it@13.0.1
pin "markdown-it", to: "https://ga.jspm.io/npm:markdown-it@13.0.1/dist/markdown-it.js"
# For code syntax highlight
# 这里使用了路径 import https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap
pin "highlight.js/", to: "https://ga.jspm.io/npm:highlight.js@11.9.0/"
-
开启HTTPS
另外注意需要开启HTTP2,能提升多文件加载的效率,例如在Nginx要这样配置:
server {
listen 443 ssl http2
}
-
逻辑动态import
除了可以通过静态的 import 来加载依赖,代码中甚至可以动态 import(),例如
import('highlight.js/lib/languages/' + language + ".js").then((module) => {
hljs.registerLanguage(language, module.default)
hljs.highlightElement(codeElement)
}).catch(err => {
console.warn("highlight error", err)
})
遇到的问题
-
有些库对ES Module支持得不好
Javascript的库一般会说用 npm install 等来安装,会依赖 window.process 里的环境变量,所以直接在Web端引入会报错。
例如 tippy.js 这个库,我实在HTML中加了下面的代码来Fix:
<script type="application/javascript">
// Fix tippy ESM bug. https://github.com/atomiks/tippyjs/issues/990
window.process = { env: { NODE_ENV: 'production' }}
</script>
-
Importmap 不会管理 CSS
虽然JS可以通过 import 来动态还需加载了,写得很顺滑,但CSS并不会。
还是 tippy.js 的例子,需要在HTML中额外配置CSS依赖
<link rel="stylesheet" href="https://ga.jspm.io/npm:tippy.js@6.3.6/dist/tippy.css">
总结
所以要不要用 importmap 还是需要谨慎。它的优势是细粒度、动态的加载JS,但其普及度还不是很高,所以容易遇到细节问题。如果要考虑低版本浏览器,importmap的加载性能和引入的代码的兼容性都可能是问题。