Skip to content
This repository has been archived by the owner on Mar 17, 2021. It is now read-only.

file-loader fails with JSON files in Webpack 4 #259

Closed
enjikaka opened this issue Feb 27, 2018 · 22 comments
Closed

file-loader fails with JSON files in Webpack 4 #259

enjikaka opened this issue Feb 27, 2018 · 22 comments

Comments

@enjikaka
Copy link

enjikaka commented Feb 27, 2018

Using import 'file-loader!./manifest.json'; fails with;

Module parse failed: Unexpected token m in JSON at position 0
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token m in JSON at position 0
    at JSON.parse (<anonymous>)
    at JsonParser.parse (/Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/webpack/lib/JsonParser.js:15:21)
    at doBuild.err (/Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/webpack/lib/NormalModule.js:367:32)
    at runLoaders (/Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/webpack/lib/NormalModule.js:264:12)
    at /Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/loader-runner/lib/LoaderRunner.js:370:3
    at iterateNormalLoaders (/Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/loader-runner/lib/LoaderRunner.js:211:10)
    at iterateNormalLoaders (/Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/loader-runner/lib/LoaderRunner.js:218:10)
    at /Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/loader-runner/lib/LoaderRunner.js:233:3
    at runSyncOrAsync (/Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/loader-runner/lib/LoaderRunner.js:130:11)
    at iterateNormalLoaders (/Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/loader-runner/lib/LoaderRunner.js:229:2)
    at Array.<anonymous> (/Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/loader-runner/lib/LoaderRunner.js:202:4)
    at Storage.finished (/Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/webpack/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:43:16)
    at provider (/Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/webpack/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:79:9)
    at /Users/jeremy/Documents/Development/webpack-file-loader-test/node_modules/graceful-fs/graceful-fs.js:78:16
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:505:3)

Minimal reproducible setup: https://ipfs.io/ipfs/QmPfPq71WD3H6RrcCu1y72FswF8zC3f43aU8FPv5ZwS2ea

@enjikaka
Copy link
Author

I assume this is related to webpack 4 now handling JSON loading natively

@alexander-akait
Copy link
Member

@enjikaka seems bug in webpack@4, he should ignore .json files which loaded other loaders

@alexander-akait
Copy link
Member

@webpack-bot move to webpack/webpack

@michael-ciniawsky
Copy link
Member

@see webpack/webpack#6586. Why is the file-loader even needed here ? Either explicitly add the type to the rule in webpack.config.js or use a different extname for inline usage (e.g x.manifest). The inline loader syntax is discouraged for a while now and it would even work in case x-loader supports module.type = 'json'.

@joelcollyer
Copy link

For anyone who's encountering the error Module parse failed: Unexpected token m in JSON at position 0 like I was, and you find this thread, you don't need to specify that json files be loaded in any special way.

Simply require your files like this:

const langFile = require('./locale/en/lang.json');

Webpack 4.x will do the rest.

No special tests, configuration, or loaders are needed for .json to be required in your JavaScript.

@rlefever68
Copy link

Please check the encoding of your .json file.
It is probably 'UTF-8 with BOM'.
Resave the file with pure 'UTF-8' and it should be solved.

@jminnick
Copy link

jminnick commented Jul 4, 2018

@joelcollyer not sure why the down votes on your post as removing the loader in my Webpack config worked for me.

I guess the only reason I can think of is it assumes you are using Webpack 4[x].

Again, if you are using Webpack 4[x] @joelcollyer is correct.

@BobbyBabes
Copy link

@joelcollyer The only problem with using require() to read JSON files, is that the file will be cached. Unless it's deleted from require()'s cache.

@joelcollyer
Copy link

@BobbyBabes: I fully agree; it'd be best to fetch json with an async request most of the time.

In this case we were loading a mandatory language file, so the require isn't so bad. If you try to do that with an import tree shaking gets in the way and the file isn't loaded.

My point was mostly that no webpack configuration is required for it to understand the loading of a json file (unlike the additional configuration you'd have to do for say, sass, or jsx loading).

@crloshro
Copy link

@joelcollyer thank you so much, that tip helped me to fix the bug!

@naretini
Copy link

naretini commented Feb 14, 2019

In my package.json I have:
"scripts":{ ... "build-mydir01": "webpack --env.ext mydir01 --mode production ./code/mydir01/index.js --output ./public/mydir01/main.js", ... }

In my webpack.config.js:
`
const HtmlWebPackPlugin = require("html-webpack-plugin");

module.exports = function (env) {
console.log(env, env);
const ext = env.ext || 'src';

const ext_file = require('./code/' + ext + '/extension.json');

return {
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            },
            {
                test: /\.(json)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {},
                    },
                ],
            },
            {
                test: /\.(html)$/,
                use: [
                    {
                        loader: "html-loader"
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebPackPlugin({
            template: `./code/${ext}/index.html`,
            filename: "./index.html"
        })
    ]
}

};
`

After executing:

npm run build-mydir01

In my ./public/mydir01/ i see index.html and main.js but extension.json is not moved there....
What do I miss?

@blachawk
Copy link

blachawk commented Mar 3, 2019

Is there any official documentation on how to output JSON files to my /dist folder with Webpack 4?

Simply adding const langFile = require('./locale/en/lang.json'); to my webpack.config.js file does not tell me much or do much for me with Webpack 4. I still encounter the same error.

@garkin
Copy link

garkin commented Oct 14, 2019

Correct way to use file-loader with JSON in Webpack 4+:

{
	test: /\.json$/,
	loader: 'file-loader',
	type: 'javascript/auto'
},

@zaitebaki
Copy link

Correct way to use file-loader with JSON in Webpack 4+:

{
	test: /\.json$/,
	loader: 'file-loader',
	type: 'javascript/auto'
},

best wishes, you awesome :)))
With saving path:

      {
        test: /\.json$/,
        loader: 'file-loader',
        type: 'javascript/auto',
        options: {
          name() {
            return '[path][name].[ext]';
          },
        },
      }

@Garwin4j
Copy link

Correct way to use file-loader with JSON in Webpack 4+:

{
	test: /\.json$/,
	loader: 'file-loader',
	type: 'javascript/auto'
},

best wishes, you awesome :)))
With saving path:

      {
        test: /\.json$/,
        loader: 'file-loader',
        type: 'javascript/auto',
        options: {
          name() {
            return '[path][name].[ext]';
          },
        },
      }

So I do this, the project build and loads, but it seem the JSON import is undefined like it isn't ready the JSON. is anyone else getting this? Does your application still recognize the JSON values after doing tihs.

@kevinlabx
Copy link

kevinlabx commented Jan 6, 2020

Correct way to use file-loader with JSON in Webpack 4+:

{
	test: /\.json$/,
	loader: 'file-loader',
	type: 'javascript/auto'
},

@garkin
Thank you this actually works.

@stories2
Copy link

stories2 commented Mar 5, 2020

Correct way to use file-loader with JSON in Webpack 4+:

{
	test: /\.json$/,
	loader: 'file-loader',
	type: 'javascript/auto'
},

best wishes, you awesome :)))
With saving path:

      {
        test: /\.json$/,
        loader: 'file-loader',
        type: 'javascript/auto',
        options: {
          name() {
            return '[path][name].[ext]';
          },
        },
      }

With exclude node_modules it makes best for me.

{
        test: /\.json$/,
        loader: 'file-loader',
        type: 'javascript/auto',
        exclude: /node_modules/
      }

@RezaZR
Copy link

RezaZR commented Apr 24, 2020

Adding esModule works best for me. Thank you for the solution

{
        test: /\.json$/,
        use: [
          {
            loader: "file-loader",
            options: {
              esModule: false,
            },
          },
        ],
        type: "javascript/auto",
      },

@Richifg
Copy link

Richifg commented May 2, 2020

Correct way to use file-loader with JSON in Webpack 4+:

{
	test: /\.json$/,
	loader: 'file-loader',
	type: 'javascript/auto'
},

This is working for me, my bundle now builds successfully and I have a separate JSON file, but now my app stop working. The js in the bundle that imports the JSON file is only getting a string with the file name instead of the javascript object I was receiving before extracting the JSON file from the bundle.

Any idea what can he causing this?

@Garwin4j
Copy link

Garwin4j commented May 3, 2020

I had the same problem. For this you have to read the file as a normal text file and transform it at runtime:

 return Axios.get(`/Config.json`, {
        method: 'GET',
      }).then(x => {
        ConfigService.globalConfig = x.data;
        return ConfigService.globalConfig;
      });

The thing to consider thou is to ensure this is done before the file is used in code.

Note that I spit out the file at the root of the app:

{
    test: /\Config.json$/,
    loader: 'file-loader',
    type: 'javascript/auto',
    options: {
      name(file) {
        return '[name].[ext]';
      },
    },
  }

@Richifg
Copy link

Richifg commented May 3, 2020

@Garwin4j thanks for the quick reply, yes I ended loading the failed asyncronously as well. I did it with fetch api and it worked well.

fetch('content.json')
      .then((res) => res.json())
      .then((data) => console.log(data))

In this example the file is also at the root.

@Eli-Black-Work
Copy link

So, to sum this up:

If you want Webpack to load the contents of your JSON, so that you can immediately use it in your code, don't use file-loader at all. (#259 (comment))

Example:

Your code

import languages from './languages.json';

console.log(translations);  // { english: 'English', spanish: 'Español' }

This method has a downside: The entire contents of the JSON file gets bundled into your app's .js file, which of course makes your app larger.

If you want to load your JSON file via AJAX, use file-loader. (#259 (comment))

Example:

Webpack config file

{
	test: /\.json$/,
	loader: 'file-loader',
	type: 'javascript/auto'
}

Your code

import languagesFileUrl from './languages.json';

console.log(languagesFileUrl);  // This just returns the URL of your JSON file. For example: '/languages.json'. You should then fetch the file via AJAX.

fetch(languagesFileUrl)
...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests