<xmp id="63nn9"><video id="63nn9"></video></xmp>

<xmp id="63nn9"></xmp>

<wbr id="63nn9"><ins id="63nn9"></ins></wbr>

<wbr id="63nn9"></wbr><video id="63nn9"><ins id="63nn9"><table id="63nn9"></table></ins></video>

加載中...

Leftpad事件 我們是不是早已忘記該如何好好地編程?

多年前的Leftpad 撤包事件使得React 、 Babel 和許多流行的npm模塊都受到波及,無法正常運行。

這些受到影響的模塊都引入了一個叫做 left-pad 的模塊。
以下就是這十一行代碼:

module.exports = leftpad;
function leftpad (str, len, ch) {
str = String(str);
var i = -1;
if (!ch && ch !== 0) ch = ' ';
len = len - str.length;
while (++i < len) {
str = ch + str;
}
return str;
}

而其中的原因大概是這樣:作者 Azer 寫了一個叫 kik 的工具和某個公司同名了,這天公司的律師要求其刪掉這個模塊,把 kik 這個名字“讓”給他們,作者不答應,律師就直接找 NPM 了,而 NPM 未經作者同意就把包的權限轉移給了這家公司。于是,Azer 一怒沖冠,將他所有的 NPM 包全部刪掉了。

有意思的是,社區中許多的模塊都選擇引入這個十一行的模塊,而不是花上兩分鐘的時間自己去實現這個簡單的字符串填充功能。

這不是npm包管理第一次出問題,也不會是最后一次。

Leftpad撤包事件、event-stream投毒事件、Ant Design彩蛋時間,使得我們不得不開始重新思考npm生態真的存在的問題,甚至去問自己:我們是不是早已忘記該如何好好地編程?

  • NPM模塊粒度
  • 代碼風格
  • 代碼質量/效率
  • 過度依賴

這種過度依賴其他npm模塊的做法是不是解決問題的正確方式呢?現在,一個空白項目模板一裝好就要引入兩萬八千多個文件、依賴成百上千個其他的npm模塊。這太瘋狂了、而且過度復雜。

那么我們可以做些什么?把命運掌握在自己手里

  • 在發布前“凍結”依賴模塊的版本號。這讓我們對安裝的依賴有信心,依賴模塊的版本都是我們驗證、測試過的。
  • 在發布前“打包”依賴模塊到自己項目。這讓我們可以坦然面對我們依賴的某個模塊“沒有了”這樣的囧境。

凍結依賴模塊:

凍結依賴模塊的版本號最簡單的辦法就是直接在 package.json 里面寫死版本號,但是這解決不了深度依賴的問題。我們來看個例子。 假設有下面這樣的依賴:

A@0.1.0 
└─┬ B@0.0.1  
  └── C@0.0.1

A 模塊依賴了 B 模塊,B 模塊又依賴了 C 模塊。我們可以將 B 模塊的依賴寫死成 0.0.1 版本,但是如果 B 模塊對 C 模塊的依賴寫的是 C@0.0.1,會怎樣?

這時候 C 模塊更新到了 0.0.2 版本,雖然我們安裝的 B 模塊是 B@0.0.1,但是安裝的 C 模塊卻是 C@0.0.2。如果不巧這個 C@0.0.2 剛好有 bug,那我們的模塊很有可能就不能正常工作了。 實際上,NPM 提供了一個叫做npm shrinkwrap的命令來解決這個問題:

NAME
  npm-shrinkwrap -- Lock down dependency versions

SYNOPSIS
  npm shrinkwrap

DESCRIPTION
  This  command  locks down the versions of a package's dependencies so that you can control exactly which versions of each  dependency  will be used when your package is installed.

這條命令會根據目前我們 node_modules 目錄下的模塊來生成一份“凍結”住的模塊依賴(npm-shrinkwrap.json)。

還是上面的例子,我們在模塊 A 的根目錄執行 npm shrinkwrap 后,生成的 npm-shrinkwrap.json 文件內容大概是下面這樣:

{
    "name": "A",
    "dependencies": {
        "B": {
            "version": "0.0.1",
            "resolved": "http://registry.npmjs.com/B-0.0.1.tgz",
            "dependencies": {
                "C": {  
                 "version": "0.0.1",
                 "resolved": "http://registry.npmjs.com/C-0.0.1.tgz"
          }
            }
        }
    }
}

然后,當我們執行 npm install 時,依賴查找的“來源”不再是 package.json,而是我們生成的 npm-shrinkwrap.json,再也不會突然裝上什么 C@0.0.2 了,依賴里面的模塊版本都是我們驗證、測試后的版本,讓人安心。

注:npm shrinkwrap 默認只會生成 dependencies 的依賴,不會生成 devDependencies 的依賴,如果你真的需要,可以加 --dev 參數。

打包依賴模塊:

我們解決了依賴模塊版本號的問題,但是每次安裝時其實還是會去 NPM 的 registry 獲取模塊的 tgz 包然后進行安裝。我們需要將這些依賴都打包進我們的項目。這可能會帶來一些問題(比如:項目體積的增大),但是好處也是顯而易見的。

上面生成的 npm-shrinkwrap.json 里面有個 resolved 字段,表示模塊所在的位置,實際上這個字段完全可以寫一個文件路徑。所以,我們可以遞歸的遍歷 npm-shrinkwrap.json 文件,將所有的 tgz 包先下載到我們項目的某個目錄,然后改寫 resolved 字段為對應的文件路徑。這樣的功能有開發者已經實現了,我們可以直接享用:https://github.com/JamieMason/shrinkpack

于是,我們以后再進行 npm install --loglevel=http 時會發現依賴模塊的安裝根本沒有網絡請求了(因為依賴都在我們自己的倉庫里了嘛)。

可能有人會說,為啥不直接把 node_modules 目錄提交進倉庫算了?原因主要是這樣:

  • 有些模塊需要編譯,編譯是和環境有關的,你當前的環境編譯可用,其他環境直接使用該模塊不一定能用。
  • node_modules 目錄里面啥東西都有,太凌亂,很容易把提交給攪亂。diff 時突然 diff 出 node_modules 下的源代碼、README,你應該不想這樣吧?

只存儲模塊的 tgz 包,安裝編譯的過程交給 NPM 命令更明智。

新方式

于是,現在我們使用 NPM 模塊的正確姿勢應該是這樣了:

  1. 本地安裝、更新需要的模塊,測試、驗證
  2. 執行 npm shrinkwrap 將依賴模塊的版本凍結
  3. 執行 shrinkpack . 將依賴模塊打包進倉庫
  4. 提交代碼(注意要將 npm-shrinkwrap.json 和 node_shrinkpack 一起提交哦)
  5. 發布模塊或者部署應用

如果你覺得這樣很繁瑣,可以定義一個 NPM 命令:

"scripts": {
  "pack": "npm shrinkwrap & shrinkpack ."
}
posted @ 2023-03-12 16:59  辜負寒徹骨  閱讀(303)  評論(0編輯  收藏  舉報
人碰人摸人爱免费视频播放

<xmp id="63nn9"><video id="63nn9"></video></xmp>

<xmp id="63nn9"></xmp>

<wbr id="63nn9"><ins id="63nn9"></ins></wbr>

<wbr id="63nn9"></wbr><video id="63nn9"><ins id="63nn9"><table id="63nn9"></table></ins></video>