1. 記事一覧 >
  2. ブログ記事
category logo

npmのpatch-packageを使って、static-tweetにパッチを当てた

(更新) (公開)

はじめに

前回記事で、react-static-tweets(GitHub)を改修して、Twitter APIをGETするときにプロキシを使うようにした話を書きました。
ソースコードの変更内容のことでしたが、今回は、具体的にどうやって反映させたかを書こうと思います。


react-static-tweetsのソースコード書き換えが必要ですので、forkするのか、自分のソースコード(itc-blog(GitHub))に取り込んでしまって良いのか?と対応に迷いが生じ、パッチを当てる方法を見つけて、実践しました。
パッチを当てる方法は、npmのpatch-packageを使います。


【 作業の流れ 】
※プロジェクト名をitc-blogとします。


react-static-tweets(GitHub)
のソースコードをダウンロード

react-static-tweets/packages/static-tweets/src/twitter/api.ts
をProxy対応に修正

react-static-tweetsをビルド

itc-blog/node_modules/static-tweets/src
itc-blog/node_modules/static-tweets/build
を更新

npx patch-package static-tweets

itc-blog/patches/static-tweets+0.5.3.patch 作成

itc-blog/package.json更新

npm install

毎回、
itc-blog/node_modules/static-tweets/src
itc-blog/node_modules/static-tweets/build
に修正内容が適用されて、プロキシを通して、Twitter APIをGET


ソースコード修正

react-static-tweets(GitHub)のソースコードをダウンロードします。
※0.5.4のバージョン固定にしたいので、react-static-tweets-0.5.4.zipをダウンロードします。

react-static-tweetsダウンロード

展開します。

$ unzip react-static-tweets-0.5.4.zip
$ mv react-static-tweets-0.5.4 react-static-tweets
$ cd react-static-tweets

ソースコードを修正します。

$ vi react-static-tweets/packages/static-tweets/src/twitter/api.ts

diff:

node_modules/static-tweets/src/twitter/api.ts CHANGED
@@ -1,4 +1,6 @@
1
- import fetch from '../fetch'
1
+ //import fetch from '../fetch'
2
+ import fetch from 'isomorphic-fetch';
3
+ import { HttpsProxyAgent } from 'https-proxy-agent';
2
4
 
3
5
  const API_URL = 'https://api.twitter.com'
4
6
  const SYNDICATION_URL = 'https://syndication.twitter.com'
@@ -13,7 +15,8 @@ function twitterLabsEnabled(expansions) {
13
15
  }
14
16
 
15
17
  export async function fetchTweetsHtml(ids) {
16
- const res = await fetch(`${SYNDICATION_URL}/tweets.json?ids=${ids}`)
18
+ const proxy = process.env.https_proxy;
19
+ const res = await fetch(`${SYNDICATION_URL}/tweets.json?ids=${ids}`, proxy ? { agent: new HttpsProxyAgent(proxy) } : {})
17
20
 
18
21
  if (res.ok) return res.json()
19
22
  if (res.status === 404) return {}
@@ -32,14 +35,17 @@ export async function fetchUserStatus(tweetId) {
32
35
  // If there isn't an API token don't do anything, this is only required for videos.
33
36
  if (!process.env.TWITTER_ACCESS_TOKEN) return
34
37
 
35
- const res = await fetch(
36
- `${API_URL}/1.1/statuses/show/${tweetId}.json?include_entities=true&tweet_mode=extended`,
37
- {
38
- headers: {
39
- authorization: `Bearer ${process.env.TWITTER_ACCESS_TOKEN}`
40
- }
38
+ const proxy = process.env.https_proxy;
39
+ const res = await fetch(`${API_URL}/1.1/statuses/show/${tweetId}.json?include_entities=true&tweet_mode=extended`, proxy ? {
40
+ headers: {
41
+ authorization: `Bearer ${process.env.TWITTER_ACCESS_TOKEN}`
42
+ },
43
+ agent: new HttpsProxyAgent(proxy)
44
+ } : {
45
+ headers: {
46
+ authorization: `Bearer ${process.env.TWITTER_ACCESS_TOKEN}`
41
47
  }
42
- )
48
+ })
43
49
 
44
50
  console.log(
45
51
  'Twitter x-rate-limit-limit:',
@@ -68,14 +74,18 @@ export async function fetchTweetWithPoll(tweetId) {
68
74
  if (!process.env.TWITTER_ACCESS_TOKEN || !twitterLabsEnabled(expansions))
69
75
  return
70
76
 
71
- const res = await fetch(
72
- `${API_URL}/labs/1/tweets?format=compact&expansions=${expansions}&ids=${tweetId}`,
73
- {
74
- headers: {
75
- authorization: `Bearer ${process.env.TWITTER_ACCESS_TOKEN}`
76
- }
77
+ const proxy = process.env.https_proxy;
78
+ const res = await fetch(`${API_URL}/labs/1/tweets?format=compact&expansions=${expansions}&ids=${tweetId}`, proxy ? {
79
+ headers: {
80
+ authorization: `Bearer ${process.env.TWITTER_ACCESS_TOKEN}`
81
+ },
82
+ agent: new HttpsProxyAgent(proxy)
83
+ } : {
84
+ headers: {
85
+ authorization: `Bearer ${process.env.TWITTER_ACCESS_TOKEN}`
77
86
  }
78
- )
87
+ })
88
+
79
89
 
80
90
  console.log(
81
91
  'Twitter Labs x-rate-limit-limit:',
@@ -99,7 +109,8 @@ export async function fetchTweetWithPoll(tweetId) {
99
109
  }
100
110
 
101
111
  export async function getEmbeddedTweetHtml(url) {
102
- const res = await fetch(`https://publish.twitter.com/oembed?url=${url}`)
112
+ const proxy = process.env.https_proxy;
113
+ const res = await fetch(`https://publish.twitter.com/oembed?url=${url}`, proxy ? { agent: new HttpsProxyAgent(proxy) } : {})
103
114
 
104
115
  if (res.ok) return res.json()
105
116
  if (res.status === 404) return

ビルド

react-static-tweets をビルドします。

$ cd react-static-tweets/
$ npm install
$ npm run build

ビルドした結果、
react-static-tweets/packages/static-tweets/build
ができます。


node_modules更新

react-static-tweetsのビルド結果をitc-blog/node_modules/static-tweetsの方に適用します。

$ cd ../
$ rm -r itc-blog/node_modules/static-tweets/src
$ rm -r itc-blog/node_modules/static-tweets/build
$ cp -rp react-static-tweets/packages/static-tweets/src itc-blog/node_modules/static-tweets/
$ cp -rp react-static-tweets/packages/static-tweets/build itc-blog/node_modules/static-tweets/

react-static-tweets更新の図


パッチ作成

npmのpatch-packageコマンドを使って、差分パッチファイルを作成します。

$ cd itc-blog
$ npx patch-package static-tweets

【 npx 】

npmで管理されたプログラムの一つです。npxを使うと、オンメモリで依存関係を解決した状態で、引数に指定したプログラムを実行できます。ディスクを汚さず、一度きりしか実行しないプログラムを実行するのに向いています。


結果、itc-blog/patches/static-tweets+0.5.3.patchが作成されます。
このパッチファイルは、普通にnpm installしたときのnode_modules/static-tweetsと上記のように修正してビルドしなおしたnode_modules/static-tweetsとの差分です。


package.json更新

package.jsonを更新して、npm install後にパッチが適用されるようにします。
"postinstall": "patch-package"
を追加します。

postinstallは、patch-packageに限らず、npm install後に実行するコマンドを指定できます。

例:

{
  "name": "itc-blog",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "export": "next build && next export",
    "postexport": "next-sitemap --config sitemap.config.js",
    "serve": "PORT=3000 serve ./out",
    "postinstall": "patch-package"
  },
  "dependencies": {
    "@mapbox/rehype-prism": "^0.6.0",
(略)

パッチ適用

patch-packageをインストールして、npm installでパッチを適用します。
patch-packageは、devDependenciesに追加されます。

$ npm install patch-package --save-dev
$ npm install
> patch-package

patch-package 6.4.7
Applying patches...
static-tweets@0.5.3
(略)
$ view node_modules/static-tweets/src/twitter/api.ts
//import fetch from '../fetch'
import fetch from 'isomorphic-fetch';
import { HttpsProxyAgent } from 'https-proxy-agent';

書き換えたところが変わっていれば、OKです。

node_modules/static-tweets/srcの方は、実際には使われないため、node_modules/static-tweets/buildの方が重要です。


できました!

loading...