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

Image handling #60

Open
tanc opened this issue Nov 29, 2018 · 26 comments
Open

Image handling #60

tanc opened this issue Nov 29, 2018 · 26 comments
Assignees
Labels
question Unsure if I am doing it right

Comments

@tanc
Copy link
Member

tanc commented Nov 29, 2018

I'm wondering what the current and future concepts around image handling are? For example, if I have image tags in the content from a remote API, how would I fetch and use them within gridsome?

@hjvedvik
Copy link
Member

Gridsome currently processes local images which can be used with the g-image component. But the plan is to download external images URLs in field values and process them. I'm not sure how to deal with image tags inside HTML yet. We could have an HTML transformer which replaces image tags as the Remark transformer does, or just allways transform the resulting HTML in node.content automatically. Unless anyone has a better idea :)

@tanc
Copy link
Member Author

tanc commented Nov 29, 2018

Sounds good to me. I'm still finding my way around gridsome but link me up if you'd like me to test a pull request.

@tanc
Copy link
Member Author

tanc commented Nov 29, 2018

Just dropping this in here in case it helps and so I can find it again: https://www.wildsmithstudio.com/blog/remote-images-with-gatsby/

@tanc
Copy link
Member Author

tanc commented Dec 17, 2018

I'm having a lot of problems with the <g-image> component, in particular getting it to pick up assets. The only method I've found that works so far is to specify the src attribute with the assets loader, like this:

<g-image
  :src="require(`!!assets-loader!@/images/${edge.node.image.fieldImage.filename}`)"
  width="300" />

This produces output like:

<img data-v-387ef93f="" src="/assets/static/src/images/img_0293.jpg?width=960" width="960" class="g-image g-image--lazy g-image--loaded" srcset="/assets/static/src/images/img_0293.jpg?width=480 480w, /assets/static/src/images/img_0293.jpg?width=960 960w" sizes="(max-width: 960px) 100vw, 960px">

In the Gridsome tests it looks like something like this should work:

<g-image src="~/assets/img_0293.jpg"/>

Unfortunately webpack doesn't pick this up and the end result is the src is still ~/assets/img_0293.jpg which obviously doesn't find the image or provide the assets.

Can you provide some clarity around the use of the component? Where should images be placed in the filesystem and how should they be referenced? How do the other attributes work?

Finally, this is possibly a feature request (I could make a different issue if it is), is it possible to provide a height and have the image cropped (and resized) so that the ratio is not automatically used as it appears to be now? It would be great to be able to specify square thumbnails for example and have images prepared to suit.

@tanc
Copy link
Member Author

tanc commented Dec 17, 2018

Oh, just to note that in my working example above I've provided the width attribute but this is ignored. I've been able to pass in the width by specifying it as a query in the require:

require("!!assets-loader?${query}!${value}"

I've had no success specifying more complex things like an array of sizes.

@tomtev
Copy link
Member

tomtev commented Dec 20, 2018

@tanc Take a look here on how to get images that are added to GraphQL: https://gridsome.org/docs/images#insert-images-via-graphql-query . Would that help?

@IrwinBridge
Copy link

IrwinBridge commented Mar 20, 2019

I have the same issue with g-image tag. I'm loading some images at build time in '~/assets/images' folder and store their paths in graphql nodes. Then I'm querying them on page and insert relative paths in src of components through Vue's props. But gridsome doesn't process paths and they stay relative.
So the question: is there any way to resolve paths which are static but depend on let's say post I'd?

@robaxelsen robaxelsen added the question Unsure if I am doing it right label Mar 23, 2019
@Al-Rozhkov
Copy link
Contributor

@IrwinBridge please see this comment. I guess it is your use case.

@aronhoyer
Copy link

Dropping in with a related question.

Is it possible to bind the src attribute from within, say, a loop?

@chug2k
Copy link

chug2k commented Jun 8, 2019

Gridsome currently processes local images which can be used with the g-image component. But the plan is to download external images URLs in field values and process them. I'm not sure how to deal with image tags inside HTML yet. We could have an HTML transformer which replaces image tags as the Remark transformer does, or just allways transform the resulting HTML in node.content automatically. Unless anyone has a better idea :)

Any plans on this would be great. g-image is super cool, would like to use it everywhere, esp. with our CMS (Contentful).

@khoipro
Copy link

khoipro commented Oct 21, 2019

Not sure what happens, but I always reach this issue when trying to use <g-image>.

 ERROR  Failed to compile with 1 errors                                                                                                                        6:03:50 AM

This dependency was not found:

* !!assets-loader?!~/../assets/img/hero.png in ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/gridsome","cacheIdentifier":"6d5062b0-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Hero.vue?vue&type=template&id=9d9a21ac&

To install it, you can run: npm install --save !!assets-loader?!~/../assets/img/hero.png

Resolve: should be setup a document better for that

  • Place your image to src/assets/img/
  • Use: <g-image src="~/assets/img/<your_file.png>"></g-image>

@noxify
Copy link
Contributor

noxify commented Feb 18, 2020

Hey guys,

I have created two plugins to download images from a remote url. Maybe this helps you to solve your problem:

https://github.com/noxify/gridsome-plugin-remark-image-download

https://github.com/noxify/gridsome-plugin-image-download

@toddsampson
Copy link

I'll give the plugin a try, but curious if there has been any progress on building this in natively? It really feels like the only major item missing from Gridsome after a few weeks using it.

@gustawdaniel
Copy link

Any example how to use simple local image from assets?

@sagrawal-idrc
Copy link

@gustawdaniel, this works for me alright:

<g-image src="~/assets/images/<image-name>.png" class=""/>

@wraybowling
Copy link

I've been feeling the pain of using @gridsome/source-airtable recently. It seems Airtable has blocked hotlinking images so I NEED to be able to download images when building.

@RehanSaeed
Copy link

What about images referenced from the static folder? It seems that they are not processed either.

<g-image src="/images/hero/Microsoft-.NET-1366x768.png"/>

I have to reference some images placed in the static folder, so I can also use the same paths to them in meta tags using vue-meta (Would love to know if there was a better way around this). Lazy loading also doesn't seem to work for these images.

@tanc
Copy link
Member Author

tanc commented May 20, 2020

I'm revisiting this after the original post 1.5 years ago... and still really struggling! It is not clear to me in the documentation what g-image is expecting if provided a :src value from graphql.

My current experiment is this: I have a beforeBuild hook which checks all my file nodes for a remote image path and uses curl to download the files into a local directory. I'm then trying to provide the new path to the file node in an onCreateNode hook as a new field on the node.

This new field with the local path is then passed through a graphql query to the :src attribute of g-image. Unfortunately this is where I'm stuck as g-image refuses to render my image.

It would help my understanding if I knew the following:

  1. Can g-image render images with a path like ~/../static/files/my-file.jpg? If not, what possible locations can g-image process?
  2. It looks like g-image is expecting an object from graphql. How do I create that object?

On question 2, it looks like graphql needs to process my field as type Image. Is it possible to do that in the onCreateNode hook for a custom field?

@hjvedvik
Copy link
Member

Can g-image render images with a path like ~/../static/files/my-file.jpg? If not, what possible locations can g-image process?

@tanc Yes, a path like that should work if you pass it as a static string to g-image, like <g-image src="~/a-file.jpg" />. Webpack is able to resolve that path to an absolute path in your filesystem. But if you are setting the paths on each node in onCreateNode, then you need to resolve the path yourself. Using the path module like path.resolve(__dirname, './static/files/my-file.jpg'). Because Gridsome needs an absolute path to locate the images and infer the field as an Image type.

It looks like g-image is expecting an object from graphql. How do I create that object?

The object should have been generated for you if the field is an Image type and Gridsome is able to locate the image to process it. But you can create it manually to use g-image with external images that shall not be processed by Gridsome, but be lazy-loaded like the processed images:

{
  src: 'https://example.com/image.jpg',
  srcset: ['https://example.com/image-small.jpg 400w', '...', '...'],
  sizes: '',
  dataUri: 'data:image/svg+xml, ...', // uri encoded svg string
  size: {
    width: 1000,
    height: 1000
  }
}

And btw, I wouldn't recommend having images that shall be processed in the /static folder. All files in that folder are copied as-is to /dist. If you download them to, for example, /images instead, then Gridsome will copy them to /dist only while processing them.

@tanc
Copy link
Member Author

tanc commented May 20, 2020

Thank you! That explanation makes perfect sense. The missing piece of the puzzle was the path.resolve and once that is in place Gridsome successfully generates the image object and I can use that as the value for my src attribute/prop. Now I've got this far I'll have a play with it and hopefully I can write up a pull request for the docs to add some useful detail for others or my future self.

@tanc
Copy link
Member Author

tanc commented May 20, 2020

@hjvedvik sometimes I see my images in graphql get processed as type file with an object like this:

{
  mimeType: "image/jpeg"
  src: "/assets/files/images/IMG_6892.JPG"
  type: "file"
}

Is this a bug or something wrong with my files? The file opens as a jpeg in an image viewer and has exif data saying its taken with a Canon EOS 550D

@RehanSaeed
Copy link

@tanc Would love to see some clear instructions on how to get this working. Showing how to also get the path to the image with the random hash on the end in a component (so I can use the image in vue-meta) would be an added bonus.

@tanc
Copy link
Member Author

tanc commented May 20, 2020

@RehanSaeed I'll try and write up some examples very soon. I'm still working my way through a site I've already built to use g-image and discovering some small issues. Once I've resolved and understood as much as I can I'll write it up

@tanc
Copy link
Member Author

tanc commented May 20, 2020

@hjvedvik I found the problem with those jpegs, its due to the file extension being uppercase and not in the array of SUPPORTED_IMAGE_TYPES:

SUPPORTED_IMAGE_TYPES: ['.png', '.jpeg', '.jpg', '.gif', '.svg', '.webp'],

Might be worth adding uppercase JPG as I know some cameras output their files with uppercase extensions.

I got around the issue be preprocessing the files when they are downloaded and changing the extension to lowercase as well as doing the same on my custom field added in onCreateNode.

For other's benefit, at the moment my onCreateNode looks like this:

  api.onCreateNode(options => {
    if (options.internal.typeName === 'DrupalFile') {
      const file = getFilenameAndExtension(options.uri.value)
      options.localImage = path.resolve(__dirname, `./images/${file.filename}${file.extension.toLowerCase()}`)
    }
  }
function getFilenameAndExtension(pathfilename) {
  return {
    filename: path.parse(pathfilename).name,
    extension: path.parse(pathfilename).ext
  }
}

@tanc
Copy link
Member Author

tanc commented Jun 8, 2020

@RehanSaeed here is a gist of my final working gridsome.server.js file. It is set up to work with Drupal but I imagine you could adapt it to any CMS as long as the images are all of the same type.

In my case, with Drupal as the remote source, the images in GraphQL have a typeName of DrupalFile and can be manipulated in the onCreateNode hook.

The downloading of images will only be triggered on the beforeBuild hook so running gridsome develop won't pull down any images (but will show already downloaded ones). Running gridsome build is required to initially fetch all the images.

At the moment the system doesn't account for modified/updated images, all it does it check if they already exist in the download directory images, if they don't exist it'll download them from the remote source using curl, if they do exist it'll skip those images.

A future enhancement will be to store the modified date contained in the metadata of the DrupalFile and if there is a newer date then re-fetch it and overwrite the old image.

I hope that helps with your efforts. It would be good to turn this into a plugin at some point but to do that we'd need to know how other systems present their files to Gridsome. It might also be worth seeing if the plugin @noxify wrote could be expanded on to include a method like this.

I hope this helps!

@bastianhilton
Copy link

So i'm having similar issues in my Gridsome and Strapi project. For starters here is the link on my post.vue page located inside of my pages/blog/Post.vue

and this works and shows the image in the post page. But say if i go to my regular blog page or any other page where their files are located in pages/ directory then the images doesn't show even with the same g-image tag as above.

Oh and example.com isn't the real URL, the real url is an public facing ip address.

Any help with this would be appreciated, i've also tried just regular img tag and still nothing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Unsure if I am doing it right
Projects
None yet
Development

No branches or pull requests