@webstir-io/webstir-frontend 0.1.40 → 0.1.41
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/README.md +124 -60
- package/dist/assets/imageOptimizer.js +10 -15
- package/dist/assets/precompression.js +1 -1
- package/dist/builders/contentBuilder.js +102 -90
- package/dist/builders/cssBuilder.js +25 -19
- package/dist/builders/htmlBuilder.js +57 -42
- package/dist/builders/index.js +1 -1
- package/dist/builders/jsBuilder.js +219 -76
- package/dist/builders/staticAssetsBuilder.js +27 -9
- package/dist/builders/types.d.ts +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +6 -30
- package/dist/config/manifest.js +7 -6
- package/dist/config/paths.js +2 -2
- package/dist/config/schema.d.ts +8 -0
- package/dist/config/schema.js +7 -6
- package/dist/config/setup.js +1 -1
- package/dist/config/workspace.js +11 -9
- package/dist/core/constants.d.ts +1 -1
- package/dist/core/constants.js +5 -5
- package/dist/core/diagnostics.js +1 -1
- package/dist/core/pages.js +4 -4
- package/dist/hooks.js +3 -3
- package/dist/html/criticalCss.js +6 -3
- package/dist/html/htmlSecurity.d.ts +6 -1
- package/dist/html/htmlSecurity.js +28 -14
- package/dist/html/lazyLoad.js +1 -1
- package/dist/html/pageScaffold.js +1 -1
- package/dist/html/resourceHints.js +5 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/inspect.d.ts +2 -0
- package/dist/inspect.js +110 -0
- package/dist/modes/ssg/metadata.js +4 -4
- package/dist/modes/ssg/routing.js +2 -5
- package/dist/modes/ssg/seo.js +5 -5
- package/dist/modes/ssg/views.js +17 -11
- package/dist/operations.js +18 -10
- package/dist/pipeline.d.ts +1 -0
- package/dist/pipeline.js +6 -1
- package/dist/provider.js +28 -24
- package/dist/runtime/boundary.d.ts +28 -0
- package/dist/runtime/boundary.js +247 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/types.d.ts +52 -0
- package/dist/utils/fs.d.ts +11 -10
- package/dist/utils/fs.js +48 -20
- package/dist/utils/glob.d.ts +8 -0
- package/dist/utils/glob.js +21 -0
- package/dist/utils/hash.js +1 -2
- package/dist/utils/pagePaths.js +2 -2
- package/package.json +19 -14
- package/scripts/publish.sh +2 -94
- package/scripts/update-contract.sh +12 -10
- package/src/assets/assetManifest.ts +39 -29
- package/src/assets/imageOptimizer.ts +91 -82
- package/src/assets/precompression.ts +22 -16
- package/src/builders/contentBuilder.ts +1224 -1149
- package/src/builders/cssBuilder.ts +466 -417
- package/src/builders/htmlBuilder.ts +511 -448
- package/src/builders/index.ts +7 -7
- package/src/builders/jsBuilder.ts +538 -280
- package/src/builders/staticAssetsBuilder.ts +166 -135
- package/src/builders/types.ts +7 -6
- package/src/cli.ts +66 -90
- package/src/config/manifest.ts +16 -14
- package/src/config/paths.ts +5 -5
- package/src/config/schema.ts +38 -37
- package/src/config/setup.ts +7 -7
- package/src/config/workspace.ts +118 -116
- package/src/config/workspaceManifest.ts +14 -14
- package/src/core/constants.ts +62 -62
- package/src/core/diagnostics.ts +26 -26
- package/src/core/pages.ts +19 -19
- package/src/hooks.ts +128 -118
- package/src/html/criticalCss.ts +84 -77
- package/src/html/htmlSecurity.ts +107 -66
- package/src/html/lazyLoad.ts +22 -19
- package/src/html/pageScaffold.ts +37 -28
- package/src/html/resourceHints.ts +83 -74
- package/src/index.ts +2 -0
- package/src/inspect.ts +158 -0
- package/src/modes/ssg/metadata.ts +53 -51
- package/src/modes/ssg/routing.ts +177 -177
- package/src/modes/ssg/seo.ts +208 -200
- package/src/modes/ssg/validation.ts +31 -25
- package/src/modes/ssg/views.ts +257 -238
- package/src/operations.ts +105 -95
- package/src/pipeline.ts +81 -69
- package/src/provider.ts +184 -176
- package/src/runtime/boundary.ts +325 -0
- package/src/runtime/index.ts +1 -0
- package/src/types.ts +107 -48
- package/src/utils/changedFile.ts +22 -22
- package/src/utils/fs.ts +73 -26
- package/src/utils/glob.ts +38 -0
- package/src/utils/hash.ts +2 -4
- package/src/utils/pagePaths.ts +35 -23
- package/src/utils/pathMatch.ts +26 -23
- package/tests/add-page-defaults.test.js +44 -39
- package/tests/bundlerParity.test.js +252 -0
- package/tests/cli.contract.test.js +13 -0
- package/tests/content-pages.test.js +108 -13
- package/tests/css-app-imports.test.js +22 -11
- package/tests/css-page-imports.test.js +26 -13
- package/tests/diagnostics.test.js +39 -36
- package/tests/features.test.js +48 -43
- package/tests/hooks.test.js +58 -42
- package/tests/htmlSecurity.test.js +66 -0
- package/tests/inspect.test.js +148 -0
- package/tests/provider.integration.test.js +71 -20
- package/tests/runtime.test.js +493 -0
- package/tests/ssg-defaults.test.js +284 -177
- package/tests/ssg-guardrails.test.js +51 -51
- package/tsconfig.json +3 -10
- package/dist/watch/frontendFiles.d.ts +0 -3
- package/dist/watch/frontendFiles.js +0 -25
- package/dist/watch/hotUpdateTracker.d.ts +0 -51
- package/dist/watch/hotUpdateTracker.js +0 -205
- package/dist/watch/pipelineHelpers.d.ts +0 -26
- package/dist/watch/pipelineHelpers.js +0 -177
- package/dist/watch/types.d.ts +0 -27
- package/dist/watch/types.js +0 -1
- package/dist/watch/watchCoordinator.d.ts +0 -36
- package/dist/watch/watchCoordinator.js +0 -551
- package/dist/watch/watchDaemon.d.ts +0 -17
- package/dist/watch/watchDaemon.js +0 -127
- package/dist/watch/watchReporter.d.ts +0 -21
- package/dist/watch/watchReporter.js +0 -64
- package/scripts/smoke.mjs +0 -35
- package/src/watch/frontendFiles.ts +0 -32
- package/src/watch/hotUpdateTracker.ts +0 -285
- package/src/watch/pipelineHelpers.ts +0 -242
- package/src/watch/types.ts +0 -23
- package/src/watch/watchCoordinator.ts +0 -666
- package/src/watch/watchDaemon.ts +0 -144
- package/src/watch/watchReporter.ts +0 -98
package/README.md
CHANGED
|
@@ -1,30 +1,92 @@
|
|
|
1
1
|
# @webstir-io/webstir-frontend
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
HTML-first frontend delivery for Webstir workspaces. This package builds page documents, shared app assets, CSS, and browser-side enhancement scripts for applications that start with server-rendered HTML and selectively add JavaScript where it improves the experience.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## What It Ships
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
7
|
+
- Multi-page HTML/CSS/JS builds for `src/frontend/**`
|
|
8
|
+
- Publish output with fingerprinted assets under `dist/frontend/**`
|
|
9
|
+
- Watch-mode rebuilds used by the Bun orchestrator
|
|
10
|
+
- Shared app-shell assets such as navigation, refresh, and client enhancement hooks
|
|
11
|
+
- Runtime helpers for boundary-style mount/unmount lifecycles and cleanup scopes
|
|
12
|
+
- SSG as a supported mode, without making static-only delivery the center of the product story
|
|
13
|
+
|
|
14
|
+
Requires Bun **1.3.11** or newer.
|
|
15
|
+
|
|
16
|
+
## Runtime Model
|
|
17
|
+
|
|
18
|
+
Client code that participates in hot updates should use the boundary runtime instead of relying on module top-level side effects.
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { createCleanupScope, defineBoundary } from '@webstir-io/webstir-frontend/runtime';
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `createCleanupScope()` collects cleanup handlers and disposes them in reverse registration order.
|
|
25
|
+
- `defineBoundary()` wraps a page or app region with explicit `mount()` and `unmount()` lifecycle methods.
|
|
26
|
+
- Boundary scopes can mount nested child boundaries with `scope.mountChild(...)`; child boundaries unmount before the parent boundary tears down.
|
|
27
|
+
- Boundaries can opt into hot-state preservation with `snapshotState()` and `restoreState()`; when those hooks are absent, remounts start fresh.
|
|
28
|
+
- `listen()`, `scheduleTimeout()`, `scheduleInterval()`, `trackObserver()`, and `createAbortController()` wrap common side effects so cleanup stays attached to the boundary scope.
|
|
29
|
+
- Boundary code should register DOM listeners, timers, observers, and similar side effects through the cleanup scope so remounts stay deterministic.
|
|
30
|
+
|
|
31
|
+
## Hot Update Rules
|
|
32
|
+
|
|
33
|
+
Webstir watch mode follows a narrow fallback policy:
|
|
34
|
+
|
|
35
|
+
- CSS edits hot-swap in the browser.
|
|
36
|
+
- JS edits remount only when the module or boundary explicitly opts in.
|
|
37
|
+
- Most content, HTML, and route-shape changes fall back to rebuild + reload.
|
|
38
|
+
- Current exception: the SSG docs-sidebar pilot also remounts on `src/frontend/content/_sidebar.json` edits.
|
|
39
|
+
- Any cleanup failure or declined boundary update falls back to reload.
|
|
40
|
+
|
|
41
|
+
## Fragment Ownership Decision
|
|
42
|
+
|
|
43
|
+
The current SSG runtime has a working fragment-ownership pilot on the docs sidebar boundary. It now covers the sidebar manifest input (`src/frontend/content/_sidebar.json`) in addition to direct docs page module edits, but owned-fragment HTML replacement is still not justified yet as a general mechanism.
|
|
44
|
+
|
|
45
|
+
Keep reload/remount as the default until the runtime has:
|
|
46
|
+
|
|
47
|
+
- More than one real owned fragment with clear parent/child invalidation rules
|
|
48
|
+
- A stable fragment-to-source mapping for generated HTML updates
|
|
49
|
+
- A lifecycle contract for replacing HTML without duplicating side effects or breaking page state
|
|
50
|
+
|
|
51
|
+
Until then, content and HTML changes should continue to fall back to rebuild + reload.
|
|
52
|
+
|
|
53
|
+
## HTML-First Workflow
|
|
54
|
+
|
|
55
|
+
The frontend package is designed to pair with the backend runtime rather than replace it:
|
|
56
|
+
|
|
57
|
+
- Build document shells under `build/frontend/pages/**`
|
|
58
|
+
- Publish optimized assets under `dist/frontend/**`
|
|
59
|
+
- Let backend routes or request-time views deliver HTML first
|
|
60
|
+
- Use enhancement scripts for fragment updates, navigation polish, and form handling when JavaScript is available
|
|
61
|
+
|
|
62
|
+
Canonical proof apps in this repo:
|
|
63
|
+
|
|
64
|
+
- [`examples/demos/auth-crud`](../../../examples/demos/auth-crud) for server-handled auth, validation, redirect-after-post, and CRUD flows
|
|
65
|
+
- [`examples/demos/dashboard`](../../../examples/demos/dashboard) for shell-level and panel-level partial refreshes without SPA architecture
|
|
9
66
|
|
|
10
67
|
## Quick Start
|
|
11
68
|
|
|
12
|
-
1.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npx webstir-frontend build --workspace /absolute/path/to/workspace
|
|
19
|
-
```
|
|
69
|
+
1. Install the package
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
bun add @webstir-io/webstir-frontend
|
|
73
|
+
```
|
|
20
74
|
|
|
21
|
-
|
|
75
|
+
2. Build a workspace
|
|
22
76
|
|
|
23
|
-
|
|
77
|
+
```bash
|
|
78
|
+
bunx webstir-frontend build --workspace /absolute/path/to/workspace
|
|
79
|
+
```
|
|
24
80
|
|
|
25
|
-
|
|
81
|
+
3. Publish optimized frontend assets
|
|
26
82
|
|
|
83
|
+
```bash
|
|
84
|
+
bunx webstir-frontend publish --workspace /absolute/path/to/workspace
|
|
27
85
|
```
|
|
86
|
+
|
|
87
|
+
## Workspace Layout
|
|
88
|
+
|
|
89
|
+
```text
|
|
28
90
|
workspace/
|
|
29
91
|
src/frontend/
|
|
30
92
|
app/
|
|
@@ -32,42 +94,44 @@ workspace/
|
|
|
32
94
|
images/
|
|
33
95
|
fonts/
|
|
34
96
|
media/
|
|
35
|
-
frontend.config.json # optional feature
|
|
36
|
-
webstir.config.mjs # optional
|
|
37
|
-
build/frontend/... #
|
|
38
|
-
dist/frontend/... # publish
|
|
39
|
-
.webstir/manifest.json # pipeline manifest
|
|
97
|
+
frontend.config.json # optional feature flags
|
|
98
|
+
webstir.config.mjs # optional hooks
|
|
99
|
+
build/frontend/... # watch/build output
|
|
100
|
+
dist/frontend/... # publish output
|
|
101
|
+
.webstir/manifest.json # pipeline manifest
|
|
40
102
|
```
|
|
41
103
|
|
|
42
104
|
## CLI Commands
|
|
43
105
|
|
|
44
|
-
Binary name: `webstir-frontend`. All commands require `--workspace
|
|
106
|
+
Binary name: `webstir-frontend`. All commands require `--workspace`.
|
|
45
107
|
|
|
46
108
|
| Command | Description | Useful options |
|
|
47
|
-
|
|
48
|
-
| `build` | Runs the development pipeline
|
|
49
|
-
| `publish` | Produces optimized assets
|
|
50
|
-
| `rebuild` | Incremental rebuild
|
|
51
|
-
| `add-page <name>` | Scaffolds
|
|
52
|
-
| `watch-daemon` | Persistent watcher + HMR coordinator. | `--no-auto-start`, `--verbose`, `--hmr-verbose`. |
|
|
109
|
+
| --- | --- | --- |
|
|
110
|
+
| `build` | Runs the development-oriented pipeline. | `--changed-file <path>` to scope rebuilds. |
|
|
111
|
+
| `publish` | Produces optimized frontend assets. | `--mode <bundle\|ssg>` |
|
|
112
|
+
| `rebuild` | Incremental rebuild after a file change. | `--changed-file <path>` |
|
|
113
|
+
| `add-page <name>` | Scaffolds `index.html`, `index.css`, and `index.ts`. | None |
|
|
53
114
|
|
|
54
|
-
|
|
115
|
+
## Feature Flags
|
|
55
116
|
|
|
56
|
-
`frontend.config.json`
|
|
117
|
+
`frontend.config.json` controls optional pipeline features:
|
|
57
118
|
|
|
58
119
|
```jsonc
|
|
59
120
|
{
|
|
60
121
|
"features": {
|
|
61
122
|
"htmlSecurity": true,
|
|
123
|
+
"externalResourceIntegrity": false,
|
|
62
124
|
"imageOptimization": true,
|
|
63
125
|
"precompression": false
|
|
64
126
|
}
|
|
65
127
|
}
|
|
66
128
|
```
|
|
67
129
|
|
|
68
|
-
|
|
130
|
+
`externalResourceIntegrity` stays `false` by default so publish does not fetch third-party script or stylesheet URLs just to compute SRI. Enable it only when you explicitly want remote fetches during publish; otherwise, add `integrity` and `crossorigin` attributes yourself for external CDN assets.
|
|
131
|
+
|
|
132
|
+
## Lifecycle Hooks
|
|
69
133
|
|
|
70
|
-
Hooks live in `webstir.config.mjs` (or `.js
|
|
134
|
+
Hooks live in `webstir.config.mjs` (or `.js` / `.cjs`) at the workspace root:
|
|
71
135
|
|
|
72
136
|
```js
|
|
73
137
|
export const hooks = {
|
|
@@ -78,7 +142,7 @@ export const hooks = {
|
|
|
78
142
|
},
|
|
79
143
|
builders: {
|
|
80
144
|
assets: {
|
|
81
|
-
after(
|
|
145
|
+
after() {
|
|
82
146
|
// custom post-processing
|
|
83
147
|
}
|
|
84
148
|
}
|
|
@@ -88,8 +152,6 @@ export const hooks = {
|
|
|
88
152
|
|
|
89
153
|
## API Usage
|
|
90
154
|
|
|
91
|
-
The package exports a `ModuleProvider` compatible with `@webstir-io/module-contract`:
|
|
92
|
-
|
|
93
155
|
```ts
|
|
94
156
|
import { frontendProvider } from '@webstir-io/webstir-frontend';
|
|
95
157
|
|
|
@@ -98,49 +160,51 @@ const result = await frontendProvider.build({
|
|
|
98
160
|
env: { WEBSTIR_MODULE_MODE: 'publish' }
|
|
99
161
|
});
|
|
100
162
|
|
|
101
|
-
|
|
102
|
-
|
|
163
|
+
console.log(result.manifest.entryPoints);
|
|
164
|
+
```
|
|
103
165
|
|
|
104
|
-
- `frontendProvider.metadata`
|
|
105
|
-
- `frontendProvider.resolveWorkspace` returns canonical source/build
|
|
106
|
-
- `frontendProvider.build` executes the pipeline and returns artifacts
|
|
166
|
+
- `frontendProvider.metadata` exposes package and runtime-compatibility metadata
|
|
167
|
+
- `frontendProvider.resolveWorkspace()` returns canonical source/build roots
|
|
168
|
+
- `frontendProvider.build()` executes the pipeline and returns artifacts plus manifest data
|
|
169
|
+
- `inspectFrontendWorkspace()` returns resolved config plus shallow workspace facts without building
|
|
107
170
|
|
|
108
|
-
## SSG
|
|
171
|
+
## SSG Mode
|
|
109
172
|
|
|
110
|
-
|
|
173
|
+
SSG is a supported frontend output mode, not a separate product:
|
|
111
174
|
|
|
112
175
|
```bash
|
|
113
|
-
|
|
176
|
+
bunx webstir-frontend publish --workspace /absolute/path/to/workspace --mode ssg
|
|
114
177
|
```
|
|
115
178
|
|
|
116
|
-
|
|
179
|
+
That run:
|
|
117
180
|
|
|
118
|
-
-
|
|
119
|
-
-
|
|
120
|
-
-
|
|
181
|
+
- Builds normal publish assets under `dist/frontend/**`
|
|
182
|
+
- Generates `index.html` aliases for document routes
|
|
183
|
+
- Uses `webstir.moduleManifest.views` metadata when present to emit extra static paths
|
|
121
184
|
|
|
122
185
|
## Maintainer Workflow
|
|
123
186
|
|
|
124
187
|
```bash
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
# Release helper (bumps version, pushes tags to trigger release workflow)
|
|
131
|
-
npm run release -- patch
|
|
188
|
+
bun install
|
|
189
|
+
bun run clean
|
|
190
|
+
bun run build
|
|
191
|
+
bun run test
|
|
192
|
+
bun run release -- patch
|
|
132
193
|
```
|
|
133
194
|
|
|
134
|
-
|
|
195
|
+
Recommended package validation before release:
|
|
135
196
|
|
|
136
|
-
|
|
137
|
-
-
|
|
197
|
+
- `bun run build`
|
|
198
|
+
- `bun run test`
|
|
138
199
|
|
|
139
200
|
## Troubleshooting
|
|
140
201
|
|
|
141
|
-
-
|
|
142
|
-
|
|
143
|
-
-
|
|
202
|
+
- `No frontend test files found`
|
|
203
|
+
The package test script expects compiled tests under `tests/**/*.test.js`.
|
|
204
|
+
- `Missing entry points in manifest`
|
|
205
|
+
Confirm `build/frontend` contains at least one generated JS entry.
|
|
206
|
+
- `SSG output missing a route`
|
|
207
|
+
Check `webstir.moduleManifest.views` for `renderMode: "ssg"` and the expected `staticPaths`.
|
|
144
208
|
|
|
145
209
|
## Community & Support
|
|
146
210
|
|
|
@@ -151,7 +215,7 @@ CI notes
|
|
|
151
215
|
|
|
152
216
|
## Third-Party Notices
|
|
153
217
|
|
|
154
|
-
Webstir Frontend depends on third-party libraries and data sets (including `sharp
|
|
218
|
+
Webstir Frontend depends on third-party libraries and data sets (including `sharp` / libvips and `caniuse-lite`) under their respective licenses. See [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md) for the attribution summary.
|
|
155
219
|
|
|
156
220
|
## License
|
|
157
221
|
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import sharp from 'sharp';
|
|
3
|
-
import { glob } from 'glob';
|
|
4
3
|
import { copy, ensureDir, emptyDir, pathExists, remove } from '../utils/fs.js';
|
|
5
4
|
import { EXTENSIONS } from '../core/constants.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
EXTENSIONS.jpg,
|
|
9
|
-
EXTENSIONS.jpeg
|
|
10
|
-
]);
|
|
5
|
+
import { scanGlob } from '../utils/glob.js';
|
|
6
|
+
const TRANSCODABLE_EXTENSIONS = new Set([EXTENSIONS.png, EXTENSIONS.jpg, EXTENSIONS.jpeg]);
|
|
11
7
|
export async function optimizeImages(sourceDir, destinationDir, files) {
|
|
12
8
|
if (!(await pathExists(sourceDir))) {
|
|
13
9
|
await emptyDir(destinationDir);
|
|
@@ -15,7 +11,7 @@ export async function optimizeImages(sourceDir, destinationDir, files) {
|
|
|
15
11
|
}
|
|
16
12
|
if (!files || files.length === 0) {
|
|
17
13
|
await emptyDir(destinationDir);
|
|
18
|
-
const allFiles = await
|
|
14
|
+
const allFiles = await scanGlob('**/*', { cwd: sourceDir });
|
|
19
15
|
await Promise.all(allFiles.map(async (relative) => processImage(sourceDir, destinationDir, relative)));
|
|
20
16
|
return;
|
|
21
17
|
}
|
|
@@ -40,9 +36,7 @@ function replaceExtension(filePath, extension) {
|
|
|
40
36
|
}
|
|
41
37
|
async function createWebpVariant(sourcePath, destinationPath) {
|
|
42
38
|
try {
|
|
43
|
-
await sharp(sourcePath)
|
|
44
|
-
.webp({ quality: 75 })
|
|
45
|
-
.toFile(destinationPath);
|
|
39
|
+
await sharp(sourcePath).webp({ quality: 75 }).toFile(destinationPath);
|
|
46
40
|
}
|
|
47
41
|
catch {
|
|
48
42
|
// Ignore failures; fall back to original image only.
|
|
@@ -50,9 +44,7 @@ async function createWebpVariant(sourcePath, destinationPath) {
|
|
|
50
44
|
}
|
|
51
45
|
async function createAvifVariant(sourcePath, destinationPath) {
|
|
52
46
|
try {
|
|
53
|
-
await sharp(sourcePath)
|
|
54
|
-
.avif({ quality: 45 })
|
|
55
|
-
.toFile(destinationPath);
|
|
47
|
+
await sharp(sourcePath).avif({ quality: 45 }).toFile(destinationPath);
|
|
56
48
|
}
|
|
57
49
|
catch {
|
|
58
50
|
// Ignore failures; fall back to original image only.
|
|
@@ -79,11 +71,14 @@ async function processImage(sourceDir, destinationDir, relative, incremental = f
|
|
|
79
71
|
}
|
|
80
72
|
await Promise.all([
|
|
81
73
|
createWebpVariant(sourcePath, replaceExtension(destinationPath, EXTENSIONS.webp)),
|
|
82
|
-
createAvifVariant(sourcePath, replaceExtension(destinationPath, EXTENSIONS.avif))
|
|
74
|
+
createAvifVariant(sourcePath, replaceExtension(destinationPath, EXTENSIONS.avif)),
|
|
83
75
|
]);
|
|
84
76
|
}
|
|
85
77
|
async function removeVariants(destinationPath, includeBase) {
|
|
86
|
-
const targets = [
|
|
78
|
+
const targets = [
|
|
79
|
+
replaceExtension(destinationPath, EXTENSIONS.webp),
|
|
80
|
+
replaceExtension(destinationPath, EXTENSIONS.avif),
|
|
81
|
+
];
|
|
87
82
|
if (includeBase) {
|
|
88
83
|
targets.push(destinationPath);
|
|
89
84
|
}
|
|
@@ -3,7 +3,7 @@ import { constants as zlibConstants, createBrotliCompress, createGzip } from 'no
|
|
|
3
3
|
export async function createCompressedVariants(filePath) {
|
|
4
4
|
await Promise.all([
|
|
5
5
|
compress(filePath, '.br', () => createBrotliCompress({ params: { [zlibConstants.BROTLI_PARAM_QUALITY]: 11 } })),
|
|
6
|
-
compress(filePath, '.gz', () => createGzip({ level: zlibConstants.Z_BEST_COMPRESSION }))
|
|
6
|
+
compress(filePath, '.gz', () => createGzip({ level: zlibConstants.Z_BEST_COMPRESSION })),
|
|
7
7
|
]);
|
|
8
8
|
}
|
|
9
9
|
async function compress(source, extension, factory) {
|