question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Importing images has the wrong route in production builds

See original GitHub issue

Reporting a bug?

When you import an image (and probably other file assets, as well), ex: import imgSrc from '../img.png';, the file is placed in a /static folder. This works perfectly fine in a local dev server.

But when you run react-static build, the path received from the import is missing the /static prefix, and your image reference is broken in the built site!

Digging through the react-static source, I think I’ve traced the problem to this file: https://github.com/react-static/react-static/blob/dbf750c/packages/react-static/src/static/webpack/rules/fileLoader.js

See how it passes different configuration to the loader depending on the “stage”? According to some console logging, this configuration is actually called twice during the build process - once for a stage of “node” and once for “prod”.

I’d love to send a PR with a fix, but unfortunately, this is where I’m stuck. I don’t know why it’s doing this or if it’s supposed to be solving another problem. In fact, I don’t even know what “stages” are - the possible values appear to be “dev”, “node”, and “prod”, which doesn’t really make sense to me - when would Webpack not run in Node? It wouldn’t exactly work in the browser, right?

I did manage to find a workaround, though - create a plugin at node.api.js:

export default () => ({
  webpack: (config, {stage}) => {
    if (stage === 'node') {
      const fileRule = config.module.rules[0].oneOf.find((x) => x.loader === 'url-loader');
      fileRule.options.name = 'static/[name].[hash:8].[ext]';
    }
    return config;
  },
});

This is probably extremely brittle, and I don’t know if it has any other detrimental side effects.

Environment

Run and copy the result of:

npx envinfo --system --npmPackages react* --binaries --npmGlobalPackages react* --browsers

here:

  System:
    OS: macOS Mojave 10.14.6
    CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
    Memory: 106.03 MB / 16.00 GB
    Shell: 5.3 - /bin/zsh
  Binaries:
    Node: 10.15.3 - ~/.nvm/versions/node/v10.15.3/bin/node
    npm: 6.9.0 - ~/.nvm/versions/node/v10.15.3/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Browsers:
    Chrome: 77.0.3865.90
    Firefox Developer Edition: 70.0
    Safari: 13.0.2
  npmPackages:
    react: ^16.9.0 => 16.10.2
    react-dom: ^16.9.0 => 16.10.2
    react-static: ^7.2.0 => 7.2.2
    react-static-plugin-reach-router: ^7.2.0 => 7.2.2
    react-static-plugin-sitemap: ^7.2.0 => 7.2.2
    react-static-plugin-source-filesystem: ^7.2.0 => 7.2.2

of course include any other package versions here if relevant.

Steps to Reproduce the problem

Base your steps off of any freshly installed react-static template!

  1. Start from the “basic” template
  2. Add an image into the “src” dir, ex. src/img.png.
  3. In pages/about.js, import that image and render it:
import React from 'react';
import imgSrc from '../img.png';

export default () => {
  return (
    <div>
      <p>React Static is a progressive static site generator for React.</p>
      <img src={imgSrc} />
    </div>
  );
};
  1. Run npm run build and then npm run serve to see a built version of the site
  2. Navigate to the “About” page on the site
  3. The image you included is missing, because the src is something like /62faa5fe0f4d6c46784c1eb0e08b0ed6.png and the image is in dist/static/img.62faa5fe.png
  4. If you navigate to the same page, you’ll see the image appear, with the correct src.

Expected Behavior

The image’s src should match up to where Webpack actually placed the image.

Reproducible Demo

Here’s a repo with the code-based steps in “Steps to Reproduce the Problem” already done: https://github.com/dallonf/react-static-img-repro

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:15
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
RossRogerscommented, Mar 18, 2020

For what it is worth, in this file
node_modules/react-static/lib/static/webpack/rules/fileLoader.js if I change this:

options: {
    limit: 10000,
} // Don't generate extra files during node build

to:

options: {
    limit: 10000,
    name: 'static/[name].[hash:8].[ext]',
} // Don't generate extra files during node build

The image paths are now correct in the dist folder. Perhaps the bug could be lanced by doing what is counter to this comment // Don't generate extra files during node build ?

1reaction
martonkaufmanncommented, Oct 28, 2019

I had the same issue, but after digging through the documentation I decided to go with the following solution

node.api.js

export default pluginOptions => ({
    webpack: (webpackConfig, state) => {
        webpackConfig.module.rules = [{
            oneOf: [
                state.defaultLoaders.jsLoader,
                state.defaultLoaders.jsLoaderExt,
                state.defaultLoaders.cssLoader,
                {
                    loader: 'url-loader',
                    test: /\.(jpg|png)$/,
                    query: {
                        limit: 100,
                        name: 'static/[name].[hash:8].[ext]',
                    },
                },
                state.defaultLoaders.fileLoader,
            ]
        }]

        return webpackConfig
    }
})

Read more comments on GitHub >

github_iconTop Results From Across the Web

Load local images in React.js - Stack Overflow
This path is not read during build time, but is read during rendering in browser ... Best approach is to import image in...
Read more >
Images not loading from assets folder in Angular
You're using the wrong path to the images. In the Angular project, you don't have to add the relative path from your file...
Read more >
Basic Features: Image Optimization - Next.js
The import must be static so it can be analyzed at build time. Next.js will automatically determine the width and height of your...
Read more >
Static Asset Handling - Vite
Importing Asset as URL​​ For example, imgUrl will be /img.png during development, and become /assets/img.2d8efhg.png in the production build. The behavior is ......
Read more >
Next.js automatic image optimization with next/image
The docs advise that it is better to use a Static Image Import, which automatically handles hashing file contents and caching the file...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found