Remix 1.16版本中如何使用await import实现模块条件导入?
Remix 1.16版本中如何使用await import实现模块条件导入?
嘿,我来帮你梳理下这个问题~你遇到的GlobalWorkerOptions为undefined的情况,主要是pdf.js的模块导出特性加上Remix的SSR环境导致的,咱们一步步来解决:
首先,排查导入和导出的适配问题
你之前的导入路径是pdfjs-dist/build/pdf,但不同版本的pdfjs-dist导出结构可能不一样,而且在ES模块环境下,它大概率是通过default导出核心对象的。试试调整导入语句,同时兼容两种导出方式:
if (typeof document !== "undefined") { // 动态导入模块,同时兼容default导出和直接导出 const pdfModule = await import('pdfjs-dist'); const pdfJS = pdfModule.default || pdfModule; // 现在再看看GlobalWorkerOptions console.log(pdfJS.GlobalWorkerOptions); }
之前拿到undefined很大概率是因为你直接取了模块的顶级导出,但实际需要的是它的default导出对象。
然后,别忘了配置Worker路径
你已经把pdf.worker.min.js复制到了public目录,这一步是对的,但导入pdf.js后必须手动指定Worker的路径,否则它找不到对应的Worker脚本:
if (typeof document !== "undefined") { const pdfModule = await import('pdfjs-dist'); const pdfJS = pdfModule.default || pdfModule; // 配置Worker的公共路径,因为文件在public根目录下 pdfJS.GlobalWorkerOptions.workerSrc = '/pdf.worker.min.js'; // 现在应该能正常访问GlobalWorkerOptions了 console.log(pdfJS.GlobalWorkerOptions); }
更贴合Remix的做法:用Client组件隔离客户端逻辑
Remix推荐把仅在客户端运行的逻辑放在client后缀的组件里,这样就不用每次都判断document是否存在了,代码会更干净:
- 创建一个
PDFHandler.client.tsx组件:
import { useEffect, useState } from 'react'; export default function PDFHandler() { const [pdfJS, setPdfJS] = useState(null); useEffect(() => { const loadPDFLib = async () => { const pdfModule = await import('pdfjs-dist'); const pdf = pdfModule.default || pdfModule; pdf.GlobalWorkerOptions.workerSrc = '/pdf.worker.min.js'; setPdfJS(pdf); }; loadPDFLib(); }, []); // 加载完成前可以显示加载状态 if (!pdfJS) return <div>加载PDF工具中...</div>; // 这里写你的PDF处理逻辑,比如渲染PDF、解析内容等 return <div>PDF工具已就绪</div>; }
- 在你的路由组件里导入这个Client组件:
import PDFHandler from './PDFHandler.client'; export default function YourRoute() { return ( <div> <h1>PDF处理页面</h1> <PDFHandler /> </div> ); }
额外提醒
- 确认你安装的pdfjs-dist版本,如果是较新的版本,可能已经支持ES模块的直接导出,不用取
default,但兼容写法能覆盖更多情况; - 如果你不想手动复制Worker文件,也可以尝试使用
pdfjs-dist/webpack版本,它会自动处理Worker的打包,但配置起来相对复杂,手动复制到public是更简单的方案。
备注:内容来源于stack exchange,提问作者MarcosCunhaLima
相关产品推荐
相关产品推荐

