Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

💡 RFC: Astro Image Assets #492

Closed
FredKSchott opened this issue Jun 18, 2021 · 10 comments
Closed

💡 RFC: Astro Image Assets #492

FredKSchott opened this issue Jun 18, 2021 · 10 comments

Comments

@FredKSchott
Copy link
Member

FredKSchott commented Jun 18, 2021

Background

  • There's been some strong interest in Discord for adding built-in image optimization support to Astro.
  • There's also been some back and forth about how asset references should work in HTML inside an Astro component. For example, an Astro component can't reference an image src by relative path because that component could end up on any page, relative to any URL. See 💡 RFC: Astro.imageAsset(...) #310
  • We'd like to add image optimization in a way that also solves for the lack of src="./some-relative-path" support inside of components.

Proposal

Pt. 0 - Assets (Terminology)

Q: What is an Asset?
A: A file managed in some part by Astro. Not all files are assets. For example, an image in the public/ directory is not managed by Astro at all and not considered an "asset" in Astro).

Assets are a generalized concept that we want to add more of going forward. Examples in the future would be fonts, images, and icons. Image Assets would be our first implemented asset type.

Pt. 1 - Adding Images

  • Move any image that you'd like into your src/ directory.
  • This becomes the image source of truth, Astro will never modify/touch this file.

Pt. 2 - Referencing Images

// Anywhere within your source directory:
import logoPic from '../images/logo.png';
import profilePic from './profile.jpg';
  • At compile/build time, Astro will check for any image asset imports.
  • (existing behavior) if a file is ESM imported from outside of the src directory, it should fail.
  • if an image is ever imported (must live in the src/ directory):
    • The image is optimized to reduce bytes (ex: Astro's social image went from 1.5Mb to 53kb after optimize)
    • Astro automatically saves the optimized image into some managed-by-Astro location (ex: .astro/assets/...)
    • The image is also converted into several formats to best serve different browsers and screen sizes. Also saved into .astro/assets/...
    • Next time, Astro will load the files from the cache (this folder should be checked into git.)

Pt. 3 - Using Images

---
import {Image} from 'astro/components';
import logoPic from '../images/logo.png';
---
<div>
    <!-- fine, but not optimized -->
    <img  src={logoPic} alt="Company logo" />
    <!-- OPTIMIZED ⚡️ -->
    <Image src={logoPic} alt="Company logo" />
</div>
  • The idea would be to borrow as many good features from https://nextjs.org/docs/api-reference/next/image as possible. Not outlined here, but just imagine all of that good stuff we would support:
    • automatic blur placeholder
    • automatic width/height optimization
    • automatic lazy loading
    • automatic srcset optimization

Pt. 4 - Using Images in Hydrated Components

import {Image} from 'astro/react'; // React component
import {Image} from 'astro/svelte'; // Svelte component
import {Image} from 'astro/web'; // Web component
  • If we want this image component to work in HTML + client-side hydrated components, we need some way to support this Image component in all frameworks.
  • Reuse as much as possible: Implement as a web component, or implement using jsx-lite and compile to each framework that way. At build time, Image will get all of the info that it needs passed to the frontend as props via the import of the image asset.

Alternative Solutions

astro image add

We'd talked about adding images explicitly via a CLI command, and then referencing them by ID. However, where your images live and how you reference them is more hidden. The proposal gives more visibly (images are obviously visible in src) and builds on an existing import system that people are familiar with (vs. how we would need to reference images by some dynamic runtime string/ID if they lived somewhere within Astro).

Why an Image component?

Note that you can still use <img> if you'd like. This component would just give you a lot of optimization for free, with zero effort from the user.

Seriously, an Image component gives you so much awesome stuff for free: https://nextjs.org/docs/api-reference/next/image.

Why ESM import of images?

By using an ESM import to do this, we get:

  • guarantees that the file exists at build time
  • statically analyzable, so we can tell you at build time if an asset doesn't exist
  • clarity on where that file lives on disk

Prior Art

@jerzakm
Copy link
Contributor

jerzakm commented Jun 19, 2021

Do you plan for the <Image/> component to have some sort of support for responsive images?

<img src="img-small.png"
    srcset="img-small.png 320w, img-medium.png 800w, img-large.png 1200w"
    alt="Coconutz">

@FredKSchott
Copy link
Member Author

Yup, we can implement most (all) of the features outlined here: https://nextjs.org/docs/basic-features/image-optimization & https://nextjs.org/docs/api-reference/next/image

@Brixy
Copy link

Brixy commented Jun 26, 2021

It would be cool if you were able to (optionally) use markdown syntax to call this component.

Hugo has Markdown Render Hooks for this which is a bit complicated or redundant. Simply executing this component to get responsive images with markdown would be a lot easier and future proof.

(Also it would be cool to be able to render assets from the folder your referencing content file lives in, e.g. /src/pages/blog/2021-06-26-my-post/ containing index.astro and assets. But your proposal seems to cover this.)

Keep up your great work!

@FredKSchott FredKSchott changed the title [Feature Request] Astro Image Assets 💡 RFC: Astro Image Assets Jun 30, 2021
@radiosilence
Copy link

radiosilence commented Jul 2, 2021

I think it would be cool if we used Snowpack to bundle and reference images, however the way it does seems to break stuff in astro if the dependency is pre-built.

Another thing to consider is how we can or can't reference images in dependencies (inside node_modules).

Currently if a dependency is bundled with snowpack, the image is replaced with a proxy with a hard-coded path (relative) to the library) This could hooked into when detected and the assets hoisted into the dist folder with either the same relative path or one that is namespaced to the library.

Might be worth doing some research into whether dependency assets are supported by other build systems etc.

Also looking at how css is managed, too, where I think the proxy actually contains the CSS and not just a path.

**Edit: However, the css proxy actually references document and breaks the build.

@jasikpark
Copy link
Contributor

https://github.com/11ty/eleventy-img I like the api that 11ty allows for loading images!

@jasikpark
Copy link
Contributor

🤔 I might try using this script for a simple component idea... https://github.com/Holben888/create-react-app-with-11ty-image/blob/main/generate-images.js

@leerob
Copy link
Contributor

leerob commented Aug 12, 2021

👋 Wanted to share a few thoughts from the Vercel/Next.js perspective and how we could collaborate:

  • There's an open RFC for changing next/image to picture that the Google Aurora team is starting to explore on our (Next.js) side.
  • We recently landed support for the next/image component to default to WASM optimization by default, but allow for using Sharp if you want (v11.1). The tradeoff is a larger install size with Sharp, but it produces faster builds. That code is OSS in the Next.js repo, if you're curious. (RFC)
  • Run-time image optimization should be possible on Vercel, using our platform API. Some of the Discord users have managed to get this working. Happy to provide more clarity here if it's something you want to explore. We're also really interested in build-time optimization, as we've found lots of Next.js users don't want run-time optimization when they don't have that many images. Run-time is more optimized for the 10,000+ images case, instead of smaller projects.

@FredKSchott
Copy link
Member Author

Hey everyone! Our current RFC process is beginning to break down at this size, with over 50 open RFCs currently in the "discussing" stage. A growing community is a great problem to have, but our ability to give you RFC feedback has suffered as a result. In an effort to improve our RFC process, we are making some changes to better organize things.

From now on, all RFCs will live in a standalone repo: https://github.com/withastro/rfcs

This allows us to do three things: 1) Use threaded discussions for high-level ideas and improvements, without necessarily requiring an implementation for every idea. 2) Improve the quality of our RFC template and the speed/quality of all feedback. 3) Support inline comments and explicit approvals on RFCs, via a new Pull Request review process.

We hope that this new process leads to better RFC weekly calls and faster feedback on your RFCs from maintainers. More detail can be found in the new RFC repo README.


We can't automatically convert this issue to an RFC in the new repo because new RFC template is more detailed that this one. But, you can still continue this discussion in the new repo by creating a new Discussion in the RFC repo and copy-and-pasting this post (and any relevant follow-up comments) into it. Discussions are available for high-level ideas and suggestions without the requirement of a full implementation proposal.

Then, when you are ready to propose (or re-propose) an implementation for feedback and approval, you can create a new RFC using the new RFC template. More detail about how to do this can be found in the new RFC repo README.

Thanks for your patience as we attempt to improve things for both authors and reviewers. If you have any questions, don't hesitate to reach out on Discord. https://astro.build/chat

@RobbieTheWagner
Copy link

Did this end up getting moved to the new repo? I'm trying to figure out the best way to do image optimization in Astro.

@FredKSchott
Copy link
Member Author

It did not! See instructions above if you want to move it there to kick off a new discussion. There is also the dev "images" channel in Discord where we are talking about this and there are a few ways to get this done in Astro already.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants