本文首发于于我的博客,可作为 prerender-spa-plugin
预渲染失败的参考
想着在年前把博客更新升级一下,于是顺手修复了一些已知的BUG,优化了留言模块,升级了nginx,更是为了利于SEO,在webpack的编译中加入了prerender-spa-plugin
预渲染模块。经本地window主机测试后,一切OK。这便着手在线上Linux主机中配置,nginx, node, mongod 等的升级一切顺利,但就是在项目中 npm install
的时候卡住了,而且这一卡就是一天多!难道是我安装姿势不对,需要起来重睡? 查看npm
报错原因,就出现在本文的主角phantomjs
上。关于phantomjs
,无论是在之前的项目中写单元测试,录制UIrecorder
测试用例时都遇到过,但仅仅也是遇到而已,只以为仅仅是一个依赖模块,照着文档npm install
一下,对其甚至连基本的了解都没有,于是问题就出现了。
遇到的问题
EPERM or operation not permitted or permission denied
在项目中执行npm install
安装依赖时,发生如下错误:
#...
Removing /XXX/node_modules/phantomjs-prebuilt/lib/phantom
Copying extracted folder /tmp/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2-extract-1496325965675/phantomjs-2.1.1-linux-x86_64 ->
/XXX/node_modules/phantomjs-prebuilt/lib/phantom
Phantom installation failed { Error: EACCES: permission denied, link '/tmp/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2-extract-1496325965675/phantomjs-2.1.1-linux-x86_64' -> '/XXX/node_modules/phantomjs-prebuilt/lib/phantom'
at Error (native)
errno: -13,
code: 'EACCES',
syscall: 'link',
path: '/tmp/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2-extract-1496325965675/phantomjs-2.1.1-linux-x86_64',
dest: '/XXX/node_modules/phantomjs-prebuilt/lib/phantom' } Error: EACCES: permission denied, link '/tmp/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2-extract-1496325965675/phantomjs-2.1.1-linux-x86_64' -> '/XXX/node_modules/phantomjs-prebuilt/lib/phantom'
at Error (native)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! phantomjs-prebuilt@2.1.14 install: `node install.js`
npm ERR! Exit status 1
#...
权限问题?瞅了眼终端,root
啊,懵逼了~于是去查看官方文档,在文档中有如下描述:
- You don't have write access to the installation directory.
- The permissions in the NPM cache got messed up, and you need to run npm cache clean to fix them.
- You have over-zealous anti-virus software installed, and it's blocking file system writes.
我没有执行权限?搞笑了,虽然linux我是个渣渣,但是root用户我想应该和我理解的没有区别吧~; 用 npm clean
来修复 npm
缓存权限,这个应该有可能,照着执行 npm clean --force
后继续 npm install
,问题依旧;
谷歌后发现这个问题很普遍,也在https://github.com/Medium/phantomjs/issues/707这里找到了解决方式,在命令后面加参数 --unsafe-perm
就行了,于是 rm -rf ./node_modules
后再次执行 npm install --unsafe-perm
, 这次除了一些警告外,算是安装成功了。接着执行 npm run build
, 于是第二个问题来了。
compile-to-html.js:82
/XXX/node_modules/prerender-spa-plugin/lib/compile-to-html.js:82
if (error) throw stdout
^
error Command failed with exit code 1.
这个问题之前有遇到过,是prerender-spa-plugin
预渲染过程中出错了。以为是自己代码中有什么问题,仔仔细细的检查了打包模块,没有问题,又在开发环境(Windows)中打包重试,还是没有问题。那么问题就还是出在phantomjs
上了,因为prerender-spa-plugin
是依赖phantomjs
的。
也就是说问题还是没有解决,只能继续谷歌,继续尝试,继续失败~
phantomjs
是什么?
不懂就问!
PhantomJS是一个基于WebKit的服务器端JavaScript API,它基于 BSD开源协议发布。PhantomJS无需浏览器的支持即可实现对Web的支持,且原生支持各种Web标准,如DOM 处理、JavaScript、CSS选择器、JSON、Canvas和可缩放矢量图形SVG。
phantomjs
的使用场景
-
Mocha
,UIrecorder
等无需浏览器的情况下进行快速测试 (这个有使用了解) - 页面自动化操作:使用标准的DOM API或一些JavaScript框架(如jQuery)访问和操作Web页面。
- 屏幕捕获:以编程方式抓起CSS、SVG和Canvas等页面内容,即可实现网络爬虫应用。构建服务端Web图形应用,如截图服务、矢量光栅图应用。
- 网络监控:自动进行网络性能监控、跟踪页面加载情况以及将相关监控的信息以标准的HAR格式导出。
简单可以总结为一个<mark>很牛逼的虚拟浏览器</mark>?
很遗憾,上面的使用场景,只有第一条 "Mocha
,UIrecorder
等无需浏览器的情况下进行快速测试" 中我们有过尝试,而且项目 UIrecorder
的测试用例 在linux中的自动化运行依然没有解决,难道还是和phantomjs
有关系?
如何解决的?
尝试到大半夜,玩了玩跳一跳后,灵感来了。可以先在系统中全局预安装phantomjs
作为系统服务啊。以下命令执行后真的成功了,喜极而泣~
#...
#下载
wget https://npm.taobao.org/mirrors/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2
tar -jxvf phantomjs-2.1.1-linux-x86_64.tar.bz2
#加入环境变量
vim /etc/profile
#末尾加入
export PATH=$PATH:/usr/local/phantomjs-2.1.1-linux-x86_64/bin
source /etc/profile
回到项目目录后, rm -rf ./node_modules
后再次执行 npm install --unsafe-perm
:
rm -rf ./node_modules
npm install --unsafe-perm
npm run build
哈哈哈,终于看到了我熟悉的结果:
总结
以上便是这次升级中遇到的最大问题,最终也只是以 知其结果而不知其所以然
的方式解决了问题。
在以后的学习道路上,应该对package
的依赖包有所了解,至少应该去浏览下其文档,了解其用处。对linux知识也要更深入的学习,不要因为前端的职位而只是肤浅的将知识层面停留在大学时的课本上;对前端的自动化知识(包括测试)也要跟上步伐,说不定哪天就解决了项目中在Linux上自动跑UIrecorder
测试用例的遗留问题。
参考
- https://www.npmjs.com/package/phantomjs
- https://github.com/Medium/phantomjs/issues/707
- https://github.com/chrisvfritz/prerender-spa-plugin/issues/93
- http://www.infoq.com/cn/news/2015/01/phantomjs-webkit-javascript-api
本文首发于我的博客
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。