1

I have a webpack loader called messageformat-loader that takes in JSON, passes it through messageformat.js, and outputs the resulting map of format functions. It works fine with a single file.

./simple-messages.json

{
  "simple-example": "A simple message.",
}

./example.js

var messages = require('messageformat?locale=en!json!./simple-messages.json');
console.log(messages['simple-example']());

To run

$ npm install webpack messageformat-loader messageformat@1.0.0-rc.3 json-loader
$ node_modules/.bin/webpack ./example.js bundle.js
<...omitted webpack output...>
$ node bundle.js
A simple message.

messageformat.js's CLI, however, accepts a glob of files, which it then aggregates into one JSON object using the name of the file as its key before passing it through the compiler.

How would I accomplish this using webpack since globs aren't supported?

./multi-example.js

var messages = require('messageformat?locale=en!json!./*.json');
console.log(messages['simple-messages']['simple-example']());

To run

$ node_modules/.bin/webpack ./multi-example.js bundle.js
<...omitted webpack output...>

ERROR in ./multi-example.js
Module not found: Error: Cannot resolve 'file' or 'directory' ./*.json in <path>/test123
 @ ./multi-example.js 1:15-63
<path>/test123/bundle.js:47
  var messages = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"messageformat?locale=en!json!./*.json\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()));

Error: Cannot find module "messageformat?locale=en!json!./*.json"
    at webpackMissingModule (<path>/test123/bundle.js:47:81)
    at Object.<anonymous> (<path>/test123/bundle.js:47:195)
    at __webpack_require__ (<path>/test123/bundle.js:20:30)
    at <path>/test123/bundle.js:40:18
    at Object.<anonymous> (<path>/test123/bundle.js:43:10)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Function.Module.runMain (module.js:441:10)

My attempts:

  • Apply the glob in webpack.config.js itself (as recommended here)

    • How do I aggregate the results and pass them into messageformat-loader? If I don't, I'll have messageformat.js's runtime included once for each JSON file.
      • It looks like this may actually be the better approach, but I'd have to modify messageformat.js's output to separate the runtime from the strings.
  • Use require.context (as recommended here)

    • See above
  • multi-json-loader

    • Unfortunately, this is awkward because webpack requires a resource file even if it isn't used

      require('messageformat?locale=en!multi-json?cwd=data&glob=**/*.json!./irrelevant.whatever')
      
    • I could move the glob into the resource file, like glob-loader, but having parameters to your loader be pulled from a source file seems even more awkward to me.

      • This is what fontgen-loader also does, so this looks like a common approach.
  • Should I make a messageformat-plugin instead of a loader? Then I'd have full control over the chunks. This feels like the wrong abstraction, though.

CletusW
  • 3,890
  • 1
  • 27
  • 42

1 Answers1

-1

I think what you want is what is called a "resolver" plugin ( in combination with your webpack loader). Pairing a plugin and a loader isn't off limits (see extract text plugin :-).

compiler.resolvers.normal.plugin('resolve', function resolverPlugin(request, cb) {
  ... 
});