2018年12月4日

プログラミング

かゆいところに手が届く!patch-packageでnpmパッケージを乗りこなそう

かゆいところに手が届く!patch-packageでnpmパッケージを乗りこなそうかゆいところに手が届く!patch-packageでnpmパッケージを乗りこなそう

目次

  1. はじめに
  2. npmパッケージを修正するには
  3. patch-packageの導入
  4. パッチの作り方
  5. まとめ

はじめに

npmパッケージを利用する際、バージョンの違いなどで動かなかったり、少しだけカスタマイズしたいといったような場面に遭遇することはないでしょうか?そんなときに使える patch-package というツールをご紹介します。

npmパッケージを修正するには

npm install によって追加されたパッケージはプロジェクトのnode_modulesというディレクトリ内に保存されます。
このnode_modules内のファイルを変更してしまえばnpmパッケージを修正できるのですが、いくつか方法があります。

node_modules内を直接修正する方法

node_modules内のファイルは一般的にはJavaScriptですので、そのファイルを直接変更してしまうことが可能です。
しかし、node_modules内のファイルは npm install 時などに上書きされる可能性がありますし、.gitignoreとしてGitの管理から除外することが一般的ですので、その都度修正する必要があり実用的ではありません。

パッケージをForkする方法

npm install で依存関係を追加する際、npmのパッケージ名の他にGitリポジトリのURLやGitHubのプロジェクト名を指定することが可能です。
これを利用して、ライブラリのGitプロジェクトをForkして修正し、依存関係にはそちらのForkしたプロジェクトを追加するという方法があります。
こちらの方法は広く使われているのですが、ちょっとした変更であってもForkしたGitプロジェクトを作成する必要があったり、元となるライブラリの更新に追従していくのが大変だったりと、実際やってみると大変なことが多いです。

postinstallで修正する方法

npmには、package.jsonのscriptsに postinstall という名前のスクリプトを追加すると、 npm install 後に任意のコマンドを実行できるという機能があります。(npmの公式ドキュメント
これを利用して、 npm install 後にnode_modules内のファイルが自動的に修正されるような仕組みになれば良さそうなのですが、ファイル内の特定の部分を修正するスクリプトを自分で書く必要が出てきます。

patch-packageは、複雑なシェルスクリプトを書くことなくpostinstallでパッチを当てることができるツールです。

patch-packageの導入

patch-packageは開発時に使われるツールですので、devDependenciesとして依存関係に追加します。

npmパッケージの使い方については以前の記事も参考にしてみてください。

npm install patch-package --save-dev

その後、package.jsonの scriptsに "postinstall": "patch-package" を追加します。

{
  ...
  scripts: {
    ...
    "postinstall": "patch-package"
  }
}

これで npm install 後にpatch-packageが実行されます。

npmコマンドではなくyarnを使う場合、postinstall-postinstallというパッケージも追加することが推奨されています。詳しくはpatch-packageのREADMEを確認してください。

パッチの作り方

例として react-native-parallax-view をみてみましょう。このパッケージはReact NativeのScrollViewにパララックス(視差効果)を追加するものですが、React Nativeのバージョン0.8.0がのころにメンテナンスされていたライブラリで、最新のReact Nativeで動かすにはいくつかの問題点があります。

  • 問題点1: React.PropTypesという廃止された機能を使っている
  • 問題点2: コンポーネントの定義にReact.createClassという廃止された方法を使っている

実際に npm install react-native-parallax-view で依存関係に追加し、 import ParallaxView from 'react-native-parallax-view' という記述をコードに追加すると以下のようなエラーが発生します。

undefined is not an object (evaluating 'React.PropTypes.number')

問題点1のPropTypesというのはFlowやTypeScriptを使わないときにコンポーネントのpropsの型チェックを動的に行うための機能ですが、動作には関係のないところですのでPropTypesを使っているところを全て削除してしまいましょう。

問題点2については、現在の書き方に従うならReact.Componentを継承したクラスに書き換えたいところですが、書き換え箇所が多くなってしまいます。今回は、 create-react-class という互換用のパッケージを使いましょう。

// create-react-classを読み込むために追加
var createReactClass = require('create-react-class'); 

// React.createClassから書き換え
var ParallaxView = createReactClass({

これらの修正を node_modules/react-native-parallax-view/lib/ParallaxView.js に対して直接加えると、エラーが発生しなくなるはずです。(今回は例ですので、実際にParallaxViewを使うのは割愛します)
修正が終わったら、 patch-package <パッチを作りたいパッケージ名> という形式でpatch-packageを実行します。

npx patch-package react-native-parallax-view

正しく実行されていれば、プロジェクト内に以下のような内容の patches/react-native-parallax-view+2.0.6.patch というパッチファイルが作成されていると思います。

patch-package
--- a/node_modules/react-native-parallax-view/lib/ParallaxView.js
+++ b/node_modules/react-native-parallax-view/lib/ParallaxView.js
@@ -9,32 +9,17 @@ var {
     ScrollView,
     Animated,
     } = ReactNative;
+var createReactClass = require('create-react-class');
 /**
  * BlurView temporarily removed until semver stuff is set up properly
  */
 //var BlurView /* = require('react-native-blur').BlurView */;
 var ScrollableMixin = require('react-native-scrollable-mixin');
 var screen = Dimensions.get('window');
-var ScrollViewPropTypes = ScrollView.propTypes;

-var ParallaxView = React.createClass({
+var ParallaxView = createReactClass({
     mixins: [ScrollableMixin],

-    propTypes: {
-        ...ScrollViewPropTypes,
-        windowHeight: React.PropTypes.number,
-        backgroundSource: React.PropTypes.oneOfType([
-          React.PropTypes.shape({
-            uri: React.PropTypes.string,
-          }),
-          // Opaque type returned by require('./image.jpg')
-          React.PropTypes.number,
-        ]),
-        header: React.PropTypes.node,
-        blur: React.PropTypes.string,
-        contentInset: React.PropTypes.object,
-    },
-
     getDefaultProps: function () {
         return {
             windowHeight: 300,

patch-packageを導入していると、このpatchesというディレクトリに作成されたパッチがpostinstallで適用されます。そのためpatchesディレクトリをGitで管理することで、他の開発メンバーが npm install したときにもnode_modules内が修正されます。
パッチファイルのファイル名に注目すると、パッケージ名の後にバージョンが入っており、node_modules内のパッケージが該当のバージョンのときのみ適用されます。パッケージのバージョンアップをするごとにパッチの見直しをして、不要になったらパッチを使わないようにしましょう。

まとめ

patch-packageを使うことによって簡単にnpmパッケージを修正することができました。
特にReact Native向けのライブラリではnode_modules内で管理されているネイティブモジュールのコードに対してもパッチを当てることが可能ですので、使いたくなる場面が多くなります。
npmライブラリをそのまま使えないという状況自体が好ましくはないため、あくまで一時的な手段としてとらえるとしてとらえるのがいいでしょう。ですが、どんな状況でも逃げ道があるということを知っておくと安心です。

JavaScriptのお仕事に関するご相談

Bageleeの運営会社、palanではJavaScriptに関するお仕事のご相談を無料で承っております。
zoomなどのオンラインミーティング、お電話、貴社への訪問、いずれも可能です。
ぜひお気軽にご相談ください。

無料相談フォームへ

7

1

AUTHOR

ゲスト bagelee

ゲスト bagelee

アプリでもっと便利に!気になる記事をチェック!

記事のお気に入り登録やランキングが表示される昨日に対応!毎日の情報収集や調べ物にもっと身近なメディアになりました。

簡単に自分で作れるWebAR

「palanAR」はオンラインで簡単に作れるWebAR作成ツールです。WebARとはアプリを使用せずに、Webサイト上でARを体験できる新しい技術です。

palanARへ
palanar

palanはWebARの開発を
行っています

弊社では企画からサービスの公開終了まで一緒に関わらせていただきます。 企画からシステム開発、3DCG、デザインまで一貫して承ります。

webar_waterpark

palanでは一緒に働く仲間を募集しています

正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。

話を聞いてみたい

運営メンバー

eishis

Eishi Saito 総務

SIerやスタートアップ、フリーランスを経て2016年11月にpalan(旧eishis)を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。

sasakki デザイナー

アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。

yamakawa

やまかわたかし デザイナー

フロントエンドデザイナー。デザインからHTML / CSS、JSの実装を担当しています。最近はReactやReact Nativeをよく触っています。

Sayaka Osanai デザイナー

Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。

はらた

はらた エンジニア

サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています

kobori

こぼり ともろう エンジニア

サーバーサイドエンジニア。SIerを経て2019年7月に入社。日々学習しながらRuby on Railsを使った開発を行っています。

sasai

ささい エンジニア

フロントエンドエンジニア WebGLとReactが強みと言えるように頑張ってます。

damien

Damien

WebAR/VRの企画・開発をやっています。森に住んでいます。

ゲスト bagelee

ゲスト bagelee

かっきー

かっきー

まりな

まりな

suzuki

suzuki

miyagi

ogawa

ogawa

雑食デザイナー。UI/UXデザインやコーディング、時々フロントエンドやってます。最近はARも。

いわもと

いわもと

デザイナーをしています。 好きな食べ物はラーメンです。

kobari

taishi kobari

フロントエンドの開発を主に担当してます。Blitz.js好きです。

shogokubota

kubota shogo

サーバーサイドエンジニア。Ruby on Railsを使った開発を行いつつ月500kmほど走っています!

nishi tomoya

aihara

aihara

グラフィックデザイナーから、フロントエンドエンジニアになりました。最近はWebAR/VRの開発や、Blender、Unityを触っています。モノづくりとワンコが好きです。

nagao

SIerを経てアプリのエンジニアに。xR業界に興味があり、unityを使って開発をしたりしています。

kainuma

Kainuma

サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています

sugimoto

sugimoto

asama

ando

iwasawa ayane

oshimo

oshimo

異業界からやってきたデザイナー。 palanARのUIをメインに担当してます。 これからたくさん吸収していきます!

CONTACT PAGE TOP