12

Is there something to enable to have next.js perform tree-shaking/removal of dead code from dependencies? I've exported two objects like this:

library.js

export const foo = {foo:"foo"}
export const bar = {bar:"bar"}

And in my next.js app I do like this:

page.tsx

import { foo } from 'library';
console.log(foo);

So now I'd expect a production-build will not include bar, and indeed something appears to go right because this line is produced:

.next/server/chunks/621.js

/* unused harmony exports bar */

But confusingly when I load the app in the browser the network-traffic indicates the unused export is included:

http://localhost:3001/_next/static/chunks/pages/page-0b2b13a7513f2849d855.js

(self.webpackChunk_N_E = self.webpackChunk_N_E || []).push([[3031], {
    80621: function(e, r, n) {
        "use strict";
        ...
        const l = a.object({
            foo: "foo"
        });
        a.object({
            bar: "bar"
        });
    },

Why would the build identify unused exports but not remove them from the payload that's transferred to the browser? Is there a setting Next expects us to enable? Some sort of post-processing that actually prunes unused exports?

Jon Lauridsen
  • 2,521
  • 5
  • 31
  • 38
  • 1
    I don’t have an answer to this but I am a bit familiar with Next.js and I can say that it does a lot to your bundle during the build process, especially if hosted on Vercel. With that said I looked around for similar issues and didn’t find much so if you find anything please share. I’m upvoting this. – A Webb Sep 02 '21 at 00:23
  • 1
    I've set up a new Next.js project here: https://github.com/gaggle/next.js-tree-shaking and it **DOES** tree-shake. So it appears I have a configuration issue in my full project to trace down – Jon Lauridsen Sep 08 '21 at 09:27
  • 1
    Yikes, good luck! – A Webb Sep 08 '21 at 20:06
  • if I am not mistaken the comment `/* unused harmony exports bar */` is so that UglifyJS can identify it can delete this bit. – Coffeeholic Apr 08 '22 at 09:35
  • For me if I export a function referring `createHash` of `crypto`, even though no where in my app refers to that function, nextjs seems to still includes the entire code of `crypto` when I see the big difference in the bundle size of `chunks/pages/_app.js`. I guess that inside `crypto`, there is this kind of code: `import "some-module"`. – Changdae Park Sep 06 '22 at 10:57

1 Answers1

0

I believe the issue with your example is that Next.js is able to tree-shake primitive values (boolean, string, int,...) and object/array's with primitive values.

However, webpack, the bundler used in Next.js, isn't able to identify whether a function call has any side-effects.

From this Github Issue #12557, some users report that setting "sideEffects:false in the package.json or even modifying webpack in the next.config.js solved this issue.

None of those worked for me. Instead, marking function's as side-effect-free using the /*#__PURE__*/ annotation worked.

Example:

const createApi = (message) => {
  console.log(message);
  return () =>{}
}

export const serverApi = /*#__PURE__*/ createApi("I should only be available server side.")

export const clientApi = /*#__PURE__*/ createApi("I should only be available client side.")

Writing my code like above prevented serverApi from being included in the client bundle.

It should be noted, that the syntax of the annotation is /*#__PURE__*/ fn(). All other usages won't work.

Advena
  • 1,664
  • 2
  • 24
  • 45