divriots / jampack Goto Github PK
View Code? Open in Web Editor NEWOptimizes static websites for best user experience and best Core Web Vitals scores.
Home Page: https://jampack.divriots.com/
License: MIT License
Optimizes static websites for best user experience and best Core Web Vitals scores.
Home Page: https://jampack.divriots.com/
License: MIT License
According to the documentation about <picture>
tags,
<picture>
<img src="./redpanda.jpg" alt="Red panda">
</picture>
should become
<picture>
<source type="image/avif" srcset="./[email protected] 1936w, ./[email protected] 1636w, ./[email protected] 1336w, ./[email protected] 1036w, ./[email protected] 736w">
<source type="image/webp" srcset="./[email protected] 1936w, ./[email protected] 1636w, ./[email protected] 1336w, ./[email protected] 1036w, ./[email protected] 736w">
<img src="./redpanda.jpg" alt="Red panda" loading="lazy" decoding="async" width="1936" height="1296" srcset="./redpanda.jpg 1936w, ./[email protected] 1636w, ./[email protected] 1336w, ./[email protected] 1036w, ./[email protected] 736w" sizes="100vw">
</picture>
However the picture is generated without any <source ...>
:
<picture>
<img src="./picture_redpanda.jpg.jpg" alt="Red panda" fetchpriority="high" decoding="async" width="1936" height="1296" srcset="./picture_redpanda.jpg.jpg 1936w, ./[email protected] 1636w, ./[email protected] 1336w, ./[email protected] 1036w" sizes="100vw">
</picture>
https://jampack.divriots.com/features/optimize-images/packed/index.html
Furthermore the src
and the first image of the srcset
have redundant extensions.
At https://futurefrontend.com/, I have multiple same images (see Ken Wheeler for example). For some reason, jampack rewrites only the first reference at speakers but not the second one at workshop instructors.
You should be able to reproduce the issue against https://github.com/ReactFinland/future-frontend-site . First you have to build the site with deno task build
and then optimize with npm run optimize:site
(needs npm install
first). You can see the output at /build
.
For me, it would make sense if it used the same image reference for both cases since it's the same image after all.
I noticed something interesting with Deno usage at https://github.com/ReactFinland/future-frontend-site . The site compiles just fine with Deno v1.38.2
while it hangs using with v1.40.5
. I was able to verify this with jampack 0.23.2 and 0.23.3 on my system.
I know it's likely a regression in Deno but I thought to open this issue so Deno users can be aware of the issue.
To push the issue upstream, we likely would have to reduce the demonstration somewhat. One easy option is to wait and see if they fix their hang.
commander
, ora
and table
provide their own type definitions, no need to depend on the corresponding @types/<package>
's.
@divriots/[email protected] requires nth-check@~1.0.1 via a transitive dependency on [email protected]
No patched version available for nth-check
I'd like lightningcss to process based on a browser target.
It would be nice if a browser target could be added via configuration, which would take a browserlist value and use it when processing through lightningcss.
I have multiple use cases for using different pictures depending on the orientation of the screen. For example a background image in a hero section can be served in landscape and portrait format.
Right now only one source is supported, the other one is being deleted by jampack.
Let's use https://github.com/natemoo-re/proload for the configuration file.
Someone asked to opt out of <style>:where(img){height:auto}</style>
.
Apparently it doesn't play nice with CSP policy. I need to understand why.
Jamstack processes images to be lazy-loaded (according to docs https://jampack.divriots.com/features/optimize-images/).
Although, for images having already lazy-loading applied (in our case, it comes from Gatsby, which has it enabled by default), it causes warnings.
warn Missing [src] on img - processing skipped.
Expected behaviour
No warnings like above for images having loading="lazy"
(even those not having src
attribute).
Lot's of svg do not need to be optimised. It would be very helpful if we could skip optimisation of svgs in the config.
I would love to be able to configure max-width of an image. Let's say a photographer provides me with large images (6000px), I like the ease of use of simply pasting these images in, but then Jampack generates almost 20 images sizes, which takes a long time.
Hi,
Im using jampack to compress static image assets to webp and avif formats for my svelte app. (Svelte is configured as SSG)
But while compressing js files there is a lot of imports and variable renaming (I'm not familiar with SWC internals).
As a result the svelte app fails during hydratation with "read properties of undefined".
Also most apps built with Vite already have good enough compression of .js and .html files resulting in the final file size savings of less than 1%.
It would be really cool thing to have simple toggles in jampack config to disable certain features.
Just like options --fast
, --onlyoptim
and --onlycomp
do.
(Which is already requested here: #91)
As a current workaround i use the existing CLI option --exclude **/*.js
.
As requested on discord by @georges-gomes i've also made replication of the svelte problem using svelte demo app to allow you to further address javascript compression problem.
My images do get transformed into multiple sizes with the correct srcset. However, all my jpg's stay jpg's. They are not turned into webp.
Summary
╔══════════════╤════════════╤═══════════╤════════════╤════════════╗
║ Action │ Compressed │ Original │ Compressed │ Gain ║
╟──────────────┼────────────┼───────────┼────────────┼────────────╢
║ svg->svg │ 16 / 16 │ 53.63 KB │ 34.78 KB │ -18.84 KB ║
║ jpg->jpg │ 21 / 21 │ 108.62 MB │ 11.10 MB │ -97.52 MB ║
║ png->webp │ 1 / 1 │ 1.46 MB │ 631.46 KB │ -867.61 KB ║
║ .css │ 2 / 2 │ 59.48 KB │ 54.25 KB │ -5.24 KB ║
║ .svg │ 2 / 2 │ 4.31 KB │ 2.60 KB │ -1.71 KB ║
║ .js │ 3 / 3 │ 42.17 KB │ 41.53 KB │ -657.00 B ║
║ .html │ 8 / 8 │ 59.33 KB │ 59.30 KB │ -30.00 B ║
║ .png │ 6 / 12 │ 1.53 MB │ 1.50 MB │ -36.73 KB ║
║ .jpg │ 12 / 12 │ 86.73 MB │ 7.32 MB │ -79.41 MB ║
║ .jpeg │ 3 / 3 │ 2.02 MB │ 1.45 MB │ -579.60 KB ║
║ .webp │ 1 / 1 │ 109.54 KB │ 97.35 KB │ -12.18 KB ║
║ webp->jpg │ 0 / 2 │ 219.07 KB │ 232.08 KB │ ║
║ .txt │ 0 / 1 │ 73.00 B │ 73.00 B │ ║
║ .xml │ 0 / 3 │ 1.18 KB │ 1.18 KB │ ║
║ .pdf │ 0 / 1 │ 325.77 KB │ 325.77 KB │ ║
║ .ico │ 0 / 1 │ 14.73 KB │ 14.73 KB │ ║
║ .webmanifest │ 0 / 1 │ 456.00 B │ 456.00 B │ ║
╟──────────────┼────────────┼───────────┼────────────┼────────────╢
║ Total │ 75 / 90 │ 201.23 MB │ 22.83 MB │ -178.41 MB ║
I tried running the optimizer on futurefrontend.com. Here are the results: https://pagespeed.web.dev/report?url=https%3A%2F%2Ffuturefrontend.com%2F .
After applying jampack (ReactFinland/future-frontend-site#1), the performance went down: https://pagespeed.web.dev/report?url=https%3A%2F%2F1b5b0924.future-frontend-site.pages.dev%2F . LCP went from 1.8s to 4.2s on mobile.
Do you know what might be causing that?
I got these insights from someone in the Astro lounge on Discord
---
/** snip */
const originalWidth = 1740;
const { image: bgHeroImage, sources: bgHeroSources } = await getPicture({
src: import("@screens/index/bg-hero.jpg") as unknown as Promise<{ default: ImageMetadata }>,
formats: ["avif", "jpeg", "webp"],
widths: [originalWidth / 2, originalWidth],
});
const bgHeroImageSrc = (bgHeroImage as { src: string }).src;
const bgHeroSourcesRemapped = bgHeroSources.flatMap(({ type, srcset }) => {
const sources = srcset.split(",");
return sources.map((unparsedSource) => {
const [source, width] = unparsedSource.split(" ");
return { type, source, width };
});
});
const imageSet = `
background-image: url("${bgHeroImageSrc}");
background-image: -webkit-image-set(
${bgHeroSourcesRemapped
.filter(({ type }) => type !== "image/avif")
.map(({ source, width }) => {
const resolution = width === `${originalWidth}w` ? "2x" : "1x";
return `url('${source}') ${resolution}`;
})
.join(",\n")}
);
background-image: image-set(
${bgHeroSourcesRemapped
.map(({ type, source, width }) => {
const resolution = width === `${originalWidth}w` ? "2x" : "1x";
return `url('${source}') ${resolution} type("${type}")`;
})
.join(",\n")}
);
`;
---
<!-- example: -->
<div style={imageSet}/>
for image-set
support on my astro site - image-set
support is fun to figure out though 😅 since there's not amazing support for all of the values, for example, safari will try to use an avif if i include it in -webkit-image-set
b/c safari and chrome don't support the type()
clause and safari doesnt' support avif
My index.astro page:
---
import Layout from '@layouts/Layout.astro'
---
<Layout>
<img src="/hero.jpg" alt="myimg">
</Layout>
Gets generated into:
<img alt="myimg" decoding="async" fetchpriority="high" height="1165" src="/hero.jpg" width="1427">
I can't find why, no errors warning nothing
Console output:
$ jampack ./dist
__ __
|__|____ _____ ___________ ____ | | __
| \__ \ / \\____ \__ \ _/ ___\| |/ /
| |/ __ \| Y Y \ |_> > __ \\ \___| <
/\__| (____ /__|_| / __(____ /\___ >__|_ \
\______| \/ \/| | \/ \/ \/
v0.13.0 |__| by ‹div›RIOTS
Options:
{}
Overriding default config with:
{
"image": {
"compress": false,
"external": {
"process": "download"
}
}
}
PASS 1 - Optimizing
▶ index.html
✔ <img> [2/2]
✔ <iframe> [2/2]
▶ algemene-voorwaarden/index.html
✔ <img> [0/0]
✔ <iframe> [0/0]
▶ index/index.html
✔ <img> [1/1]
✔ <iframe> [1/1]
▶ privacyverklaring/index.html
✔ <img> [0/0]
✔ <iframe> [0/0]
Done: 44.087ms
PASS 2 - Compressing the rest
✔ 21 files | 2.92 MB → 2.41 MB | -523.21 KB
Done: 26.618ms
Summary
╔════════╤════════════╤═══════════╤════════════╤════════════╗
║ Action │ Compressed │ Original │ Compressed │ Gain ║
╟────────┼────────────┼───────────┼────────────┼────────────╢
║ .jpg │ 1 / 4 │ 2.18 MB │ 1.82 MB │ -363.13 KB ║
║ .css │ 2 / 2 │ 42.52 KB │ 39.14 KB │ -3.38 KB ║
║ .js │ 3 / 3 │ 36.37 KB │ 35.81 KB │ -569.00 B ║
║ .html │ 4 / 4 │ 11.28 KB │ 11.25 KB │ -28.00 B ║
║ .webp │ 3 / 3 │ 601.57 KB │ 481.31 KB │ -120.26 KB ║
║ .png │ 1 / 1 │ 51.50 KB │ 15.64 KB │ -35.86 KB ║
║ .txt │ 0 / 1 │ 73.00 B │ 73.00 B │ ║
║ .xml │ 0 / 2 │ 744.00 B │ 744.00 B │ ║
║ .svg │ 0 / 1 │ 11.20 KB │ 11.20 KB │ ║
╟────────┼────────────┼───────────┼────────────┼────────────╢
║ Total │ 14 / 21 │ 2.92 MB │ 2.41 MB │ -523.21 KB ║
╚════════╧════════════╧═══════════╧════════════╧════════════╝
✔ No issues
✨ Done in 3.51s.
Hi. I just tries your tool with my astro website and it results in a lot of errors because it can't obtain metadata on avif images.
The repository for my website can be found here: https://github.com/mandar1jn/portfolio.
Logs:
__ __
|__|____ _____ ___________ ____ | | __
| \__ \ / \\____ \__ \ _/ ___\| |/ /
| |/ __ \| Y Y \ |_> > __ \\ \___| <
/\__| (____ /__|_| / __(____ /\___ >__|_ \
\______| \/ \/| | \/ \/ \/
v0.5.0 |__| by ‹div›RIOTS
PASS 1 - Optimizing
▶ 404.html
✔ <img> [0/0]
▶ index.html
⠋ avif
avif
avif
avif
avif
avif
avif
avif
avif
avif
✖ <img> [5/5]
5 issues
▶ projects/index.html
⠋ avif
avif
✖ <img> [1/1]
1 issue
▶ posts/index.html
⠋ avif
avif
avif
avif
avif
avif
avif
avif
avif
avif
✖ <img> [5/5]
5 issues
▶ projects/planet-clash/index.html
⠋ avif
avif
avif
avif
avif
avif
avif
avif
✖ <img> [4/4]
4 issues
▶ posts/dissecting-the-skylanders-portal-part1/index.html
⠋ avif
avif
✖ <img> [1/1]
1 issue
▶ posts/dissecting-the-skylanders-portal-part2/index.html
⠋ avif
avif
✖ <img> [1/1]
1 issue
▶ posts/dissecting-the-skylanders-portal-part3/index.html
⠋ avif
avif
avif
avif
✖ <img> [2/2]
2 issues
▶ posts/dissecting-the-skylanders-portal-part4/index.html
⠋ avif
avif
✖ <img> [1/1]
1 issue
▶ posts/some-big-skylanders-discoveries/index.html
⠋ avif
avif
✖ <img> [1/1]
1 issue
Done: 318.286ms
PASS 2 - Compressing the rest
✔ 39 files | 467.96 KB → 378.87 KB | -89.09 KB
Done: 393.445ms
Summary
╔════════╤════════════╤═══════════╤════════════╤═══════════╗
║ Action │ Compressed │ Original │ Compressed │ Gain ║
╟────────┼────────────┼───────────┼────────────┼───────────╢
║ .html │ 10 / 10 │ 83.25 KB │ 82.97 KB │ -283.00 B ║
║ .css │ 9 / 9 │ 18.47 KB │ 17.69 KB │ -795.00 B ║
║ .jpg │ 1 / 1 │ 174.23 KB │ 86.20 KB │ -88.04 KB ║
╟────────┼────────────┼───────────┼────────────┼───────────╢
║ Total │ 20 / 39 │ 467.96 KB │ 378.87 KB │ -89.09 KB ║
╚════════╧════════════╧═══════════╧════════════╧═══════════╝
Issues
▶ index.html
erro Can't get image meta information of "/_astro/foto_1dyieW.avif" - some optimizations are not possible without this information.
erro Can't get image meta information of "/_astro/icon_ZeHo3k.avif" - some optimizations are not possible without this information.
erro Can't get image meta information of "/_astro/runic-portal_ZnccTB.avif" - some optimizations are not possible without this information.
erro Can't get image meta information of "/_astro/runic-portal_ZnccTB.avif" - some optimizations are not possible without this information.
erro Can't get image meta information of "/_astro/runic-portal_ZnccTB.avif" - some optimizations are not possible without this information.
▶ projects/index.html
erro Can't get image meta information of "/_astro/icon_ZeHo3k.avif" - some optimizations are not possible without this information.
▶ posts/index.html
erro Can't get image meta information of "/_astro/runic-portal_ZnccTB.avif" - some optimizations are not possible without this information.
erro Can't get image meta information of "/_astro/runic-portal_ZnccTB.avif" - some optimizations are not possible without this information.
erro Can't get image meta information of "/_astro/runic-portal_ZnccTB.avif" - some optimizations are not possible without this information.
erro Can't get image meta information of "/_astro/runic-portal_ZnccTB.avif" - some optimizations are not possible without this information.
erro Can't get image meta information of "/_astro/runic-portal_ZnccTB.avif" - some optimizations are not possible without this information.
▶ projects/planet-clash/index.html
erro Can't get image meta information of "/_astro/icon_ZrLxOj.avif" - some optimizations are not possible without this information.
erro Can't get image meta information of "/_astro/main_menu_ZEQqL3.avif" - some optimizations are not possible without this information.
erro Can't get image meta information of "/_astro/gameplay_ZPk7AJ.avif" - some optimizations are not possible without this information.
erro Can't get image meta information of "/_astro/lose_ro12T.avif" - some optimizations are not possible without this information.
▶ posts/dissecting-the-skylanders-portal-part1/index.html
erro Can't get image meta information of "/_astro/runic-portal_Z1Va0dh.avif" - some optimizations are not possible without this information.
▶ posts/dissecting-the-skylanders-portal-part2/index.html
erro Can't get image meta information of "/_astro/runic-portal_Z1Va0dh.avif" - some optimizations are not possible without this information.
▶ posts/dissecting-the-skylanders-portal-part3/index.html
erro Can't get image meta information of "/_astro/runic-portal_Z1Va0dh.avif" - some optimizations are not possible without this information.
erro Can't get image meta information of "/_astro/editor-raylib_ZPrYO9.avif" - some optimizations are not possible without this information.
▶ posts/dissecting-the-skylanders-portal-part4/index.html
erro Can't get image meta information of "/_astro/runic-portal_Z1Va0dh.avif" - some optimizations are not possible without this information.
▶ posts/some-big-skylanders-discoveries/index.html
erro Can't get image meta information of "/_astro/runic-portal_Z1Va0dh.avif" - some optimizations are not possible without this information.
21 issue(s) over 9 files
Here is my dist folder (uncompressed):
dist (2).zip
It would be nice if there was a way to create a custom cache directory through either a config or using the cli.
My use case is with Cloudflare Pages - currently in beta, but you can enable build caching, which currently supports:
Framework | Directories cached |
---|---|
Gatsby | .cache, public |
Next.js | .next/cache |
Astro | node_modules/.astro |
My current workaround is to build locally and then use wrangler
to deploy manually.
I noticed something curious at https://futurefrontend.com/speakers/ . If you check out the Network
tab of the browser inspector, you can see that specifically the first two speaker images were not converted to WebP but remained in jpeg while the rest were converted correctly.
I have the site source available at https://github.com/ReactFinland/future-frontend-site in case someone wants to have a look.
Ideally you should be to do import * as jampack from "npm:@divriots/[email protected]";
. In my quick test that gave the following:
error: Uncaught (in worker "") (in promise) TypeError: Could not resolve 'npm:@divriots/[email protected]'.(463/464)
Caused by:
Failed resolving package subpath '.' for '/Users/juhovepsalainen/Library/Caches/deno/npm/registry.npmjs.org/@divriots/jampack/0.22.1/package.json'
[ERR_PACKAGE_PATH_NOT_EXPORTED] No "exports" main defined in '/Users/juhovepsalainen/Library/Caches/deno/npm/registry.npmjs.org/@divriots/jampack/0.22.1/package.json' imported from '/Users/juhovepsalainen/Projects/github/gustwindjs/gustwind/plugins/jampack/mod.ts'
If you want to try, you can find the related code at gustwindjs/gustwind#126 . After pulling, run deno task build
to see the error. I used Deno 1.38.2 for testing.
Looking at the code, I can see the project is using an older version of Sharp that doesn't support Deno yet. Here's a bit more info on how to get it going: lovell/sharp#3750 (comment) . The version that worked for me is npm:[email protected]
. Based on the error, it's possible there's something else to amend as well and I understand if you want to wait for a stable 0.33.0.
On a related note, it would be nice if you could document how to use the API as a JavaScript module although it's quite trivial to figure out anyway.
Requested by Ben
We can use https://www.npmjs.com/package/ffprobe-wasm to get the dimensions.
Hi
Is there an option available to disable the JPEG in picture tag => no sources required
function when optimizing above the fold?
I set up an image with different sizes for different breakpoints and jampack is choosing the lowest one to display so Pagespeed then complains about the image being too small.
I'd like to use everything else. Changing loading and fetchpriority sound great. I'd just like to keep my different sources.
Fom:
<picture><source type="image/avif" srcset="data:image/avif;base64,AAAAHGZ...UYhKY= 300w, /assets/CNt-PnDVr4-600-611e33c6.avif 600w, /assets/CNt-PnDVr4-800-1c040ee0.avif 800w" sizes="(min-width: 66em) 33vw, (min-width: 44em) 50vw, 100vw"><source type="image/webp" srcset="/assets/CNt-PnDVr4-300-22037960.webp 300w, /assets/CNt-PnDVr4-600-faf01c02.webp 600w, /assets/CNt-PnDVr4-800-3999a53a.webp 800w" sizes="(min-width: 66em) 33vw, (min-width: 44em) 50vw, 100vw"><source type="image/png" srcset="/assets/CNt-PnDVr4-300-7e7401a9.png 300w, /assets/CNt-PnDVr4-600-658bcd90.png 600w, /assets/CNt-PnDVr4-800-1aa0fa89.png 800w" sizes="(min-width: 66em) 33vw, (min-width: 44em) 50vw, 100vw"><img class="aspect-[1.78]" alt="Test" loading="lazy" decoding="async" src="/assets/CNt-PnDVr4-300-7e7401a9.png" width="800" height="450"></picture>
To:
<picture><img alt="Test" class="aspect-[1.78]" decoding="async" height="450" src="/assets/CNt-PnDVr4-300-7e7401a9.png.jpg" width="800" fetchpriority="high"></picture>
Thanks
Congrats on launching jampack! It's an absolute game-changer in automating a lot of tedious performance optimizations. I'm a big fan.
The one issue preventing me from using this more is support for external images.
Currently, jampack will add decoding="async" loading="lazy" to an externally referenced image which is an excellent start. I'd love a CLI option to process external images further.
At a minimum, I'm looking to add missing width/height attributes without touching the src. Even better (or as an option) is downloading the external image, processing it, and changing the src to serve it locally.
Would you happen to have any thoughts about this?
Hi there, I really love jampack and we use it in production (see https://github.com/Stadt-Geschichte-Basel/stadtgeschichtebasel.ch). Cloudflare automatically compresses the contents of our page with GZIP and Brotli (see https://developers.cloudflare.com/speed/optimization/content/brotli/content-compression/). Could this be integrated into jampack? SvelteKit has a nice implementation https://github.com/sveltejs/kit/blob/main/packages/kit/src/core/adapt/builder.js#L214 using https://nodejs.org/api/zlib.html.
devDependencies:
WARN Issues with peer dependencies found
.
└─┬ @divriots/jampack 0.22.1
└─┬ quicklink 2.3.0
├── ✕ unmet peer react@^16.8.0: found 18.2.0
└── ✕ unmet peer react-dom@^16.8.0: found 18.2.0
media queries using range context syntax are getting stripped
in (index.css)
@media (width >= 500px) {
h1 { font-size: 2em; }
}
bennypowers.dev on decks/brno/content [$!?] via v18.16.0
❯ cat _site/index.css | grep media (base)
before jampack:
<link rel="stylesheet" media="(prefers-color-scheme: light)" href="/assets/theme-light.css">
<link rel="stylesheet" media="(prefers-color-scheme: dark)" href="/assets/theme-dark.css">
after jampack
<link rel="stylesheet" media="" href="/assets/theme-light.css">
<link rel="stylesheet" media="" href="/assets/theme-dark.css">
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.