Giter Club home page Giter Club logo

unpic-img's Introduction

🌳 unpic-img

A cross-framework component for responsive, high-performance images using image CDNs

Features

  • Just an <img> tag! No extra elements, no runtime JavaScript. Easy to style. No legacy hacks or workarounds.
  • Automatically generates correct srcset and sizes attributes for responsive images.
  • Handles responsive resizing of images, preserving aspect ratio and avoiding layout shift.
  • Uses native lazy loading and async decoding for offscreen images.
  • Handles different image layouts: fixed, constrained and full width.
  • Uses eager loading and high priority fetching for important images.
  • Delivers modern image formats, including WebP and AVIF if supported by the browser.
  • No build step or server-side rendering required for the images: uses your existing image CDN or CMS, with no additional configuration.
  • Uses unpic lib to support most image CDNs, including Cloudinary, Imgix, and Shopify.
  • Can generate a low-res background image for a blurred placeholder effect, or use with @unpic/placeholder for more options.

Usage

For details of usage, see the documentation.

FAQ

Why do I need this?

While it's easy to use an <img> tag for images, if you want to follow best practices and deliver the most performant image to your users then it can take a lot of work. Some frontend frameworks will automate this for you, but they often rely on slow pre-rendering of images, or on running image optimizers on your own site. They also generate complex HTML with wrappers and spacer elements that make images hard to style.

Most images on modern websites are hosted on a CDN or CMS that can resize images on the fly and deliver them at the edge. Despite this, most web frameworks will still download and resize the image at build time or on your server, rather than using the CDN, or just uses a single source image rather than handling multiple resolutions.

This library works with any frontend framework or none, and uses your existing image CDN or CMS, with no additional configuration.

For more details, see this post.

How does this work?

This library uses unpic to detect the image CDN, and then uses the CDN's URL API to resize and format images. It then generates the correct srcset and sizes attributes for the image. It uses new features built into modern browsers to handle lazy loading, fetch priority and decoding. It also uses pure CSS to handle responsive resizing of images, preserving aspect ratio and avoiding layout shift. Unlike most other image components, it does not use any client-side JavaScript by default, and generates just a single <img> tag without any wrapper divs or padding elements.

What HTML does this generate?

Generated HTML for a constrained image It turns this:
<Image
  src="https://cdn.shopify.com/static/sample-images/bath_grande_crop_center.jpeg"
  layout="constrained"
  width={800}
  height={600}
  alt="Shopify"
/>

...into this:

<img
  alt="Shopify"
  loading="lazy"
  decoding="async"
  sizes="(min-width: 800px) 800px, 100vw"
  srcset="
    https://cdn.shopify.com/static/sample-images/bath.jpeg?crop=center&amp;width=1600&amp;height=2133 1600w,
    https://cdn.shopify.com/static/sample-images/bath.jpeg?crop=center&amp;width=1280&amp;height=1707 1280w,
    https://cdn.shopify.com/static/sample-images/bath.jpeg?crop=center&amp;width=1080&amp;height=1440 1080w,
    https://cdn.shopify.com/static/sample-images/bath.jpeg?crop=center&amp;width=960&amp;height=1280   960w,
    https://cdn.shopify.com/static/sample-images/bath.jpeg?crop=center&amp;width=828&amp;height=1104   828w,
    https://cdn.shopify.com/static/sample-images/bath.jpeg?crop=center&amp;width=800&amp;height=1067   800w,
    https://cdn.shopify.com/static/sample-images/bath.jpeg?crop=center&amp;width=750&amp;height=1000   750w,
    https://cdn.shopify.com/static/sample-images/bath.jpeg?crop=center&amp;width=640&amp;height=853    640w
  "
  src="https://cdn.shopify.com/static/sample-images/bath.jpeg?width=800&amp;height=600&amp;crop=center"
  style="
        object-fit: cover;
        max-width: 800px;
        max-height: 600px;
        aspect-ratio: 1.33333 / 1;
        width: 100%;
      "
/>

Supported CDNs

You can use any image CDN supported by unpic lib, including:

  • Adobe Dynamic Media (Scene7)
  • Builder.io
  • Bunny.net
  • Cloudflare
  • Contentful
  • Cloudinary
  • Directus
  • Imgix, including Unsplash, DatoCMS, Sanity and Prismic
  • Kontent.ai
  • Netlify
  • Shopify
  • Storyblok
  • Vercel / Next.js
  • WordPress.com and Jetpack Site Accelerator

License

Published under the MIT licence. © Matt Kane 2023.

unpic-img's People

Contributors

ascorbic avatar aurelienbobenrieth avatar benmccann avatar bertybot avatar chrislarocque avatar colbyfayock avatar danestves avatar davedbase avatar dummdidumm avatar eladroz avatar eshlox avatar github-actions[bot] avatar huang-julien avatar jlarmstrongiv avatar leanderg avatar mixie-bot[bot] avatar monsterdeveloper avatar mrkiffie avatar patdx avatar renovate[bot] avatar rjbeers avatar ruijdacd avatar seancdavis avatar steve8708 avatar ydoc118 avatar zachleat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

unpic-img's Issues

Portrait images seem to get flipped into landscape in srcset

Describe the bug
It seems that using a sufficently portrait aspect-ratio image will create a srcset that has width and height flipped. All other props on the image are right, but it means that it'll produce small crops of the image inside the element

To Reproduce
Steps to reproduce the behavior:

  1. I'm using React, so use the react library
  2. Load a portrait-orientation image. Mine specifically 523x723. The CDN is Contentful
  3. Set width and height to the values above.
  4. Set layout to constrained
  5. See that the img element is the right size, but you have a weirdly stretched out cropped of the image in its place.

Expected behavior
The image looks correct.

Screenshots
Sorry, I can't share the image we're using at the moment

Desktop (please complete the following information):

  • OS: Mac
  • Browser Testing in Chrome and Safari
  • Version: Latest

Additional context
I feel that something is going wrong with getSrcset but I haven't been able to figure out why just yet

Add support for WebC

The pattern of taking all props from a parent, passing some to the helper funciton and then spreading them into the child component is hard to do with rendered components in WebC right now. Once 11ty/webc#104 is implemented then we can add support for WebC

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (automergeLinters)

srcset attribute is broken in version 0.0.23 with Directus cdn

Describe the bug
srcset attribute is broken in version 0.0.23 of unpic/svelte with Directus cdn, worked in version 0.0.22.
Instead of desugaring to multiple comma separated sources in the srcset attribute, it fallbacks to a single src attribute.

To Reproduce
Steps to reproduce the behavior:

  1. Just duplicate the basic svelte/unpic component example and provide a Directus url
  2. Set the cdn prop to Directus

Expected behavior
srcset attribute should be rendered with multiple sources

Desktop (please complete the following information):

  • osX 13.3.1 - all browsers

Additional context
Note that the src passed to the component is still parsed and processed since it adds a ?width query string at the end.

Angular support

I'd very much like to support Angular, but I'm finding it hard to do. If anyone wants to contribute one then please let me know. It would be much appreciated.

unpic-svelte cause Vite ReferenceError: exports is not defined with style-object-to-css-string pacakge

Describe the bug
I'm buiding a component library, one of the component use unpic-svelte
After successfully packaging the library with sveltekit package mode I try to use it locally through pnpm link

When running the application that will use the component library I gest this

[vite] Error when evaluating SSR module /@fs/Users/matias/Development/MyLibrary/node_modules/.pnpm/@[email protected][email protected]/node_modules/@unpic/svelte/dist/image.svelte: failed to import "/@fs/Users/matias/Development/MyLibrary/node_modules/.pnpm/[email protected]/node_modules/style-object-to-css-string/dist/index.js"
|- ReferenceError: exports is not defined
    at eval (/@fs/Users/matias/Development/MyLibrary/node_modules/.pnpm/[email protected]/node_modules/style-object-to-css-string/dist/index.js:5:23)
    at instantiateModule (file:///Users/matias/Development/MyLibrary/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-f7d05e3f.js:54346:15)

To Reproduce
Steps to reproduce the behavior:

  1. Crea a fresh sveltekit app
  2. Install unpic-svelte
  3. Create a component inside src/lib/components/MyImage.svelte that uses unpic
  4. run pnpm package
  5. Create another svelkit app.
  6. run pnpm link <path-to-the-original-project>
  7. import the package into the new app
  8. run the new app

Expected behavior
The component imported from the "source" app should work correctly.

Screenshots

Desktop (please complete the following information):

  • OS: Macos
  • Browser chrome, safari, Arc

`transformer` is rendered as attributes in `@unpic/vue`

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.
image

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
related : nuxt-modules/cloudinary#181

How to use unpic vue with `transformer`?

Hey!

I tried using the unpic vue package and specifically the Image component in my module and it works quite well but I have an issue with using the transformer.

Could you tell me how to use it? I couldn't find any examples of that in the docs. I saw the usage of it for different framework like Svelte but the syntax is a bit different for vue so I am not sure how to make it work :)

objectFit props @unpic/solid

Describe the bug
The objectFit props isn't documented. And by default it resolves to cover, even overrides styles provided via class attribute.

To Reproduce
Steps to reproduce the behavior:

  1. Create a solid start project https://start.solidjs.com/getting-started/project-setup
  2. Install @unpic/solid
  3. Use Image component
    I'm using macron-css for styling. But I guess css module will also work.
<Image
        src={props.img.src}
        background={props.img.placeholder}
        layout="fullWidth"
        class={style({
          border: `2px solid ${vars.color.gray[300]}`,
          borderRadius: vars.space[5],
          objectFit: "contain",
        })}
      />
  1. Inspect element. The object-fit: contain gets overridden

Expected behavior
img element should have object-fit: contain

Screenshots

Issue:
Screenshot 2023-07-03 at 12 05 09 PM

Temporary Fix:

Screenshot 2023-07-03 at 12 05 27 PM

Add params prop

Thanks for your great work on the unpic package. I appreciate the effort to solve image handling for everyone.

However, I find the limitation to only the most common parameters a bit restrictive. I'm looking to implement custom cropping with the Sanity CDN. Could we introduce a params prop for custom parameters? These would be added to the URL and ignored if the chosen/detected CDN doesn't support them.

Or else, how would you suggest I could go about supporting a custom crop for images?

Cap images for > 2x DPR screens and use quality to reduce file size

Describe the bug
The used srcset technique makes high-DPR devices download too big images, see the screenshots below.
At a screen width of 390px, for a 3x DPR screen (e.g. iPhone 12), it should download e.g. 750w, not 800w. For the example image, the difference is 80.8 kB -> 77.6 kB.

While 4.2 kB is not the end of the world, I do think the images are not compressed enough. Most image CDNs listed here support a quality parameter, which would drastically reduce the file size. See: https://jakearchibald.com/2021/serving-sharp-images-to-high-density-screens/

If you wonder why I say the iPhone 12 should download 750w and not 800w: https://www.andreaverlicchi.eu/capping-image-fidelity-2x-minimize-loading-time/ and a study from Cloudinary: https://observablehq.com/@eeeps/visual-acuity-and-device-pixel-ratio.
We reach a point where humans no longer see the difference, thus the additional resolution are wasted kB's. Yoav Weiss proposed to cap at 2-2.2x in Chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=1125973. So for 3x DPR screens, or even 4x DPR, loading 2x is enough to have very crisp image.

To Reproduce
Steps to reproduce the behavior:

  1. Paste the example HTML in the readme into e.g. a new Codepen
  2. Open Dev Tools, use responsive mode and set it to iPhone 12
  3. Use e.g. $0.currentSrc to find which image is currently rendered

Expected behavior

  • Images are capped at 2x dimensions
  • File size is reduced when applicable

Screenshots
image

Additional context
I've written a lengthy blog post here about this topic: https://kurtextrem.de/posts/modern-way-of-img.
<img srcset> sadly makes this a bit complicated if you compare it to the <picture> tag like used by Jake Archibald, but it is definitely possibly to control which image is loaded by using a more complex sizes attribute (which I call boolean <img> as it toggles the image around like a boolean).

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • chore(deps): update all non-major dependencies (@astrojs/react, @sveltejs/kit, @testing-library/react, @typescript-eslint/eslint-plugin, @typescript-eslint/parser, astro, solid-js, undici, vite, vue, vue-tsc)

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/e2e.yml
  • actions/checkout v4
  • actions/setup-node v4
  • actions/upload-artifact v4
  • actions/checkout v4
  • actions/setup-node v4
  • actions/download-artifact v4
  • actions/upload-artifact v4
.github/workflows/release-please.yml
  • navikt/github-app-token-generator v1
  • google-github-actions/release-please-action v4
  • actions/checkout v4
  • actions/setup-node v4
.github/workflows/semantic-prs.yml
  • amannn/action-semantic-pull-request v5
  • marocchino/sticky-pull-request-comment v2
  • marocchino/sticky-pull-request-comment v2
.github/workflows/test.yml
  • actions/checkout v4
  • actions/setup-node v4
npm
docs/package.json
  • @algolia/client-search ^4.23.3
  • @astrojs/mdx ^2.3.1
  • @astrojs/preact ^3.2.0
  • @astrojs/react ^3.3.0
  • @astrojs/rss ^4.0.5
  • @astrojs/sitemap ^3.1.4
  • @docsearch/css ^3.6.0
  • @docsearch/react ^3.6.0
  • @preact/signals ^1.2.3
  • @types/node ^20.12.7
  • @types/react ^18.2.79
  • @types/react-dom ^18.2.25
  • @unpic/placeholder ^0.1.2
  • astro ^4.6.3
  • astro-icon ^0.8.2
  • blurhash ^2.0.5
  • pako ^2.1.0
  • preact ^10.20.2
  • prism-react-renderer ^2.3.1
  • react ^18.2.0
  • react-dom ^18.2.0
  • react-live ^4.1.6
  • @types/pako ^2.0.3
  • html-escaper ^3.0.3
package.json
  • unpic ^3.18.0
  • @netlify/plugin-nextjs 5.1.2
  • @playwright/test ^1.43.1
  • @testing-library/dom ^10.0.0
  • @testing-library/svelte ^4.2.3
  • @typescript-eslint/eslint-plugin ^7.7.0
  • @typescript-eslint/parser ^7.7.0
  • eslint ^8.57.0
  • eslint-config-prettier ^9.1.0
  • jsdom ^24.0.0
  • npm-run-all2 ^6.1.2
  • prettier ^3.2.5
  • prettier-plugin-astro ^0.13.0
  • process ^0.11.10
  • publint ^0.2.7
  • typescript ^5.4.5
  • vite ^5.2.9
  • vitest ^1.5.0
  • cssstyle ^4.0.1
  • pnpm 8.15.7
packages/angular/package.json
  • tslib ^2.6.2
  • @angular-devkit/build-angular ^17.3.5
  • @angular/cli ~17.3.5
  • @angular/compiler-cli ^17.3.5
  • @angular/core ^17.3.5
  • ng-packagr ^17.3.0
  • publint ^0.2.7
  • typescript 5.4.5
packages/astro/package.json
  • @unpic/pixels ^1.2.2
  • @unpic/placeholder ^0.1.2
  • blurhash ^2.0.5
  • astro ^4.6.3
  • astro ^2.0.0 || ^3.0.0 || ^4.0.0
packages/core/package.json
  • unpic ^3.18.0
  • tsup ^8.0.2
  • vitest ^1.5.0
  • pnpm 8.15.7
packages/lit/package.json
  • lit ^3.1.3
  • publint ^0.2.7
  • web-component-analyzer 2.0.0
  • lit ^2.0.0 || ^3.0.0
packages/preact/package.json
  • @testing-library/preact ^3.2.3
  • preact ^10.20.2
  • tsup ^8.0.2
  • typescript ^5.4.5
  • vitest ^1.5.0
  • preact *
packages/qwik/package.json
  • @builder.io/qwik 1.5.2
  • @types/eslint 8.56.10
  • @types/node ^20.12.7
  • @types/node-fetch ^2.6.11
  • @typescript-eslint/eslint-plugin 7.7.0
  • @typescript-eslint/parser 7.7.0
  • eslint 8.57.0
  • eslint-plugin-qwik ^1.5.2
  • node-fetch 3.3.2
  • np 10.0.5
  • prettier ^3.2.5
  • typescript 5.4.5
  • undici 6.13.0
  • vite 5.2.9
  • vitest ^1.5.0
  • @builder.io/qwik *
  • node >=16.8.0 <18.0.0 || >=18.11
packages/react/package.json
  • @arethetypeswrong/cli ^0.15.3
  • @testing-library/react ^15.0.2
  • @types/node ^20.12.7
  • @types/react ^18.2.79
  • @types/react-dom ^18.2.25
  • @vitejs/plugin-react ^4.2.1
  • cssstyle ^4.0.1
  • jsdom ^24.0.0
  • next ^14.2.2
  • publint ^0.2.7
  • react ^18.2.0
  • react-dom ^18.2.0
  • tsup ^8.0.2
  • typescript ^5.4.5
  • vitest ^1.5.0
  • next ^14.0.0
  • react ^17.0.0 || ^18.0.0
  • react-dom ^17.0.0 || ^18.0.0
packages/solid/package.json
  • @solidjs/testing-library ^0.8.7
  • esbuild ^0.20.2
  • esbuild-plugin-solid ^0.5.0
  • jsdom ^24.0.0
  • prettier ^3.2.5
  • solid-js ^1.8.16
  • tsup ^8.0.2
  • tsup-preset-solid ^2.2.0
  • typescript ^5.4.5
  • vite ^5.2.9
  • vite-plugin-solid ^2.10.2
  • vitest ^1.5.0
  • solid-js ^1.0.0
packages/svelte/package.json
  • style-object-to-css-string 1.1.3
  • unpic ^3.18.0
  • @sveltejs/adapter-auto ^3.2.0
  • @sveltejs/kit ^2.5.6
  • @sveltejs/package ^2.3.1
  • @sveltejs/vite-plugin-svelte ^3.1.0
  • prettier ^3.2.5
  • prettier-plugin-svelte ^3.2.3
  • svelte ^4.2.15
  • svelte-check ^3.6.9
  • tslib ^2.6.2
  • typescript ^5.4.5
  • vite ^5.2.9
  • vitest ^1.5.0
  • svelte *
packages/vue/package.json
  • vue ^3.4.23
  • @testing-library/vue ^8.0.3
  • @vitejs/plugin-vue ^5.0.4
  • tsup ^8.0.2
  • typescript ^5.4.5
  • vite ^5.2.9
  • vitest ^1.5.0
  • vue-tsc ^2.0.13
packages/webc/package.json
  • style-object-to-css-string 1.1.3
  • @11ty/webc ^0.11.4
  • @types/jsdom ^21.1.6
  • jsdom ^24.0.0
  • vitest ^1.5.0
  • @11ty/webc >=0.9.0
  • pnpm 8.15.7
nvm
.nvmrc
  • node 20.12.2

  • Check this box to trigger a request for Renovate to run again on this repository

placeholder support

Is your feature request related to a problem? Please describe.
It's important to show our visitor the image is still loading. Hence, adding placeholder which can fiiled with animated svg would be nice for our visitors.

Describe the solution you'd like
Nuxt Image Placeholder-like would be nice if added here.

Wong computation of `lowResHeight`

There is an issue in the computation of the lowResHeight with aspectRatio. There is a multiplication whereas it should be a division.

https://github.com/ascorbic/unpic-img/blob/main/packages/core/src/core.ts#L404

(pretty much just like it's done there: https://github.com/ascorbic/unpic-img/blob/main/packages/core/src/core.ts#L384)

    const lowResHeight = aspectRatio
      ? Math.round(LOW_RES_WIDTH * aspectRatio) // ❌
      : undefined;

should be

    const lowResHeight = aspectRatio
      ? Math.round(LOW_RES_WIDTH / aspectRatio) // ✅
      : undefined;

Given a width of 24 and an aspect ratio of 16/9, the height should be 13.5 and not 42.6 (like it is actually returned) else the aspect ratio is reversed.

src gets double transformed with srcset

Describe the bug

During transformProps, the src is first transformed with the results overwriting src, then transformed a second time as part of getSrcSet.

const transformed = transformer({ url: src, width, height });
if (transformed) {
src = transformed.toString();
}
props.srcset = getSrcSet({
src,

This works when passing in a standard URL format, but if passing in an ID such as my-cool-image, it ends up creating an issue where the base URL is applied twice.

Example:

https://res.cloudinary.com/example/image/upload/c_limit,w_750/f_auto/q_auto/https://res.cloudinary.com/example/image/upload/c_limit%252Cw_800/f_auto/q_auto/cld-sample-5%3F_a%3DATFGlAA0

Use Case

My use case here is using a custom transformer to perform my own operations for constructing a URL:

<Image
  src="cld-sample-5"
  layout="constrained"
  width={800}
  height={600}
  alt="A lovely bath"
  transformer={({url, width, height,}) => {
    return constructCloudinaryUrl({
      options: {
        src: url,
        width,
        height
      },
      config: {
        cloud: {
          cloudName: 'example'
        }
      }
    });
  }}
/>

The produced src attribute is accurate on that first run, but all srcset URLs have an issue.

I know this isn't the primary use case but from what I can tell, I'm not seeing any actual benefit of having that second pass of the transformer

Example Output

<img alt="A lovely bath" loading="lazy" decoding="async" sizes="(min-width: 800px) 800px, 100vw" style="object-fit:cover;max-width:800px;max-height:600px;aspect-ratio:1.3333333333333333;width:100%" srcset="https://res.cloudinary.com/example/image/upload/c_limit,w_640/f_auto/q_auto/https://res.cloudinary.com/example/image/upload/c_limit%252Cw_800/f_auto/q_auto/cld-sample-5%3F_a%3DATFGlXu0 640w,
https://res.cloudinary.com/example/image/upload/c_limit,w_750/f_auto/q_auto/https://res.cloudinary.com/example/image/upload/c_limit%252Cw_800/f_auto/q_auto/cld-sample-5%3F_a%3DATFGlXu0 750w,
https://res.cloudinary.com/example/image/upload/c_limit,w_800/f_auto/q_auto/https://res.cloudinary.com/example/image/upload/c_limit%252Cw_800/f_auto/q_auto/cld-sample-5%3F_a%3DATFGlXu0 800w,
https://res.cloudinary.com/example/image/upload/c_limit,w_828/f_auto/q_auto/https://res.cloudinary.com/example/image/upload/c_limit%252Cw_800/f_auto/q_auto/cld-sample-5%3F_a%3DATFGlXu0 828w,
https://res.cloudinary.com/example/image/upload/c_limit,w_960/f_auto/q_auto/https://res.cloudinary.com/example/image/upload/c_limit%252Cw_800/f_auto/q_auto/cld-sample-5%3F_a%3DATFGlXu0 960w,
https://res.cloudinary.com/example/image/upload/c_limit,w_1080/f_auto/q_auto/https://res.cloudinary.com/example/image/upload/c_limit%252Cw_800/f_auto/q_auto/cld-sample-5%3F_a%3DATFGlXu0 1080w,
https://res.cloudinary.com/example/image/upload/c_limit,w_1280/f_auto/q_auto/https://res.cloudinary.com/example/image/upload/c_limit%252Cw_800/f_auto/q_auto/cld-sample-5%3F_a%3DATFGlXu0 1280w,
https://res.cloudinary.com/example/image/upload/c_limit,w_1600/f_auto/q_auto/https://res.cloudinary.com/example/image/upload/c_limit%252Cw_800/f_auto/q_auto/cld-sample-5%3F_a%3DATFGlXu0 1600w" src="https://res.cloudinary.com/example/image/upload/c_limit,w_800/f_auto/q_auto/cld-sample-5?_a=ATFGlXu0">

Options

Work with it as is

I could theoretically construct my image first then pass that in:

const url = constructCloudinaryUrl({
  options: {
    src: 'cld-sample-5',
    width: 800,
    height: 600
  },
  config: {
    cloud: {
      cloudName: 'example'
    }
  }
})

<Image
  src={url}
  layout="constrained"
  width={800}
  height={600}
  alt="A lovely bath"
/>

This seems to work, but then in my mind it's doing double the work, where really i want to use my own transformer logic, and unpic will always sit on top of that

Prevent a 2nd pass of src

Move the src transformation:

const transformed = transformer({ url: src, width, height });
if (transformed) {
src = transformed.toString();
}

Below the srcSet:

props.srcset = getSrcSet({

This works and doesn't break any tests (but maybe we should write a test for that?)

Unscientifically test this by hacking at the node_modules directory in a sample Next.js app with React

To Reproduce

Pass in a non-URL as the src with a custom transformer:

import { constructCloudinaryUrl } from '@cloudinary-util/url-loader';

<Image
  src="cld-sample-5"
  layout="constrained"
  width={800}
  height={600}
  alt="A lovely bath"
  transformer={({url, width, height,}) => {
    return constructCloudinaryUrl({
      options: {
        src: url,
        width,
        height
      },
      config: {
        cloud: {
          cloudName: 'example'
        }
      }
    });
  }}
/>

Expected behavior

the resulting URL wouldn't be double-"transformed" or at least not create a URL issue

Desktop (please complete the following information):**

  • OS: [e.g. iOS] Mac
  • Browser [e.g. chrome, safari] Chrome
  • Version [e.g. 22] Version 111.0.5563.64 (Official Build) (arm64)

How can i add viewTransitionName to Image component in React?

How can I enhance my React application by incorporating the viewTransitionName property into the Image component for using View Transition API?

For example:

 <Image
    width={200}
    height={240}
    src={product.defaultImage || ''}
    alt={product.title}
    layout="constrained"
    style={{
      viewTransitionName="image-expand"
    }}
  />

Malformed data-attributes

Describe the bug
When passing data attributes, the output is either ignored (passing boolean) or malformed.

To Reproduce
CodeSandbox repro

Expected behavior
Any props supported by the <img> tags can be passed in and should work as expected.

Screenshots
CleanShot 2023-05-10 at 11 36 54@2x

Warning: React does not recognize the `fetchPriority` prop on a DOM element

Describe the bug

Warning: React does not recognize the `fetchPriority` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `fetchpriority` instead. If you accidentally passed it from a parent component, remove it from the DOM element.
    at img
    at Image2 (file:///Users/user/Desktop/projects/project/node_modules/@unpic/react/dist/chunk-W7EQS7E7.mjs:30:42)

To Reproduce

        <UnpicReactImage
          priority
          layout="constrained"
          width={1023}
          height={682}
          src="/static/assets/images/owl.jpg"
          alt="Owl"
          cdn="astro"
        />

Expected behavior
No warnings logged to the console

Desktop (please complete the following information):

  • OS: macOS
  • Browser: Chrome
  • Version: 0.0.23

I suppose the solution is using fetchpriority instead of fetchPriority for now

Disable console.error message

Describe the bug
Most of the time I can't set the width, height or aspect-ratio via component props (React version), since they are based on media queries. It however still works when set via CSS. The logging of the errors however makes the Image basically unusable since it clutters completely the dev tools with multiple images on a page

Question about <picture> for WebP/AVIF support

This is more of a curiosity than a feature request and might be limited by my own understanding as responsive images can melt the brain a bit!

Is your feature request related to a problem? Please describe.
I'm using Contentful and I've done some basic experiments with unpic-img and the results are good, however, I was rather hoping to automatically serve the more optimised formats like webp and avif where applicable. It seems that the Contentful API image formatting parameter doesn't accept auto like some of the other CDNs do, which allows them to pick the right format at request time (I think?!), so the alternative is to use the <picture> element and drop in the avif and webp paths as <source> elements before the <img>... (see Salma's responsive image React component for inspiration)

Describe the solution you'd like
Not too sure as it might be more of Contentful's problem, but perhaps an exported Picture (if it's JS/React, <unpic-picture> for WebC maybe) with some options for opting in the additional formats.

Describe alternatives you've considered
Rolling my own component like Salma's referenced above is an option of course, but the Unpic API is very nice, so would be a shame to not use it! It seems like the heavy-lifting is generating the srcsets and that's already done, so maybe adding the <source> options is straight forward, but I could be very naive and trying to make this component do too much and it varies quite wildly between the CDNs I think...?

@unpic/svelte throws error "Cannot use import statement outside a module"

Describe the bug
When using the unpic <Image /> Svelte component, it throws this error.
I use both Astro and Svelte components in an Astro project and funny enough, @unpic/astro has no error.

error Cannot use import statement outside a module
/Users/flayks/sites/portfolio/node_modules/.pnpm/[email protected]/node_modules/style-object-to-css-string/dist/index.es.js:1
import { camelToKebab as t } from "./parsers/index.es.js";

To Reproduce
Import the Image component normally, here is my code:

<script lang="ts">
    import { Image } from '@unpic/svelte'
</script>

<Image
    src="{card.url}?q=85"
    alt={card.alt}
    layout="constrained"
    width={card.width}
    height={card.width * cardRatio}
    breakpoints={[320, 550]}
    sizes="(max-width: 550px) 64vw, 28vw"
    priority
/>

Expected behavior
It should have no error and work as intended

Desktop (please complete the following information):

  • OS: macOS
  • Browser Arc / Chromium
  • Version 1.15.2 (43100) - Chromium Engine Version 119.0.6045.123

Additional context
Add any other context about the problem here.

Angular: Add standalone versions of Unpic directives

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

The UnpicModule is used to import the UnpicImageDirective and UnpicSourceDirective directives

Describe the solution you'd like
A clear and concise description of what you want to happen.

The UnpicImageDirective and UnpicSourceDirective directives are exported as standalone directives that can also be used inside the UnpicModule.

Standalone components/pipes/directives have been out since Angular v14 and are the default and recommended way going forward.

This would be solved by adding standalone: true to the directive decorator metadata, and moving the directives from the declaratations array in the UnpicModule to the imports array.

The exports array would remain the same. The public API would remain the same also.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Installing unpic in a next.js project causes module not found error

Hey Matt Thanks for all hard work and excited for the future of unpic 👍 .

Describe the bug
Installing and using @unpic/react in a next.js project cause module not found error.

More details: I first tried to use @unpic/react in my personal project and I got the Cannot find module. Then I tried with a next nextjs project and got module not found error. Thought it's not the same module..... I think.

To Reproduce
Steps to reproduce the behavior:

  1. Install @unpic/react
  2. use the same example form the next.js example documentation.
  3. See sandbox for reference. https://codesandbox.io/p/sandbox/distracted-wood-j0jjcw?file=%2Fpages%2Findex.tsx

Expected behavior
To be working without errors

Screenshots
image

image

Developer/DX a bit awkward for providing your own CDN detectors

Is your feature request related to a problem? Please describe.
I've been reading through the magic behind how the CDNs are detected and it seems that the logic is hardcoded on a basis of:

  • Prefixes
  • Domains
  • Subdomains

There's 2x assumptions that are causing me grief:

  • Imgix is either a hardcoded list of domains, or it's when you have a domain like: mysite.imgix.net
  • Cloudflare images are prefixed with: /cdn-cgi/image//

Cloudflare
In the case of Cloudflare, your image doesn't need to start with /cdn-cgi/image// - only when an optimisation is actually added on top. So from a developer perspective, it would be nice if I could specify my own domain to tell unpic what is being routed through Cloudflare.

Now when it comes to transforming the URL, it's simple logic to add:

const url = new URL(src);
const args = [...];
return `${url.hostname}/cdn-cgi/image/${args.join(',')}/${url.pathname}`;

Was doing this myself before attempting to use unpic. I thought ok I just need to provide the cdn:

export function getDetectedCdn(src: string) {
  if (src.startsWith('https://imgix.')) {
    return 'imgix';
  }
  
  return 'cloudflare';
}

<Image cdn={getDetectedCdn(src)} src={src} />

And now it throws, because the url doesn't match the hardcoded regex for Cloudflare URLs. Another hack I could do to get around it is by find/replacing my URLs beforehand so it adheres to the regex I suppose.

Imgix
In the case of imgix, it assumes that it's either a hardcoded list of domains or that it ends in imgix.net and doesn't support custom domains. We actually have Cloudflare sitting in front of Imgix so that we can reduce costs by caching for free there. It would be easy if we could just specify how to detect the CDN using the domain: https://imgix.mysite.com.

Describe the solution you'd like

  • Cloudflare transformer shouldn't assume /cdn-cgi/image/ exists and it could be added dynamically
  • Since it can't detect imgix, we've had to re-implement the transformer and pass that into the src property, and it would be nice to just use the transformer used by this library (if it was exported... think not?)
  • It could be easier to provide a set of detectors and transformers (provide either the original transformer or replace with your own)

Requirement to add external hostnames to Next.js config

Describe the bug
Hostnames for images loaded from external sites need to be declared in Next.js config.
Not doing so prevents the image from loading and doesn't produce an error, unlike next/image.

To Reproduce
Steps to reproduce the behavior:

  1. Create a fresh Next.js project
  2. Add an with src as any external URL.
  3. Image does not load.

Expected behavior
An error occurs telling the user to add the image hostname to the Next config.
Similar to next/image.

Desktop (please complete the following information):

  • OS: macOS
  • Browser: Chrome
  • Version: 113

Module not found with Next.js 14

Describe the bug
The same as #118 with a different cause.

Seems like this is caused by Next changing the next/dist/shared/lib/image-config-context.js file to next/dist/shared/lib/image-config-context.shared-runtime.js.

Changing that seems to fix it.

I'm not sure when this might have happened but might be Next 14.

Src is required to be a CDN URL for srcset generation

Description

We're currently attempting to use the transformer prop as the mechanism to construct URLs using our own utilities.

When doing this, we're using the src attribute as a public ID, where the API of the component we're building does just that, so we're passing that value in, and allowing the transformer to piece together the src (Public ID), width, and height, along with some other props, to construct the URL.

The issue we're running into is by not passing in a fully formed CDN URL into the src prop, we seem to be bypassing the srcset generation, at least thats my current suspicion.

https://github.com/ascorbic/unpic-img/blob/main/packages/core/src/core.ts#L296

That said, if we pass in a constructed base URL into the src then still define our custom transformer for the rest of the generated URLs, we seem to get a working version.

This isn't necessarily the way this component was designed to be used, but I'm curious if this use case is able to be satisfied by recognizing a custom defined transformer that wouldn't require a canonical URL.

While this would immediately help my use case, I could also see this able to give more flexibility for using the component for custom patterns that might not make it as part of official support, though I recognize that's certainly an edge case.

Here's the current code that we're working with:

https://github.com/cloudinary-community/svelte-cloudinary/pull/16/files#diff-3563ec9de2b673c6456b0e69471f7845227183497dada6a5bb2d503d98ea0d8bR71

To Reproduce

Our ideal Unpic component code would look along the lines of:

<Image
  src="myid"
  width="600"
  height="600"
  alt="Text"
  transformer={({ width, height, url }) => {
    return imageFunction({
      src: url, // "myid"
      width,
      height,
      ...extraProps
    })
  }}
/>

This however does not generate a srcset.

image

Possible Solution

Given this line will use either the custom passed in transformer or find the appropriate one:

https://github.com/ascorbic/unpic-img/blob/main/packages/core/src/core.ts#L302C3-L302C49

If the transformer prop is indeed custom, the canonical check could be skipped.

Could be something along the lines of:

  const canonical = getCanonicalCdnForUrl(src, cdn);

  // No canonical URL found and there is NOT a custom transformer to satisfy it

  if (!canonical && !transformer) { 
    return;
  }

  transformer ||= getTransformer(canonical.cdn);

  if (!transformer) {
    return;
  }

Cannot build using `unpic/astro` when `output: 'server'` in Astro config

Describe the bug
I figured that I couldn't build my Astro site, and for some reason it was coming from undici. Looking at the lockfile, it is used by Unpic, then breaks the build when using the server output.

To Reproduce
Use Unpic for Astro for images with the following Astro config:

export default defineConfig({
    output: 'server',
    adapter: cloudflare({
        // mode: 'directory',
    }),

It might be linked to Cloudflare as well?

Repro URL: https://stackblitz.com/edit/withastro-astro-mxdlug?file=src%2Fpages%2Findex.astro

Expected behavior
It should build normally without error

Issue with Qwik, Vite and Vercel deployment

I followed Qwik integration documentation, and build worked locally but when deployed to Vercel I got the following error:
on command pnpm run build:

Error: [vite]: Rollup failed to resolve import "@unpic/core" from "/vercel/path0/src/s_w1wzaavnrf0.js".

I assume its related to vite configuration and not the core unpic-img library, but it would be great if a solution to this was documented in the readme as well.

Thanks

Astro types broken

image
../../node_modules/@unpic/astro/index.ts:4:34 - error TS2307: Cannot find module './src/Image.astro' or its corresponding type declarations.

4 export { default as Image } from "./src/Image.astro";
                                   ~~~~~~~~~~~~~~~~~~~

../../node_modules/@unpic/astro/index.ts:5:35 - error TS2307: Cannot find module './src/Source.astro' or its corresponding type declarations.

5 export { default as Source } from "./src/Source.astro";
                                    ~~~~~~~~~~~~~~~~~~~~


Found 2 errors in the same file, starting at: ../../node_modules/@unpic/astro/index.ts:4

npm ERR! Lifecycle script `typecheck` failed with error:
npm ERR! Error: command failed

Solutions

  • Using the astrojs/ts-plugin
  • Using @ts-ignore in the typescript index files passes the tests, while still providing types in the editor

Unpic causes a build failure to a fresh SolidStart install

Describe the bug
A clean Solid start install has a build issue with unpic

the project builds as expected without unpic

To Reproduce
Steps to reproduce the behavior:

  1. Npm init solid@latest'
  2. npm install
  3. npm install @unpic/solid
  4. place your Solid example code in index.tsx
  5. npm run build
Circular dependency: node_modules/unpic/esm/src/transform.js -> node_modules/unpic/esm/src/transformers/vercel.js -> node_modules/unpic/esm/src/transform.js
file:////node_modules/rollup/dist/es/shared/node-entry.js:2125
        base = Object.assign(new Error(base.message), base);

Error [RollupError]: "template" is not exported by "node_modules/solid-js/web/dist/server.js", imported by "node_modules/@unpic/solid/dist/index.js".

binding: 'template',
  code: 'MISSING_EXPORT',
  exporter: '\node_modules\\solid-js\\web\\dist\\server.js',
  id: '\node_modules\\@unpic\\solid\\dist\\index.js',
  url: 'https://rollupjs.org/troubleshooting/#error-name-is-not-exported-by-module',
  pos: 29,
  loc: {
    column: 29,
    file: '\node_modules\\@unpic\\solid\\dist\\index.js',
    line: 1
  },
  frame: "1: import { spread, mergeProps, template } from 'solid-js/web';\n" +
    '                                ^\n' +
    "2: import { transformProps } from '@unpic/core';",

@unpic/svelte: lazy loading problem (different behavior than @unpic/react)

Describe the bug
My project is a Astro website, one page is using React and another page is using Svelte. When loading the React page, all is well. When loading the Svelte page, it seems to me that @unpic/svelte does not lazy load the images but loads all the images on page load. When using @unpic/react, it does lazy load the first N images and loads the rest as you scroll.

To Reproduce

Here's the version with Svelte: https://codesandbox.io/p/devbox/unpic-svelte-lazy-loading-nyznkw

When loading the page at https://nyznkw-5173.csb.app/, I can see the first 3 images loading and then all the images loading right away (without interacting with the page at all).

image

Here's the React version: https://codesandbox.io/p/devbox/unpic-react-lazy-loading-9ftzh8 which does not exhibit the same behavior. Loading the page at https://9ftzh8-5173.csb.app/:

image

Expected behavior
It is my understanding @unpic/* components would only load the images as they appear in the viewport and it works like a charm with React I must say. I also understand this is using the browser to do it. So is it a browser problem? Is it a Svelte problem, somehow?

I've looked through the code and both component use the core package, but maybe the React binding is doing more than the Svelte one?

Smartphone (please complete the following information):

  • OS: iOS
  • Browser: Chrome
  • Version 120.0.6099.129

Additional context

In my project, I also don't get completion for Image props but that might be my setup for some reason.

Export `ImageProps` in `index.ts`

Is your feature request related to a problem? Please describe.
Hi, I'm trying to make a wrapper component around Image. My wrapper component has some props and I want to construct props for Image component based on my wrapper component props. However because ImageProps is not exported so it's not so convenient for typescript to get autocomplete.

Describe the solution you'd like
Add export for ImageProps to https://github.com/ascorbic/unpic-img/blob/main/packages/qwik/src/index.ts

Describe alternatives you've considered
N.A.

Additional context
N.A.

HTML Web Component

The web component version of unpic currently requires markup like this

<unpic-img
  src="https://cdn.whatever.com/bath_grande.jpg"
  layout="constrained"
  width="{800}"
  height="{600}"
  alt="A lovely bath"
></unpic-img>

I'd like to discuss an alternative markup:

<unpic-img layout="constrained">
  <img
    src="https://cdn.whatever.com/bath_grande.jpg"
    alt="A lovely bath"
    width="800"
    height="600">
</unpic-img>

The first advantage here is that it'll work without javascript. The idea is to enhance the <img> element instead of trying to replace it. The unpic-img element would take care of any non-standard attributes and modify the child image accordingly.

This would break->change the current API. Could consider making another web component instead of breaking the current one made with LitElement.

See https://www.zachleat.com/web/a-taxonomy-of-web-component-types/#html-web-components and https://adactio.com/journal/20618 for more thoughts on this.

What do you think?

Eleventy (11ty) Shortcode

Is your feature request related to a problem? Please describe.
As an Eleventy (11ty) user, I struggle to integrate the existing WebC image component provided by unpic-img. While WebC works well for some projects, not everyone using Eleventy relies on it. Eleventy shortcodes (https://www.11ty.dev/docs/shortcodes/) are very flexible and they can be used in Nunjucks, Liquid, JavaScript, languages used by most of the people that are using Eleventy.

Describe the solution you'd like
I propose adding a new Eleventy shortcode. This shortcode would allow users to easily embed responsive images using the unpic-img library within their Eleventy templates and pages, to "generates a responsive tag that follows best practices, with the correct srcset, sizes and styles; detect image URLs from most image CDNs and CMSs and can resize images with no build step." (taken from the @unpic/webc docs).

Describe alternatives you've considered
Creating my own 11ty shortcode for integrating Unpic, but I think a built-in shortcode that comes with the library, or at least an "official" example of how to implement it would be great.

Additional context
I guess the unpic-img.webc file should be translated to an 11ty shortcode?

Thank you

[Vue warn]: Do not use built-in or reserved HTML elements as component id: image

Describe the bug
i had this error when use @unpic/vue with storyblok cdn

To Reproduce

<Image
        cdn="storyblok"
        loading="lazy"
        width="342"
        height="342"
        sizes="xs:237px lg:342px"
        :src="`${blok.photo}/m/342x342`"
        :alt="blok.caption"
        :title="title"
        :placeholder="[100, 100, 10]"
      />

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
Screen Shot 2023-02-15 at 10 31 27 AM

How to create a fullscreen image

Hi, I am trying to create a fullscreen hero section. I know I can use the fullWidth layout to fill the width of the container but how about the height? My image comes from a Sanity CMS and I am using the Astro component with Tailwind CSS.

I know I can add the h-screen class but this will stretch the image to fit which seems not ideal. Am I missing something obvious here?

import { Image } from "@unpic/astro";
<Image
  src={image}
  layout="fullWidth"
  class="h-screen"
  priority
/>

Support for `styles` attribute in @unpic/react

Hey there, first and foremost thank you for maintaining this fantastic library!

I stumbled on this small issue and I had some ideas about potential work arounds that might benefit other folks as well.

Is your feature request related to a problem? Please describe.
Using the style attribute in React throws TS errors.

<Image
  {/* 
    Type '{ src: string; height: number; width: number; style: { objectFit: string; }; alt: string; }' 
    is not assignable to type 'IntrinsicAttributes & (ImageProps & RefAttributes<HTMLImageElement>)'.
  */}
  style={{objectFit: 'cover'}}
  width={500}
  height={300}
  layout="constrained"
  src={src || placeholder}
/>

This does, however, apply the desired styles.

Describe the solution you'd like
What I'd like to do is extend the prop types definition to include React.CSSProperties so that I don't get TS errors when using those attributes

// packages/react/src/image.tsx

import * as React from "react";
import { transformProps, UnpicImageProps } from "@unpic/core";
import { camelizeProps } from "./camelize";

export type ImageProps = UnpicImageProps<
  React.ImgHTMLAttributes<HTMLImageElement>
> & {style: React.CSSProperties}

export const Image = React.forwardRef<HTMLImageElement, ImageProps>(
  function Image(props, ref) {
    const {style, ...rest} = props;
    const transformedProps = transformProps(rest);
    const camelizedProps = camelizeProps(transformedProps as React.ImgHTMLAttributes<HTMLImageElement>);
    return <img {...camelizedProps} ref={ref} style={style}/>;
  },
);

Describe alternatives you've considered
An alternative would be to support styling the underlying element with the undocumented objectFit prop when there is no transformer present.

// packages/core/src/core.ts

// If the objectFit prop is set and there's no transformer, add the style
  if (objectFit && !transformedProps.style) {
    transformedProps = {
      ...transformedProps,
      style: {['object-fit']: objectFit},
    }
  }

  return {
    ...transformedProps,
    src: url?.toString(),
    width,
    height,
  } as TImageAttributes;
}

Additional context
The reason I'd like to be able to do this is to set objectFit to contain for blob: URLs. This way, I can use a single <Image> component for previewing and displaying image uploads.

// FileUpload.tsx

import { useState } from "react";
import { Image } from "@unpic/react";


function FileUploadForm() {
  const [file, setFile] = useState<File | null>(null);
  // ...
  return (
    <div>
      <form style={{paddingBottom: 50}} onSubmit={handleSubmit}>
        <input
          type="file"
          name="file"
          accept="image/*"
          onChange={handleFileChange}
        />
        <button type="submit">Upload File</button>
      </form>
      <div>{status}</div>
      {src || placeholder && <Image
          style={{objectFit: 'cover'}}
          width={500}
          height={300}
          layout="constrained"
          src={src || placeholder}
        />}
    </div>
  );
}

export default FileUploadForm;

Thanks for taking the time to read this issue! This is a niche use-case, so I'm more than happy to close this if you all consider this to be out-of-scope.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.