VOOZH about

URL: https://blog.logrocket.com/tree-shaking-json-files-webpack/

⇱ Tree shaking JSON files with webpack - LogRocket Blog


2022-01-06
1206
#webpack
Kumar Abhirup
85338
👁 Image

See how LogRocket's Galileo AI surfaces the most severe issues for you

No signup required

Check it out

Tree shaking is critical to developers because it removes dead code and unused functions, variables, and methods that take up space in your final production build.

👁 Treeshaking JSON in Webpack

Popular tools like rollup.js and webpack perform out-of-the-box tree shaking when compiling multiple JavaScript files into a single one.

In frontend development, modules and packages are managed in various ways to achieve the best results. During development, your code will be split into many small modules.

When you deploy your application, you should bundle these modules into one — or a few very large — files, preferably using webpack.

Why, you ask? Here are a few reasons.

  • A bundled file is easier to compress versus multiple, non-bundled JavaScript files
  • When loading all the modules, it’s preferable to load them from fewer files rather than several
  • Unused exports get removed when bundling (i.e., tree shaking), helping to save space and reduce the final build size

🚀 Sign up for The Replay newsletter

The Replay is a weekly newsletter for dev and engineering leaders.

Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.

Tree shaking JSON files

Imagine you have this JSON file, named strings.json.

{
 "usedString1": "Hello world!",
 "usedString2": "Hello world again!",
 "unusedString": "I'm never used in the code ever"
}

Now, try to access its content in JavaScript index.js, like so:

const strings = require("./strings.json");
console.log(strings.usedString1, strings.usedString2);

You’d see we are only using one key in the entire JSON file, the usedString. unusedString is dead code, so we’re not using it. Yet, when you import/require strings.json, the dead code comes with it and makes its way into your final build, taking significant space and increasing your file size unnecessarily.

Currently, when you bundle with webpack, dead JSON code is not removed by default. You must use a webpack plugin, generally webpack-json-access-optimizer.

Let’s see how this plugin tree shakes your code using a JSON file.

The plugin first converts the JSON structure into an array, so strings.json now looks like this:

["Hello world!", "Hello world again!"]

The plugin compiles JavaScript code to adjust to this new array structure, so index.js now looks like this:

const strings = require("./strings.json");
console.log(strings[0], strings[1]);

Notice in strings.json that the plugin removes the unused value, unusedString.

Using webpack-json-access-optimizer

Here’s a GitHub demo I’ve created. First, clone it.

git clone https://github.com/KumarAbhirup/webpack-treeshaking-json

Now, run yarn, yarn build, and yarn start.

If you check webpack.config.js, you’ll see it’s pretty simple, except from lines 16 to 33.

const path = require('path');
const DIST_DIR = path.resolve(__dirname, 'dist');

const { JsonAccessOptimizer } = require('webpack-json-access-optimizer');
const { ProvidePlugin } = require('webpack');

let config = {
 entry: './src/index.js',
 output: {
 filename: 'bundle.js',
 path: DIST_DIR
 },
 resolve: {
 extensions: ['.js', '.json']
 },
 module : {
 rules: [
 {
 test: /strings\.json$/,
 use: [
 'webpack-json-access-optimizer', 
 ],
 type: 'json'
 }
 ]
 },
 plugins: [
 new ProvidePlugin({
 $t: './$tProvider'
 }),
 new JsonAccessOptimizer({
 accessorFunctionName: '$t', // i18n function name
 })
 ],
 optimization: {
 usedExports: false,
 },
 devtool: 'source-map'
};
module.exports = config;

Take a closer look here:

module : {
 rules: [
 {
 test: /strings\.json$/,
 use: ['webpack-json-access-optimizer'],
 type: 'json'
 }
 ]
},
plugins: [
 new ProvidePlugin({
 $t: './$tProvider'
 }),
 new JsonAccessOptimizer({
 accessorFunctionName: '$t', // i18n function name
 })
],

Notice we tell webpack to parse strings.json using the webpack-json-access-optimizer plugin so we can tree shake the JSON file.


Over 200k developers use LogRocket to create better digital experiences

👁 Image
Learn more →

In the plugins section, we make the $t function available globally so that all files will be able to access strings.json, like so: $t('usedString1').

Now, check out ./src/$tProvider.js.

const t = require("./strings.json");
const $t = keyString => {
 return t?.[keyString];
};
module.exports = $t;

It fetches all key-value pairs from strings.json, then exports a default function that returns the value by taking in a key string.

Let’s look at our ./src/index.js file. We are using the $t function that we made available on a global scope.

console.log($t("usedString1"), $t("usedString2"));

Now, if you code yarn build && yarn start, you should see an output like this.

➜ webpack-treeshaking-json git:(main) yarn start
yarn run v1.19.1
$ node dist/bundle.js
Hello world! Hello world again!
✨ Done in 0.26s.

Reviewing the compiled code

Let’s check out the compiled code in ./dist/bundle.js:

(()=>{var r,o={500:(r,o,e)=>{const t=e(46);r.exports=r=>t?.\[r]},46:r=>{"use strict";r.exports=JSON.parse('["Hello world!","Hello world again!"]')}},e={};r=function r(t){var s=e[t];if(void 0!==s)return s.exports;var l=e[t]={exports:{}};return o[t\](l,l.exports,r),l.exports}(500),console.log(r(0),r(1))})();
//# sourceMappingURL=bundle.js.map

You’ll see it only uses key-value pairs from strings.json that were actually used in the code, and it omits the unusedString. This way, you save important space in your final build.

Tree shaking and removing unused exports

Let’s look at this JavaScript file.

const sum = (a, b) => {
 return a + b;
};

const multiply = (a, b) => {
 return a * b;
};

const divide = (a, b) => {
 return a / b;
};

console.log(sum(1, 9));

module.exports = { sum, multiply };

You can see that the divide function is present in the code but is not being put to use anywhere, but functions such as sum and multiply are being used in the code.


More great articles from LogRocket:


sum() was used in the console.log() statement, and also in the module.exports when we exported that function. multiply() is used in module.exports upon exporting the function.

If you compile this without tree shaking, the divide function will be present in the compiled code, hogging space even though it isn’t being used.

Additional learning

Eliminating unused exports using webpack

Eliminating unused exports with webpack also helps save space, greatly reduce the final build size, and result in quicker page load times.

Use this setting for your webpack config:

optimization: {
 usedExports: true
}

webpack.config.js should now look like this:

const path = require('path');
const DIST_DIR = path.resolve(__dirname, 'dist');

const { JsonAccessOptimizer } = require('webpack-json-access-optimizer');
const { ProvidePlugin } = require('webpack');

let config = {
 entry: './src/index.js',
 output: {
 filename: 'bundle.js',
 path: DIST_DIR
 },
 resolve: {
 extensions: ['.js', '.json']
 },
 module : {
 rules: [
 {
 test: /strings\.json$/,
 use: [
 'webpack-json-access-optimizer', 
 ],
 type: 'json'
 }
 ]
 },
 plugins: [
 new ProvidePlugin({
 $t: './$tProvider'
 }),
 new JsonAccessOptimizer({
 accessorFunctionName: '$t', // i18n function name
 })
 ],
 optimization: {
 usedExports: true,
 },
 devtool: 'source-map'
};

module.exports = config;

Notice the usedExports: true above. With it, unused functions and variables won’t make it in your final build and compiled code.

Tree shaking CSS

If you have configured webpack to import CSS modules in JS before, you might want to learn how to tree shake the CSS you are importing. CSS code often goes unused, so this would be helpful to optimize your app.

Say you have a CSS rule in your webpack config:

{
 test: /\.css$/,
 use: ['style-loader', 'css-loader'],
}

You just have to add the sideEffects: true property to it.

{
 test: /\.css$/,
 use: ['style-loader', 'css-loader'],
 sideEffects: true
}

After doing so, and assuming your webpack config mode: 'production' is set, it should tree shake all of your imported CSS files during compilation — awarding you a huge bundle size reduction to make apps production-ready!

Conclusion

Tree shaking your code is critical when you compile code. Webpack does perform tree shaking for JavaScript exports, but it doesn’t do so with JSON files unless you use webpack-json-access-optimizer. Using these techniques in your projects should save you space and optimize your apps. Happy coding!

Get set up with LogRocket's modern error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID
  2. Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not server-side

    $ npm i --save logrocket 
    
    // Code:
    
    import LogRocket from 'logrocket'; 
    LogRocket.init('app/id');
     
    // Add to your HTML:
    
    <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
     
  3. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • NgRx middleware
    • Vuex plugin
Get started now
👁 Image
👁 Image
👁 Image

Stop guessing about your digital experience with LogRocket

Get started for free

Recent posts:

What is TSRX?: What JSX would look like if it were designed today

TSRX adds first-class control flow, conditional hooks, and scoped styles to React via a TypeScript compiler extension — no new framework required.

👁 Image
Ikeh Akinyemi
Jun 12, 2026 ⋅ 6 min read

How to add authentication to a React Native app with Better Auth

Learn how to build a full React Native auth system using Better Auth and Expo — with email/password login, Google OAuth, session persistence, and protected routes.

👁 Image
Chinwike Maduabuchi
Jun 9, 2026 ⋅ 13 min read

AI dev tool power rankings & comparison [June 2026]

Compare the top AI development tools and models of June 2026. View updated rankings, feature breakdowns, and find the best fit for you.

👁 Image
Chizaram Ken
Jun 8, 2026 ⋅ 11 min read

How to check username availability at scale with Bloom filters

Learn how Bloom filters reduce database lookups for username availability checks while preserving correctness at scale.

👁 Image
Rosario De Chiara
Jun 8, 2026 ⋅ 6 min read
View all posts

Hey there, want to help make our blog better?

Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

Sign up now