2

Webpack has a JSON loader built into it. How can I write a custom loader that doesn't try to run the built-in JSON loader on the result?

Basically, I want my loader to take in a config object (stored in a JSON file) and generate source code from that configuration, which is no longer valid JSON, it's JavaScript (which could subsequently be fed through babel-loader).

Here's a really stupid, contrived example. The source file is a JSON file, but I want the output of my loader to instead be some JS.

Loader

function compile(doc) {
  return `alert(${JSON.stringify(doc.title)})`
}

function myLoader(source) {
  return compile(JSON.parse(source))
}

Webpack config

rules: [
  {
    test: /\.json$/,
    use: [
      'babel-loader',
      'my-loader',
    ],
  },
],

Instead, I end up getting this error:

ERROR in ./config.json
Module parse failed: Unexpected token ' in JSON at position 0
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token ' in JSON at position 0
  at JSON.parse (<anonymous>)
  at JsonParser.parse (.../node_modules/webpack/lib/JsonParser.js:15:21)

As you can see from the stack trace, it's coming from webpack/lib/JsonParser.js. How can I tell Webpack not to run its built-in JSON parser in the first place, and instead delegate the processing of JSON files that match this rule to my loader?

M Miller
  • 5,364
  • 9
  • 43
  • 65
  • How about just use `const config = require('./config.json');`? – Tan Duong May 02 '18 at 06:30
  • The goal here is for an `import './config.json'` to compile the JSON into executable JS at build time, because currently the app simply embeds our JSON object into the app bundle and performs this work at runtime. Since this is a resource-intensive task in our app, and since the JSON is constant, we want to compile the JSON directly into executable code – M Miller May 02 '18 at 06:33
  • check this https://stackoverflow.com/questions/35563915/webpack-ignore-loaders-in-require?rq=1 hope it helps(and if it works - please create/confirm an answer on your own) – skyboyer May 02 '18 at 06:39

1 Answers1

2

I think I figured it out, although it appears to be an undocumented feature (at least, I couldn't find it on the configuration docs.

It looks like one of the properties you can pass in the Rule object is type. By setting it to javascript/auto, you can override the default JSON parser and have it parse the source of the file as JavaScript.

This property is in the JSON schema used by Webpack to validate the config object.

rules: [
  {
    test: /\.json$/,
    use: [
      'babel-loader',
      'my-loader',
    ],
    type: 'javascript/auto',
  },
],
M Miller
  • 5,364
  • 9
  • 43
  • 65