NPM這6個有趣實(shí)用的知識點(diǎn),你知道幾個?
一、 啥?npm add 和 npm install 完全等價
注意:是完全等價!
如果你試圖在 npm 官方搜索 npm add 這個指令,你會發(fā)現(xiàn)這個指令似乎根本不存在,如下圖:

那我們平時使用的 npm add vue@latest --save 又是什么鬼?
其實(shí),npm add 是 npm install 的 別名 之一,所以當(dāng)我們執(zhí)行 npm add 時,對于 npm 來說完完全全等同于執(zhí)行了 npm install!
下次,你可以試試 npm install vue@latest --save 了??
如你所知,
npm install還有另一個常見的別名:npm i;
二、啥?npm isntall、npm instal 也能執(zhí)行?
你沒看錯,上面不是
install,而是稀奇古怪的拼寫錯誤;
那么 npm isntall、npm instal 這種錯誤的拼寫指令,執(zhí)行起來是什么效果呢?
答案是:和 npm install 一模一樣!
哈哈,沒想到吧!

其實(shí),這是 npm 8.x 版本的新特性,可能某個核心貢獻(xiàn)者和你我一樣也是老手殘黨,常年因為 手指跟不上大腦的運(yùn)算速度 而輸入錯誤的指令。
所以在 8.x 版本,npm install 在之前 add、i的基礎(chǔ)上增加了 9個別名,它們是:
in, ins, inst, insta, instal, isnt, isnta, isntal, isntall
媽耶,各種能想到的不能想到的拼寫錯誤都在里面,這位貢獻(xiàn)者,一定是個有故事的同學(xué)。
三、每個 script 腳本都有前任與下一任?
你目前所開發(fā)的項目里定義的構(gòu)建指令是什么?
假如,構(gòu)建腳本是:
npm run build
那么你知道如何在執(zhí)行 npm run build 指令執(zhí)行之前,做一些特定的別的操作,或者在執(zhí)行之后執(zhí)行一些操作,應(yīng)該怎么做嗎?
答案是定義以下兩個腳本:
{
"scripts": {
"prebuild": "",// 這是 build 執(zhí)行前的鉤子
"postbuild": "" // 這是 build 執(zhí)行后的鉤子
}
}
哪怕你定義一個腳本叫 papapa,也是具備 “前任” prepapapa 和 “下一任” postpapapa 這樣的鉤子的!
你是否發(fā)現(xiàn)很多組件庫的 package.json 里都有 postinstall 腳本?
沒錯,它們正是在 install 執(zhí)行之后執(zhí)行的腳本。
四、通過 npm link,能創(chuàng)造一些實(shí)用的工具指令
npm link 很多人都知道,它最廣為人知的用途是:
創(chuàng)建一個軟連接,使得你可以在不發(fā)布到
npm源的情況下,在B項目里依賴A項目進(jìn)行聯(lián)調(diào)。
但如果你在項目的 package.json 里定義了 bin 屬性,并將它指向某個可執(zhí)行的腳本文件。
比如:
{
"bin": {
"i-love-u": "src/index.js"
}
}
一旦你在項目里通過 npm link 發(fā)布了,恭喜你,你只需要在命令行中輸入 i-love-u 就會直接執(zhí)行它所指向的腳本了。
這難道不 cooool 嗎?
這會讓你看起來,更像一個 "極客" 。
五、當(dāng)你使用依賴時,導(dǎo)入的具體是哪個文件?
你能告訴我,當(dāng)你在代碼里寫下如下代碼時:
import { createStore } from 'vuex';
// 或者是
const { createStore } = require('vuex');
兩種語句引入的是同一個文件嗎?區(qū)別在哪?
會對程序產(chǎn)生什么差別嗎?
有些同學(xué)或許能回答出 "前者是 CommonJS 語法,后者是 ESM 語法。",然后呢?
然后,我們需要先了解幾個知識點(diǎn):
從 node 14.x版本開始,package.json里支持了exports屬性,當(dāng)它存在時,它的優(yōu)先級最高。
// 這說明無論是 import 還是 require 都只會以 `main.js` 作為入口
"exports": "main.js"
// 以下則可以給 `require` 和 `import` 分別設(shè)置入口
"exports": {
"import": "es/index.js",
"require": "cjs/index.js"
}
當(dāng)
exports屬性不存在,而module屬性存在時,構(gòu)建工具(如webpack、rollup)會把module屬性作為ESM的入口來使用。因此,如果
package.json文件里有:
name: "yy",
exports: "lib/index.js",
在 webpack/rollup 項目中:
import xx from 'yy';
入口會被指向 node_modules/yy/lib/index.js
如果 exports和module都不存在,則package.json中的main屬性會成為指定入口的唯一屬性。
關(guān)于 “模塊入口” 的話題,可以拓展出一整篇文章,因此不再贅述,有興趣的朋友可以自行閱讀 Node.js 相關(guān)文檔:
http://nodejs.cn/api/packages.html#main-entry-point-export
(好吧,嚴(yán)格來說,這不屬于 npm 的知識點(diǎn),orz)
六、公源、私源切換,.npmrc 居然這么好用?
npm 默認(rèn)的源是 https://registry.npmjs.org 。但因為眾所周知的原因,這個源在國內(nèi)訪問起來速度很慢。
此時,我們可以通過以下命令將其設(shè)置為 taobao 源:
# npm 自帶的設(shè)置功能
npm config set registry https://registry.npm.taobao.org
# or
# 如果你安裝了nrm
nrm use taobao
以上做法雖然有效,但并沒有將 “指定源” 固話在項目配置中,新同學(xué)上手時可能需要在這些問題上花費(fèi)大量精力。
更好的選擇是 .npmrc 文件。
registry = https://registry.npm.taobao.org/
@juejin:registry = https://siyouyuan.org/
通過 .npmrc 文件可以設(shè)置項目級的配置,以上兩行代碼分別做了如下兩件事:
@juejin命名空間的項目,直接在私有源請求包;其他包則從 taobao源發(fā)起請求。
這樣一來,新人上手項目、或在 jenkins 上構(gòu)建就無需設(shè)置任何配置,執(zhí)行 npm i 即可。
請你喝杯?? 記得三連哦~
1.閱讀完記得給?? 醬點(diǎn)個贊哦,有?? 有動力
2.關(guān)注公眾號前端那些趣事,陪你聊聊前端的趣事
3.文章收錄在Github frontendThings 感謝Star?
