I'm experimenting with Webpack and React, trying out new loaders to see how they work. Here's my webpack.config.js
:
const webpack = require('webpack')
const path = require('path')
module.exports = {
entry: "./src/index.js",
mode: "development",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: "babel-loader",
options: { presets: ["@babel/env"] }
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.txt$/,
use: 'raw-loader',
},
{
test: /\.json$/,
use: 'json-loader',
}
],
},
resolve: {
extensions: ["*", ".js", ".jsx"],
},
output: {
path: path.resolve(__dirname, "dist/"),
publicPath: "/dist/",
filename: "bundle.js",
},
plugins: [new webpack.HotModuleReplacementPlugin()],
devServer: {
contentBase: path.join(__dirname, "public/"),
port: 3000,
hotOnly: true,
publicPath: "http://localhost:3000/dist/",
}
}
As you can see, json-loader
is included in the 'rules' section.
I have "json-loader": "^0.5.7"
installed under the 'dependencies' section of my package.json, and have run yarn install
to make sure it's included in my node_modules directory.
I have a simple 'foo.json' file in my /src directory which looks like this:
{
"foo": "bar",
"bazz": {
"buzz": [1, 2, 3, 4, 5]
}
}
And I am importing this JSON into a React component:
import React from "react";
import "./App.css";
import text from './foo.txt';
import myJson from './foo.json'
const App = () => {
const buzz = myJson.bazz.buzz;
return (
<div className="App">
<h1> Hello, World! </h1>
{
text.split("\n").map((item) => <p>{item}</p> )
}
<ul>
{ buzz.map((item) => <li>{item}</li> )}
</ul>
</div>
);
}
export default App;
However, when I run yarn run build
, I get the following error:
ERROR in ./src/foo.json
Module parse failed: Unexpected token m in JSON at position 0 while parsing near 'module.exports = {"f...'
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token m in JSON at position 0 while parsing near 'module.exports = {"f...'
at JSON.parse (<anonymous>)
at parseJson (/Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/json-parse-better-errors/index.js:7:17)
at JsonParser.parse (/Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/webpack/lib/JsonParser.js:16:16)
at /Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/webpack/lib/NormalModule.js:445:32
at /Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/webpack/lib/NormalModule.js:327:12
at /Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/loader-runner/lib/LoaderRunner.js:373:3
at iterateNormalLoaders (/Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/loader-runner/lib/LoaderRunner.js:214:10)
at iterateNormalLoaders (/Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/loader-runner/lib/LoaderRunner.js:221:10)
at /Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/loader-runner/lib/LoaderRunner.js:236:3
at runSyncOrAsync (/Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/loader-runner/lib/LoaderRunner.js:130:11)
at iterateNormalLoaders (/Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/loader-runner/lib/LoaderRunner.js:232:2)
at Array.<anonymous> (/Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/loader-runner/lib/LoaderRunner.js:205:4)
at Storage.finished (/Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:55:16)
at /Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:91:9
at /Users/richiethomas/Desktop/Workspace/InvestmentTime/new-react-app/node_modules/graceful-fs/graceful-fs.js:123:16
at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:63:3)
@ ./src/App.js 4:0-32 7:13-19
@ ./src/index.js
It says I need an appropriate loader to handle this type, but isn't that what json-loader
is supposed to do? Do I have a setup or syntax error somewhere?
I have raw-loader
installed and I'm able to import and render the text from foo.txt
successfully, so I'm confused why json-loader
isn't similarly straightforward for me.
Thanks.
EDIT:
I also get this same error when I use const myJson = require('./foo.json');
instead of import myJson from './foo.json'
.
Also interestingly, when I remove json-loader
from my Webpack config, both require
and import
work as expected.
So, my immediate problem of getting the JSON to load is solved, but I'd still like to know why json-loader
wasn't working the way I expected it to.
EDIT #2:
From the docs, I do see that there is special require
syntax for inline-importing a JSON file via json-loader:
const json = require('json-loader!./file.json');
I tried the following, but it also didn't work:
const myJson = require('json-loader!./foo.json');
CodePudding user response:
From the error message posted
Module parse failed: Unexpected token m in JSON at position 0 while parsing near 'module.exports = {"f...'
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token m in JSON at position 0 while parsing near 'module.exports = {"f...'
It looks like the most important part has been truncated a bit.
Note that the first token according to webpack's parser of the posted file is a CommonJS export.
Many webpack loaders are string to string transforms. One after another. The default webpack JSON handling is to convert the file into a CommonJS/ESM as a string. json-loader
is probably expecting raw JSON, and is instead getting the string form of a CommonJS module of the same.
https://webpack.js.org/migrate/4/#json-and-loaders suggests removing the JSON loader unless you have special file endings for JSON files.