30歳からのプログラミング

30歳無職から独学でプログラミングを開始した人間の記録。

パブリッシュしていない npm ライブラリをプロジェクトで使う方法

社内プロジェクトなどで、共通の処理をライブラリとして切り出したいが、そのライブラリもクローズドにしたいのでパブリッシュできない。というケースを想定している。

package.jsonは、ライブラリのGitリポジトリのパスを指定することも出来るので、それを利用する。
プライベートリポジトリでも問題なく動く。

この記事では、GitのホスティングサービスとしてGitHubを用いる。

リポジトリのパスを指定してインストールする

題材として、私が公開しているeslint-config-numbをインストールしてみる。

以下でインストールできる。

$ yarn add -D git+https://github.com/numb86/eslint-config-numb.git

$ cat node_modules/eslint-config-numb/package.jsonでインストールされたpackage.jsonを確認してみると、現時点での最新バージョンである2.0.0が入っていることが分かる。

末尾に#{TAG_NAME}をつけることでタグを指定することも出来る。
以下のコマンドを打つと、1.xの最新バージョンである1.0.2が入る。
もちろん#1.0.1のようにパッチバージョンまで明示的に指定することも出来る。

$ yarn add -D git+https://github.com/numb86/eslint-config-numb.git#1

プライベートリポジトリ

プライベートリポジトリでも、全く同じように利用できる。

念の為、認証していないユーザーではインストールできないことを確認してみる。

自分の環境(macOS Mojave 10.14.2)では GitHub のパスワードは「キーチェーンアクセス.app」に保存されている。
「キーチェーンアクセス.app」は以下のコマンドで開ける。

$ open /Applications/Utilities/Keychain\ Access.app

一覧の中からgithub.comを探して、削除する。

この状態でプライベートリポジトリをインストールしようとするとエラーになる。

fatal: could not read Username for 'https://github.com': terminal prompts disabled

再び「キーチェーンアクセス.app」にパスワードを登録するためには、適当なリポジトリpushpullをすればユーザー名とパスワードを求められるので、それを入力すると「キーチェーンアクセス.app」にも保存される。

参考資料

webpack のビルドとマークアップのパース処理

Vueのコンポーネントをwebpackでビルドする際のパフォーマンスの話。
他のライブラリでは分からない。

詳しい人にとっては常識かもしれないし、大した話ではないのだが、ここまでパフォーマンスに違いが出るのは知らなかったので、記録しておく。

webpackという文脈で「パフォーマンス」というとき、ビルドされたアプリのパフォーマンスと、ビルドそのもののパフォーマンスの2種類の話がある。この記事で扱うのは、後者。

結論から言うと、対象となるファイルのサイズよりも、コンポーネントの階層構造の複雑さが、ビルド時間に大きな影響を与える。

事例

担当中のウェブアプリがビルドに4分以上かかっており、原因を調べていたところ、とあるコンポーネントがボトルネックの1つになっていることが分かった。

そのコンポーネントは、規約の一種で、申込画面のなかでユーザーの同意を得るために表示させている。
プレーンテキストではなくマークアップされており、リスト形式や表が使われている。特にリストは何重にも入れ子になっており、それなりに複雑な構造。

規約なのでスタティックな内容であり、ユーザー毎に表示を出し分けたり、状態によって表示内容が変化したりすることはない。
他のコンポーネントとの依存関係もないので、ハードコーディングというか、用意されたマークアップファイルをそのまま貼り付けていた。

しかしこれが失敗で、このコンポーネントの存在だけでビルドが数分遅くなってしまっていた。
v-forによるリストレンダリングを使って重複する記述を省いていったところ、ビルド時間を大幅に短縮できた。

検証

どの程度の影響があるのか、実際に検証してみる。

使用したライブラリのバージョン。

  • vue@2.5.22
  • vue-loader@15.6.0
  • vue-template-compiler@2.5.22
  • webpack@4.29.0
  • webpack-cli@3.2.1

webpack.config.jsの内容は以下。vue-loader以外は何も使っていない。

const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.vue$/,
        exclude: /node_modules/,
        loader: 'vue-loader',
      },
    ],
  },
  plugins: [new VueLoaderPlugin()],
};

webpack --mode=productionを実行してビルドする。

複雑な構造のコンポーネント(ハードコーディング)

リスト構造やテーブル構造を多用し、それなりに複雑な構造を持っているコンポーネントを用意した。
かなり長いので、Gist に貼る。

Complex.vue

手元の環境だと、ビルドに52.14s.かかった。

シンプルな構造のコンポーネント

次に、先程と全く同じファイルサイズ(8128バイト)だが、構造としては単純なコンポーネントを用意した。

Simple.vue

<p>ランダムな文字列</p>が続いているだけ。

これのビルドは、3.33s.で終わった。
このことから、ファイルサイズは重要ではないということが分かる。

複雑な構造のコンポーネント(リストレンダリングによる効率化)

最後に、複雑なほうのコンポーネントを、リファクタリングする。
リストレンダリングを使うことで、マークアップの記述を減らした。

Improve.vue

面倒なので一部分しか改善を行わなかったが、それだけでも15.13s.にまでビルド時間を短縮できた。