问题:组件库内有一个PDF预览功能,引用了vue-pdf,(多个项目均有引用这个组件库)。项目打包build后产生worker文件,发布生产访问404
通过伟大的搜索引擎找到各种类似的解决方案:修改node_modules里的打包目录,如,vue使用vue-pdf预览开发正常,打包报错work.js404_波塞冬的博客-CSDN博客_vue-pdf
vue中使用vue-pdf打包之后预览报错hash+worker.js路径不对404_茶荼-CSDN博客_vue-pdf 打包报错
但是这个解决方案被我pass,修改node_modules不能治本,每次重新打包重新发布生产,就失效了,也不可能每次都去修改,不符合程序员一劳永逸的追求。
找到一个还不错的解决思路,给node_modules打补丁:vue-pdf问题解决及patch-package简介 - 简书
但依旧不符合我的需求,打补丁只能解决当前项目的,如果我其他项目也需要用到这个pdf预览功能,又得打一次补丁。
有什么办法可以一劳永逸?那就是打包不产生worker文件!
不通过npm引入vue-pdf包,打包就不会不产生worker文件。原来的vue-pdf可以通过script引入。
写一个添加script的方法
addScript (name, src) {
let script = document.getElementById(name)
if (!script) {
script = document.createElement('script')
script.id = name
script.src = src
document.body.append(script)
}
}
在mounted中引入脚本
脚本文件可以通过cdn下载引入,例如BootCDNpdf.js (v2.12.313) - pdf.js 是一个基于 web 标准的通用 pdf 解析和渲染库。 | BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务
mounted () {
this.addScript('pdfjs', 'https://xxxx.xxxx.com/lib/pdf.min.js')
this.addScript('pdfworkerjs', 'https:/xxx.xxx.com/lib/pdf.worker.min.js')
}
再修改一下原来写的方法
原来通过
import pdf from 'vue-pdf'
pdf.xxx 访问vue-pdf的方法
改为通过 window.pdfjsLib 即可
handlePDFView (index, file) {
this.showPDFViewer = true
this.PDFLoading = true
this.PDFScale = 1.0
this.PDFRotate = 0
this.attachment.getFileUrl(file).then(url => {
this.PDFsrc = window.pdfjsLib.getDocument({
url,
cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.2.228/cmaps/',
cMapPacked: true
})
this.PDFsrc.promise.then(pdf => {
this.PDFNum = pdf.numPages
this.numPages = pdf._pdfInfo.numPages
this.totalNumPages = pdf._pdfInfo.numPages
this.pageHeight = window.screen.height * this.numPages
this.pdfCreator(pdf, 1)
}).catch(err => {
console.error('pdf 加载失败', err)
}).finally(() => {
this.PDFLoading = false
})
}, () => {
this.$message.error('查看失败。')
this.PDFLoading = false
})
},
pdfCreator (pdf, index) {
let that = this
var className = 'container the-canvas-' + index
var div = document.createElement('DIV')
var canvas = document.createElement('CANVAS')
var gap = document.createElement('DIV')
div.setAttribute('class', className)
canvas.id = 'the-canvas-' + index
gap.setAttribute('class', 'gap')
div.appendChild(canvas)
let pdfContainer = document.getElementById('pdf-viewer-canvas')
if (index > 1) {
pdfContainer.appendChild(gap)
}
pdfContainer.appendChild(div)
pdf.getPage(index).then(function (page) {
var viewport = page.getViewport({
scale: that.PDFScale
})
let width = viewport.width
viewport = page.getViewport({
scale: 1200 / width
})
var canvas = document.getElementById('the-canvas-' + index)
var context = canvas.getContext('2d')
canvas.height = viewport.height
canvas.width = viewport.width
var renderContext = {
canvasContext: context,
viewport: viewport
}
page.render(renderContext).promise.then(function (r) {
that.renderFlag = index
if (that.renderFlag < that.numPages) {
that.pdfCreator(pdf, that.renderFlag + 1)
}
})
})
},
原先引用vue-pdf组件的地方不再使用,抛弃组件,写个新的div承接pdf canvas即可
<div class="pdf-viewer">
<div class="pdf-viewer-canvas">
<pdf :src="PDFsrc" v-for="i in PDFNum" :key="i"
style="display: flex;align-self: center"
:style="{transform: `rotate(${PDFRotate}deg)`,width: `${PDFScale * 1200}px`}"
:page="i">
</pdf>
</div>
</div>
更改为如下:
<div class="pdf-viewer">
<div class="pdf-viewer-canvas">
<div id="pdf-viewer-canvas" :style="{transform: `rotate(${PDFRotate}deg)`,width: `${PDFScale * 1200}px`}"></div>
</div>
</div>
最后试一下打包,完美!不再产生woker文件不再404,pdf预览功能也能正常使用。