翻譯:瘋狂的技術宅原文:https://www.twilio.com/blog/l...html
未經容許嚴禁轉載前端
「但是在個人機器上能工做啊!」這種場景多是調試 bug 時最多見的問題。這一般是因爲出錯的機器和你本身的機器上系統的底層依賴性不一樣的結果。因此 yarn 和 npm 在引入了所謂的「lock file」,來跟蹤你依賴項確切的版本。可是當你在開發要發佈到 npm 的包時,應避免使用這類 lock file 。在本文中,咱們將討論爲何要這樣。node
若是你開發像 Web 服務器之類的程序,那麼 lock file 是很是有用的。可是若是將庫或 CLI 發佈到 npm,則永遠不要發佈 lock file。由於若是你使用它,則意味着你和你的用戶可能在使用不一樣版本的依賴項。git
lock file 描述了整個依賴關係樹,它在建立時被解析,包括具備特定版本的嵌套依賴關係。在 npm
名爲 package-lock.json
,在 yarn
中名爲 yarn.lock
。在這兩個npm
和yarn
它們被放置旁邊你的package.json
。程序員
package-lock.json
的內容應該是這樣:面試
{ "name": "lockfile-demo", "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { "color-convert": "^1.9.0" } }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } } } }
yarn.lock
的格式不一樣,但也包含相似的信息:npm
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" supports-color "^5.3.0"
二者都包含一些重要的信息:json
既然 lock file 中已經列出了全部的依賴項,拿爲何還要將它們寫在 package.json
中呢?爲何咱們須要兩個文件?segmentfault
package.json
中 dependencies
字段顯示你的項目應該安裝的依賴項,但不顯示這些依賴項的依賴項。依賴項能夠指定精確版本或 semver 範圍。對於 semver 範圍,npm
或 yarn
將h會選擇最適合的版本。服務器
這意味着,若是在發佈新版本時屢次運行 npm install
,有可能會獲得相同版本的依賴項。例如用 npm install twilio
安裝 twilio
這樣的依賴項,那麼 package.json
中的依賴項可能會存在相似於這樣的條目:
{ "dependencies": { "twilio": "^3.30.3" } }
若是你查閱 npm 網站上的 semver 文檔,就會看到 ^
意味着任何大於 3.30.3
的版本和小於 4.0.0
都是有效版本。所以,若是在發佈新版本時你沒有鎖定文件,npm install
或 yarn install
會自動安裝一個,你的 package.json
將不會被更新。可是 lock file 的內容會有所不一樣。
若是 npm
或 yarn
找到它們各自的 lock file,將使用它們代替模塊安裝。這對於持續集成(CI)等狀況尤爲有用。對於此這種場景,你能夠針對相應的包管理器使用特殊命令或標誌:
npm ci # will install exactly what's in the package-lock.json yarn install --frozen-lock-file # will install exactly what's in yarn.lock without updating it
當你在構建 Web 程序或服務器之類的應用時,這很是有用,由於咱們但願在 CI 環境中模擬用戶的行爲。所以,若是在源代碼控制(如 git)中跟蹤咱們的 lock file,就能夠確保每一個開發人員以及服務器或構建系統還有 CI 系統都可以使用相同版本的依賴項。
那麼當咱們編寫要發佈到 npm 的庫時,爲何不能作一樣的事呢?要回答這個問題,首先要討論發佈的工做原理。
與某些人想的相反,你發佈到 npm 的內容並不老是與 GitHub 上或項目中的內容徹底相同。發佈模塊的方式是 npm
將經過檢查 package.json
和 .npmignore
文件中的 files
鍵或者若是沒有`來肯定應該發佈的文件。 gitignore
文件。還有一些文件老是包含在內,有些文件將永遠被排除在外。你能夠在 npm page 上找到這些文件的完整列表。例如,.git
目錄始終會被忽略。
以後 npm
將會獲取文件列表,並用 npm pack
將它們一塊兒打包成 tarball
。若是要查看打包的文件,能夠在項目中運行 npm pack --dry-run
,能看到包含全部文件的輸出:
那個 tarball 將被上傳到 npm註冊表。運行此命令時你可能會注意到加入你已經有了一個 package-lock.json
,它實際上沒有被捆綁。這是由於 package-lock.json
將始終被忽略。
這意味着若是另外一個開發人員安裝了你發佈的軟件包,他們永遠不會下載你的 package-lock.json
,所以在安裝過程當中將會徹底忽略它。
這可能會致使「在個人機器上可以工做」的意外,由於你的 CI 和開發環境可能會選擇不一樣的依賴項版本。那麼咱們能夠作些什麼呢?
首先,應該中止跟蹤咱們的 lock file。若是你用的是git,請將如下內容添加到項目中的 .gitignore
文件中:
yarn.lock package-lock.json
Yarn 的文檔說即便你建立了庫,也應該簽入 yarn.lock
,可是若是你想確保本身可以保證與用戶相同的體驗,我建議將其添加到 .gitignore
。
你能夠經過在項目裏的 .npmrc
文件中添加如下內容來關閉 package-lock.json
文件的生成:
package-lock=false
對於 yarn
,你能夠經過添加 yarn install --no-lockfile
標誌保證不生成 lock file。
擺脫了 package-lock.json
並不意味着沒法固定咱們所擁有的依賴關係和子依賴關係。咱們能夠用另外一個名爲 npm-shrinkwrap.json
的文件。
它與 package-lock.json
基本相同,並由 npm shrinkwrap
生成並實際的打包併發布到 npm
註冊表中。
所以,經過將 npm shrinkwrap
添加到 npm
腳本做爲 prepack
腳本甚至是 git commit hook,能夠確保在你的開發環境中,與你的用戶和 CI 中使用相同版本的依賴項。
一個重要的提示:經過使用 shrinkwrap 文件,你能夠肯定精確的版本,但它也會阻止人們得到自動安裝的關鍵補丁程序。 npm
強烈反對庫的 shrinkwrap
的用例。
不幸的是,雖然 npm docs 中有不少相關內容,但有時很難找到你想要的東西。若是你想更好地瞭解安裝或打包的內容,那麼你一個常見標誌就是 --dry-run
。運行該命令而不會影響你的系統。例如 npm install --dry-run
並不會將依賴項安裝到你的文件系統,或者 npm publish --dry-run
實際上也不會發布該包。
如下是你可能想要查看的一些命令:
npm ci --dry-run # mock-installs based on package-lock.json or npm-shrinkwrap.json npm pack --dry-run # lists all files that would be packaged up as well as meta info npm install <dep> --verbose --dry-run # will run the installation of a package in verbose mode without actually installing it to your file system
一些有用連接:
npm ci
and npm install
package-lock.json
or npm-shrinkwrap.json