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

[Feature] Image plugin #1130

Closed
dev-rsilver opened this issue Apr 16, 2019 · 4 comments
Closed

[Feature] Image plugin #1130

dev-rsilver opened this issue Apr 16, 2019 · 4 comments
Labels
help wanted Inviting contributors to work on this plugin 🏷 Issue or PR related to a plugin wontfix 🙅‍♀️ This won't be applied, fixed, worked on, continued.

Comments

@dev-rsilver
Copy link

Any plans to introduce an image plugin to do things like lazy load images?

I found an old discussion #309 about plugins, but it, and the referenced project, have been closed.

@dev-rsilver
Copy link
Author

@tannerlinsley is there interest in adding an image plugin to React Static? If so, I can look into it

@tannerlinsley
Copy link
Contributor

Yes there is. I'll do my best to outline some of the requirements that said plugin would need, but we'll most definitely need more discussion to happen around it.

  • Images run through this system are different from images that are simply imported via webpack in the application or referenced directly in an <img> element. These images will need to follow a spec that should enable their usage across a wide range of <Image/> components.
  • Should be built around extended image properties like src, srcset, svg placeholders, width, height, aspect ratio, basically anything we can get.
  • Could follow the same paradigm as routeInfo and theoretically be sent to routes using the same underlying getData interface. OR, it could be it's own feature in React Static. We should discuss this, but any scenarios where we increase the existing API should be avoided.
  • Should work with any image that can be imported by:
    • External URL
    • Local file path
  • Should work with both:
    • Mappable pre-optimized image information (like 3rd party image services that already provide information like srcset and svg placeholders)
    • Image sources that are not yet optimized, but will be at build time.
  • Should support an unopinionated image transformation pipeline for images that will be pre-processed and optimized at build time. This pipeline could probably be implemented using plugins and should be able to ingest, cache and supply image information for both external and locally-processed images.
  • Should not pierce the static data boundary. This primarily means that image data must always be imported, managed and routed from outside of the application to routes. In other words, the template should easily be able to map an image object from routeData to an Image component for display.
  • Should provide a generic enough shape/info so that most, if not all image component implementations could use the data. Of course, props won't map one-to-one with a React Static Image object, but should at least be mappable. It would be cool if these objects at least contained all the info that components like Gatsby's gatsby-image component need or any other lazy-loading React Image component you can find on Github.
  • The image plugin should also provide its own Image component that is compatible out-of-the-box with a React Static Image Object. It should support:
    • Lazy loading images via the intersection observer api
    • Immediately loading and inlining images marked with a critical prop
    • SVG placeholders
    • Dimensions and aspect ratio
    • srcset definitions
    • Anything else we can think of.

I'm sure there's even more we need to discuss, but I think this is a good start.

@dev-rsilver
Copy link
Author

Thank you for all the information! Based on the information you provided, my initial thoughts on a potential structure for the image plugin are below.

From a user's perspective, I think the plugin can be split into a few parts:

  • Transforming images
  • Passing images to a route
  • Utilizing images within a route

I considered whether the plugin should be utilized via configuration or programmatically. I think that users will have a wide range of requirements as to how they would like to transform images. As a result, I think that a programmatic approach could work well, if you think it fits with the style and simplicity of React Static's approach. Alternatively, we could consider plugins.

Here's a quick example of what I'm thinking...

static.config.js

import { Image } from plugin
getRoutes: async() => {
    var MyImage = await Image.get(filepath_folder_url_or_function, (image) => {
        //Transform callback is executed for one or more images. The image object will provide
        //methods for transforms. Images will be saved to disk or base64 encoded automatically.
        
        let thumbnail = image.resize(200,200)

        //When transforms are complete, return an object literal that has associated options set
        return {
            image,
            load: "lazy",
            placeholder: thumbnail
        }
    })

    return [{
       path: "/",
       getData() => ({
            MyImage
       }) 
    }]
}

If transform callback is not provided, plugin will set reasonable defaults (or user could set defaults), such as generating a placeholder image and setting image to lazy load. Details would change slightly if importing a folder since it'd return an array.

Meanwhile, plugin provides its own version of useRouteData that transforms the object into a ReactStaticImage object. Alternatively, we could use a separate hook instead of replacing useRouteData.

To use:

blog.js

import { useRouteData } from plugin

export default function Blog() {
    const { posts, MyImage } = useRouteData()

    return(
        <div>
             <MyImage />
        </div>
    )
}

Thoughts?

@dev-rsilver
Copy link
Author

@tannerlinsley please see https://github.com/dev-rsilver/plugin-react-static-images for a start to this plugin.

Implementation is slightly different from what I outlined in the previous message.

Currently implements:

  • File/folder import
  • Builtin image transformations
  • User-defined image transformations
  • Cacheable file names, or base64 encoded data URLs, based on size
  • Image component for use in React
  • Low quality placeholders
  • Lazy loading via intersection observer
  • Responsive images

The ImageComponent is designed to be a drop-in replacement for img elements with respect to CSS styling.

To test (note that instructions are for testing only, not production):

  • Install into a React Static project via Github url
  • Navigate to node_modules/plugin-react-static-images and run build script to compile dist folder via Babel (requires Babel cli)
  • Follow instructions in repository readme

Feedback would be welcomed, even if you would like to move in another direction.

@SleeplessByte SleeplessByte added help wanted Inviting contributors to work on this plugin 🏷 Issue or PR related to a plugin labels Jul 18, 2019
@SleeplessByte SleeplessByte added the wontfix 🙅‍♀️ This won't be applied, fixed, worked on, continued. label Apr 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Inviting contributors to work on this plugin 🏷 Issue or PR related to a plugin wontfix 🙅‍♀️ This won't be applied, fixed, worked on, continued.
Projects
None yet
Development

No branches or pull requests

3 participants