1

I know that in a Create React App project, one can import images like this:

import image from './image.png'

This would result in image variable assigned not to actual image data, but a URL, which one then fetches or puts into an src attribute.

By default this doesn't work the same way for .json files: they are bundled and imported as full content instead. But since in my case the JSON quite big, I don't want to bundle it. Instead I want to have a URL, which I would fetch separately, same as with images. How do I do that?

I don't want to eject, but I can use @craco/craco to override something in config if needed.

1valdis
  • 1,009
  • 1
  • 15
  • 27
  • Hi @1valdis, sorry for pinging you here, I have revised my answer below that includes a workaround / "hack", let me know whether it works for you. – AngYC Apr 28 '23 at 08:23

2 Answers2

2

You can consider dynamic import instead to solve your case, an example of using it would be as follow:

function Component() {
  const [json, setJson] = useState(null);
  useEffect(() => {
    import('./some.json').then((res) => setJson(res));
  }, []);

  return <pre>{JSON.stringify(json)}</pre>;
}

In most build tools, dynamic import will cause it to split into an additional chunk / file, which is not bundled in the initial bundle / entry file and should make the initial loading fast even if it the content in the JSON file is large.


An alternative "hack" would be change your .json extension to match with those images. Based on the documentation of create-react-app. The extension that ends with bmp, gif, jpg, jpeg and png, will automatically be loaded with file-loader.

Assuming your CDN / file servers doesn't have CORS restriction, you can then rename your .json file to .jpg and obtain the URL generated from there, usage sample below:

import theJsonFile from './some.json.jpg';

const [json, setJson] = useState(null);
useEffect(() => {
  fetch(theJsonFile)
    .then((res) => res.json())
    .then((json) => setJson(json));
}, []);

return <pre>{JSON.stringify(json)}</pre>;

(It is not the best idea, as Content-Type / CORS and other stuff can mess with it, but it is worth a try for small project)

AngYC
  • 3,051
  • 6
  • 20
  • Hi and thank you for your time. While your answer with dynamic import looks to suggest the best practice, it's a bit farther away from my question. If I get the approach with file-loader working, I will probably accept one of the other answers suggesting it, BUT I expect your answer to be most upvoted and used after all. Does this sound good? – 1valdis Apr 28 '23 at 08:57
0

You can use the file-loader package.

Install it using: npm install file-loader --save-dev

Add this to your webpack.config.js:

module.exports = {
  module: {
    rules: [
      {
        test: /\.json$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]',
          outputPath: 'json/',
          publicPath: 'json/'
        }
      }
    ]
  }
};

You can then import your JSON file as follows:

import json from 'file-loader!./path/to/json/file.json';

If your react app isn't ejected:

You can use Craco. Add this to your craco.config.js:

const path = require('path');

module.exports = {
  webpack: {
    configure: (webpackConfig, { env, paths }) => {
      webpackConfig.module.rules.push({
        test: /\.json$/,
        loader: 'file-loader',
        options: {
          name: 'json/[name].[ext]',
          publicPath: (path) => path.replace(/^(src|\.\/)/, ''),
          outputPath: (url) => url.replace(/^json\//, ''),
        },
      });

      return webpackConfig;
    },
  },
};

Hope this helps!

Sources:

https://www.npmjs.com/package/file-loader

https://craco.js.org/docs/configuration/webpack/

ItsQuadrus
  • 32
  • 7
  • Hello and welcome to Stack Overflow. My react app is not ejected, so I don't have `webpack.config.js`. Can I accomplish this without ejecting, possibly with Craco by modifying `craco.config.js`? – 1valdis Apr 28 '23 at 08:14
  • @1valdis Yes, you can. I'm editing my answer right now. – ItsQuadrus Apr 28 '23 at 08:29
  • Using your craco config I'm getting the following error: `ERROR in ./src/data.json Module parse failed: Unexpected token "e" (0x65) in JSON at position 0 while parsing near "export default \"..\\\\..." File was processed with these loaders: * ./node_modules/file-loader/dist/cjs.js You may need an additional loader to handle the result of these loaders.` – 1valdis Apr 28 '23 at 08:41
  • Try this: https://stackoverflow.com/a/65709536 – ItsQuadrus Apr 29 '23 at 09:33