source: node_modules/patch-package/README.md

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 13.2 KB
Line 
1<p align="center">
2 <img src="https://ds300.github.io/patch-package/patch-package.svg" width="80%" alt="patch-package" />
3</p>
4
5`patch-package` lets app authors instantly make and keep fixes to npm
6dependencies. It's a vital band-aid for those of us living on the bleeding edge.
7
8```sh
9# fix a bug in one of your dependencies
10vim node_modules/some-package/brokenFile.js
11
12# run patch-package to create a .patch file
13npx patch-package some-package
14
15# commit the patch file to share the fix with your team
16git add patches/some-package+3.14.15.patch
17git commit -m "fix brokenFile.js in some-package"
18```
19
20Patches created by `patch-package` are automatically and gracefully applied when
21you use `npm`(>=5) or `yarn`.
22
23No more waiting around for pull requests to be merged and published. No more
24forking repos just to fix that one tiny thing preventing your app from working.
25
26## Set-up
27
28In package.json
29
30```diff
31 "scripts": {
32+ "postinstall": "patch-package"
33 }
34```
35
36Then
37
38### npm
39
40 npm i patch-package
41
42You can use `--save-dev` if you don't need to run npm in production, e.g. if
43you're making a web frontend.
44
45### yarn v1
46
47 yarn add patch-package postinstall-postinstall
48
49You can use `--dev` if you don't need to run yarn in production, e.g. if you're
50making a web frontend.
51
52To understand why yarn needs the `postinstall-postinstall` package see:
53[Why use postinstall-postinstall](#why-use-postinstall-postinstall-with-yarn)
54
55### yarn workspaces
56
57Same as for yarn ☝️ Note that if you want to patch un-hoisted packages you'll
58need to repeat the setup process for the child package. Also make sure you're in
59the child package directory when you run `patch-package` to generate the patch
60files.
61
62### yarn v2+
63
64yarn 2+ have native support for patching dependencies via
65[`yarn patch`](https://yarnpkg.com/cli/patch). You do not need to use
66patch-package on these projects.
67
68### pnpm
69
70pnpm has native support for patching dependencies via
71[`pnpm patch`](https://pnpm.io/cli/patch). You do not need to use patch-package
72on these projects.
73
74### Heroku
75
76For `patch-package` to work on Heroku applications, you must specify
77[`NPM_CONFIG_PRODUCTION=false` or `YARN_PRODUCTION=false`](https://devcenter.heroku.com/articles/nodejs-support#package-installation).
78See [this issue](https://github.com/ds300/patch-package/issues/130) for more
79details.
80
81### Docker and CI
82
83- If having errors about working directory ("cannot run in wd [...]") when
84 building in Docker, you might need to adjust configuration in `.npmrc`. See
85 [#185](https://github.com/ds300/patch-package/issues/185).
86- In your `Dockerfile`, remember to copy over the patch files _before_ running
87 `[npm|yarn] install`
88- If you cache `node_modules` rather than running `yarn install` every time,
89 make sure that the `patches` dir is included in your cache key somehow.
90 Otherwise if you update a patch then the change may not be reflected on
91 subsequent CI runs.
92
93### CircleCI
94
95Create a hash of your patches before loading/saving your cache. If using a Linux
96machine, run `md5sum patches/* > patches.hash`. If running on a macOS machine,
97use `md5 patches/* > patches.hash`
98
99```yaml
100- run:
101 name: patch-package hash
102 command: md5sum patches/* > patches.hash
103```
104
105Then, update your hash key to include a checksum of that file:
106
107```yaml
108- restore_cache:
109 key:
110 app-node_modules-v1-{{ checksum "yarn.lock" }}-{{ checksum "patches.hash"
111 }}
112```
113
114As well as the save_cache
115
116```yaml
117- save_cache:
118 key:
119 app-node_modules-v1-{{ checksum "yarn.lock" }}-{{ checksum "patches.hash"
120 }}
121 paths:
122 - ./node_modules
123```
124
125## Usage
126
127### Making patches
128
129First make changes to the files of a particular package in your node_modules
130folder, then run
131
132 yarn patch-package package-name
133
134or use npx (included with `npm > 5.2`)
135
136 npx patch-package package-name
137
138where `package-name` matches the name of the package you made changes to.
139
140If this is the first time you've used `patch-package`, it will create a folder
141called `patches` in the root dir of your app. Inside will be a file called
142`package-name+0.44.0.patch` or something, which is a diff between normal old
143`package-name` and your fixed version. Commit this to share the fix with your
144team.
145
146#### Options
147
148- `--create-issue`
149
150 For packages whose source is hosted on GitHub this option opens a web browser
151 with a draft issue based on your diff.
152
153- `--use-yarn`
154
155 By default, patch-package checks whether you use npm or yarn based on which
156 lockfile you have. If you have both, it uses npm by default. Set this option
157 to override that default and always use yarn.
158
159- `--exclude <regexp>`
160
161 Ignore paths matching the regexp when creating patch files. Paths are relative
162 to the root dir of the package to be patched.
163
164 Default value: `package\\.json$`
165
166- `--include <regexp>`
167
168 Only consider paths matching the regexp when creating patch files. Paths are
169 relative to the root dir of the package to be patched.
170
171 Default value: `.*`
172
173- `--case-sensitive-path-filtering`
174
175 Make regexps used in --include or --exclude filters case-sensitive.
176
177- `--patch-dir`
178
179 Specify the name for the directory in which to put the patch files.
180
181#### Nested packages
182
183If you are trying to patch a package at, e.g.
184`node_modules/package/node_modules/another-package` you can just put a `/`
185between the package names:
186
187 npx patch-package package/another-package
188
189It works with scoped packages too
190
191 npx patch-package @my/package/@my/other-package
192
193### Updating patches
194
195Use exactly the same process as for making patches in the first place, i.e. make
196more changes, run patch-package, commit the changes to the patch file.
197
198### Applying patches
199
200Run `patch-package` without arguments to apply all patches in your project.
201
202#### Options
203
204- `--error-on-fail`
205
206 Forces patch-package to exit with code 1 after failing.
207
208 When running locally patch-package always exits with 0 by default. This
209 happens even after failing to apply patches because otherwise yarn.lock and
210 package.json might get out of sync with node_modules, which can be very
211 confusing.
212
213 `--error-on-fail` is **switched on** by default on CI.
214
215 See https://github.com/ds300/patch-package/issues/86 for background.
216
217- `--reverse`
218
219 Un-applies all patches.
220
221 Note that this will fail if the patched files have changed since being
222 patched. In that case, you'll probably need to re-install `node_modules`.
223
224 This option was added to help people using CircleCI avoid
225 [an issue around caching and patch file updates](https://github.com/ds300/patch-package/issues/37)
226 but might be useful in other contexts too.
227
228- `--patch-dir`
229
230 Specify the name for the directory in which the patch files are located
231
232#### Notes
233
234To apply patches individually, you may use `git`:
235
236 git apply --ignore-whitespace patches/package-name+0.44.2.patch
237
238or `patch` in unixy environments:
239
240 patch -p1 -i patches/package-name+0.44.2.patch
241
242### Dev-only patches
243
244If you deploy your package to production (e.g. your package is a server) then
245any patched `devDependencies` will not be present when patch-package runs in
246production. It will happily ignore those patch files if the package to be
247patched is listed directly in the `devDependencies` of your package.json. If
248it's a transitive dependency patch-package can't detect that it is safe to
249ignore and will throw an error. To fix this, mark patches for transitive dev
250dependencies as dev-only by renaming from, e.g.
251
252 package-name+0.44.0.patch
253
254to
255
256 package-name+0.44.0.dev.patch
257
258This will allow those patch files to be safely ignored when
259`NODE_ENV=production`.
260
261### Creating multiple patches for the same package
262
263_💡 This is an advanced feature and is not recommended unless you really, really
264need it._
265
266Let's say you have a patch for react-native called
267
268- `patches/react-native+0.72.0.patch`
269
270If you want to add another patch file to `react-native`, you can use the
271`--append` flag while supplying a name for the patch.
272
273Just make you changes inside `node_modules/react-native` then run e.g.
274
275 npx patch-package react-native --append 'fix-touchable-opacity'
276
277This will create a new patch file while renaming the old patch file so that you
278now have:
279
280- `patches/react-native+0.72.0+001+initial.patch`
281- `patches/react-native+0.72.0+002+fix-touchable-opacity.patch`
282
283The patches are ordered in a sequence, so that they can build on each other if
284necessary. **Think of these as commits in a git history**.
285
286#### Updating a sequenced patch file
287
288If the patch file is the last one in the sequence, you can just make your
289changes inside e.g. `node_modules/react-native` and then run
290
291 npx patch-package react-native
292
293This will update the last patch file in the sequence.
294
295If the patch file is not the last one in the sequence **you need to use the
296`--rebase` feature** to un-apply the succeeding patch files first.
297
298Using the example above, let's say you want to update the `001+initial` patch
299but leave the other patch alone. You can run
300
301 npx patch-package react-native --rebase patches/react-native+0.72.0+001+initial.patch
302
303This will undo the `002-fix-touchable-opacity` patch file. You can then make
304your changes and run
305
306 npx patch-package react-native
307
308to finish the rebase by updating the `001+initial` patch file and re-apply the
309`002-fix-touchable-opacity` patch file, leaving you with all patches applied and
310up-to-date.
311
312#### Inserting a new patch file in the middle of an existing sequence
313
314Using the above example, let's say you want to insert a new patch file between
315the `001+initial` and `002+fix-touchable-opacity` patch files. You can run
316
317 npx patch-package react-native --rebase patches/react-native+0.72.0+001+initial.patch
318
319This will undo the `002-fix-touchable-opacity` patch file. You can then make any
320changes you want to insert in a new patch file and run
321
322 npx patch-package react-native --append 'fix-console-warnings'
323
324This will create a new patch file while renaming any successive patches to
325maintain the sequence order, leaving you with
326
327- `patches/react-native+0.72.0+001+initial.patch`
328- `patches/react-native+0.72.0+002+fix-console-warnings.patch`
329- `patches/react-native+0.72.0+003+fix-touchable-opacity.patch`
330
331To insert a new patch file at the start of the sequence, you can run
332
333 npx patch-package react-native --rebase 0
334
335Which will un-apply all patch files in the sequence. Then follow the process
336above to create a new patch file numbered `001`.
337
338#### Deleting a sequenced patch file
339
340To delete a sequenced patch file, just delete it, then remove and reinstall your
341`node_modules` folder.
342
343If you deleted one of the patch files other than the last one, you don't need to
344update the sequence numbers in the successive patch file names, but you might
345want to do so to keep things tidy.
346
347#### Partially applying a broken patch file
348
349Normally patch application is atomic per patch file. i.e. if a patch file
350contains an error anywhere then none of the changes in the patch file will be
351applied and saved to disk.
352
353This can be problematic if you have a patch with many changes and you want to
354keep some of them and update others.
355
356In this case you can use the `--partial` option. Patch-package will apply as
357many of the changes as it can and then leave it to you to fix the rest.
358
359Any errors encountered will be written to a file `./patch-package-errors.log` to
360help you keep track of what needs fixing.
361
362## Benefits of patching over forking
363
364- Sometimes forks need extra build steps, e.g. with react-native for Android.
365 Forget that noise.
366- Get told in big red letters when the dependency changed and you need to check
367 that your fix is still valid.
368- Keep your patches colocated with the code that depends on them.
369- Patches can be reviewed as part of your normal review process, forks probably
370 can't
371
372## When to fork instead
373
374- The change is too consequential to be developed in situ.
375- The change would be useful to other people as-is.
376- You can afford to make a proper PR to upstream.
377
378## Isn't this dangerous?
379
380Nope. The technique is quite robust. Here are some things to keep in mind
381though:
382
383- It's easy to forget to run `yarn` or `npm` when switching between branches
384 that do and don't have patch files.
385- Long lived patches can be costly to maintain if they affect an area of code
386 that is updated regularly and you want to update the package regularly too.
387- Big semantic changes can be hard to review. Keep them small and obvious or add
388 plenty of comments.
389- Changes can also impact the behaviour of other untouched packages. It's
390 normally obvious when this will happen, and often desired, but be careful
391 nonetheless.
392
393## Why use postinstall-postinstall with Yarn?
394
395Most times when you do a `yarn`, `yarn add`, `yarn remove`, or `yarn install`
396(which is the same as just `yarn`) Yarn will completely replace the contents of
397your node_modules with freshly unpackaged modules. patch-package uses the
398`postinstall` hook to modify these fresh modules, so that they behave well
399according to your will.
400
401Yarn only runs the `postinstall` hook after `yarn` and `yarn add`, but not after
402`yarn remove`. The `postinstall-postinstall` package is used to make sure your
403`postinstall` hook gets executed even after a `yarn remove`.
404
405## License
406
407MIT
408
409[![Empowered by Futurice's open source sponsorship program](https://img.shields.io/badge/sponsor-chilicorn-ff69b4.svg)](http://futurice.com/blog/sponsoring-free-time-open-source-activities?utm_source=github&utm_medium=spice&utm_campaign=patch-package)
Note: See TracBrowser for help on using the repository browser.