7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

そろそろlockファイルを理解するための最初のページ【composer.lock/package-lock.json】

Posted at

.lockファイルって邪魔だよね。って思っている人いたら校舎裏来てください。優しく解説します。

こんにちは! @ykhirao です。最近ジョインさせていただいた案件で composer.lock のバージョンが本番が一番新しくて、ローカルが一番古い素敵な状況を発見しました :relaxed:

本番環境でSSHして composer update かけたんだなあーー。そっかーーー、バグ起きたらどないすんねん、。。。。。。

というのが私の感想で、実際にnpmパッケージを使ってバグを再現しながら
ゆっくり解説していこうと思います。どうぞ最後までよろしくお願いします。!!!

このQiitaを呼んで得ること

  • あーー、ほんとだ。バグが入る可能性があるんだ!
  • lockファイルはちゃんとコミットするね!

というお気持ちになれると思います。

このQiitaで解説しないこと

  • 詳しい依存関係の解消法
  • packageの公開の仕方
  • むずかしいはなし

です!

さて時系列を見てみよう!

こんな事故が起こる可能性がありますよって話をします。

時系列 OSSのmypackage.js ローカル 本番サーバー
1日目 v1.0.0公開 動いている 動いている
2日目 ローカルでmypackage.jsをinstall
動作確認OK、明後日本番に適応させる
3日目 v1.0.1公開 バグあり
4日目 本番サーバーで新しいコードを反映、install。本番が動かなくなってしまった。ぴえん
もちろんソースコードはローカルと同じだし、ローカルで動いていたのになんで…?:flushed:
5日目 v1.0.2公開 バグ修正された
6日目 v1.0.2を適応ローカル確認OK
今度はlockファイルを本番にアップロードする予定!
7日目 package-lock.jsonを使ってinstallする!今度は動いた!

npmでパッケージを作りながら説明する

OSSっぽい動作をするpackageフォルダと、ローカル環境と本番環境っぽいフォルダを作る。

yk@yk ~ % cd qiita 
yk@yk qiita % mkdir package
yk@yk qiita % mkdir local
yk@yk qiita % mkdir production
yk@yk qiita % ll
total 0
drwxr-xr-x   5 yk  staff   160  7 11 00:34 .
drwxr-xr-x+ 83 yk  staff  2656  7 11 00:33 ..
drwxr-xr-x   2 yk  staff    64  7 11 00:34 local
drwxr-xr-x   2 yk  staff    64  7 11 00:34 package
drwxr-xr-x   2 yk  staff    64  7 11 00:34 production
yk@yk qiita % cd package 
yk@yk package % npm init -y
Wrote to /Users/yk/qiita/package/package.json:

{
  "name": "package",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}


yk@yk package % vim package.json
yk@yk package % vim index.js
yk@yk package % npm publish --access=public
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN package@1.0.0 No description
npm WARN package@1.0.0 No repository field.

up to date in 0.429s
found 0 vulnerabilities

/Users/yk/.nodebrew/node/v13.8.0/lib/node_modules/package -> /Users/yk/qiita/package

yk@yk package % cat index.js 
const text = "sample"

module.exports = text;

index.jsにただただ "sample" という文字列を返す動作を記述して、パッケージとして認識させる。
@y_hirao/mypackage というパッケージをnpmに公開した。

localフォルダでいろいろゴリゴリしてみる。

yk@yk local % npm init -y
Wrote to /Users/yk/qiita/local/package.json:

{
  "name": "local",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@y_hirao/mypackage": "^1.0.0"
  },
  "devDependencies": {},
  "description": ""
}


yk@yk local % cat index.js 
const text = require("@y_hirao/mypackage");
console.log(text)

yk@yk local % node index.js 
sample

sampleという文字列が返却されました。!!!!!!!!!

このときpackage.jsonを見ると ^ キャレット指定なのでバージョンアップは 1.系 は守られるけど残りはすべてアップデートされます。

  "dependencies": {
    "@y_hirao/mypackage": "^1.0.0"
  },

さてパッケージの方を更新します。 v1.0.2 にしましょう!

yk@yk package % cat package.json 
{
  "name": "@y_hirao/mypackage",
  "version": "1.0.2",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

yk@yk package % cat index.js    
const text = "sample2"
throw 'エラーを出したい気分';

module.exports = text;
yk@yk package % npm publish   

このパッケージをそのまま使うとthrowされます。

さてローカルでinstallしてみましょう!

yk@yk local % npm install
npm WARN local@1.0.0 No description
npm WARN local@1.0.0 No repository field.

audited 1 package in 0.411s
found 0 vulnerabilities

yk@yk

あれ、エラーが起きませんね。
これは 一度ダウンロードしたパッケージはlockファイルというものでバージョン指定されているので、新しく勝手にバージョンがあがったりしないのです。

さてローカルから本番環境に package.json と index.js をコピーしてnpm installして動かしてみましょう!

yk@yk production % cp ../local/package.json package.json
yk@yk production % cp ../local/index.js index.js        
yk@yk production % npm i
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN local@1.0.0 No description
npm WARN local@1.0.0 No repository field.

added 1 package and audited 1 package in 2.811s
found 0 vulnerabilities

yk@yk production % node index.js 

/Users/yk/qiita/production/node_modules/@y_hirao/mypackage/index.js:2
throw 'エラーを出したい気分';
^
エラーを出したい気分
(Use `node --trace-uncaught ...` to show where the exception was thrown)

さて、、、本番環境でinstallを走らせるとエラーがおきました。。。。

npm install したときに package-lock.json がないと package.json を使って ^1.0.0 が指定されているので 1.系で一番新しいもの つまり今回だとバグが混入している v1.0.2 がインストールされたことになります。

lockファイルを見てみましょう。

yk@yk production % cat package-lock.json 
{
  "name": "local",
  "version": "1.0.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "@y_hirao/mypackage": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/@y_hirao/mypackage/-/mypackage-1.0.2.tgz",
      "integrity": "sha512-W2RoQsC1FVnHxximVJMovEvfl/3WNI95EjGxPbMlmyuDZ+0SImS76dOII/0AiP4cVVjXZUbFzaLs9h6l8TrrFQ=="
    }
  }
}

まさしく v1.0.2 が指定されていますね!localだともちろん最初に npm install したときに最新だった @y_hirao/mypackagev1.0.0 が使われています。

yk@yk local % cat package-lock.json 
{
  "name": "local",
  "version": "1.0.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "@y_hirao/mypackage": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/@y_hirao/mypackage/-/mypackage-1.0.0.tgz",
      "integrity": "sha512-auQ5grIpWd0IRkMR3rn6xRjIhGZqBu/Q/g1lDkS5AWakAysrZ3iQAIRngbgBGBAFlPZxQ/LCVYdAW+3VLxeSEw=="
    }
  }
}

更にインストールされているフォルダを確認しても

yk@yk production % cat node_modules/@y_hirao/mypackage/index.js
const text = "sample2"
throw 'エラーを出したい気分';

module.exports = text;
yk@yk production % 

どう見てもエラーが起きそうです。

package-lock.jsonをlocalからコピーしてきましょう。

yk@yk production % cp ../local/package-lock.json package-lock.json
yk@yk production % npm i
npm WARN local@1.0.0 No description
npm WARN local@1.0.0 No repository field.

updated 1 package and audited 1 package in 0.45s
found 0 vulnerabilities

yk@yk production % cat node_modules/@y_hirao/mypackage/index.js
const text = "sample"

module.exports = text;
yk@yk production % node index.js 
sample
yk@yk production % 

lockファイルを持ってきてインストールするだけで、エラーが起きなくなりました! :clap::clap::clap::clap::clap:

まとめ

本番環境で lockファイルごと更新する composer update とかlockファイルの存在しない状態での npm install とか、そんなことはやめましょう。ってことを主張したいです!!!!!

ローカルでしっかり確認してlockファイルを作り、それを本番にアップロードして、lockファイルの状態で依存パッケージをインストールしちゃってください。。 :pray:

インストールする時期によって最新のバージョンが使われるので、もしそのバージョンにバグがあるのなら本番死んじゃいますよ。。

終わりに

新しい会社に入って色々根本的に変えたいところがあるので、最近はdevopsの領域をごりごり触らせていただいてます。環境構築、開発フローの策定とかもろもろやらせてもらっているのでかなり楽しいです :muscle:

読んでいただきありがとうございました。lockファイル入門したい方、事故りそうな不安があるかたは同僚と一緒に「弊社のパッケージ依存関係の運用どうする…?」と一度話し合ってみてください。

ありがとうございました。

.

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?