Here is a simple test case that breaks:
First, save a json file from Node:
const fs = require('fs')
let test = {
foo: [
{ 1: 'a'},
{ 2: 'b'}
]
};
fs.writeFileSync('./test.json', JSON.stringify(test), 'utf-8');
Then, try importing this json into a js file that is processed by Webpack (I am using the latest version of Webpack, 3.4.1):
import test from './test.json';
console.log(test);
This fails with the following error:
ERROR in ./test.json
Module build failed: SyntaxError: Unexpected token, expected ; (1:6)
> 1 | {"foo":[{"1":"a"},{"2":"b"}]}
The offending character that the console output is pointing at is the colon after "foo".
My Webpack config was very simple, with only these module
options:
module: {
rules: [
{
test: /\.js/,
exclude: [ path.resolve(__dirname, 'node_modules') ],
loader: 'babel-loader'
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
Confused, I opened the JSON loader page, which informed me that:
Since webpack >= v2.0.0, importing of JSON files will work by default.
Since I was using Webpack v. 3.4.1, I assumed json-loader was unnecessary. Still, out of desperation, I added the following rule to the modules field of Webpack config:
{
test: /\.json/,
loader: 'json-loader'
}
This actually worked! The json file got loaded, and the error disappeared.
So my question is: was I doing something wrong with Webpack trying to import the json file, or is the newest Webpack somehow broken as regards to the importing of json files?
The regular expression you used for the .js
rule also matches .json
, because all you're looking for is a .js
anywhere in the path. All of the following would match successfully (most of them aren't likely to be imported or even exist):
file.js
file.json
file.js.backup
.js/file.css
.jshintrc
test.json
matches the regular expression, which means that you are applying babel-loader
to it. Babel only accepts JavaScript and JSON will fail to parse. The reason that it complains about the colon (:
) is because with ES6 you can create a new scope with curly brackets. For example:
const msg = "Outer";
// Entering new scope
{
// msg is free in this scope, shadows the outer one.
const msg = "Inner";
console.log(msg); // Inner
}
// Exiting scope
console.log(msg); // Outer
// SyntaxError: Identifier 'msg' has already been declared
const msg = "Re-definition";
I don't think there are many uses of this in JavaScript, but it is used a lot more in other languages (e.g. Rust). The opening curly bracket of the JSON started a new scope, not an object, and a colon is not valid after a string in JavaScript.
To not apply babel-loader
to .json
files you need to only match .js
at the end of the path, by using the $
anchor (end of string), like you did with the .css
rule.
{
test: /\.js$/,
exclude: [ path.resolve(__dirname, 'node_modules') ],
loader: 'babel-loader'
},
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With