2018年12月4日
プログラミング
かゆいところに手が届く!patch-packageでnpmパッケージを乗りこなそう
はじめに
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が実行されます。
パッチの作り方
例として 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'
という記述をコードに追加すると以下のようなエラーが発生します。
問題点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
関連記事
2018年7月6日
【js】jQueryでできるハンバーガーメニューの作成
2018年6月18日
プログレスバーを簡単に実装できるprogressbar.js
2018年5月8日
画像に簡単にアニメーションをつけるcurtain.js
2018年2月14日
【js】jQueryでできるアコーディオンメニューの作成
2017年9月4日
【JS】スクロールした時にCSSanimationを発動させる「scrollMonitor」
簡単に自分で作れるWebAR
「palanAR」はオンラインで簡単に作れるWebAR作成ツールです。WebARとはアプリを使用せずに、Webサイト上でARを体験できる新しい技術です。
palanARへpalanでは一緒に働く仲間を募集しています
正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。
運営メンバー
Eishi Saito 総務
SIerやスタートアップ、フリーランスを経て2016年11月にpalan(旧eishis)を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。
sasakki デザイナー
アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。
やまかわたかし デザイナー
フロントエンドデザイナー。デザインからHTML / CSS、JSの実装を担当しています。最近はReactやReact Nativeをよく触っています。
Sayaka Osanai デザイナー
Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。
はらた エンジニア
サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています
こぼり ともろう エンジニア
サーバーサイドエンジニア。SIerを経て2019年7月に入社。日々学習しながらRuby on Railsを使った開発を行っています。
ささい エンジニア
フロントエンドエンジニア WebGLとReactが強みと言えるように頑張ってます。
Damien
WebAR/VRの企画・開発をやっています。森に住んでいます。
ゲスト bagelee
かっきー
まりな
suzuki
miyagi
ogawa
雑食デザイナー。UI/UXデザインやコーディング、時々フロントエンドやってます。最近はARも。
いわもと
デザイナーをしています。 好きな食べ物はラーメンです。
taishi kobari
フロントエンドの開発を主に担当してます。Blitz.js好きです。
kubota shogo
サーバーサイドエンジニア。Ruby on Railsを使った開発を行いつつ月500kmほど走っています!
nishi tomoya
aihara
グラフィックデザイナーから、フロントエンドエンジニアになりました。最近はWebAR/VRの開発や、Blender、Unityを触っています。モノづくりとワンコが好きです。
nagao
SIerを経てアプリのエンジニアに。xR業界に興味があり、unityを使って開発をしたりしています。
Kainuma
サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています
sugimoto
asama
ando
iwasawa ayane
oshimo
異業界からやってきたデザイナー。 palanARのUIをメインに担当してます。 これからたくさん吸収していきます!