解决 vue-pdf 打包后跨域报错

vue 搭建的项目中,很多部署方式是将HTMl页面放到一个服务器上,js、css这些静态资源放到另一个服务器上,这种部署方式可能会带来一些问题,标题中描述的 vue-pdf 报错就属于这种情况;

背景

vue-pdf 是一个 pdf 展示库,默认白色背景,比浏览器下默认黑底的效果要好;而且提供了一些 API,能很方便的操作PDF文档;基本原理是将 PDF 绘制到 Canvas 中;

报错

打包后,html 放到 b.com 上,js、css 静态资源放到 a.com 上;访问展示PDF的页面,报下面这种错误:

Uncaught DOMException: Failed to construct 'Worker': 
Script at 'http://a.com/ef3086d432cfbec65966.worker.js' 
cannot be accessed from origin 'http:/b.com'.

错误信息是说不能在 b.com 中跨域加载 xx.worker.js;

查看 vue-pdf 源码,发现里边用了 web worker,worker 里大体是包含了一些将 PDF 转到 Canvas 中的一些计算工作;

worker 是不能跨域的,将页面和静态资源分开的场景,就会出现跨域问题;

*解决方案1

node_modules/vue-pdf/src/vuePdfNoSss.vue 中,有一个 Worker 支持的判断,注释掉重新打包就可以了;

// 注释if内的两句代码或者注释整个if语句
if ( typeof window !== 'undefined' && 'Worker' in window && navigator.appVersion.indexOf('MSIE 10') === -1 ) {
  // var PdfjsWorker = require('worker-loader!pdfjs-dist/build/pdf.worker.js');
  // PDFJS.GlobalWorkerOptions.workerPort = new PdfjsWorker();
}

注释掉上面的代码,就不走 web worker 了,页面能够正常运行了;相对的,页面加载时间可能会变长,性能可能会降低;

维护

通过修改源码的方式,将 worker 跨域报错的问题解决了,但是又带来了一个维护方面的问题:

vue-pdf 是通过 npm 安装到 node_modules 中的,使用 Git 或其他版本控制工具时,肯定不会将 node_modules 加到版本控制里的;
这样,其他人在获取代码时,上面的改动并没有同步到本地,部署后还是会报错;

目前,我的做法,是在项目的 Readme 里添加说明,在对应的代码处添加 TODO 说明,一般可能都不会看注释、说明文档,所以必要时,还要口述该改动;但这并不是一个可持续的标准做法,无法自动化实现;

解决方案2

自动化的标准做法:添加自定义 loader,在加载 vue-pdf 代码时,将需要注释的代码(字符串)替换为空串或注释掉,这样就不会有维护问题了,具体的解决方案之后会整理到下面;

如果这篇文章对你有用,可以点击下面的按钮告诉我

4

发表回复