如何在 Inertia.js SSR 中正确使用动态导入避免 ES 模块错误

2次阅读

如何在 Inertia.js SSR 中正确使用动态导入避免 ES 模块错误

本文详解 inertia.js + vue 3 服务端渲染(ssr)配置中因混合使用 commonjs require() 与 es 模块导致的运行时错误,并提供兼容性修复方案、完整 ssr 入口代码及关键注意事项。

本文详解 inertia.js + vue 3 服务端渲染(ssr)配置中因混合使用 commonjs require() 与 es 模块导致的运行时错误,并提供兼容性修复方案、完整 ssr 入口代码及关键注意事项。

在基于 AdonisJS(或类似 Node.js 框架)集成 Inertia.js 实现 Vue 3 SSR 时,一个常见但易被忽略的陷阱是模块系统不匹配。错误信息明确指出:

require() of ES Module ...@inertiajs/vue3/dist/index.js ... not supported.

根本原因在于:你的 ssr.js 文件作为 ES 模块(由 import 语句和 package.json 中 “type”: “module” 触发),却调用了 CommonJS 风格的 require() 动态加载页面组件——而现代 ES 模块规范中,require() 不可用,必须改用 import()(返回 promise 的动态导入)。

✅ 正确写法:将 require() 替换为 import()

修改 resources/js/ssr.js 中的 resolve 函数,必须使用异步 import() 并确保返回 Promise(Inertia SSR 内部会 await 它):

// resources/js/ssr.js import { createSSRApp, h } from 'vue' import { renderToString } from '@vue/server-renderer' import { createInertiaApp, Link } from '@inertiajs/vue3'  export default async function render(page) {   return createInertiaApp({     page,     render: renderToString,     // ✅ 关键修复:使用 import() 返回 Promise,而非 require()     resolve: (name) => import(`./Pages/${name}.vue`),     setup({ app, props, plugin }) {       const root = createSSRApp({         render: () => h(app, props),       })       root.use(plugin)       root.component('inertia-link', Link)       return root     },   }) }

? 注意文件扩展名:显式添加 .vue 后缀(如 ./Pages/${name}.vue),避免 webpack/Vite 或 Node.js ESM 解析器因无后缀而失败。若使用 Vite SSR,还需确保 ssr.js 在构建配置中被正确识别为 SSR 入口。

⚠️ 其他关键注意事项

  • Node.js 版本要求:确保使用 Node.js ≥ 18.12(推荐 ≥ 18.18 或 ≥ 20.9),以获得稳定 ESM 支持和 import() 在服务端的可靠行为。
  • SSR 构建与入口一致性:若项目使用 typescript,请确认 ssr.js 对应的 .d.ts 类型声明或通过 ts-node/esbuild 正确转译;AdonisJS 用户需确保 ace ssr:watch 命令能识别并监听该文件变更。
  • 页面组件导出规范:所有 ./Pages/*.vue 文件必须默认导出一个 Vue 组件(支持 <script setup> 语法),且不能依赖浏览器专属 API(如 window、document),否则 SSR 渲染将抛错。</script>
  • 开发环境热重载:inertia.ssr.autoreload: true 仅控制 Inertia 自身的 SSR 服务重启逻辑,实际需配合框架(如 AdonisJS 的 –watch)实现文件变更自动重建。

? 验证是否生效

执行以下命令启动 SSR 服务:

node ace serve --watch node ace ssr:watch

若不再出现 require() of ES Module 错误,且访问页面时 HTML 中包含已服务端渲染的

内容(可查看源码验证),即表示修复成功。

总之,在 ES 模块环境下,import() 是唯一合规的动态模块加载方式。坚持这一原则,不仅能解决当前 Inertia SSR 报错,更能规避未来因模块混用引发的隐蔽兼容性问题。

text=ZqhQzanResources