歡迎關注富途web開發團隊,php , 前端需要你。缺人從眾
富途一天天的在成長,小夥伴們也越來越多。前端的更新迭代,一直都在進行。Vue已經作為前端的主要開發框架,想想2年前,我還在寫JQ
,後面寫angular.js
。前端打包也從原來的打包檔案提交入Gitlab庫,到後來接入jenkins(打包檔案不入庫),再到今天的Gitlab CI。
敢於嘗試,推動落地執行。
今天給大家分享一下前端打包接入Gitlab CI遇到的坑。
另外附帶一個用於下載Gitlab CI 打包檔案的元件:檢視元件
背景
對的,最近寫文章都會交代一下背景。因為按標題的套路,這本應該是一篇教程類的文章,但這種文章其實挺無趣的。之所以想寫這篇,是因為確實碰到了一些很麻煩的事情。閒言少敘,我們進入正題。
最近我們前端程式碼打包正在接入Gitlab CI,使用Docker來作為Executor,也就是在Docker中進行前端程式碼打包,然後收集打包結果,以備釋出時使用。打包時Docker映象很自然地就選擇了官方Node映象,最新版本(Node 10)。
一開始我們嘗試性地接入了幾個專案,有使用NPM scripts進行打包的,也有使用Gulp進行打包的,一切都很正常。但是昨天在接入一個新專案,使用Gulp打包的時候,卻突然碰到了報錯:
$ gulp gitlab-ci
gulp[85]: ../src/node_contextify.cc:631:static void node::contextify::ContextifyScript::New(const v8::FunctionCallbackInfo<v8::Value>&): Assertion `args[1]->IsString()` failed.
Aborted
ERROR: Job failed: exit code 134
複製程式碼
看了一眼這個錯誤資訊,一下子就發現,這並不是來自JS層的錯誤,而是來自Node原生層,這就超出了我的理解範圍了。
模組版本相容問題
通過搜尋,首先找到一篇中文的解決方案:升級node10後gulp報錯的解決辦法。文中給出瞭如下解決辦法:
rm -fr node_modules
rm -fr package-lock.json
npm cache clean --force
npm install
複製程式碼
所以這是什麼原理呢?沒看到文章有解釋,另外這文章本身也寫得不是很清楚。抱著半信半疑的態度,在CI的指令碼中加上了npm cache clean --force
,結果問題依舊。
接著搜尋了一下,很快發現一些和這個問題有關的issue:
- nodejs/node: node 10.0.0安裝模組時core dump
- nodejs/node: 新發布的版本與Gulp ^3.9.0不相容
- gulpjs/gulp: 將graceful-fs的升級合併回Gulp 3
- gulpjs/gulp: node 10中崩潰
- isaacs/node-graceful-fs v3.x分支與Node.js master不相容
- isaacs/node-graceful-fs v3.0.11依賴natives 1.1.1,後者與node 10不相容
通過npm ls
,一下子就看到了natives
模組的版本是1.1.1,於是定位到真正的問題:gulp
依賴vinyl-fs
,vinyl-fs
依賴graceful-fs
,graceful-fs
依賴natives
,而natives
在1.1.3之前都不相容Node 10。
那麼解決方案就簡單了,想辦法升級一下模組不就好了?
如何升級間接依賴
首先想到的是Gulp是否有解決這個問題,npm info gulp
看了一下,發現最新版本是3.9.1
,然後npm ls
一下,發現本機裝的已經是3.9.1
了,也就是說,Gulp根本沒有升級的可能。那要如何升級這個間接的依賴呢?
這裡我繞了個彎子,package.json
中直接依賴的模組無法升級,npm update
也不能搞定。於是想到,如果顯式安裝一下這個模組,是不是能解決問題?
npm install natives@1.1.3
複製程式碼
安裝完之後還要在package.json
中將直接依賴natives
刪除(因為我並不直接依賴它,留著沒用)。然後再次檢視依賴:
▶ npm ls natives
seed@1.0.0 /Users/TooBug/work/oa/learn/frontend
└─┬ gulp@3.9.1
└─┬ vinyl-fs@0.3.14
└─┬ graceful-fs@3.0.11
└── natives@1.1.3
複製程式碼
這次對了。
但是,這個操作我是在本機進行的,這個操作到底改了什麼呢?如果去CI上再次執行npm install
,會不會依然安裝到舊版本呢?畢竟package.json
並沒有任何改動。
於是翻看了一下git diff
,發現了本文的主角package-lock.json
被修改了,其中的natives
由1.1.1變成了1.1.3。
"natives": {
"version": "1.1.3",
"resolved": "http://registry.npm.oa.com/natives/download/natives-1.1.3.tgz",
"integrity": "sha1-RKV5vmRQfqLW7RygSpQVkVz3VVg="
},
複製程式碼
於是怦然大悟:本來npm在安裝模組是是按語義化版本安裝最新版的,但是在CI上卻沒有安裝natives
1.1.3版本,而是安裝了natives
1.1.1版本,這正是因為package-lock.json
裝版本鎖定了,從而導致了與Node 10的不相容問題。
這也能很好地解釋,為什麼其它專案沒有這樣的問題,因為其它的專案在程式碼倉庫中沒有包含package-lock.json
,在安裝時自然就安裝了natives
1.1.3版本。
於是再回頭看一開始搜到的文章提出的解決辦法:
rm -fr node_modules
rm -fr package-lock.json
npm cache clean --force
npm install
複製程式碼
其實是非常有效的,因為它將package-lock.json
直接刪除了,然後重新安裝一遍最新版本,生成新的package-lock.json
,從而解決問題。
延伸:如何正確地在專案中使用package-lock.json
最後,也補充說明一下package-lock.json
的正確用法。(雖然我知道,但還是不小心踩坑了。如果不清楚它的用法的話,可能會在坑裡待更長時間爬不出來。)
首先,需要確保npm
的版本在5.6以上,因為在5.0 – 5.6中間,對package-lock.json
的處理邏輯更新過幾個版本。5.6以上的才是符合認知的邏輯。
然後,在專案中如果沒有鎖版本的必要,可以不使用package-lock.json
,在安裝模組時指定--no-lock
即可。
如果專案中有package-lock.json
,則安裝模組時會以這個檔案中指定的版本和地址為準,直接下載安裝。(除非它和package.json
中指定的版本不相符。)
最後,如果已經鎖定了版本的情況下,需要更新直接依賴,則直接安裝指定版本,package.json
和package-lock.json
都會同步更新。如果需要更新間接依賴的話,則需要像本文這樣,手工安裝一下,保證package-lock.json
被更新到。或者如果其它模組的鎖定並不是那麼重要時,也可以直接刪除package-lock.json
,然後重新安裝一遍,相當於把所有(直接依賴+間接依賴)模組全部更新一遍。
原文連結:檢視原文