Closed hechuan9 closed 1 year ago
直接 import { Document, Page } from 'react-pdf'
require is not defined
是因为你这种引入方式被当作业务代码而不是第三方代码被vite处理。直接使用 bare import。使用配置项也有办法解决但对大多数人来说理解难度过大,建议使用上面的方案或下面的方案。
参考
只在客户端阶段使用
我试了下这段代码
import React, { useState, useEffect } from 'react'
let reactpdf = {}
export default function AllPages (props) {
useEffect(() => {
initReactPdf()
}, [])
const initReactPdf = async () => {
reactpdf = await import('react-pdf/dist/esm/entry.vite')
console.log('react-pdf', reactpdf)
}
const { pdf } = props
console.log(props)
return (
123
)
}
然后错误变成了
Uncaught (in promise) TypeError: Failed to construct 'URL': Invalid URL
我打开看了下,在react-pdf/dist/esm/entry.vite
中,有句pdfjs6.GlobalWorkerOptions.workerSrc = new URL("pdfjs-dist/build/pdf.worker.js"
,程序是找不到pdfjs这个module。
我的理解是,pdfjs并没有在客户端被载入,这样理解对不对?请问怎么载入?
我试了默认ssr的controller,和把model调整csr
的controller,但是都是同样的错误。
import React, { useState, useEffect } from 'react'
import { Document, Page } from 'react-pdf'
let reactpdf = {}
export default function AllPages(props) {
const [numPages, setNumPages] = useState(null)
function onDocumentLoadSuccess({ numPages }) {
setNumPages(numPages);
}
const { pdf } = props;
console.log(reactpdf)
return (
<Document file={pdf} onLoadSuccess={onDocumentLoadSuccess}>
{Array.from(new Array(numPages), (el, index) => (
<Page key={`page_${index + 1}`} pageNumber={index + 1} />
))}
</Document>
)
}
BaseImport 也不行 报错是
Uncaught SyntaxError: Unexpected token '<' (at pdf.worker.js:1:1)
这个pdf.worker.js长这样
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><title>Serverless Side Render</title><script src="/@vite/client" type="module"></script><script type="module"> import RefreshRuntime from "/@react-refresh"
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true</script></head><body><div id="app"></div><script>window.prefix="/";</script><script>window.__USE_VITE__=true</script><script type="module" src="/node_modules/ssr-plugin-react/esm/entry/client-entry.js"></script></body></html>
我在FAQ里看到了,onlyCsr个选项,我的理解是也可以实现获取客户端的react-pdf的功能?
import React, { useState, useEffect } from 'react'
import { Document, Page } from 'react-pdf/dist/esm/entry.vite'
import { onlyCsr } from 'ssr-hoc-react'
function PdfViewer (props) {
const [numPages, setNumPages] = useState(null)
function onDocumentLoadSuccess ({ numPages }) {
setNumPages(numPages)
}
const { pdf } = props
console.log(pdf)
return (
<Document file={pdf} onLoadSuccess={onDocumentLoadSuccess}>
{Array.from(new Array(numPages), (el, index) => (
<Page key={`page_${index + 1}`} pageNumber={index + 1} />
))}
</Document>
)
}
export default onlyCsr(PdfViewer)
但是试了好像并没有用,好像依然在服务器端在载入?
步骤一
把 pdf.worker.js
移动到本地node静态资源文件夹
"start:vite": "cp ./node_modules/pdfjs-dist/build/pdf.worker.js ./public && ssr start --vite",
"build:vite": "cp ./node_modules/pdfjs-dist/build/pdf.worker.js ./public && ssr build --vite",
步骤二
设置worker的文件路径,在客户端阶段渲染具体的pdf组件。不使用 entry.vite,其中的 new url import.meta
语法解析有问题
import React, { useContext, useState, useEffect } from 'react'
import { SProps, IContext } from 'ssr-types'
import { pdfjs } from 'react-pdf'
pdfjs.GlobalWorkerOptions.workerSrc = 'pdf.worker.js'
let Document = () => (<></>)
let Page = () => (<></>)
export default (props: SProps) => {
const [refresh, setRe] = useState(false)
useEffect(() => {
init()
})
const init = async () => {
const pdf = await import('react-pdf/dist/esm/entry')
Document = pdf.Document
Page = pdf.Page
setRe(true)
}
const [numPages, setNumPages] = useState(null)
const [pageNumber, setPageNumber] = useState(1)
function onDocumentLoadSuccess ({ numPages }) {
setNumPages(numPages)
}
return (
<div>
<Document file="report.pdf" onLoadSuccess={onDocumentLoadSuccess}>
<Page pageNumber={pageNumber} />
</Document>
</div>
)
}
我试了一下大佬的代码,但是还是出现同样的错误,我最后用了外部的pdf.worker.min.js让这个程序work的。
import React, { useState } from 'react'
import { Document, Page, pdfjs } from 'react-pdf'
pdfjs.GlobalWorkerOptions.workerSrc = '//unpkg.com/pdfjs-dist@2.16.105/build/pdf.worker.min.js'
function PdfViewer (props) {
const [numPages, setNumPages] = useState(null)
function onDocumentLoadSuccess ({ numPages }) {
setNumPages(numPages)
}
const { pdf } = props
return (
<Document file={pdf} onLoadSuccess={onDocumentLoadSuccess}>
{Array.from(new Array(numPages), (el, index) => (
<Page key={`page_${index + 1}`} pageNumber={index + 1} />
))}
</Document>
)
}
export default PdfViewer
试了下csr和ssr都能成功render。现在还有个小问题,外部的链接不是很可靠,有什么办法能把该文件放到本地并访问的?
我试了大佬提供的
"start:vite": "cp ./node_modules/pdfjs-dist/build/pdf.worker.js ./public && ssr start --vite"
, 但是并不能用,好像有个语法错误,但是改成,"start:vite": "cp ./node_modules/pdfjs-dist/build/pdf.worker.js ./public/. && ssr start --vite"
也找不到这个文件。
hmm,我搞定了,就是把pdf.worker.min.js
复制到public/js
文件夹里,然后引用改成pdfjs.GlobalWorkerOptions.workerSrc = '/js/pdf.worker.min.js'
可以关闭这个issue了...
提问前请确认以下几点信息,否则你的问题将不会被解答
详细描述你的问题
我试图在我的项目中使用wojtekmaj/react-pdf:
import { Document, Page } from 'react-pdf/dist/esm/entry.vite'
执行npx ssr start --vite
会直接报错期望的结果
找到一种正确办法引用
react-pdf
当前使用的版本
复现仓库地址
超过一行代码能描述的问题必须提供复现地址, 用默认的
example
给最简单的复现代码不要给包含着一堆业务代码的仓库你本人对问题可能的原因判断(如果你能大概判断的话)
whiteList
, 我试了但是也没什么用