作者:JowayYoung
倉庫:Github、CodePen
博客:掘金、思否、知乎、簡書、頭條、CSDN
公衆號:IQ前端
聯繫我:關注公衆號後有我的微信喲
特別聲明:原創不易,未經授權不得對此文章進行轉載或抄襲,否則按侵權處理,如需轉載或開通公衆號白名單可聯繫我,希望各位尊重原創的知識產權
前言
由於國內網絡環境的原因,在執行npm i
安裝項目依賴過程中,肯定會遇上安裝過慢
或安裝失敗
的情況。有經驗的同學通常會在安裝完Node時順便把NPM鏡像設置成國內的淘寶鏡像。
npm config set registry https://registry.npm.taobao.org/
這樣就能爽歪歪應付大部分npm i
的安裝情況了。當然,這只是解決了大部分的安裝過慢
或安裝失敗
的情況,隨着項目的深入開發,肯定還會遇上一些比較奇葩的情況,這也是筆者爲什麼要寫本文的原因。
管理鏡像
你還可能會遇上這種情況,開發項目時使用淘寶鏡像
,但是發佈NPM第三方模塊時就必須使用原鏡像
了。在着手解決那些奇葩情況前,先推薦大家使用一個NPM鏡像管理工具。
- 原鏡像:
https://registry.npmjs.org/
- 淘寶鏡像:
https://registry.npm.taobao.org/
主角就是nrm
,它是一個可隨時隨地自由切換NPM鏡像的管理工具。有了它,上面所說的何時使用什麼鏡像的問題就迎刃而解了。下面對其進行安裝並簡單講解如何使用。
安裝
npm i -g nrm
查看鏡像
nrm ls
增加鏡像
nrm add <name> <url>
移除鏡像
nrm del <name>
測試鏡像
nrm test <name>
使用鏡像
nrm use <name>
查看當前鏡像
nrm current
熟悉命令後一波操作如下,原鏡像
和淘寶鏡像
之間隨意切換。當然,如果你記性好也不需要用這個工具了,哈哈。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-beYb9O4O-1591699357746)(https://yangzw.vip/static/frontend/npm-registry/nrm操作.png)]
遇坑填坑
有了nrm
切換到淘寶鏡像上,安裝速度會明顯加快,但是遇上安裝的模塊依賴了C++模塊
那就坑爹了。在安裝過程中會隱式安裝node-gyp
,node-gyp
可編譯這些依賴C++模塊
的模塊。
那麼問題來了,node-gyp
在首次編譯時會依賴Node源碼
,所以又悄悄去下載Node
。雖然在前面已設置了淘寶鏡像
,但是在這裏一點卵用都沒有。這樣又因爲國內網絡環境的原因,再次遇上安裝過慢
或安裝失敗
的情況。
還好npm config
提供了一個參數disturl
,它可設置Node鏡像地址,當然還是將其指向國內的淘寶鏡像。這樣又能爽歪歪安裝這些依賴C++模塊
的模塊了。
npm config set disturl https://npm.taobao.org/mirrors/node/
問題一步一步解決,接下來又出現另一個問題。平常大家都會使用node-sass
作爲項目開發依賴,但是node-sass
的安裝一直都是一個令人頭疼的問題。
安裝node-sass
時,在install階段
會從Github上下載一個叫binding.node
的文件,而GitHub Releases裏的文件都託管在s3.amazonaws.com
上,這個網址被Q了,所以又安裝不了。
然而辦法總比困難多,從node-sass
的官方文檔中可找到一個叫sass_binary_site
的參數,它可設置Sass鏡像地址,毫無疑問還是將其指向國內的淘寶鏡像。這樣又能爽歪歪安裝node-sass
了。
npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
其實還有好幾個類似的模塊,爲了方便,筆者還是把它們源碼裏的鏡像參數
和淘寶鏡像裏對應的鏡像地址
扒出來,統一設置方便安裝。以下是筆者常用的幾個模塊鏡像地址配置,請收下!
分別是:Sass
、Sharp
、Electron
、Puppeteer
、Phantom
、Sentry
、Sqlite
、Python
。
鏡像地址配置
npm config set <name> <url>
,趕緊一鍵複製,永久使用。特別注意,別漏了最後面的/
。
npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
npm config set sharp_dist_base_url https://npm.taobao.org/mirrors/sharp-libvips/
npm config set electron_mirror https://npm.taobao.org/mirrors/electron/
npm config set puppeteer_download_host https://npm.taobao.org/mirrors/
npm config set phantomjs_cdnurl https://npm.taobao.org/mirrors/phantomjs/
npm config set sentrycli_cdnurl https://npm.taobao.org/mirrors/sentry-cli/
npm config set sqlite3_binary_site https://npm.taobao.org/mirrors/sqlite3/
npm config set python_mirror https://npm.taobao.org/mirrors/python/
有了這波操作,再執行npm i
安裝以上模塊時就能享受國內的速度了。如果有條件,建議把這些鏡像文件搬到自己或公司的服務器上,將鏡像地址
指向自己的服務器即可。在公司內網搭建一個這樣的鏡像服務器,一直安裝一直爽,目前筆者所在的團隊就是如此處理。
npm config set electron_mirror https://xyz/mirrors/electron/
源碼分析
以經常卡住的node-sass
爲例,下面是坑爹貨node-sass/lib/extensions.js
的源碼部分,可看出它會默認走GitHub Releases的託管地址,上面也分析過原因,在這裏就不重複了。
function getBinaryUrl() {
const site = getArgument("--sass-binary-site")
|| process.env.SASS_BINARY_SITE
|| process.env.npm_config_sass_binary_site
|| (pkg.nodeSassConfig && pkg.nodeSassConfig.binarySite)
|| "https://github.com/sass/node-sass/releases/download";
const result = [site, "v" + pkg.version, getBinaryName()].join("/");
return result;
}
而其他模塊也有類似的代碼,例如puppeteer
這個安裝Chronium
的源碼部分,有興趣的同學都去扒一下源碼,如出一轍。
async function download() {
await compileTypeScriptIfRequired();
const downloadHost =
process.env.PUPPETEER_DOWNLOAD_HOST
|| process.env.npm_config_puppeteer_download_host
|| process.env.npm_package_config_puppeteer_download_host;
const puppeteer = require("./index");
const product =
process.env.PUPPETEER_PRODUCT
|| process.env.npm_config_puppeteer_product
|| process.env.npm_package_config_puppeteer_product
|| "chrome";
const browserFetcher = puppeteer.createBrowserFetcher({
product,
host: downloadHost,
});
const revision = await getRevision();
await fetchBinary(revision);
// 還有很多
}
坑貨小結
由於node-sass
是大家經常使用的項目開發依賴,也是安裝時間較長和最常見到報錯的模塊,在這裏筆者就花點篇章分析和解決下可能會遇到的問題。
node-sass
安裝失敗的原因其實並不止上面提到的情況,我們可從安裝過程中分析並獲取突破口來解決問題。根據npm i node-sass
的輸出信息來分析,可得到下面的過程。
- 檢測項目
node_modules
的node-sass
是否存在且當前安裝版本是否一致- Yes:跳過,完成安裝過程
- No:進入下一步
- 從NPM上下載
node-sass
- 檢測
全局緩存
或項目緩存
中是否存在binding.node
- Yes:跳過,完成安裝過程
- No:進入下一步
- 從Github Releases上下載
binding.node
並將其緩存到全局- Success:將版本信息寫入
package-lock.json
- Error:進入下一步
- Success:將版本信息寫入
- 嘗試本地編譯出
binding.node
- Success:將版本信息寫入
package-lock.json
- Error:輸出錯誤信息
- Success:將版本信息寫入
不難看出,node-sass
依賴了一個二進制文件binding.node
,不僅需要從NPM上下載本體
還需要從Github Releases上下載binding.node
。
從實際情況來看,node-sass
出現安裝過慢
或安裝失敗
的情況可能有以下幾種:
NPM鏡像託管在國外服務器
上面有提到,在這裏不再敘述,解決辦法如下。
nrm use taobao
安裝過程中悄悄下載
node-gyp
上面有提到,在這裏不再敘述,解決辦法如下。
npm config set disturl https://npm.taobao.org/mirrors/node/
binding.node
文件託管在國外服務器
上面有提到,在這裏不再敘述,解決辦法如下。
npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
Node版本與node-sass版本不兼容
node-sass
版本兼容性好差,必須與Node版本對應使用纔行,詳情請參考node-sass-version-association,複用官方文檔的版本對照表,如下。
NodeJS | Minimum node-sass version | Node Module |
---|---|---|
Node 14 | 4.14+ | 83 |
Node 13 | 4.13+ | 79 |
Node 12 | 4.12+ | 72 |
Node 11 | 4.10+ | 67 |
Node 10 | 4.9+ | 64 |
Node 8 | 4.5.3+ | 57 |
執行npm i
安裝依賴前請確保當前的Node版本和node-sass
版本已兼容。
全局緩存中的binding.node版本與Node版本不兼容
假如本地使用nvm
或n
進行Node版本管理,並且已切換了Node版本,在安裝過程中可能會出現Windows/OS X/Linux 64-bit with Node.js 12.x
這樣的提示,這種情況也是筆者經常遇上的情況(筆者電腦裏安裝了30多個Node版本並且經常來回切換😂)。
這是因爲node-sass
版本和Node版本是關聯的(看上面的表格),修改Node版本後在全局緩存中匹配不到對應的binding.node
文件而導致安裝失敗。根據錯誤提示,清理NPM緩存且重新安裝即可,解決辦法如下。
npm cache clean -f
npm rebuild node-sass
所以沒什麼事就別來回切換Node版本了,像筆者裝這麼多Node版本也是逼不得已,老項目太多了😂。
安裝失敗後重新安裝
有可能無權限刪除已安裝的內容,導致重新安裝時可能會產生某些問題,建議將node_modules
全部刪除並重新安裝。
在Mac系統和Linux系統上刪除node_modules
比較快,但是在Windows系統上刪除node_modules
就比較慢了,推薦大家使用rimraf刪除node_modules
,一個Node版的rm -rf
工具。
npm i -g rimraf
在項目的package.json
中加入npm scripts
讓rimraf
常駐。三大操作系統通用,非常推薦使用。
{
"scripts": {
"reinstall": "rimraf node_modules && npm i"
}
}
一有什麼安裝失敗
、重新安裝
之類的操作,先執行npm run remove
刪除node_modules
再npm i
。
npm run reinstall
終極總結
如果看得有點亂,那下面直接貼代碼操作順序,建議前端小白在安裝完Node後立馬處理這些NPM鏡像問題,防止後續產生不必要的麻煩(解決這些問題是需要花費時間的😂)。
# 查看Node版本和NPM版本確認已安裝Node環境
node -v
npm -v
# 安裝nrm並設置NPM的淘寶鏡像
npm i -g nrm
nrm use taobao
# 設置依賴安裝過程中內部模塊下載Node的淘寶鏡像
npm config set disturl https://npm.taobao.org/mirrors/node/
# 設置常用模塊的淘寶鏡像
npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
npm config set sharp_dist_base_url https://npm.taobao.org/mirrors/sharp-libvips/
npm config set electron_mirror https://npm.taobao.org/mirrors/electron/
npm config set puppeteer_download_host https://npm.taobao.org/mirrors/
npm config set phantomjs_cdnurl https://npm.taobao.org/mirrors/phantomjs/
npm config set sentrycli_cdnurl https://npm.taobao.org/mirrors/sentry-cli/
npm config set sqlite3_binary_site https://npm.taobao.org/mirrors/sqlite3/
npm config set python_mirror https://npm.taobao.org/mirrors/python/
針對node-sass
的情況:
# 安裝rimraf並設置package.json
npm i -g rimraf
# 安裝前請確保當前的Node版本和node-sass版本已兼容
# 安裝失敗
npm cache clean -f
npm rebuild node-sass 或 npm run reinstall
package.json
中加入npm scripts
:
{
"scripts": {
"reinstall": "rimraf node_modules && npm i"
}
}
總結
NPM鏡像問題的坑確實很多,歸根到底還是網絡環境導致的。當然這些問題也阻礙不了樂於探索的我們,辦法總比困難多,堅持下去始終能找到解決方式。
筆者總結出一個解決這種NPM鏡像問題的好方法,遇到一些上面沒有提到的模塊,可嘗試通過以下步驟去解決問題。
- 執行
npm i
前設置淘寶鏡像,保證安裝項目依賴時都走國內網絡 - 安裝不成功時,肯定是在安裝過程中該模塊內部又去下載了其他國外服務器的文件
- 在Github上克隆一份該模塊的源碼進行分析,搜索包含
base、binary、cdn、config、dist、download、host、mirror、npm、site、url
等這樣的關鍵詞(自行探索,通常mirror的匹配度最高) - 在搜查結果裏查找形態像鏡像地址的代碼塊,再分析該代碼塊的功能並提取最終的鏡像地址,例如
node-sass
的sass_binary_site
- 去淘寶鏡像官網、百度、谷歌等網站查找你需要的鏡像地址,如果實在找不到就規範上網把國外服務器的鏡像文件拉下來搬到自己或公司的服務器上
- 設置模塊依賴的鏡像地址:
npm config set <registry name> <taobao url / yourself url>
- 重新執行
npm i
安裝項目依賴,大功告成
如果以上內容幫不了你或在解決NPM鏡像問題上還遇到其他坑,歡迎添加筆者微信一起交流。如有錯誤地方也歡迎指出,如有更好的解決方法也可提上建議。
另外筆者花了一些時間用Xmind整理了本文內容並生成一張知識點分佈圖,濃縮就是精華。由於圖片太大無法上傳就保存到公衆號裏,如有需要可關注IQ前端
,掃描文章底部二維碼
,後臺回覆NPM鏡像
獲取該圖片,希望能幫助到你。
結語
❤️關注+點贊+收藏+評論+轉發❤️,原創不易,鼓勵筆者創作更好的文章
關注公衆號IQ前端
,一個專注於CSS/JS開發技巧的前端公衆號,更多前端小乾貨等着你喔
- 關注後回覆
關鍵詞
免費領取視頻教程 - 關注後添加
我微信
拉你進技術交流羣 - 歡迎關注
IQ前端
,更多CSS/JS開發技巧只在公衆號推送