3

Given the following two files :

//a.js
export const X = /*#__PURE__*/ "X";

const a = function () {
  return "About a!";
};
a.foo = function () {
  return "foo";
};
export default a;

and

//main.js
import { X } from "./a";
import { Y } from "./b";

console.log(X, Y);

I have added

  • "sideEffect": false to package.json
  • optimization.usedExports: true to webpack.config.js

but running webpack -p still includes the whole a.js file in the bundle. Rollup only includes X from a.js (demo)

Removing the a.foo definition "fixes" the issue but is not a solution outside the demo repository. I have read the tree-shaking documentation page multiple times, read [countless issues about tree shaking on the webpack issue tracker, I still cant figure out the following :

  • Why is the /*#__PURE__*/ marker on X not being used ?
  • Is there a way to configure webpack to only include X from a.js ?

You can also checkout the sandbox repository to see the full webpack configuration and the corresponding next.js/react issue (see pages/index.jsx) which led me to this specific issue.

Jean
  • 21,329
  • 5
  • 46
  • 64

2 Answers2

1

After raising the issue on webpack's issue tracker ~sokra provided an answer:

Seems like a single compression pass in terser is not enough to compress this code.

The default number of passes is 1 but once raised to 3, a.js is no longer fully inlined. This is how this can be achieved at the cost of a longer build time.

const TerserWebpackPlugin = require("terser-webpack-plugin");

/** @type {import("webpack").Configuration} */
module.exports = {
    optimization: {
        minimizer: [
            new TerserWebpackPlugin({
                terserOptions: {
                    compress: {
                        passes: 3
                    }
                }
            })
        ]
    }
}
Jean
  • 21,329
  • 5
  • 46
  • 64
0

My guess: export default affects tree shaking. See: https://medium.com/@bluepnume/javascript-tree-shaking-like-a-pro-7bf96e139eb7#43e1

Try not remove the default.

noirbizarre
  • 3,429
  • 1
  • 30
  • 21
  • As mentionned in my question, if I remove the `a.foo=` definition the default export is correctly tree-shaken. Also whether with or without the `a.foo` definition, the export is correctly marked as `/* unused harmony default export */` – Jean Jun 08 '20 at 16:48
  • the article is interesting, I will look into the plugins it recommends – Jean Jun 08 '20 at 16:51
  • both techniques described in the article fail to detect a tree shaking failure which would explain the full inlining of a.js – Jean Jun 15 '20 at 13:12