gatsby: gatsby-remark-images in MDX doesn't generate base64 placeholders

Description

Using gatsby-remark-images in MDX (see this guide) doesn’t generate a base64 placeholder.

➡️ demo repo ⬅️ ➡️ live example ⬅️

Steps to reproduce

  1. create a new default gatsby site gatsby new gatsby-image-with-mdx
  2. cd gatsby-image-with-mdx
  3. install mdx and gatsby-remark-images yarn add gatsby-plugin-mdx @mdx-js/mdx @mdx-js/react gatsby-remark-images
  4. configure the plugin and filesystem source in gatsby-config.js:
    {
      resolve: `gatsby-plugin-mdx`,
      options: {
        gatsbyRemarkPlugins: [
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 600,
            },
          },
        ],
      },
    },
    // source posts 
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `posts`,
        path: `${__dirname}/src/posts`,
      },
    },
  1. create a post at /src/posts/testing-gatsby-image/index.mdx:
---
slug: testing-gatsby-image
---

# Testing gatsby-image in MDX

![An image](./image.png)
  1. Drop any image in the same directory (copy the astronaut for example) and rename it image.png
  2. Implement a simple gatsby-node.js:
const path = require("path")
exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions
  return new Promise((resolve, reject) => {
    resolve(
      graphql(
        `
          {
            allMdx {
              edges {
                node {
                  id
                  frontmatter {
                    slug
                  }
                }
              }
            }
          }
        `
      ).then(result => {
        // handle errors
        if (result.errors) {
          console.error(result.errors)
          reject(result.errors)
        }

        // create posts pages
        result.data.allMdx.edges.forEach(({ node }) => {
          createPage({
            // slug generated with createNodeField
            path: node.frontmatter.slug,
            // post template
            component: path.resolve(`./src/templates/post.js`),
            // pass id as context
            context: { id: node.id },
          })
        })
      })
    )
  })
}
  1. Add a template at /src/templates/post.js:
import React from "react"
import { graphql } from "gatsby"
import MDXRenderer from "gatsby-plugin-mdx/mdx-renderer"

const PostTemplate = ({ data }) => <MDXRenderer>{data.mdx.body}</MDXRenderer>

export const POST_QUERY = graphql`
  query POST_QUERY($id: String) {
    mdx(id: { eq: $id }) {
      body
    }
  }
`

export default PostTemplate
  1. run gatsby develop
  2. navigate to http://localhost:8000/testing-gatsby-image
  3. inspect the image

Expected result

The generated markup should include a base64 placeholder image for the “blur up” effect, like when using gatsby-remark-images with gatsby-transformer-remark.

Actual result

Generated markup:

<span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px;">
  <span class="gatsby-resp-image-background-image" style="padding-bottom: 100%; position: relative; bottom: 0px; left: 0px; background-size: cover; display: block;"></span>
  <img class="gatsby-resp-image-image" style="width: 100%; height: 100%; margin: 0px; vertical-align: middle; position: absolute; top: 0px; left: 0px; box-shadow: white 0px 0px 0px 400px inset;" alt="An image" title="" src="/static/6d91c86c0fde632ba4cd01062fd9ccfa/34e8a/image.png" srcset="/static/6d91c86c0fde632ba4cd01062fd9ccfa/d4214/image.png 150w,/static/6d91c86c0fde632ba4cd01062fd9ccfa/135ae/image.png 300w,/static/6d91c86c0fde632ba4cd01062fd9ccfa/34e8a/image.png 600w,/static/6d91c86c0fde632ba4cd01062fd9ccfa/8ff1e/image.png 800w" sizes="(max-width: 600px) 100vw, 600px">
</span>

Environment

  System:
    OS: Linux 4.15 Ubuntu 18.04.2 LTS (Bionic Beaver)
    CPU: (4) x64 Intel(R) Core(TM) i5-4260U CPU @ 1.40GHz
    Shell: 4.4.19 - /bin/bash
  Binaries:
    Node: 10.9.0 - ~/.nvm/versions/node/v10.9.0/bin/node
    Yarn: 1.16.0 - /usr/bin/yarn
    npm: 6.9.0 - ~/.nvm/versions/node/v10.9.0/bin/npm
  Languages:
    Python: 2.7.15+ - /usr/bin/python
  Browsers:
    Chrome: 67.0.3396.87
    Firefox: 67.0.2
  npmPackages:
    gatsby: ^2.10.0 => 2.10.0
    gatsby-image: ^2.2.1 => 2.2.1
    gatsby-plugin-manifest: ^2.2.0 => 2.2.0
    gatsby-plugin-mdx: ^1.0.5 => 1.0.5
    gatsby-plugin-offline: ^2.2.0 => 2.2.0
    gatsby-plugin-react-helmet: ^3.1.0 => 3.1.0
    gatsby-plugin-sharp: ^2.2.1 => 2.2.1
    gatsby-remark-images: ^3.1.0 => 3.1.0
    gatsby-source-filesystem: ^2.1.0 => 2.1.0
    gatsby-transformer-sharp: ^2.2.0 => 2.2.0
  npmGlobalPackages:
    gatsby-cli: 2.7.0

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 30 (23 by maintainers)

Most upvoted comments

My PR has shipped in the latest Gatsby and MDX dependencies, and from my tests, seems this issue is no more! 🙂

@robinmetral I have a fix now, some more tests and will push a fix in a couple of hours!

Confirmed: the issue is with the to-style package!

These are calls to that specific function, differing only that on the first you have “data:image” as part of the url, and the other “data_image” (so I removed the “:” from the url)

> toStyleObject("border-radius: 10px; background: red; background-image: url('data:image/base64,asdasdasdasdasdasdasdasdasdasdasdasaasdas')", {camelize: true})

{ borderRadius: '10px', background: 'red' }

> toStyleObject("border-radius: 10px; background: red; background-image: url('data_image/base64,asdasdasdasdasdasdasdasdasdasdasdasaasdas')", {camelize: true})

{ borderRadius: '10px',
  background: 'red',
  backgroundImage:
   'url(\'data_image/base64,asdasdasdasdasdasdasdasdasdasdasdasaasdas\')' }

As you can see, it successfully added the background-image on the second example, so the problem is here!

We fix the to-style package, we fix our problem!

This is likely related to https://github.com/gatsbyjs/gatsby/issues/15486

The proposed solution there by @cwgw solves this problem.

The problem: gatsby-remark-x plugins that use the gatsby config files (like gatsby-remark-images) are not getting loaded properly by gatsby-plugin-mdx due to the gatsbyRemarkPlugins option not being processed correctly by gatsby.

workaround: supply the name of the plugin under a new plugins array in gatsby-plugin-mdx

{
  resolve: `gatsby-plugin-mdx`,
  options: {
    gatsbyRemarkPlugins: [
      {
        resolve: `gatsby-remark-images`,
        options: {
          maxWidth: 1152,
          linkImagesToOriginal: false,
          quality: 75,
          withWebp,
        },
      },
    ],
    plugins: ['gatsby-remark-images'],
  },
},

@robinmetral I haven’t had a chance to look into it yet since I just got back from vacation yesterday 😃 Thanks for this issue and the repro repo, that’ll make it much easier to figure out what’s going on.

gatsby-plugin-mdx was the gatsby-1-compatible version and gatsby-mdx the 2.0 compatible version. Since I’m in the process of giving gatsby-mdx to the gatsby monorepo in #14657, we’re also doing a rename with the gatsby-mdx 1.0 release. The future-facing package will be gatsby-plugin-mdx@1.0.

I’ll make this clear when I write and release the official gatsby-mdx 1.0 blog post. Until then the gatsby-plugin-mdx package is basically “dark launched”.

@vpicone this was unclear to me as well, but with the plugin being integrated into Gatsby gatsby-mdx will be deprecated in favor of gatsby-plugin-mdx. See #15068 🙂

The upcoming merge of #15076 should make things clearer overall!

As you mentioned though, I don’t think this is related to the package.

I’ve made a PR that replaces to-style with style-to-object. From my tests, this fixes the main issue which was the base64 data not being output.

Smooth transitions might still be failing but I was going to leave that for when this gets approved/merged in the master branch.

@codepunkt I do know that Gatsby on Windows is not as seamless as on Unix. If you think this might be a broader problem, it might deserve its own issue!

The markdownImageNode or rawHtmlNodes are found, but the generateImagesAndUpdateNode method bails out resolving to undefined because it can’t find the appropriate imageNode in the files array.

Not sure where the getNodes method which is used to retrieve a list of all File nodes in get-source-plugins-as-remark-plugins.js (gatsby-plugin-mdx) is coming from and why it lists some files, but not others.

Will dig in deeper.

@ChristopherBiscardi I was just about to open an issue on this, but just found it has already been reported. The branch remarkImages-md-vs-mdx on https://github.com/codepunkt/codepunkt.de also shows this problem with svg placeholders.

Steps to reproduce:

  1. check out the repo
  2. switch to remarkImages-md-vs-mdx branch
  3. yarn && gatsby build && gatsby serve
  4. click the articles link on the root page to get to /blog, compare the markdown and mdx posts

My debugging into gatsby-remark-images shows that the placeholders are created, the placeholder html with data-uri placeholders is set as node.value here:

https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-remark-images/src/index.js#L339

but i’m not sure i understand what’s actually happening in that plugin and especially don’t understand the interaction between markdownImageNodes and rawHtmlNodes. Maybe someone can walk us through this so we can get to the bottom of this together - or point us to documentation about what the plugin actually does 🙈

Glad I found this already reported by @robinmetral as I was about to do it myself! 😛