cnpm 安裝全局模塊引發(fā)的思考

起因

因為工作的時候勾扭,公司提供的是 Windows 臺式機纽绍,因此一般都是在 Windows 環(huán)境下開發(fā)的。

但是最近在用 cnpm 安裝腳本的時候上鞠,忽然發(fā)現(xiàn)一個很有意思的問題:用 cnpm 安裝的全局腳本际邻,比如 vue-cli 居然只能在 cmd 中運行,無法在 powerShell 中運行芍阎。

類似的問題世曾,其實以前也碰到過,但是以前一般都是報著能用就用谴咸,不去深究原理的想法轮听。

其實很多時候,自己內(nèi)心深處還是有一個聲音不斷地在提醒自己:“知其然更知其所以然方能走的更遠”岭佳!

但是奈何血巍,自己實力不允許,對很多東西都是一知半解珊随,沒有形成一套體系述寡,沒有擁有看透問題本質(zhì)的能力。

但是現(xiàn)在叶洞,開始找到感覺了鲫凶,于是現(xiàn)在碰到問題,多花點時間衩辟,稍微深究一下螟炫,事后收獲還是很大的。

閑話不多說艺晴,轉(zhuǎn)回我們的正題吧昼钻。

npm、cnpm封寞、yarn 選擇問題

至于為什么會用 npm然评,我想前端的同學應該都深有感觸,特別是國內(nèi)的前端同學狈究。

我想或多或少都會經(jīng)歷過一下場景:

同事1:反正大家都說 npm 不好用沾瓦!
同事2:npm 垃圾玩意兒,下東西太慢了谦炒!
同事3:cnpm 下東西快贯莺,比 npm 強一萬倍!
同事4:你竟然還在用 npm宁改,太老土了缕探!
。还蹲。爹耗。

類似的情景對話耙考,我想大家應該都經(jīng)歷過。

但是究竟為什么 npm 不好用潭兽,cnpm 好用呢倦始?

這種踩 npm 的情況,是從什么時候開始的山卦,現(xiàn)在還是這樣嗎鞋邑?

npm 跟 cnpm 的差別是什么呢?

npm 可以通過什么方式變得跟 cnpm 一樣好用嗎账蓉?

其實這些問題枚碗,并沒有多少人去深究,特別是對于很多其前端初級選手來說铸本,估計很多人都下意識的認為肮雨,其實這兩個是一個東西,都是下 nodejs 模塊的嘛箱玷。

估計很多人都這樣想:這些問題關(guān)我鳥事怨规,我研究的那么透徹,老板也不會給我漲工資拔恪波丰!我前端,寫好頁面就行了舱污,這些個框架呀舔,能用好就行了弥虐,我開車扩灯,干嘛要了解汽車的原理呢!

如果你符合以上的思維霜瘪,那么請及時中斷往下看的念頭吧珠插,這篇文章不適合你。

那么究竟為什么大家都重口一詞的說 npm 不好用 cnpm 好用呢颖对?

原因是就是捻撑,以前 npm 真的挺不好用的!

這篇博主的文章分析的非常好缤底,有興趣的同學可以閱讀一下:https://blog.xgheaven.com/2018/05/03/npm-to-yarn-to-npm/

就因為 npm 不好用顾患,所以才催生出像 cnpm、yarn 等第三方包管理系統(tǒng)个唧。

但是隨著 npm 6.x 版本的發(fā)布江解,這些問題已經(jīng)被被解決了,已經(jīng)被掃進了歷史的垃圾堆里了徙歼。

所以結(jié)論就是:現(xiàn)在用 nodejs 的包管理系統(tǒng)犁河,首選 npm鳖枕,實在不能用 npm 的情況下,再考慮用第三方的包管理系統(tǒng)桨螺。

比如 create-react-app 這個腳手架宾符,就是只支持 yarn 的,但是如果你非要用 npm灭翔,就很麻煩了魏烫。

但是有的童鞋會發(fā)問,npm 安裝模塊太慢了缠局,不能忍则奥。

說實話,我也忍不了狭园,忍不了你就改個 npm 模塊的源唄读处,從鏡像站去下載模塊不久快很多么。

這個問題其實不止是出現(xiàn)在 npm 上唱矛,很多包管理系統(tǒng)都會出現(xiàn)在這樣的問題罚舱。

比如 python 的 pip,Ubuntu 的 apt-get绎谦,homebrew管闷,centos 的 yum 等等,都會因為官方源服務器在國外窃肠,訪問起來太慢包个。

但是這個問題其實是有解決方案的,換成國內(nèi)的鏡像源就能解決冤留。

比如 npm 換成淘寶的國內(nèi)鏡像源就能解決下載過慢的問題了碧囊,下面是配置方式:

# 換源
npm config set registry https://registry.npm.taobao.org

# 檢查是否改成功了
npm config get registry

第三方包管理工具

再聊聊為什么會出現(xiàn)第三方包管理工具。

其實之前就說過了纤怒,因為 npm 在開始的時候不好用糯而,所以后來社區(qū)就誕生出了更優(yōu)秀的包管理工具。

但是 npm 也是在進步的泊窘,我們不能總是以一種陳舊的眼光去看待問題熄驼,以一種擁抱未來的姿態(tài)去剔除我們思想中的偏見成分。

npm 的這種歷史烘豹,有點類似于 JavaScript 的發(fā)展歷史瓜贾。

以前 JavaScript 很多地方用起來不友好,所以催生出了很多優(yōu)秀的 JavaScript 框架携悯,十年前祭芦,風頭最盛的大概就是 jQuery 了吧。

甚至一度蚌卤,有人豪言壯語的宣稱:不用學 JavaScript 了实束,學了 jQuery 就行了奥秆。

但是歷史總是這么驚人的相似,隨著 es6 以及后續(xù)版本的出現(xiàn)咸灿,jQuery构订、lodash 等很多增強 JavaScript 語言功能的框架都漸漸的開始退出了歷史的舞臺了。

至于原因避矢,我想大家因該也知道悼瘾,同樣實現(xiàn)一種功能,自帶的肯定是更好用的审胸,如果不好用亥宿,只能說明他還有提升的空間。

這個定律砂沛,在很多時候都是比較符合現(xiàn)實的表現(xiàn)的烫扼。

所以,為什么說代碼開源碍庵,有助于計算機行業(yè)的發(fā)展映企。

因為同樣一個工具,總有人覺得不好用静浴,覺得不好用堰氓,你拿出更好用的東西出來,大家都會學習你這種更加先進的理念苹享。

正式因為有了這個不斷循環(huán)往復的過程双絮,才造就了近幾十年以來,互聯(lián)網(wǎng)行業(yè)的蓬勃發(fā)展得问。

深入剖析

說了太多對于這個話題的思考囤攀,還是讓我們回到這個問題的本身來吧。

究竟是什么誘因椭赋,讓我奮筆疾書的寫下這篇文章的呢抚岗?

先來讓我們檢查一下 cnpm 的版本:

C:\Users\Administrator>cnpm --version
cnpm@6.1.0 (C:\Users\Administrator\AppData\Roaming\npm\node_modules\cnpm\lib\parse_argv.js)
npm@6.12.0 (C:\Users\Administrator\AppData\Roaming\npm\node_modules\cnpm\node_modules\npm\lib\npm.js)
node@10.16.3 (C:\Program Files\nodejs\node.exe)
npminstall@3.23.0 (C:\Users\Administrator\AppData\Roaming\npm\node_modules\cnpm\node_modules\npminstall\lib\index.js)
prefix=C:\Users\Administrator\AppData\Roaming\npm
win32 x64 10.0.18362
registry=https://r.npm.taobao.org

不得不說或杠,這個命令顯示的內(nèi)容可真多哪怔,一下子將 nodejs、npm向抢、cnpm 的版本都給暴露了认境,不過沒關(guān)系,這正是我們想要看到的結(jié)果挟鸠。

為了真實的情景再現(xiàn)叉信,我接下來要安裝 vue-cli 了:

C:\Users\Administrator>cnpm install vue-cli -g

為了文章的簡介,安裝過程的 log 就不黏貼上來了艘希,反正沒有報錯硼身,異常退出的話硅急,vue-cli 就裝成功了。

下面我來運行一下 vue :

C:\Users\Administrator>vue

C:\Users\Administrator>"node"  "C:\Users\Administrator\AppData\Roaming\npm\\node_modules\vue-cli\bin\vue"
Usage: vue <command> [options]

Options:
  -V, --version  output the version number
  -h, --help     output usage information

Commands:
  init           generate a new project from a template
  list           list available official templates
  build          prototype a new project
  create         (for v3 warning only)
  help [cmd]     display help for [cmd]

可以看到的是佳遂,我運行 vue 命令的時候营袜,并沒有直接執(zhí)行 node vue 腳本 這樣的命令,而是喚出了一串很字符來執(zhí)行 vue:

"node"  "C:\Users\Administrator\AppData\Roaming\npm\\node_modules\vue-cli\bin\vue"

為什么會這樣呢丑罪?

相信跟我以前一樣荚板,沒怎么思考過這個問題的人,肯定會誤以為吩屹,我們安裝了某個模塊跪另,是不是說我們就安裝了某個直接可以執(zhí)行的二進制文件呢?

這個答案是否定的煤搜,其實我們安裝的 nodejs 模塊都是一些 nodejs 腳本免绿,我們在調(diào)用像 vue 這樣的命令的時候,其實就是調(diào)用 nodejs 這個引擎擦盾,去執(zhí)行對應的 nodejs 腳本针姿。

這個問題,你往大了想厌衙,就能夠看透計算機的本質(zhì)了距淫。

我們計算機其實不能識別我們的編程語言,不說高級編程語言婶希,即使是匯編榕暇、機器碼他也無法識別,他最原始的一面是喻杈,只能識別 0彤枢、1 兩個不同的電壓信號。

機器碼的作用筒饰,就是讓我們來驅(qū)動不同的電壓信號組合缴啡,來使計算機產(chǎn)生對應的反應。

所以簡而言之瓷们,我們寫代碼业栅,其實都只是在按照編程語言提供給我們的規(guī)則,來創(chuàng)造一些復雜的組合邏輯谬晕,做一些看似很簡單的事情碘裕。

這個問題往深了說,就說到計算機組成原理攒钳、操作系統(tǒng)的本質(zhì)等等方面了辽社,我目前也只是略知一二濒翻,所以就不往這方面展開了恭垦。

我們只要明白,其實無論是我們?nèi)职惭b的模塊還是局部安裝的模塊晤斩,運行起來都是同一套邏輯。

甚至就連 npm 本身也就是一個模塊姆坚,這個模塊和其他的第三方模塊也沒有什么本質(zhì)方面的區(qū)別尸昧。

image.png
image.png

打開全局安裝的模塊的目錄,我們可以看到旷偿,有個 node_modules 文件夾烹俗,然后目錄里面有我們?nèi)职惭b的模塊的命令行運行的腳本。

可以看到的是萍程,與 vue 相關(guān)的腳本就有 3 個幢妄,這是因為我用 cnpm 安裝的緣故,如果你用 npm 安裝的茫负,應該就只有兩個腳本蕉鸳。

我們分別打開這三個腳本,看看里面的內(nèi)容:

首先是 vue:

#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

case `uname` in
    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac

if [ -x "$basedir/node" ]; then
  "$basedir/node"  "$basedir/node_modules/vue-cli/bin/vue" "$@"
  ret=$?
else 
  node  "$basedir/node_modules/vue-cli/bin/vue" "$@"
  ret=$?
fi
exit $ret

可以看到忍法,這是一個 bash 腳本潮尝,可以直接在 Linux 或者 Mac 下運行的。

其次是 vue.cmd:

@SETLOCAL

@IF EXIST "%~dp0\node.exe" (
  @SET "_prog=%~dp0\node.exe"
) ELSE (
  @SET "_prog=node"
  @SET PATHEXT=%PATHEXT:;.JS;=;%
)

"%_prog%"  "%~dp0\node_modules\vue-cli\bin\vue" %*
@ENDLOCAL

這是一個 Windows 批處理腳本饿序,這個腳本也很簡單勉失,就是拿到 node 的路徑,然后用 node 執(zhí)行全局模塊中的 vue原探。

最后是 vue.psl:

#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent

$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
  # Fix case when both the Windows and Linux builds of Node
  # are installed in the same directory
  $exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
  & "$basedir/node$exe"  "$basedir/node_modules/vue-cli/bin/vue" $args
  $ret=$LASTEXITCODE
} else {
  & "node$exe"  "$basedir/node_modules/vue-cli/bin/vue" $args
  $ret=$LASTEXITCODE
}
exit $ret

這是一個 powerShell 腳本乱凿,同樣也是拿到 node 的路徑,然后執(zhí)行 vue 腳本咽弦。

這個寫法本身是沒問題的徒蟆,但是會造成在某些電腦上無法使用,比如我的電腦型型,執(zhí)行的過程中段审,會報這樣的錯誤:


image.png
image.png

接下來,讓我們看看用 npm 安裝的模塊闹蒜,生成的一鍵運行的腳本寺枉,有何不同呢?

為了公平起見嫂用,我們先將用 cnpm 安裝的 vue-cli 刪除掉:

E:\work2\caidademo>npm uninstall -g vue-cli

刪除成功以后型凳,再用 npm 安裝一遍 vue-cli:

E:\work2\caidademo>npm install -g vue-cli

安裝成功以后丈冬,我們會發(fā)現(xiàn)嘱函,這次只生成了兩個腳本:

image.png
image.png

稍微想想就能明白,他們應該是分別運行在類 Unix 系統(tǒng)和 Windows 系統(tǒng)中的腳本埂蕊。

vue 腳本我們就不看了往弓,讓我們來研究下 vue.cmd 腳本與之前的有何差異:

@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe"  "%~dp0\node_modules\vue-cli\bin\vue" %*
) ELSE (
  @SETLOCAL
  @SET PATHEXT=%PATHEXT:;.JS;=;%
  node  "%~dp0\node_modules\vue-cli\bin\vue" %*
)

可以看到疏唾,差異不大,唯一的差異就是函似,這個腳本里面直接用 node 槐脏,來執(zhí)行 vue,不是用 "node.exe" 撇寞,因為這種寫法顿天,在 cmd 中是支持的,但是在 powerShell 中是不支持的蔑担。

所以其實我們也能用 cnpm 來管理我們的 node 模塊牌废,只是需要改一改 cnpm 給我們自動生成的腳本就行了。

又或許啤握,這就是一個 bug鸟缕,需要你給 npm 倉庫去貢獻代碼,修改生成腳本的邏輯排抬。

但是 cnpm 的問題肯定不僅僅只是這一個懂从,這個問題只是其中的一個小問題而已。

所以蹲蒲,就像之前說的那樣番甩,如果可以的話,盡量用 npm 去管理 nodejs 模塊吧届搁。

對于某些曾經(jīng)推動歷史發(fā)展对室,后又淹沒在歷史的長河中的事務,我們同樣保持敬意咖祭。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末掩宜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子么翰,更是在濱河造成了極大的恐慌牺汤,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浩嫌,死亡現(xiàn)場離奇詭異檐迟,居然都是意外死亡,警方通過查閱死者的電腦和手機码耐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門追迟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人骚腥,你說我怎么就攤上這事敦间。” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵廓块,是天一觀的道長厢绝。 經(jīng)常有香客問我,道長带猴,這世上最難降的妖魔是什么昔汉? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮拴清,結(jié)果婚禮上靶病,老公的妹妹穿的比我還像新娘。我一直安慰自己口予,他們只是感情好嫡秕,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著苹威,像睡著了一般昆咽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上牙甫,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天掷酗,我揣著相機與錄音,去河邊找鬼窟哺。 笑死泻轰,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的且轨。 我是一名探鬼主播浮声,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼旋奢!你這毒婦竟也來了泳挥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤至朗,失蹤者是張志新(化名)和其女友劉穎屉符,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锹引,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡矗钟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嫌变。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吨艇。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖腾啥,靈堂內(nèi)的尸體忽然破棺而出东涡,到底是詐尸還是另有隱情冯吓,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布软啼,位于F島的核電站桑谍,受9級特大地震影響延柠,放射性物質(zhì)發(fā)生泄漏祸挪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一贞间、第九天 我趴在偏房一處隱蔽的房頂上張望贿条。 院中可真熱鬧,春花似錦增热、人聲如沸整以。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽公黑。三九已至,卻和暖如春摄咆,著一層夾襖步出監(jiān)牢的瞬間凡蚜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工吭从, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留朝蜘,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓涩金,卻偏偏與公主長得像谱醇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子步做,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容