11

I am building a reactJs bundle with webpack. I am currently trying to concatenate json files into an object to use with i18next. I feel it's simple, I don't want to use overcomplicated solutions.

I have a directory structure like

messages/locale_name/domain_name.json

How can I import all the json files in a regular object in my code ?

So far, I'm struggling at the very beginning as I found suggestions which need to require('fs") but webpack tells me it cannot resolve the fs module and I've seen I can't install it as it is part of default node config.

Some help appreciated.

Thanks !

6
  • My answer doesn't totally answer the question -- if you are looking to dynamically detect which i18n files are available, it seems like you'd want to create another JSON file that lists out the JSON files. This would be very easy to do in a script, or a custom WebPack plugin. There may already be a WebPack plugin to do this like webpack-shell-plugin
    – mejdev
    Commented May 6, 2016 at 13:00
  • well, this json-loader does not really help as i'd like to customize the way the object is created in a loop. My stuff seem pretty standard, I would know how to do it in php but I'm stuck here with npm & webpack as i can't find a way to get require('fs') to work out. thanks anyway
    – Sébastien
    Commented May 6, 2016 at 14:40
  • fs would be available in a webpack plugin since webpack runs on Node, but fs is not available on a web app that's running in the browser. You could write JS to pull the JSON files from the web and parse them that way. As far as the json-loader, it gives you a JavaScript object that you can do anything you want with it. How would you "customize the way the object is created"? Sounds like you would just normalize the JSON?
    – mejdev
    Commented May 6, 2016 at 14:41
  • 1
    well, indeed, I understand I can't use fs in a client js. But can't I loop through files of a directory and make it available for webpack ? the idea is I want to concatenate all my language files and I'd prefer to include this in the bundle rather than make another xhr call
    – Sébastien
    Commented May 6, 2016 at 14:47
  • Okay; I suggest you re-read my first comment and then look into webpack-shell-plugin. I believe it can do what you need it to.
    – mejdev
    Commented May 6, 2016 at 14:48

4 Answers 4

7

After a lot of futzing around, it was actually pretty easy. Below is what I ended up with. The key was getting the JSON Loader set up properly.

Install the JSON Loader for Webpack

  1. npm install --save-dev json-loader

Add the JSON Loader to your Webpack loaders

  1. This is required to use context to pull the files in.
  2. Add this to your webpack.config.js loaders { test: /\.json$/, loader: 'json' },
  3. The final might be something like this:
module.exports = {
  entry: './src/app.js',
  output: { path: __dirname, filename: './build/bundle.js' },
  module: {
    loaders: [
      { test: /\.json$/, loader: 'json' }
    ]
  }
}

Use Context to load the files in and save them into an array

in my app.js:

function requireAll( requireContext ) {
  return requireContext.keys().map( requireContext );
}
var modules = requireAll( require.context("./modules", false, /.json$/) );
  1. Where "modules" is a subdirectory from my app.js (./src/modules in my case).
  2. All of the JSON files will be loaded into an array [Object, Object, Object], which I am storing into var modules
1
  • Sorry a little new to webpack, I was wondering if I am understanding your requireAll() function correctly. So you map the keys of the requireContext using the requireContext as the mapping function, is the result built during build or run time? Commented Dec 28, 2016 at 4:49
0

This is best done with something like json-loader

With it installed (npm install json-loader --save-dev), you could either import as described in the projects readme:

var json = require("json!./messages/locale_name/domain_name.json");

Or you could add a loader to your webpack.config.js and import the json normally:

webpack.config.js:

module: { 
    loaders: [
        {test: /\.json$/, loader: 'json-loader'},
    ]
},

And in your source:

var json = require("./messages/locale_name/domain_name.json");

Or of course, you could use ES6 imports if that's what you use in your project

0

To merge json files use merge-webpack-plugin (also with grouping for example by filename)

Example configuration:

MergePlugin = require("merge-webpack-plugin");
module.exports = {
  module: {
    rules: [
      {
        test: /\.(json)$/i, use: [ MergePlugin.loader() ],
        // also yaml by preloader there too 
        test: /\.(yaml)$/i, use: [ MergePlugin.loader(), 'yaml-loader' ],
      }
    ]
  },
  plugins: [
    new MergePlugin({
      search: './src/**/*.json',
      group: '[name]',
    })
  ]
}

It this example files will be devided into groups by filename. Each group will be loaded and merged and saved into destination json file. To require destination merged file you only need to require one its source file and load it.

0

@Sébastien check this plugin https://www.npmjs.com/package/merge-jsons-webpack-plugin

You can pass array of files/patterns as an input and it will emit single file as json.

for example if you have many json files inside a directory /node_modules/module-a and /node_modules/module-b

You can use below pattern to concatenate all jsons into one single json file like below

new MergeJsonWebpackPlugin({
  "files": [
    './jsons/file1.json',
    './jsons/file3.json',
    './jsons/file2.json'
  ],
  "output":{
    "fileName":"./dist/result.json"
  },
})

Disclaimer: I contributed to this plugin

1
  • Please, add some relevant information in your answer. Link only answers are not encouraged. Commented Feb 9, 2017 at 21:09

Not the answer you're looking for? Browse other questions tagged or ask your own question.