Lodash not TreeShaking with Webpack with Webpack 4?
Asked Answered
V

2

9

I want to tree shake lodash as well as my unused multiply function from the generated bundle from webpack

I have 2 main files app.js & math.js

It contains the following code -

app.js

import map from "lodash/map";

import { sum } from "./math";

console.log("πŸ’©");

console.log(`2 + 3 = ${sum(2, 3)}`);

map([1, 2, 3], x => {
    console.log(x);
});

math.js

export const sum = (a, b) => a + b;
export const multiply = (m, n) => m * n;

webpack.config.js

const path = require("path");
const webpack = require("webpack");
const UglifyJSPlugin = require("uglifyjs-webpack-plugin");
const Jarvis = require("webpack-jarvis");

let plugins = [new Jarvis()];

if (process.env.NODE_ENV === "production") plugins.push(new UglifyJSPlugin());

const config = {
    entry: "./app.js",
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "bundle.js"
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: "babel-loader"
            }
        ]
    },
    plugins
};

module.exports = config;

My npm script look like -

"scripts": {
    "dev": "webpack --optimize-minimize --mode development",
    "dev:watch": "webpack --watch --optimize-minimize --mode development",
    "prod": "webpack -p --optimize-minimize --mode production",
    "prod:watch": "webpack -p --watch --optimize-minimize --mode production",
    "start": "npm run prod",
    "clean": "rm -rf dist"
  }

The complete code is available at https://github.com/deadcoder0904/webpack-treeshake

I've tried using UglifyJSPlugin but in the generated bundle it still shows my unused multiply function from math.js. Also, the production bundle generated from npm run prod remains 20kB which is a lot & I see a lot of lodash stuff included as well.

Virginia answered 15/2, 2018 at 21:37 Comment(0)
V
11

I found the answer

To use lodash with tree shaking we should first install lodash-es & then remove the lodash dependency

Also, it should not be transpiled first, so we make our .babelrc file as follows -

{
  "presets": [
    [
      "env",
      {
        "modules": false
      }
    ]
  ]
}

Notice, that setting modules to false makes it not transpile

And now the bundle reduces to 16.2kB & 5.79kB gzip

Some code from lodash module will still be used because it is required to run lodash itself, other than that multiply function from ./math.js isn't added in the resulting bundle

I also needed lodash-webpack-plugin for it to be working

Treeshaking works πŸŽ‰

I've made some basic repos solving the stated problem -

https://github.com/deadcoder0904/webpack-exam

https://github.com/deadcoder0904/webpack-treeshake

Virginia answered 16/2, 2018 at 13:48 Comment(4)
I get Unexpected token import after I try to start express with server-side-rendering. – Retrogressive
@Tomasz its because you need to transpile it to require using something like babel otherwise use require – Virginia
I have found an interesting article about it about how to configure it either via babel or with typescript: medium.com/@martin_hotell/… – Charmian
@Charmian the contents of that article aren't really relevant anymore (see the Aug. 2017 update) that was relevant before lodash pure modules and webpack 4. – Vocal
V
0

Building off of @deadcoder0904's answer, here's how to do the same with babel-loader in webpack 4 (instead of using .babelrc):

...
        {
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
                loader: 'babel-loader',
                options: {
                    plugins: ['lodash'],
                    presets: [['env', { modules: false }]]
                }
            }
        },

Note: I wasn't able to get this to work without explicitly importing from 'lodash-es' (even if I pointed lodash-es to lodash in my tsconfig (I'm using typescript). If someone can get this working without having to use the special import { map } from 'lodash-es'; and instead with import { map } from 'lodash'; it would be great to know how!

Vocal answered 27/12, 2018 at 7:12 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.