From c6d62e1fd496a1867c70f0e7cc80511151dece55 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Nov 2023 19:33:18 +0800 Subject: [PATCH 1/4] chore(deps): update dependency jest-light-runner to v0.6.0 (#15734) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 111 ++++++--------------------------------------------- 2 files changed, 14 insertions(+), 99 deletions(-) diff --git a/package.json b/package.json index d8026c940..7fad53897 100644 --- a/package.json +++ b/package.json @@ -138,7 +138,7 @@ "esm-utils": "4.2.1", "execa": "7.2.0", "jest": "30.0.0-alpha.2", - "jest-light-runner": "0.6.0-alpha.1", + "jest-light-runner": "0.6.0", "jest-snapshot-serializer-ansi": "2.1.0", "jest-snapshot-serializer-raw": "2.0.0", "jest-watch-typeahead": "2.2.2", diff --git a/yarn.lock b/yarn.lock index a0daadb6a..7c03398ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -36,13 +36,6 @@ __metadata: languageName: node linkType: hard -"@assemblyscript/loader@npm:^0.10.1": - version: 0.10.1 - resolution: "@assemblyscript/loader@npm:0.10.1" - checksum: fd1f57bdf2c55252a48c2d93fbec3c5a9ef4ca40e581e8709dd8ee437613eb47af74c8cdba011a324077eda9605d6f24983f429c2ce18b0b582ddcc5acf75c26 - languageName: node - linkType: hard - "@babel/code-frame@npm:7.0.0": version: 7.0.0 resolution: "@babel/code-frame@npm:7.0.0" @@ -2527,13 +2520,6 @@ __metadata: languageName: node linkType: hard -"base64-js@npm:^1.2.0": - version: 1.5.1 - resolution: "base64-js@npm:1.5.1" - checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 - languageName: node - linkType: hard - "benchmark@npm:2.1.4": version: 2.1.4 resolution: "benchmark@npm:2.1.4" @@ -4102,13 +4088,6 @@ __metadata: languageName: node linkType: hard -"eventemitter-asyncresource@npm:^1.0.0": - version: 1.0.0 - resolution: "eventemitter-asyncresource@npm:1.0.0" - checksum: 3cfbbc3490bd429a165bff6336289ff810f7df214796f25000d2097a5a0883eae51542a78674916ff99bbd4c66811911b310df1cb4fc96dfc9546ba9dfc89f8f - languageName: node - linkType: hard - "execa@npm:7.2.0, execa@npm:^7.1.1": version: 7.2.0 resolution: "execa@npm:7.2.0" @@ -4737,24 +4716,6 @@ __metadata: languageName: node linkType: hard -"hdr-histogram-js@npm:^2.0.1": - version: 2.0.3 - resolution: "hdr-histogram-js@npm:2.0.3" - dependencies: - "@assemblyscript/loader": ^0.10.1 - base64-js: ^1.2.0 - pako: ^1.0.3 - checksum: 7bb252ba3596bed72b90427ffc6f6fa332a460c4810788faa9b9a743f7ac6f1cb42dccd7ae7555740f0a8c0602884944d00d1ccfb746af4976a816772361a6d6 - languageName: node - linkType: hard - -"hdr-histogram-percentiles-obj@npm:^3.0.0": - version: 3.0.0 - resolution: "hdr-histogram-percentiles-obj@npm:3.0.0" - checksum: ab238edcb38d9b60d23ca53da0ecd9a6b1c8ee9a49e30a6146bd3f8f70f26244652f28b79974157c00504e7ddf3129e0ddb217baf71d32330e3fae0105bf30ed - languageName: node - linkType: hard - "hermes-estree@npm:0.17.1": version: 0.17.1 resolution: "hermes-estree@npm:0.17.1" @@ -5715,9 +5676,9 @@ __metadata: languageName: node linkType: hard -"jest-light-runner@npm:0.6.0-alpha.1": - version: 0.6.0-alpha.1 - resolution: "jest-light-runner@npm:0.6.0-alpha.1" +"jest-light-runner@npm:0.6.0": + version: 0.6.0 + resolution: "jest-light-runner@npm:0.6.0" dependencies: "@jest/expect": ^30.0.0-alpha.1 "@jest/fake-timers": ^30.0.0-alpha.1 @@ -5725,11 +5686,11 @@ __metadata: jest-each: ^30.0.0-alpha.1 jest-mock: ^30.0.0-alpha.1 jest-snapshot: ^30.0.0-alpha.1 - piscina: ^3.1.0 supports-color: ^9.2.1 + tinypool: ^0.8.1 peerDependencies: jest: ^27.5.0 || ^28.0.0 || ^29.0.0|| ^30.0.0-0 - checksum: ce18c3531d9083873832bbc6a8058bc8669a05e3bc278a3539a0edbc2233103cdfcdb3f73a5c5addcc193173801ba08ececf12f05dac6a27c2721306d7ea4a79 + checksum: 8ebfb05e1d01f959b1bd46e37d52d18b07e49a26c4ddef796c311470b998e8fa9a600e405a64cb499ad195a48b3d2552588b8fb5bdd6bb6f8c7c37a40ed72d00 languageName: node linkType: hard @@ -6724,37 +6685,6 @@ __metadata: languageName: node linkType: hard -"nice-napi@npm:^1.0.2": - version: 1.0.2 - resolution: "nice-napi@npm:1.0.2" - dependencies: - node-addon-api: ^3.0.0 - node-gyp: latest - node-gyp-build: ^4.2.2 - conditions: "!os=win32" - languageName: node - linkType: hard - -"node-addon-api@npm:^3.0.0": - version: 3.2.1 - resolution: "node-addon-api@npm:3.2.1" - dependencies: - node-gyp: latest - checksum: 2369986bb0881ccd9ef6bacdf39550e07e089a9c8ede1cbc5fc7712d8e2faa4d50da0e487e333d4125f8c7a616c730131d1091676c9d499af1d74560756b4a18 - languageName: node - linkType: hard - -"node-gyp-build@npm:^4.2.2": - version: 4.7.1 - resolution: "node-gyp-build@npm:4.7.1" - bin: - node-gyp-build: bin.js - node-gyp-build-optional: optional.js - node-gyp-build-test: build-test.js - checksum: 2ef8248021489db03be3e8098977cdc797b80a9b12b77c6dcb89b0dc89b8c62e6a482672ee298f61021740ae7f080fb33154cfec8fb158cec620f57b0fae87c0 - languageName: node - linkType: hard - "node-gyp@npm:latest": version: 10.0.1 resolution: "node-gyp@npm:10.0.1" @@ -7112,13 +7042,6 @@ __metadata: languageName: node linkType: hard -"pako@npm:^1.0.3": - version: 1.0.11 - resolution: "pako@npm:1.0.11" - checksum: 1be2bfa1f807608c7538afa15d6f25baa523c30ec870a3228a89579e474a4d992f4293859524e46d5d87fd30fa17c5edf34dbef0671251d9749820b488660b16 - languageName: node - linkType: hard - "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -7283,21 +7206,6 @@ __metadata: languageName: node linkType: hard -"piscina@npm:^3.1.0": - version: 3.2.0 - resolution: "piscina@npm:3.2.0" - dependencies: - eventemitter-asyncresource: ^1.0.0 - hdr-histogram-js: ^2.0.1 - hdr-histogram-percentiles-obj: ^3.0.0 - nice-napi: ^1.0.2 - dependenciesMeta: - nice-napi: - optional: true - checksum: c1980c7d45d85f53265652dd2fc62a2b9e9d2321f5bbb9fc1796edb9c1324bb77c153e823a0d6454c3c35098820efedff584737cc282207480afe478a3b8a166 - languageName: node - linkType: hard - "pkg-dir@npm:^4.2.0": version: 4.2.0 resolution: "pkg-dir@npm:4.2.0" @@ -7489,7 +7397,7 @@ __metadata: iterate-directory-up: 1.1.1 jest: 30.0.0-alpha.2 jest-docblock: 29.7.0 - jest-light-runner: 0.6.0-alpha.1 + jest-light-runner: 0.6.0 jest-snapshot-serializer-ansi: 2.1.0 jest-snapshot-serializer-raw: 2.0.0 jest-watch-typeahead: 2.2.2 @@ -8594,6 +8502,13 @@ __metadata: languageName: node linkType: hard +"tinypool@npm:^0.8.1": + version: 0.8.1 + resolution: "tinypool@npm:0.8.1" + checksum: e1162629b32a694edd92323fe7cc57379723f36b03f37e3f9442cb8fd3a99785b2b9416ef586d2f4cec8624f356b38558c2cfd272eb265a30841371d3d67d37a + languageName: node + linkType: hard + "titleize@npm:^3.0.0": version: 3.0.0 resolution: "titleize@npm:3.0.0" From 1632e25b1762c4b9af70c81855fd2f9791e620f5 Mon Sep 17 00:00:00 2001 From: Fabio Spampinato Date: Thu, 30 Nov 2023 16:48:53 +0000 Subject: [PATCH 2/4] Added a blog post about the new CLI (#15731) Co-authored-by: uncenter <47499684+uncenter@users.noreply.github.com> Co-authored-by: fisker Cheung --- cspell.json | 3 + website/blog/2023-11-29-cli-deep-dive.md | 284 ++++++++++++++++++ website/blog/assets/prettier-architecture.png | Bin 0 -> 58651 bytes website/blog/assets/prettier-bench.png | Bin 0 -> 53363 bytes 4 files changed, 287 insertions(+) create mode 100644 website/blog/2023-11-29-cli-deep-dive.md create mode 100644 website/blog/assets/prettier-architecture.png create mode 100644 website/blog/assets/prettier-bench.png diff --git a/cspell.json b/cspell.json index 6b11070f0..93da3c59a 100644 --- a/cspell.json +++ b/cspell.json @@ -35,6 +35,7 @@ "bitshift", "blenda", "Bopomofo", + "bottlenecked", "Breakell", "Brevik", "Burgener", @@ -98,6 +99,7 @@ "estree", "execa", "Fabio", + "fabiospampinato", "fbglyph", "fdescribe", "fesm", @@ -262,6 +264,7 @@ "Rattray", "rattrayalex", "Rauch", + "readdir", "readline", "readlines", "rebalance", diff --git a/website/blog/2023-11-29-cli-deep-dive.md b/website/blog/2023-11-29-cli-deep-dive.md new file mode 100644 index 000000000..52caf7e65 --- /dev/null +++ b/website/blog/2023-11-29-cli-deep-dive.md @@ -0,0 +1,284 @@ +--- +author: "Fabio Spampinato (@fabiospampinato)" +authorURL: "https://github.com/fabiospampinato" +title: "Prettier's CLI: A Performance Deep Dive" +--- + +Hey, I'm [Fabio](https://twitter.com/fabiospampinato) and I've been contracted by the Prettier team to speed up Prettier's command line interface (CLI). In this post we'll take a look at the optimizations I've discovered, the process that lead to finding them, some exciting numbers comparing the current CLI with the new one, and some guesses about what could be optimized next. + +## Installation + +The new work-in-progress CLI for Prettier has just been [released](https://github.com/prettier/prettier-cli), and you can install it now: + +```sh +npm install prettier@next +``` + +It should be largely backwards compatible: + +```sh +prettier . --check # Like before, but faster +``` + +If you find any issues you can temporarily use the old CLI using an environment variable: + +```sh +PRETTIER_LEGACY_CLI=1 prettier . --check +``` + +You can also try it via `npx`, though `npx` itself is pretty slow: + +```sh +npx prettier@next . --check +``` + +The goal is to make it close to ~100% backwards compatible, and then just ship it in a future stable release of the `prettier` package, replacing the current CLI. + +## Overview + +

+ +

+ +Prettier's CLI works roughly like in the diagram above: + +1. There's some action we want to execute on files, for example checking if they are formatted properly. +2. We need to actually find all the files to execute this action on. +3. We need to resolve `.gitignore` and `.prettierignore` files, to figure out if some of those files are to be ignored. +4. We need to resolve `.editorconfig` files, for [EditorConfig](https://editorconfig.org)-specific formatting configurations for those files. +5. We need to resolve `.prettierrc` files, and [~10 more](https://prettier.io/docs/en/configuration), for Prettier-specific formatting configurations for those files. +6. We need to check if each of the files matches its formatting configuration. +7. Finally we need to output some kind of result to the terminal. + +After this high-level look at the CLI's architecture I think there are mainly 3 observations to make: + +1. The amount of work to do scales with the number of target files, but most files are completely unchanged between runs of the CLI, because for example a commit in a large-enough repository generally only touches a fraction of the files, so if we could only remember work done in the previous run most of the work on the current run could be skipped. +2. There are potentially a huge number of configuration files to resolve, since our repository could have thousands of folders and each folder could have some configuration files in it, moreover if for example we find 10 different `.editorconfig` files, each of them could define different settings for files matching specific [globs](), so they all need to be combined together in a file-specific way, for each target file. But, in almost every case a repository is only going to contain just one or a handful of `.editorconfig` files, even if the repo has thousands of folders, so somehow this shouldn't be _that_ expensive. +3. This isn't a particularly insightful observation, but if everything a program is doing is necessary, and everything done is done efficiently, then the program itself must execute efficiently as a result, so we are generally just going to try to skip unnecessary work as much as possible, and what we can't skip we'll try to make efficient. + +From these observations I started writing a new CLI for Prettier from scratch, as it's often easier to rewrite things with performance in mind from the start than to patch them to be performant. + +I'll use [Babel](https://github.com/babel/babel)'s monorepo to take measurements throughout this post, as it provides a good sort of benchmark, and it should give you a sense of what the improvement will be in practice for a real, fairly large, monorepo. + +## Finding files fast + +First of all we need to find our target files. Prettier's current CLI uses [`fast-glob`](https://github.com/mrmlnc/fast-glob) for that, and the code for using it may look like this: + +```js +import fastGlob from "fast-glob"; + +const files = await fastGlob("packages/**/*.{js,cjs,mjs}", { + ignore: ["**/.git", "**/.sl", "**/.svn", "**/.hg", "**/node_modules"], + absolute: true, + dot: true, + followSymbolicLinks: false, + onlyFiles: true, + unique: true, +}); +``` + +If we run that on Babel's monorepo we'll see that it takes some ~220ms to find ~17k files matching our globs, out of ~30k total files found, which seems reasonably good, considering that Babel's monorepo contains over 13k folders also. + +With a quick profiling we can spot that a significant amount of time is being spent checking if the found files match any of our "ignore" globs, which seem internally converted to regexes and matched one by one. So I tried merging the globs into a single one: `"**/{.git,.sl,.svn,.hg,node_modules}"`, but it seems to get internally split up again for some reason, so that didn't change anything. + +By commenting our ignore globs out entirely we can find pretty much the same files, because almost none of them got actually ignored, in just around ~180ms, which is ~20% less time. So if we could match those globs differently, in a faster way, we could lower times a bit. + +This is probably a good time to mention that `fast-glob` does a pretty cool optimization, if our glob looks like this: `packages/**/*.{js,cjs,mjs}`, then it can spot that the beginning of it is entirely static, what we are actually asking it to do is to search for `**/*.{js,cjs.mjs}` inside the `packages` folder only. This optimization can be significant if there are lots of files in other folders we don't actually care about, because they will just never be scanned at all. + +That got me thinking: our ignore globs are basically the same, but the static part is at the end, rather than at the start. So I wrote another [library](https://github.com/fabiospampinato/tiny-readdir-glob) for finding files with a glob that is able to take advantage of globs with a static end too. The equivalent code for finding files with that would be this: + +```js +import readdir from "tiny-readdir-glob"; + +const { files } = await readdir("packages/**/*.{js,cjs,mjs}", { + ignore: "**/{.git,.sl,.svn,.hg,node_modules}", + followSymlinks: false, +}); +``` + +And it finds the same files in just around ~130ms. By commenting out the ignore glob, just to check how much overhead that adds, it seems to take about the same amount of time, so that got optimized enough that it's hard to measure its cost in this scenario. + +It got faster than we perhaps expected, for a few reasons: + +1. Other than the ignore glob, the `**/*.{js,cjs,mjs}` portion of the main glob ended up getting optimized too. +2. Globs are matched against the relative path of a file from the root folder we started searching from, so there would be a bunch of `path.relative` calls in there, but if our glob looks like this: `**/.git`, then it doesn't matter if we calculate the relative path or not, we'll effectively be looking at the end of that string for a child path anyway, so I'm just skipping those `path.relative` calls completely. +3. Node's [`fs.readdir`](https://nodejs.org/api/fs.html#fsreaddirpath-options-callback) API is used internally in both libraries to scan directories, and it gives us the names of the found files and folders, not their absolute paths, which is what we actually want, but we can generate that more manually, by joining the parent path and the name with the path separator, rather than by calling `path.join`, which speeds things up a bit more. + +Additionally this new library is ~90% smaller, about 65kb of minified code is no longer needed, which speeds up startup for the entire CLI. In much smaller repos than Babel's the new CLI might be able to find all the target files by the time the old one just finished parsing `fast-glob`. + +Rewriting this part of the CLI may seem a little heavy-handed for the kind of speed up that we got, but the main reason for the rewrite is actually another. It would seem that there should be nothing that we could do here that would speed up the CLI by multiple seconds, since finding all the files takes less than half a second to begin with, but, the crucial point to highlight here is that for the entire CLI we not only need to find files to format, but we also need to find configuration files, and knowing every single file and folder that was found, even if they didn't match our globs, is very valuable information that will allow us to shave multiple seconds later. `tiny-readdir-glob` can give us that information more or less for free, so it seemed worth writing it even just for that alone. + +To summarize the perhaps interesting points from this section: + +1. If you can, always tell Prettier the extensions to look for, for example with a glob like `packages/**/*.{js,cjs,mjs}`. If you used `packages/**/*` or just `packages` instead in this scenario 13k extra files would need to be processed, and it would be more expensive for Prettier to discard them later on. +2. There's always something left to optimize or special-case for performance, even in already optimized libraries, if one has the time to look into it. +3. It's worth thinking about what kind of information is being thrown away, or made somewhat expensive to reconstruct. Here the glob library has to know the found files and folders just to do its work, exposing that information to the caller unlocks additional performance basically for free, in some cases. + +Guesses on how to speed this up further: + +1. This seems to be bottlenecked by the performance of `fs.promises.readdir` in Node, and/or the overhead of creating a Promise for each found folder. It may be worth looking into using the callback-style version of that API, and into optimization opportunities in Node itself. + +## Resolving configurations fast + +This is possibly the most impactful optimization behind the new CLI, and it's basically about finding configuration files as fast as possible, for each folder only ever checking once if it contains configuration files, and parsing the found configuration files only once. + +A major problem behind the current CLI is that it caches resolved configurations by file path, rather than by folder path, so for example Babel's monorepo has ~17k files to format, but only 1 `.editorconfig` file in the whole repo, we should be parsing that file once, but instead it got parsed ~17k times. Additionally if you imagine those ~17k files being under the same folder, that folder got asked if it contained an `.editorconfig` file ~17k times, so actually the deeper nested into folders files to format were, the slower the entire CLI would get. + +This problem got largely solved in two steps: + +1. Resolved configuration files are cached by folder path, so it doesn't matter anymore how many files each folder contains, or how deep they are into folders. +2. The found folders are now being asked basically 0 times if they contain each of the ~15 supported configuration files, because we know from the previous section every single file in the repo, so we can just do a lookup in there, which ends up being a lot faster than asking the filesystem. This wouldn't matter much in most small repos, but Babel's for example has ~13k folders, and 13k \* 15 checks with the filesystem ~~added~~ multiplied up quickly enough. + +Let's now take a deeper look into how each specific supported type of configuration is resolved. + +#### Resolving EditorConfig configurations + +Assuming from the previous step that we've parsed every `.editorconfig` file in the repo and that we can fetch the relevant ones for any target file in constant time, what we now want to do is to merge them together into a single configuration object, for each target file, basically. + +Right away this idea kinda goes out of the window, because the [`editorconfig`](https://www.npmjs.com/package/editorconfig) package doesn't provide a function for doing this. The closest one seems the one called `parseFromFiles`, which besides being deprecated it seems to do what we want, but it wants configurations as strings, so it will presumably parse them by itself after each call, which is the thing we wanted to avoid in the first place, we only want to ever parse those once. + +So that package got rewritten for Prettier's needs, [`tiny-editorconfig`](https://github.com/fabiospampinato/tiny-editorconfig) provides exactly the `resolve` function we need, and it leaves the logic for finding configuration files to us, which is what we want anyway because we need to cache these files in a custom way. + +While I was at it I've rewritten the [INI parser](https://github.com/fabiospampinato/ini-simple-parser) behind it too, and it seems to be ~9x faster. It shouldn't matter much, because most repos will only have 1 `.editorconfig` file in them, but I enjoy writing these little parsers, and hey if you happen to have thousands of `.editorconfig` files in your repo you'll notice the extra performance boost! + +Additionally this new library is ~82% smaller, ~50kb of minified code got deleted, which speeds up startup for the whole CLI. Also it uses the same glob library that `tiny-readdir-glob` uses, while in the current CLI `fast-glob` and `editorconfig` use different ones, so actually a bit more code than that got effectively deleted. + +Previously it would have taken multiple seconds to resolve these files for Babel's monorepo, now it takes roughly ~100ms. + +Guesses on how to speed this up further: + +1. It should be possible in some (most?) cases to pre-resolve these configuration files for any possible file path we could encounter, for example depending on the globs in them it may be possible that we can end up with 3 possible resolved configurations at most, one for files that don't match any of the globs, one for files that match the `**/*.js` glob, and one for files that match the `**/*.md` glob. It's a bit complicated to implement though, and unclear what the speedup will be in practice, but it's something to think about for the future. + +#### Resolving Prettier configurations + +For Prettier-specific configurations, like the `.prettierrc` file, we are also assuming that we've resolved all the found configuration files, and can retrieve them in constant time for any target file. + +It's basically an identical situation to what we had for EditorConfig-specific configurations, so we'll basically do the same, this time hard-coding the logic for merging the configurations inside the CLI itself, as making a standalone package for it seems of basically no utility to the ecosystem. + +The main aspects to consider here for the future are, in my opinion: + +1. A large number of [different configuration files](https://prettier.io/docs/en/configuration) are supported. In Babel's monorepo this translates to ~150k lookups in the object of known paths we created in the first step, which while not super expensive it's not free either. If this number could be reduced by a lot it would speed things up a bit. +2. Also some of the parsers required to parse those configuration files are relatively expensive, the [`json5`](https://npmjs.com/package/json5) parser requires ~100x as much code as the smallest [JSONC](https://code.visualstudio.com/docs/languages/json) (JSON with Comments) parser that I know of for JavaScript, while being in some cases ~50x slower at parsing also. If fewer formats could be supported the CLI would be leaner as a result. +3. If we could check just once if a file named for example `.prettierrc.json5` got found anywhere in the repo we could reduce the number of checks for these configuration files by an order of magnitude, because if no file with that name was found anywhere in the repo then we don't need to ask each of Babel's ~13k folders if they have it. The list of all known file names is another piece of valuable information that the glob library we are using could give us for free. + +#### Resolving Ignore configurations + +Lastly we need to resolve `.gitignore` and `.prettierignore` files, to understand which found files to ignore. We are also assuming that we resolved all the found ones already and can fetch them in constant time for any target file. + +I'm not doing any major optimizations here, I'm largely just asking [`node-ignore`](https://github.com/kaelzhang/node-ignore) to make us a function that we can call to check if a file should be ignored. + +A small optimization though is skipping calling `path.relative`, and the `ignore` function itself in some cases. Ignore files match more or less the relative path of found files from the folder where the ignore file exist in, and since we know that all the paths we are dealing with are normalized, if the absolute path of a target file doesn't start with the absolute path of the folder where each ignore file existed in then that file exists outside of the folder that the ignore file manages, so we don't have to call the `ignore` function that `node-ignore` made for us. + +A decent amount of time seems spent matching the globs in these files against the found files though, hundreds of milliseconds for thousands of files, because there can just be a large number of globs in these files and a large number of files to match, which multiplied together gives us roughly the number of glob matches that will be attempted in the worst case. + +The nice thing about `.gitignore` and `.prettierignore` files though is that they often repay for themselves, because the time spent parsing them and matching files against them is often less than the time needed to process every file that would have gotten discarded by them. + +Guesses on how to speed this up further: + +1. Maybe most of those globs could be sort of merged together into a single more complicated glob, and matched all together in one go by the engine, since we are not interested in knowing which exact glob matched, only if any of them did. +2. Maybe globs could be executed in a different order, perhaps executing cheaper and broader globs first allows us to spend less time matching globs, on average. This wouldn't make a difference if most found files are not ignored though. +3. Perhaps we could just remember which file paths matched or not with a cache, but it feels like this could be sped up a lot without caching too. + +## Caching + +At this point we've found all the files, and we've parsed all the configurations, what's left to do is doing the actual potentially expensive work of formatting each target file, and that's where caching comes in. + +The current CLI has support for some form of caching, but it's opt-in, requiring an explicit `--cache` flag, and it doesn't remember if a file in the previous run was found to _not_ be formatted properly, only if it was formatted properly, which can cause some unnecessary overhead in some cases, as those unformatted files would get formatted again to check if they are formatted, when we could have just remembered from the previous run that they aren't. + +What we want to do here is skip the most amount of work possible, by remembering if a file was formatted or not, while generating reasonably small cache files, and while not introducing much overhead with the caching mechanism itself. + +The new CLI has opt-out caching instead, so caching is always turned on, unless you explicitly disable it with a `--no-cache` flag, this way its benefits should reach a much higher number of people by default. Also the cache is now turned on by default because it takes everything into account, so it shouldn't be realistic for the cache to tell the CLI something that's actually incorrect. If any of the following change, then the cache, or parts of it, get invalidated automatically: Prettier's version, all resolved EditorConfig/Prettier/Ignore configurations files and their paths, formatting options provided via CLI flags, the actual content of each file, and the file path of each file. + +The main trick here is that we don't want to have the cache for each file to be _directly_ dependent on its resolved formatting configuration, because that would require merging those configuration files for each target file, serializing the resulting object, and hashing that, which can be more expensive than we'd like. + +What the new CLI is doing instead is just parsing all found configurations files, and then just serializing and hashing them, which takes a constant amount of time to do no matter how many files we need to format later, and it only requires a single hash to be remembered in the cache file to account _indirectly_ for configuration files. This is safe to do because if the paths to configuration files _and_ their contents don't change, then any file with the same path from the previous run will necessarily be formatted with the same resolved formatting configuration object. The only potential issue is if any dependency used to parse those configuration files is actually buggy, but worst case scenario Prettier's own version can be bumped along with the buggy dependency's. + +To give some numbers the current CLI checks Babel's monorepo without a cache in around ~29 seconds, the new CLI needs ~7.5s to do the same without a cache and without parallelization. If the cache file is enabled and it exists though the current CLI still needs ~22 seconds, while the new CLI needs ~1.3 seconds, and this number can probably be cut in half with more optimizations in the future. + +If there's anything to remember from this long post is that if you want the CLI to go as fast as it can, you need to **remember the cache file**. The cache file is stored under `./node_modules/.cache/prettier` by default, and its location can be customized by passing the `--cache-location ` flag. I'll say it again: if performance matters for your scenario the single biggest thing to do to speed things up here is to remember the cache file between runs. + +Guesses on how to speed this up further: + +1. An optimization opportunity would be speeding up hashing in Node. Calculating the same hashes in Bun seems ~3x faster, so surely there's some room for optimization there. I've [reported](https://github.com/nodejs/performance/issues/136) that to Node, no PR has been submitted yet to address it, it seems complicated. +2. Potentially the parsed configuration files could be cached too, rather than just remembering their hash, but there should usually only be a handful of them, so it probably wouldn't matter too much. +3. Potentially more code could be deleted or lazy-loaded, speeding up the fully cached path a bit more. + +## Formatting + +We've now almost reached the end of the pipeline, we know which files we need to format, and we've just gotta do it. + +I haven't looked into optimizing the core formatting function itself much, since for few files it seems reasonably fast already, and most of the slowdown for the CLI seemed to come from resolving configurations inefficiently and not remembering work done in the past, but that could be one of the major things to look into next. There may just not be any major and/or easy optimizations opportunities in there though, with some quick profiling I didn't spot any at least. + +I've tried a couple of other things though. + +First of all multiple files can be formatted in parallel, that's the default now and a `--no-parallel` flag is supported to opt-out of it. The `--parallel-workers ` flag can also be used to set a custom number of workers to use, for some manual fine-tuning. On my 10 core computer with parallelization the time needed to check Babel's monorepo goes down from ~7.5s to ~5.5s, which doesn't seem particularly impressive, I'm not sure why I'm not getting better scaling than that, I'd like to look deeper into this eventually. There are much larger repos and CI machines with hundreds of cores though, it may make a much bigger difference for your use case, on top of all the other optimizations. + +Lastly I tried quickly replacing Prettier's format function with [`@wasm-fmt/biome_fmt`](https://www.npmjs.com/package/@wasm-fmt/biome_fmt), which is [Biome](https://biomejs.dev)'s format function compiled to WASM, and I see ~3.5s for checking Babel's monorepo without parallelization, and ~2.2s with parallelization. So roughly 2x better numbers than I'm seeing with Prettier's own formatter. Potentially the improvement could be even larger if Biome's format function was compiled to a native Node module, I'm not sure. + +Guesses on how to speed this up further: + +1. I haven't done much work on the core formatting, which seems roughly at least 2x slower than optimal, but the work required to get there may be major, we'll see. There's definitely some room for improvement though. +2. The `--parallel` flag, while enabled by default, has one minor issue: if you don't have many files to format, but you have many cores to feed, you could end up feeding few files to each core, which can actually slow things down a bit. This can probably be addressed by dynamically sizing the pool depending on some heuristics. It's currently enabled by default because it slows things down a bit only in scenarios where things are pretty fast anyway, while providing a significant improvement in scenarios that would be much slower otherwise. + +## Outputting to the terminal + +Lastly the final step is just to output the result of the command that the CLI was asked to execute to the terminal. + +There wasn't much to do here, but there were a couple of optimizations possible: + +1. First of all in some cases, like when formatting many small files, the current CLI would very quickly output the current file's path it was formatting, just to delete it a millisecond later, after formatting was done. Doing that for thousands of files is actually surprisingly expensive because `console.log` calls are synchronous and block the main thread, moreover if we do that 100 times within 16ms it's a bit pointless because our screen maybe got refreshed only once or twice in that amount of time, whatever was logged we didn't even see it. The new CLI at the moment doesn't log files that are currently being formatted, shaving some hundreds of milliseconds in some cases. +2. Lastly the current CLI may call `console.log` thousands of times, depending on how many files are being formatted, while the new CLI batches logs and just performs a single `console.log` at the end, which in some cases can be surprisingly faster also. + +I think the main room for improvement in this area is doing something visually interesting, which keeps the user busy looking at it, since perceived performance can be even more important than actual performance, but doing it in a way that doesn't keep the computer busy nearly as much. + +## Results + +

+ +

+ +Before we wrap up, here are some numbers I see when checking files in Babel's monorepo, with all files formatted, but 9 erroring files, with various flags, and with the current and new CLI: + +```sh +prettier packages --check # 29s +prettier packages --check --cache # 20s + +prettier@next packages --check --no-cache --no-parallel # 7.3s +prettier@next packages --check --no-cache # 5.5s +prettier@next packages --check # 1.3s +``` + +By default times for the same command go from ~29s to ~1.3s, for a ~22x speedup. This requires the cache file to be remembered between executions. We can probably get much closer to a 50x speedup in the future also. + +If the cache file is not remembered, or if you explicitly turn caching off, or if this is the first run, then times go from ~29s to ~5.5s with parallelization, on my computer, for a ~5x speedup, which should still be pretty significant. + +Worth noting again that this improvement is achieved without changing anything in Prettier's `format` function itself. + +## Results compared to Biome + +It's interesting to compare the numbers we got with the numbers that [Biome](https://github.com/biomejs/biome), the leading Rust formatter and probably performance champion, would give us: + +```sh +biome format packages +# Diagnostics not shown: 25938. +# Compared 28703 file(s) in 869ms +# Skipped 4770 file(s) +``` + +Here Biome is checking the formatting for ~11k more files compared to our CLI, since they don't seem to be implementing `.gitignore` and/or `.prettierignore` resolution yet. There may be other, potentially significant, differences in behavior also, I'm not sure. + +Manually patching our CLI to disable support for ignore files, to try to more closely mimic Biome's behavior, gives us the following number: + +```sh +prettier@next packages --check --no-cache # 15s +``` + +Comparison to take with a pinch of salt because the two tools aren't doing exactly the same thing, but it's interesting to see the speed at which Biome is able to check the formatting of many files. Speed that we probably need a cache file to match. + +Different approaches to try to speed things up massively for users. + +## Wrapping up + +The new CLI is still a work in progress, but we are excited for you to give it a try! You can [install](#installation) it today. + +I'd be interesting to see the speedup that the new CLI enables for you, feel free to tweet those results at [`@PrettierCode`](https://twitter.com/PrettierCode) or at [`@fabiospampinato`](https://twitter.com/fabiospampinato) directly, especially if you have some questions or ideas on how to speed things up further. diff --git a/website/blog/assets/prettier-architecture.png b/website/blog/assets/prettier-architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..ca5f0cb10b71526d019a9e45c39691b078e54b69 GIT binary patch literal 58651 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 OB$B?jHp|}ccJ;ra?4F_k literal 0 HcmV?d00001 diff --git a/website/blog/assets/prettier-bench.png b/website/blog/assets/prettier-bench.png new file mode 100644 index 0000000000000000000000000000000000000000..06aa5b5a4daf63b9aa9b80de4b1c1ace19a2ad2f GIT binary patch literal 53363 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 E0;5gP_5c6? literal 0 HcmV?d00001 From da1d4e93013fe8d9947c9cb34eb520ac082750d4 Mon Sep 17 00:00:00 2001 From: SUZUKI Sosuke Date: Fri, 1 Dec 2023 02:03:47 +0900 Subject: [PATCH 3/4] Fix blog date and add truncate comment (#15736) --- ...{2023-11-29-cli-deep-dive.md => 2023-11-30-cli-deep-dive.md} | 2 ++ 1 file changed, 2 insertions(+) rename website/blog/{2023-11-29-cli-deep-dive.md => 2023-11-30-cli-deep-dive.md} (99%) diff --git a/website/blog/2023-11-29-cli-deep-dive.md b/website/blog/2023-11-30-cli-deep-dive.md similarity index 99% rename from website/blog/2023-11-29-cli-deep-dive.md rename to website/blog/2023-11-30-cli-deep-dive.md index 52caf7e65..23a02a4a0 100644 --- a/website/blog/2023-11-29-cli-deep-dive.md +++ b/website/blog/2023-11-30-cli-deep-dive.md @@ -6,6 +6,8 @@ title: "Prettier's CLI: A Performance Deep Dive" Hey, I'm [Fabio](https://twitter.com/fabiospampinato) and I've been contracted by the Prettier team to speed up Prettier's command line interface (CLI). In this post we'll take a look at the optimizations I've discovered, the process that lead to finding them, some exciting numbers comparing the current CLI with the new one, and some guesses about what could be optimized next. + + ## Installation The new work-in-progress CLI for Prettier has just been [released](https://github.com/prettier/prettier-cli), and you can install it now: From 56408635eb01002940513e89fa5e8d9c98c9a5af Mon Sep 17 00:00:00 2001 From: SUZUKI Sosuke Date: Fri, 1 Dec 2023 13:29:30 +0900 Subject: [PATCH 4/4] Add simple lint script for blog post (#15737) --- .github/workflows/lint.yml | 3 +++ package.json | 1 + scripts/draft-blog-post.js | 2 +- scripts/lint-blog.js | 17 +++++++++++++++++ website/README.md | 2 +- website/blog/2017-04-13-1.0.0.md | 2 +- website/blog/2017-04-20-1.2.0.md | 2 +- website/blog/2017-05-03-1.3.0.md | 2 +- website/blog/2017-06-03-1.4.0.md | 2 +- website/blog/2017-06-28-1.5.0.md | 2 +- website/blog/2017-08-29-1.6.0.md | 2 +- website/blog/2017-09-15-1.7.0.md | 2 +- website/blog/2017-11-07-1.8.0.md | 2 +- website/blog/2017-12-05-1.9.0.md | 2 +- website/blog/2018-01-10-1.10.0.md | 2 +- website/blog/2018-02-26-1.11.0.md | 2 +- website/blog/2018-04-09-plugin-php-0.1.md | 2 +- website/blog/2018-04-11-1.12.0.md | 2 +- website/blog/2018-05-27-1.13.0.md | 2 +- website/blog/2018-07-29-1.14.0.md | 2 +- website/blog/2018-11-07-1.15.0.md | 2 +- website/blog/2019-01-20-1.16.0.md | 2 +- website/blog/2019-04-12-1.17.0.md | 2 +- website/blog/2019-06-06-1.18.0.md | 2 +- website/blog/2019-11-09-1.19.0.md | 2 +- website/blog/2020-03-21-2.0.0.md | 2 +- website/blog/2020-08-24-2.1.0.md | 2 +- website/blog/2020-11-20-2.2.0.md | 2 +- website/blog/2020-12-11-plugin-ruby-1.0.md | 2 +- website/blog/2021-05-09-2.3.0.md | 2 +- website/blog/2021-09-09-2.4.0.md | 2 +- website/blog/2021-11-25-2.5.0.md | 2 +- ...-01-06-prettier-begins-paying-maintainers.md | 2 +- website/blog/2022-03-16-2.6.0.md | 4 ++-- website/blog/2022-06-14-2.7.0.md | 2 +- website/blog/2022-11-23-2.8.0.md | 2 +- website/blog/2023-07-05-3.0.0.md | 2 +- website/blog/2023-11-13-3.1.0.md | 2 +- .../blog/2023-11-27-20k-bounty-was-claimed.md | 2 ++ website/blog/2023-11-30-cli-deep-dive.md | 2 +- 40 files changed, 60 insertions(+), 37 deletions(-) create mode 100755 scripts/lint-blog.js diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 700685d76..ff66d8bff 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -49,6 +49,9 @@ jobs: - name: Lint Changelog run: yarn lint:changelog + - name: Lint blog post + run: yarn lint:blog + - name: Lint docs code block # TODO: Lint files in `website/versioned_docs/version-stable` too run: yarn "docs/**/*.md" diff --git a/package.json b/package.json index 7fad53897..463c77ed7 100644 --- a/package.json +++ b/package.json @@ -174,6 +174,7 @@ "lint:prettier": "prettier . \"!test*\" --check --cache", "lint:spellcheck": "cspell --no-progress --relative --dot --gitignore", "lint:deps": "node ./scripts/check-deps.js", + "lint:blog": "node ./scripts/lint-blog.js", "fix": "run-s fix:eslint fix:prettier", "fix:eslint": "yarn lint:eslint --fix", "fix:prettier": "yarn lint:prettier --write", diff --git a/scripts/draft-blog-post.js b/scripts/draft-blog-post.js index 54df7538f..8582c452f 100644 --- a/scripts/draft-blog-post.js +++ b/scripts/draft-blog-post.js @@ -79,7 +79,7 @@ for (const filePath of fg.sync(postGlob)) { const introFileData = fs.readFileSync(introFile, "utf8").trim(); -const TRUNCATE_COMMENT = ""; +const TRUNCATE_COMMENT = ""; const shouldPrintTruncate = !introFileData.includes(TRUNCATE_COMMENT); fs.writeFileSync( diff --git a/scripts/lint-blog.js b/scripts/lint-blog.js new file mode 100755 index 000000000..a04c96083 --- /dev/null +++ b/scripts/lint-blog.js @@ -0,0 +1,17 @@ +#!/usr/bin/env node + +import fs from "node:fs"; + +const blogPostDir = new URL("../website/blog/", import.meta.url); + +const files = fs.readdirSync(blogPostDir); + +for (const file of files) { + if (file.endsWith(".md")) { + const fileData = fs.readFileSync(new URL(file, blogPostDir), "utf8"); + if (!fileData.includes("")) { + console.error(`${file}: Should include a comment`); + process.exitCode = 1; + } + } +} diff --git a/website/README.md b/website/README.md index 33a2e507b..1755ebe1a 100644 --- a/website/README.md +++ b/website/README.md @@ -72,7 +72,7 @@ authorURL: http://github.com/author # (or some other link) --- ``` -In the blog post, you should include a line ``. This determines under which point text will be ignored when generating the preview of your blog post. Blog posts should have the file name format: `yyyy-mm-dd-your-file-name.md`. +In the blog post, you should include a line ``. This determines under which point text will be ignored when generating the preview of your blog post. Blog posts should have the file name format: `yyyy-mm-dd-your-file-name.md`. ## Static Build diff --git a/website/blog/2017-04-13-1.0.0.md b/website/blog/2017-04-13-1.0.0.md index e5579fb3c..56b17f1be 100644 --- a/website/blog/2017-04-13-1.0.0.md +++ b/website/blog/2017-04-13-1.0.0.md @@ -13,7 +13,7 @@ solve the problem of wasting time formatting your code. It started as an experiment but it clearly resonated with a lot of people, amassing ~7000 GitHub stars and over 100,000 monthly `npm downloads` in just two months. - + In case you don't know, prettier is a JavaScript formatter that works by compiling your code to an AST, and then pretty-printing the AST. Like browsers diff --git a/website/blog/2017-04-20-1.2.0.md b/website/blog/2017-04-20-1.2.0.md index d20f82b3b..1456c43df 100644 --- a/website/blog/2017-04-20-1.2.0.md +++ b/website/blog/2017-04-20-1.2.0.md @@ -6,7 +6,7 @@ title: Prettier 1.2 1.0 is not the end of prettier, we're going to continue to work on the long tail of formatting issues in order to make it an awesome JavaScript code formatter. You should expect minor version releases like this one to change small things and edge cases but nothing major or controversial. - + ### Format diff --git a/website/blog/2017-05-03-1.3.0.md b/website/blog/2017-05-03-1.3.0.md index 60f5f7c51..891df578d 100644 --- a/website/blog/2017-05-03-1.3.0.md +++ b/website/blog/2017-05-03-1.3.0.md @@ -6,7 +6,7 @@ title: Prettier 1.3 This post provides an update to Facebook's adoption or Prettier, outlines our progress on TypeScript, and details some of the improvements and fixes included in the 1.3.0 release of Prettier. - + ### Facebook Adoption Update diff --git a/website/blog/2017-06-03-1.4.0.md b/website/blog/2017-06-03-1.4.0.md index ab5ee4606..91edc7955 100644 --- a/website/blog/2017-06-03-1.4.0.md +++ b/website/blog/2017-06-03-1.4.0.md @@ -6,7 +6,7 @@ title: "Prettier 1.4: TypeScript and CSS support" This release introduces support for TypeScript, CSS, Less, and SCSS languages to Prettier! - + [![prettier-revolution-conf](/blog/assets/prettier-revolution-conf.png)](https://revolutionconf.com/talk/a-prettier-printer) diff --git a/website/blog/2017-06-28-1.5.0.md b/website/blog/2017-06-28-1.5.0.md index f17500699..f3a84f882 100644 --- a/website/blog/2017-06-28-1.5.0.md +++ b/website/blog/2017-06-28-1.5.0.md @@ -6,7 +6,7 @@ title: "Prettier 1.5: GraphQL, CSS-in-JS & JSON" This release adds GraphQL formatting support, CSS-in-JS (including styled-components), and JSON support to Prettier. - + This is the release I've been waiting for a very long time: one that has only minimal changes to JavaScript! diff --git a/website/blog/2017-08-29-1.6.0.md b/website/blog/2017-08-29-1.6.0.md index 0b1ae7c27..19a9bb91e 100644 --- a/website/blog/2017-08-29-1.6.0.md +++ b/website/blog/2017-08-29-1.6.0.md @@ -6,7 +6,7 @@ title: "Prettier 1.6: Config File, JSX" This release adds configuration file support to Prettier, as well as some significant enhancements to JSX printing. - + I want to give a special shout out to [@azz](https://github.com/azz) who has been maintaining the repository and implementing a bunch of the changes in this release as I had less time to devote to prettier due to vacation and switching team :) diff --git a/website/blog/2017-09-15-1.7.0.md b/website/blog/2017-09-15-1.7.0.md index 9a0f0ef29..6c4bf31cd 100644 --- a/website/blog/2017-09-15-1.7.0.md +++ b/website/blog/2017-09-15-1.7.0.md @@ -6,7 +6,7 @@ title: "Prettier 1.7: JSX tweaks, Pragma, TypeScript and CSS fixes" This release features some bugfixes and tweaks around JSX, TypeScript, CSS, and JavaScript formatting, as well as a couple new features. - + ## Highlights diff --git a/website/blog/2017-11-07-1.8.0.md b/website/blog/2017-11-07-1.8.0.md index 163223983..cbe5074eb 100644 --- a/website/blog/2017-11-07-1.8.0.md +++ b/website/blog/2017-11-07-1.8.0.md @@ -6,7 +6,7 @@ title: "Prettier 1.8: Markdown Support" This release adds Markdown support, a new `--insert-pragma` flag, fixes a number of formatting issues, adds support for some new _experimental_ operators, and improves our editor integration support. - + ## Highlights diff --git a/website/blog/2017-12-05-1.9.0.md b/website/blog/2017-12-05-1.9.0.md index 87b0922fd..7bd9786de 100644 --- a/website/blog/2017-12-05-1.9.0.md +++ b/website/blog/2017-12-05-1.9.0.md @@ -6,7 +6,7 @@ title: "Prettier 1.9: JSX Fragments, EditorConfig and Arrow Parens" This release adds an option for arrow function parens in arguments, support for the [new JSX fragment syntax (`<>`)](https://reactjs.org/blog/2017/11/28/react-v16.2.0-fragment-support.html), support for `.editorconfig` files, and nice additions to our GraphQL and Markdown support. - + ## Highlights diff --git a/website/blog/2018-01-10-1.10.0.md b/website/blog/2018-01-10-1.10.0.md index 9976a04d1..9a7b53c39 100644 --- a/website/blog/2018-01-10-1.10.0.md +++ b/website/blog/2018-01-10-1.10.0.md @@ -8,7 +8,7 @@ Happy Prettier-versary! It's pretty incredible that Prettier was only released a It's also an exciting release in itself because Prettier now has partial support for `.vue` files and the internals have been refactored such that there's a proper plugin API in order to support different languages! - + ## Retrospective diff --git a/website/blog/2018-02-26-1.11.0.md b/website/blog/2018-02-26-1.11.0.md index af1619ded..a70753e60 100644 --- a/website/blog/2018-02-26-1.11.0.md +++ b/website/blog/2018-02-26-1.11.0.md @@ -14,7 +14,7 @@ Another exciting announcement is that all the JavaScript files in the Facebook c In 8 months, 75% of the codebase was organically converted and last week we did a final push to convert the rest and enforce that every file from now on is using Prettier! It shows that Prettier is robust to support all the crazy edge cases you can imagine and also that it provides a lot of value given the crazy adoption rate. - + ## Highlights diff --git a/website/blog/2018-04-09-plugin-php-0.1.md b/website/blog/2018-04-09-plugin-php-0.1.md index c13fd937a..145817fa2 100644 --- a/website/blog/2018-04-09-plugin-php-0.1.md +++ b/website/blog/2018-04-09-plugin-php-0.1.md @@ -6,7 +6,7 @@ title: Prettier for PHP 0.1: First alpha release πŸŽ‰ After more than 200 merged pull requests since mid December 2017, we're happy to announce the first alpha release of [Prettier for PHP](https://github.com/prettier/plugin-php). In this blog post, we'd like to give a short overview of how the plugin works, its philosophy, and what to expect in the future. - + ## How does it work? diff --git a/website/blog/2018-04-11-1.12.0.md b/website/blog/2018-04-11-1.12.0.md index 0f9fb2833..78bb4cf25 100644 --- a/website/blog/2018-04-11-1.12.0.md +++ b/website/blog/2018-04-11-1.12.0.md @@ -6,7 +6,7 @@ title: "Prettier 1.12: Fixes, Features, and Formatting, Oh My!" Hello everyone, and welcome to Prettier 1.12.0! This release contains a lot of bugfixes, formatting adjustments, new features for our plugin API, and new Markdown features. - + ## Highlights diff --git a/website/blog/2018-05-27-1.13.0.md b/website/blog/2018-05-27-1.13.0.md index 9d6f8879d..d95b92bff 100644 --- a/website/blog/2018-05-27-1.13.0.md +++ b/website/blog/2018-05-27-1.13.0.md @@ -6,7 +6,7 @@ title: "Prettier 1.13: Conquering the web!" This releases adds support for several new syntax features, formatting fixes and first-class support for working in the browser. - + ## Highlights diff --git a/website/blog/2018-07-29-1.14.0.md b/website/blog/2018-07-29-1.14.0.md index d1033d0d1..dd471cc34 100644 --- a/website/blog/2018-07-29-1.14.0.md +++ b/website/blog/2018-07-29-1.14.0.md @@ -6,7 +6,7 @@ title: "Prettier 1.14: YAML Support" This release adds YAML support, pragma (i.e. `/** @prettier */`) support for every language, and improves performance on large files. It also adds support for several new syntax features, and has a few formatting tweaks to make your code even prettier. ✨ - + ## Highlights diff --git a/website/blog/2018-11-07-1.15.0.md b/website/blog/2018-11-07-1.15.0.md index 25f11d254..1a5754ff3 100644 --- a/website/blog/2018-11-07-1.15.0.md +++ b/website/blog/2018-11-07-1.15.0.md @@ -10,7 +10,7 @@ adds an option for JSX single quotes, allows parser inference via shebang, adds support for several new syntax features, and has a few formatting tweaks. - + ## Highlights diff --git a/website/blog/2019-01-20-1.16.0.md b/website/blog/2019-01-20-1.16.0.md index 1465ab0c3..b0e7d88d7 100644 --- a/website/blog/2019-01-20-1.16.0.md +++ b/website/blog/2019-01-20-1.16.0.md @@ -7,7 +7,7 @@ title: "Prettier 1.16: HTML improvements and better CRLF handling" This release improves HTML formatting and contains better CRLF handling, new syntax features, and fixes several bugs. - + ## Highlights diff --git a/website/blog/2019-04-12-1.17.0.md b/website/blog/2019-04-12-1.17.0.md index f674cb190..cdd57c011 100644 --- a/website/blog/2019-04-12-1.17.0.md +++ b/website/blog/2019-04-12-1.17.0.md @@ -8,7 +8,7 @@ This release brings long-requested flexibility to quotes around object propertie [lwc]: https://developer.salesforce.com/docs/component-library/documentation/lwc - + ## Highlights diff --git a/website/blog/2019-06-06-1.18.0.md b/website/blog/2019-06-06-1.18.0.md index 1a782cfba..7030976ec 100644 --- a/website/blog/2019-06-06-1.18.0.md +++ b/website/blog/2019-06-06-1.18.0.md @@ -8,7 +8,7 @@ This release doesn't include shiny new features, but has lots of fixes for JavaS It's also a good opportunity to remind that Prettier is now accepting donations! If you enjoy Prettier and would like to support our work, head to our [OpenCollective](https://opencollective.com/prettier). - + ## Highlights diff --git a/website/blog/2019-11-09-1.19.0.md b/website/blog/2019-11-09-1.19.0.md index d66c706fe..9c87636f5 100644 --- a/website/blog/2019-11-09-1.19.0.md +++ b/website/blog/2019-11-09-1.19.0.md @@ -6,7 +6,7 @@ title: "Prettier 1.19: Long awaited Vue option, TypeScript 3.7 and new JavaScrip This release adds the long awaited `--vue-indent-script-and-style` option, support for TypeScript 3.7 and some cutting edge JavaScript syntax. Not to mention a whole bunch of bug fixes and improvements! - + ## Highlights diff --git a/website/blog/2020-03-21-2.0.0.md b/website/blog/2020-03-21-2.0.0.md index b2e94e421..02f79eaec 100644 --- a/website/blog/2020-03-21-2.0.0.md +++ b/website/blog/2020-03-21-2.0.0.md @@ -8,7 +8,7 @@ Better defaults, a better CLI and better heuristics. Oh, and TypeScript 3.8. After a long and careful consideration, we decided to change the default values for the `trailingComma`, `arrowParens`, and `endOfLine` options. We made the CLI more intuitive. And we've finally dropped support for Node versions older than 10, which had grown to become a huge maintenance hassle and an obstacle for contributors. Read below in details. - + ## Highlights diff --git a/website/blog/2020-08-24-2.1.0.md b/website/blog/2020-08-24-2.1.0.md index 215b2102c..7145720d8 100644 --- a/website/blog/2020-08-24-2.1.0.md +++ b/website/blog/2020-08-24-2.1.0.md @@ -6,7 +6,7 @@ title: "Prettier 2.1: new --embedded-language-formatting option and new JavaScri This release adds a new `--embedded-language-formatting` option, supports new JavaScript/TypeScript features, and includes many bug fixes and improvements! - + ## Highlights diff --git a/website/blog/2020-11-20-2.2.0.md b/website/blog/2020-11-20-2.2.0.md index b110f0c38..957c600d0 100644 --- a/website/blog/2020-11-20-2.2.0.md +++ b/website/blog/2020-11-20-2.2.0.md @@ -6,7 +6,7 @@ title: "Prettier 2.2: new JavaScript parsers, TS 4.1 and ESM standalone bundles" This release supports new JavaScript parsers [espree](https://github.com/eslint/espree) and [meriyah](https://github.com/meriyah/meriyah), supports [TypeScript 4.1](https://devblogs.microsoft.com/typescript/announcing-typescript-4-1-rc/), ships ESM standalone bundles for modern browsers, and includes many bug fixes and improvements! - + ## Highlights diff --git a/website/blog/2020-12-11-plugin-ruby-1.0.md b/website/blog/2020-12-11-plugin-ruby-1.0.md index cd788e384..241e5cf89 100644 --- a/website/blog/2020-12-11-plugin-ruby-1.0.md +++ b/website/blog/2020-12-11-plugin-ruby-1.0.md @@ -6,7 +6,7 @@ title: Prettier for Ruby goes v1.0 πŸŽ‰ After 1500 commits and 50 releases since July 2018, we're happy to announce that we've just released v1.0 of [Prettier for Ruby](https://github.com/prettier/plugin-ruby). In this blog post, we'd like to give a short overview of how the plugin works, its philosophy, and what to expect in the future. - + ## How does it work? diff --git a/website/blog/2021-05-09-2.3.0.md b/website/blog/2021-05-09-2.3.0.md index 644586081..73b86cbb3 100644 --- a/website/blog/2021-05-09-2.3.0.md +++ b/website/blog/2021-05-09-2.3.0.md @@ -14,7 +14,7 @@ Most of the changes in this release are thanks to the hard work of [Fisker Cheun And just a reminder, when Prettier is installed or updated, it’s [strongly recommended](https://prettier.io/docs/en/install.html#summary) to specify the exact version in `package.json`: `"2.3.0"`, not `"^2.3.0"`. - + ## Highlights diff --git a/website/blog/2021-09-09-2.4.0.md b/website/blog/2021-09-09-2.4.0.md index ce1109438..5205fa9c8 100644 --- a/website/blog/2021-09-09-2.4.0.md +++ b/website/blog/2021-09-09-2.4.0.md @@ -10,7 +10,7 @@ We’ve also added support for [TypeScript 4.4](https://www.typescriptlang.org/d If you enjoy Prettier and would like to support our work, consider sponsoring us directly via [our OpenCollective](https://opencollective.com/prettier) or by sponsoring the projects we depend on, including [typescript-eslint](https://opencollective.com/typescript-eslint), [remark](https://opencollective.com/unified), and [Babel](https://opencollective.com/babel). - + ## Highlights diff --git a/website/blog/2021-11-25-2.5.0.md b/website/blog/2021-11-25-2.5.0.md index db69b66a6..7761d11a3 100644 --- a/website/blog/2021-11-25-2.5.0.md +++ b/website/blog/2021-11-25-2.5.0.md @@ -8,7 +8,7 @@ This release adds support for [TypeScript 4.5](https://devblogs.microsoft.com/ty If you enjoy Prettier and would like to support our work, consider sponsoring us directly via [our OpenCollective](https://opencollective.com/prettier) or by sponsoring the projects we depend on, including [typescript-eslint](https://opencollective.com/typescript-eslint), [remark](https://opencollective.com/unified), and [Babel](https://opencollective.com/babel). - + ## Highlights diff --git a/website/blog/2022-01-06-prettier-begins-paying-maintainers.md b/website/blog/2022-01-06-prettier-begins-paying-maintainers.md index c2049b7bb..ec2be057c 100644 --- a/website/blog/2022-01-06-prettier-begins-paying-maintainers.md +++ b/website/blog/2022-01-06-prettier-begins-paying-maintainers.md @@ -6,7 +6,7 @@ title: "Prettier begins paying maintainers" Prettier, an opinionated code formatter for JavaScript and many web languages, has been accepting donations at [OpenCollective](https://opencollective.com/prettier) since 2019 and thanks to many generous donations we now have \$50,000 in the bank! As a result, we are now able to pay the two active maintainers \$1,500/month each. This funding will ensure that they will be able to continue consistent maintenance of Prettier into the future. - + diff --git a/website/blog/2022-03-16-2.6.0.md b/website/blog/2022-03-16-2.6.0.md index 0689d84c5..54cc89615 100644 --- a/website/blog/2022-03-16-2.6.0.md +++ b/website/blog/2022-03-16-2.6.0.md @@ -8,7 +8,7 @@ This release includes a new `singleAttributePerLine` option. This is an option t We've also added support formatting for some new JavaScript syntax proposals via Babel. - + ## Thanks to our sponsors! @@ -30,7 +30,7 @@ As discussed in [a blog post from earlier this year](https://prettier.io/blog/20 If you enjoy Prettier and would like to support our work, consider sponsoring us directly via [our OpenCollective](https://opencollective.com/prettier) or by sponsoring the projects we depend on, including [typescript-eslint](https://opencollective.com/typescript-eslint), [remark](https://opencollective.com/unified), and [Babel](https://opencollective.com/babel). - + ## Highlights diff --git a/website/blog/2022-06-14-2.7.0.md b/website/blog/2022-06-14-2.7.0.md index f56fa544e..741f7c7bb 100644 --- a/website/blog/2022-06-14-2.7.0.md +++ b/website/blog/2022-06-14-2.7.0.md @@ -10,7 +10,7 @@ We've also added support formatting for TypeScript 4.7 syntax! If you enjoy Prettier and would like to support our work, consider sponsoring us directly via [our OpenCollective](https://opencollective.com/prettier) or by sponsoring the projects we depend on, including [typescript-eslint](https://opencollective.com/typescript-eslint), [remark](https://opencollective.com/unified), and [Babel](https://opencollective.com/babel). - + ## Highlights diff --git a/website/blog/2022-11-23-2.8.0.md b/website/blog/2022-11-23-2.8.0.md index 0445b6ca6..e6103f6e5 100644 --- a/website/blog/2022-11-23-2.8.0.md +++ b/website/blog/2022-11-23-2.8.0.md @@ -12,7 +12,7 @@ If you enjoy Prettier and would like to support our work, consider sponsoring us The Prettier team plans to release 3.0 within the next few months. If you are a plugin developer, get ready for the migration. Visit [the migration guide](https://github.com/prettier/prettier/wiki/How-to-migrate-my-plugin-to-support-Prettier-v3%3F) and issue [#13606](https://github.com/prettier/prettier/issues/13616) for more information. - + ## Highlights diff --git a/website/blog/2023-07-05-3.0.0.md b/website/blog/2023-07-05-3.0.0.md index 6bf19ce18..a28947510 100644 --- a/website/blog/2023-07-05-3.0.0.md +++ b/website/blog/2023-07-05-3.0.0.md @@ -16,7 +16,7 @@ This release also includes numerous formatting improvements and bug fixes. If you appreciate Prettier and would like to support our work, please consider sponsoring us directly via [our OpenCollective](https://opencollective.com/prettier) or by sponsoring the projects we depend on, such as [typescript-eslint](https://opencollective.com/typescript-eslint), [remark](https://opencollective.com/unified), and [Babel](https://opencollective.com/babel). Thank you for your continued support! - + ## Highlights diff --git a/website/blog/2023-11-13-3.1.0.md b/website/blog/2023-11-13-3.1.0.md index 0501613da..ba18ffb63 100644 --- a/website/blog/2023-11-13-3.1.0.md +++ b/website/blog/2023-11-13-3.1.0.md @@ -8,7 +8,7 @@ This release adds indentation back to nested ternaries along with a new `--exper We have also added support for the control flow syntax in Angular v17. For details on the syntax, please read [the official Angular release post](https://blog.angular.io/introducing-angular-v17-4d7033312e4b). - + If you appreciate Prettier and would like to support our work, please consider sponsoring us directly via [our OpenCollective](https://opencollective.com/prettier) or by sponsoring the projects we depend on, such as [typescript-eslint](https://opencollective.com/typescript-eslint), [remark](https://opencollective.com/unified), and [Babel](https://opencollective.com/babel). Thank you for your continued support! diff --git a/website/blog/2023-11-27-20k-bounty-was-claimed.md b/website/blog/2023-11-27-20k-bounty-was-claimed.md index a6809a207..9c5b02268 100644 --- a/website/blog/2023-11-27-20k-bounty-was-claimed.md +++ b/website/blog/2023-11-27-20k-bounty-was-claimed.md @@ -12,6 +12,8 @@ On November 9th, we put up a [$10k bounty](https://twitter.com/Vjeux/status/1722 [![](https://console.algora.io/prettier/og.png)](https://console.algora.io/challenges/prettier) + + ## Winner Winner Chicken Dinner **I'm so excited to report that the [Biome project](https://biomejs.dev/) claimed the bounty!** It has been so epic to see a dozen people come together to improve compatibility in only a short 3 weeks. You can read their [full report](https://biomejs.dev/blog/biome-wins-prettier-challenge) for the details. diff --git a/website/blog/2023-11-30-cli-deep-dive.md b/website/blog/2023-11-30-cli-deep-dive.md index 23a02a4a0..ffe6557f9 100644 --- a/website/blog/2023-11-30-cli-deep-dive.md +++ b/website/blog/2023-11-30-cli-deep-dive.md @@ -6,7 +6,7 @@ title: "Prettier's CLI: A Performance Deep Dive" Hey, I'm [Fabio](https://twitter.com/fabiospampinato) and I've been contracted by the Prettier team to speed up Prettier's command line interface (CLI). In this post we'll take a look at the optimizations I've discovered, the process that lead to finding them, some exciting numbers comparing the current CLI with the new one, and some guesses about what could be optimized next. - + ## Installation