viewfit 0.0.1 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +161 -3
- package/dist/cli.js +1451 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.js +1333 -0
- package/dist/index.js.map +1 -0
- package/package.json +57 -6
- package/index.js +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Andrea Bonacci
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,8 +1,166 @@
|
|
|
1
1
|
# ViewFit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Fit and compress every image to the size it is actually rendered at, using a real headless browser.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
ViewFit opens your site in Chromium, measures each `<img>` and CSS `background-image` with `getBoundingClientRect()`, applies the device pixel ratio, and recommends a per-image target size. Sharp then resizes and compresses each file individually instead of applying one generic setting to everything.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
- Node.js >= 18
|
|
10
|
+
- A Chromium browser for Playwright:
|
|
11
|
+
- `npx playwright install chromium`, or
|
|
12
|
+
- use an installed Google Chrome with `--browser chrome`
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g viewfit # then run: viewfit
|
|
18
|
+
# or run without installing:
|
|
19
|
+
npx viewfit
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Report only. Nothing is written to disk.
|
|
26
|
+
viewfit ./dist
|
|
27
|
+
|
|
28
|
+
# Write an optimized copy of the site with one preset.
|
|
29
|
+
viewfit optimize ./dist --preset web --site --yes
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`./dist` is the folder to analyze: whatever your build outputs (`dist`, `build`, `out`, `public`, or `.` for the current directory). When it is a folder, ViewFit recursively analyzes every `.html`/`.htm` page inside it (skipping `node_modules`, `.git` and the output folder). You can also pass a single HTML file or an already running URL.
|
|
33
|
+
|
|
34
|
+
## Before / after
|
|
35
|
+
|
|
36
|
+
The Chrome DevTools Network panel for the demo gallery page, before and after ViewFit. Click an image to open it full size.
|
|
37
|
+
|
|
38
|
+
| Before | After |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| [](https://raw.githubusercontent.com/andrea-bonacci/viewfit/main/docs/before.webp) | [](https://raw.githubusercontent.com/andrea-bonacci/viewfit/main/docs/after.webp) |
|
|
41
|
+
| **12.0 MB · 12.88 s** | **893 KB · 1.21 s** |
|
|
42
|
+
|
|
43
|
+
Same page and same 18 requests. Its four images go from 2.4 MB, 2.2 MB, 4.0 MB and 2.9 MB to 55 KB, 101 KB, 176 KB and 19 KB as WebP.
|
|
44
|
+
|
|
45
|
+
### Single image
|
|
46
|
+
|
|
47
|
+
The card is rendered at 733×949. Both images are shown at the same display width; click one to open it full size.
|
|
48
|
+
|
|
49
|
+
| Before (JPG) | After (WebP) |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| <a href="https://raw.githubusercontent.com/andrea-bonacci/viewfit/main/examples/demo-site/assets/gallery-card-1.jpg"><img src="https://raw.githubusercontent.com/andrea-bonacci/viewfit/main/examples/demo-site/assets/gallery-card-1.jpg" width="480" alt="Before: JPG"></a> | <a href="https://raw.githubusercontent.com/andrea-bonacci/viewfit/main/docs/gallery-card-1-after.webp"><img src="https://raw.githubusercontent.com/andrea-bonacci/viewfit/main/docs/gallery-card-1-after.webp" width="480" alt="After: WebP"></a> |
|
|
52
|
+
| **2.2 MB** · 3902×5050 | **101 KB** · 733×949 |
|
|
53
|
+
|
|
54
|
+
## Two commands
|
|
55
|
+
|
|
56
|
+
| Command | What it does |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| `viewfit [target]` | Analyze and print a report. Never writes files. |
|
|
59
|
+
| `viewfit inspect [target]` | Explicit name for the same report-only command. |
|
|
60
|
+
| `viewfit optimize [target]` | Analyze, then write the optimized images. Asks for confirmation. |
|
|
61
|
+
|
|
62
|
+
A directory target means **all HTML pages recursively**; each unique image is reported and compressed once, using the largest rendered size found across pages.
|
|
63
|
+
|
|
64
|
+
## Presets
|
|
65
|
+
|
|
66
|
+
`--preset` sets device, tier, format and quality with one flag. Any option passed explicitly overrides the preset.
|
|
67
|
+
|
|
68
|
+
| Preset | Device | Format | Tier | Quality |
|
|
69
|
+
| --- | --- | --- | --- | --- |
|
|
70
|
+
| `web` | Mobile | WebP | 90% | 80 |
|
|
71
|
+
| `hq` | Desktop | AVIF | 100% | 85 |
|
|
72
|
+
| `fast` | Mobile | WebP | 75% | 70 |
|
|
73
|
+
|
|
74
|
+
## Common examples
|
|
6
75
|
|
|
7
76
|
```bash
|
|
8
|
-
|
|
77
|
+
# Analyze a build output on desktop
|
|
78
|
+
viewfit ./dist
|
|
79
|
+
|
|
80
|
+
# Analyze as mobile
|
|
81
|
+
viewfit ./dist --device mobile
|
|
82
|
+
|
|
83
|
+
# Custom tier: 80% of the exact rendered size
|
|
84
|
+
viewfit ./dist --tier 80
|
|
85
|
+
|
|
86
|
+
# Write to a custom folder, converting to WebP
|
|
87
|
+
viewfit optimize ./dist --format webp --out optimized
|
|
88
|
+
|
|
89
|
+
# Also copy HTML/CSS/JS and rewrite image references
|
|
90
|
+
viewfit optimize ./dist --preset web --site --yes
|
|
91
|
+
|
|
92
|
+
# Overwrite originals (same format only)
|
|
93
|
+
viewfit optimize ./dist --in-place --yes
|
|
94
|
+
|
|
95
|
+
# Interactive choices for tier, format and quality
|
|
96
|
+
viewfit optimize ./dist --interactive
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Options
|
|
100
|
+
|
|
101
|
+
| Option | Description | Default |
|
|
102
|
+
| --- | --- | --- |
|
|
103
|
+
| `[target]` | Local directory, HTML file or URL | `.` |
|
|
104
|
+
| `-p, --preset <name>` | `web`, `hq` or `fast` | none |
|
|
105
|
+
| `-d, --device <mode>` | `desktop` or `mobile` | preset or `desktop` |
|
|
106
|
+
| `--viewport <w>x<h>` | Viewport override, e.g. `1440x900` | device preset |
|
|
107
|
+
| `-t, --tier <tier>` | `exact`, `safe`, `aggressive`, `extreme` or a number (1-100) | preset or `exact` |
|
|
108
|
+
| `-q, --quality <number>` | Encoder quality (1-100) | preset or `80` |
|
|
109
|
+
| `-f, --format <format>` | `original`, `webp` or `avif` | preset or `original` |
|
|
110
|
+
| `--out <dir>` | Output directory (only `optimize`) | `viewfit-output` |
|
|
111
|
+
| `-w, --in-place` | Overwrite originals (requires `--format original`) | `false` |
|
|
112
|
+
| `--site` | Copy HTML/CSS/JS into the output folder and rewrite image references | `false` |
|
|
113
|
+
| `--root <dir>` | Root used to map URLs to local files when using a URL | none |
|
|
114
|
+
| `--browser <channel>` | Playwright channel: `chromium` or `chrome` | `chromium` |
|
|
115
|
+
| `--timeout <ms>` | Navigation timeout | `30000` |
|
|
116
|
+
| `-i, --interactive` | Choose tier, format and quality interactively | `false` |
|
|
117
|
+
| `-y, --yes` | Skip confirmation prompts | `false` |
|
|
118
|
+
| `--json` | Print the analysis as JSON | `false` |
|
|
119
|
+
|
|
120
|
+
### Tiers
|
|
121
|
+
|
|
122
|
+
| Tier | Scale |
|
|
123
|
+
| --- | --- |
|
|
124
|
+
| `exact` | 100% of the exact rendered size |
|
|
125
|
+
| `safe` | 90% |
|
|
126
|
+
| `aggressive` | 75% |
|
|
127
|
+
| `extreme` | 50% |
|
|
128
|
+
| number | Custom percentage, e.g. `--tier 85` |
|
|
129
|
+
|
|
130
|
+
## Demo
|
|
131
|
+
|
|
132
|
+
A ready-to-run example lives in [`examples/demo-site`](https://github.com/andrea-bonacci/viewfit/tree/main/examples/demo-site). It has two pages, six high-resolution Unsplash photos and a heavy PNG icon (about 24 MB total). The before/after screenshots above come from this example. From the repository root:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
npm run build
|
|
136
|
+
node dist/cli.js ./examples/demo-site --browser chrome
|
|
137
|
+
node dist/cli.js ./examples/demo-site --browser chrome --device mobile --tier 80
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## How it works
|
|
141
|
+
|
|
142
|
+
1. Discovers every HTML page in the target directory (or uses the single file/URL).
|
|
143
|
+
2. Serves the target directory and opens each page in Chromium with the selected viewport, device pixel ratio and mobile emulation.
|
|
144
|
+
3. Scrolls each page to trigger lazy loading and waits for images to decode.
|
|
145
|
+
4. Collects every rendered `<img>` and CSS background image with its CSS box and fit mode, merging duplicates across pages.
|
|
146
|
+
5. Reads real dimensions and file size with Sharp.
|
|
147
|
+
6. Computes the target size from the rendered box, DPR and compression tier.
|
|
148
|
+
7. Prints a report with original size, rendered size, target size and estimated savings.
|
|
149
|
+
8. With `optimize`, resizes and re-encodes each image with Sharp.
|
|
150
|
+
9. With `--site`, copies HTML/CSS/JS into the output folder and rewrites image references to the new files.
|
|
151
|
+
|
|
152
|
+
Images that cannot be mapped to a local file (remote/CDN assets) are reported but not modified.
|
|
153
|
+
|
|
154
|
+
## Development
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npm install
|
|
158
|
+
npm run dev -- ./dist --browser chrome
|
|
159
|
+
npm run typecheck
|
|
160
|
+
npm test
|
|
161
|
+
npm run build
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
MIT
|