Gatsby: [question] Importing all images from a folder

Created on 23 Jan 2018  ·  16Comments  ·  Source: gatsbyjs/gatsby

This is a question and not an issue.
First of all, thanks to the creator and to all the contributors for this awesome project. I recently started working as a freelance and I'm moving to Gatsby for all my static websites project.

I'm trying to recursively importing all the images from a specific folder. Since I'm new to Gatsby and I'm not so skilled in Webpack, my idea was to use the gatsby-source-filesystem to retrieve all the images from a specific folder and then mapping them to my webpage:

const IndexPage = ({ data }) => {
  console.log(data);

  return (
    <div>
      <h1>Hi people</h1>
      <p>Welcome to your new Gatsby site.</p>
      <p>Now go build something great.</p>

      {data.allFile.edges.map(img => {
        return <img src={withPrefix(`images/${img.node.relativePath}`)} />;
      })}
    </div>
  );
};

export default IndexPage;

export const query = graphql`
  query ImagesQuery {
    allFile {
      edges {
        node {
          extension
          dir
          modifiedTime
          relativePath
        }
      }
    }
  }
`;

As you could imagine, even if I'm successfully retrieving all images' filenames with my query, the <img> element is not able to find the image file to the given path.
Reading the documentation is not helping to reduce the fog I have in my mind and apparently there is not a question like this one... I know I have two possible choices to import images:

  • Requiring the images directly on my component --> best practice
  • Putting the images in the static folder

The problem with the first solution is that I don't know which files the component should load and there could be something like 400 images to load.
The problem with the second solution is that... I can't make it work 🏆

What am I doing wrong? Also, is there some better solution to my code which makes use of the Webpack importing feature?

Thanks!

Most helpful comment

Hi! I think I can help. Just to be clear, you want to import all images in a folder, correct? If so, I use the following code for importing _all_ my SVG's from a folder.

var req = require.context("../path/to/my/directory", false, /.*\.svg$/);
req.keys().forEach(function(key){
    req(key);
});

Obviously, if you're not using SVG's, replace the /.*\.svg$/ with whatever file type you're using.

All 16 comments

Hi! I think I can help. Just to be clear, you want to import all images in a folder, correct? If so, I use the following code for importing _all_ my SVG's from a folder.

var req = require.context("../path/to/my/directory", false, /.*\.svg$/);
req.keys().forEach(function(key){
    req(key);
});

Obviously, if you're not using SVG's, replace the /.*\.svg$/ with whatever file type you're using.

Hello and thanks for the comment!
Where should I write that piece of code? In my component?

Thanks!

Me personally, in my layouts/index.js, I call it in the componentDidMount() function.

componentDidMount() {
    var req = require.context("../path/to/my/directory", false, /.*\.svg$/);
    req.keys().forEach(function(key){
      req(key);
    });
 }

Though I don't know if thats the best place to put it. Maybe in your html.js would be a better place? I'm not exactly sure of the best practice in this scenario.

Have you looked at gatsby-image?

This will take care that the image is copied to the output in public/ and can also perform all kinds of optimizations.

Thanks again for the comment. Below my code:

class IndexPage extends React.Component {
  componentDidMount() {
    var req = require.context('../../public/static/images', false, /.*\.jpg$/);
    req.keys().forEach(function(key) {
      req(key);
    });
  }

  render() {
    const data = this.props.data;

    return (
      <div>
        <h1>Hi people</h1>
        <p>Welcome to your new Gatsby site.</p>
        <p>Now go build something great.</p>
        <Link to="/page-2/">Go to page 2</Link>
        {data.allFile.edges.map((img, index) => {
          return (
            <img
              key={index}
              src={withPrefix(`images/${img.node.relativePath}`)}
            />
          );
        })}
      </div>
    );
  }
}

Now Webpack it's complaining and returning this warning message when he tries to import the image:

warning  in ./src/images/DSC02887.JPG

Module parse failed: [...]/src/images/DSC02887.JPG Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type.

It seems like he wants an appropriate loader for the JPG file...

@zionis137 Thanks I'm going to check right now

var req = require.context('../../public/static/images', false, /.*\.jpg$/);

If you put your images in the static/ directory they will be copied directly to public/ and not public/static/.
The public/static/ directory also exists, mostly plugins put stuff there with a hash in the filename.

If I edit it to var req = require.context('/public/', false, /.*\.jpg$/) I get the following error:

ERROR  Failed to compile with 1 errors                                                                                    16:11:11
This dependency was not found:

* /public/images in ./src/pages/index.js

To install it, you can run: npm install --save /public/images

If, instead, I use the relative path: var req = require.context('../../public/static/images', false, /.*\.jpg$/) I'm still having the 404 not found error.

Look at gatsby-image. It really is the better way :smile:

I'm looking at it. As far as I understand it's not solving the problem with the upload of all the bunch of images I have in my folder but it's "just overlaying" a React Component on the <img> element with useful props for managing and optimizing images. Am I wrong?

Seriously... I'm such in a thick fog right now! Why can't I find anyone who has the same problem as me 😞

I made a demo here: https://github.com/zionis137/gatsby-all-image

This takes all images in data/ and displays them on the homepage

Thanks for the demo! It's exactly what I was looking for!
I'm still wondering why it's not working without the gatsby-image plugin. But I think I'll not complain too much 😝

Thanks!

@Lc0rE yeah the relativePath is just the relative path from the root of your gatsby-source-filesystem setup to where the file is at. That won't give you a path you can use.

You'll want to add gatsby-plugin-sharp and gatsby-transformer-sharp so you can query just the images + transform the images to get image thumbnails of the right size.

Check out also the using-gatsby-image example site https://github.com/gatsbyjs/gatsby/tree/master/examples/using-gatsby-image

Going to close this as the original question seems to have been answered :)

@KyleAMathews surely you did an amazing work and I'm here to congratulate you! I'd wish to have a bit more experience to be able to properly contribute to this amazing project.

By the way, I'm still wondering how I could use gatsby-image with something like Bootstrap Carousel.
I mean, components like Carousels are composed like this:

import React from 'react';
import { UncontrolledCarousel } from 'reactstrap';

const items = [
  {
   src: 'url/to/image/myImage.jpg',
    altText: 'Slide 1',
    caption: 'Slide 1'
  },
  {
   src: 'url/to/image/myImage.jpg',
    altText: 'Slide 2',
    caption: 'Slide 2'
  },
  {
    src: 'url/to/image/myImage.jpg',
    altText: 'Slide 3',
    caption: 'Slide 3'
  }
];

const Example = () => <UncontrolledCarousel items={items} />;

export default Example;

As you can see, this component is expecting me to put a path to my image. Now, I surely can require the single images because I've not the scalability problem since a Carousel should contain just a bunch of images. But how should I behave if I want to use the path instead?

I'm actually trying to do the same thing right now and I had no issues with jpgs using the sharp plugins. But I have some animated gifs that aren't exported. Any advice?

@Lc0rE I don't think you would use gatsby-image with bootstrap carousel. You would just need to use one of the sources from your graphql query. Or you could try another carousel that's more idiomatic to react. I usually use https://github.com/FormidableLabs/nuka-carousel. It's not perfect but pretty good.

There is an issue with require.context(). It duplicates the context across chunks that use it.
https://github.com/gatsbyjs/gatsby/issues/6372#issuecomment-581155819

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jimfilippou picture jimfilippou  ·  3Comments

kalinchernev picture kalinchernev  ·  3Comments

KyleAMathews picture KyleAMathews  ·  3Comments

totsteps picture totsteps  ·  3Comments

Oppenheimer1 picture Oppenheimer1  ·  3Comments