skip to Main Content

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.

2

Answers


  1. 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)

    Login or Signup to reply.
  2. 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/

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search