Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next.js includes inefficiently transpiled code #37142

Open
1 task done
gaearon opened this issue May 23, 2022 · 13 comments
Open
1 task done

Next.js includes inefficiently transpiled code #37142

gaearon opened this issue May 23, 2022 · 13 comments
Labels
bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team.

Comments

@gaearon
Copy link

gaearon commented May 23, 2022

Verify canary release

  • I verified that the issue exists in Next.js canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 21.2.0: Sun Nov 28 20:28:41 PST 2021; root:xnu-8019.61.5~1/RELEASE_ARM64_T6000
Binaries:
  Node: 16.14.2
  npm: 8.5.0
  Yarn: 1.22.15
  pnpm: 6.11.0
Relevant packages:
  next: 12.1.7-canary.11
  react: 18.1.0
  react-dom: 18.1.0

What browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

Describe the Bug

Even an empty Next.js project, when compiled, seems to include a bunch of inefficiently transpiled code.

Here is a prettified main.js from an empty Next.js project: https://gist.github.com/gaearon/6ce1f86577a55a738f2319fcdaa90892

Some parts that look particularly suspicious:

     function a(e, t) {
        (null == t || t > e.length) && (t = e.length);
        for (var r = 0, n = new Array(t); r < t; r++) n[r] = e[r];
        return n;
      }
      function i(e, t) {
        if (!(e instanceof t))
          throw new TypeError("Cannot call a class as a function");
      }
      function u(e, t) {
        for (var r = 0; r < t.length; r++) {
          var n = t[r];
          (n.enumerable = n.enumerable || !1),
            (n.configurable = !0),
            "value" in n && (n.writable = !0),
            Object.defineProperty(e, n.key, n);
        }
      }
      function c(e) {
        return (c = Object.setPrototypeOf
          ? Object.getPrototypeOf
          : function (e) {
              return e.__proto__ || Object.getPrototypeOf(e);
            })(e);
      }
      function l() {
        if ("function" !== typeof WeakMap) return null;
        var e = new WeakMap();
        return (
          (l = function () {
            return e;
          }),
          e
        );
      }
      function s(e, t) {
        return !t || ("object" !== d(t) && "function" !== typeof t)
          ? (function (e) {
              if (void 0 === e)
                throw new ReferenceError(
                  "this hasn't been initialised - super() hasn't been called"
                );
              return e;
            })(e)
          : t;
      }
      function f(e, t) {
        return (f =
          Object.setPrototypeOf ||
          function (e, t) {
            return (e.__proto__ = t), e;
          })(e, t);
      }
      function p(e, t) {
        return (
          (function (e) {
            if (Array.isArray(e)) return e;
          })(e) ||
          (function (e, t) {
            var r =
              null == e
                ? null
                : ("undefined" !== typeof Symbol && e[Symbol.iterator]) ||
                  e["@@iterator"];
            if (null != r) {
              var n,
                o,
                a = [],
                i = !0,
                u = !1;
              try {
                for (
                  r = r.call(e);
                  !(i = (n = r.next()).done) &&
                  (a.push(n.value), !t || a.length !== t);
                  i = !0
                );
              } catch (c) {
                (u = !0), (o = c);
              } finally {
                try {
                  i || null == r.return || r.return();
                } finally {
                  if (u) throw o;
                }
              }
              return a;
            }
          })(e, t) ||
          (function (e, t) {
            if (!e) return;
            if ("string" === typeof e) return a(e, t);
            var r = Object.prototype.toString.call(e).slice(8, -1);
            "Object" === r && e.constructor && (r = e.constructor.name);
            if ("Map" === r || "Set" === r) return Array.from(r);
            if (
              "Arguments" === r ||
              /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)
            )
              return a(e, t);
          })(e, t) ||
          (function () {
            throw new TypeError(
              "Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
            );
          })()
        );
      }
      var d = function (e) {
        return e && "undefined" !== typeof Symbol && e.constructor === Symbol
          ? "symbol"
          : typeof e;
      };
      function h(e) {
        var t = (function () {
          if ("undefined" === typeof Reflect || !Reflect.construct) return !1;
          if (Reflect.construct.sham) return !1;
          if ("function" === typeof Proxy) return !0;
          try {
            return (
              Boolean.prototype.valueOf.call(
                Reflect.construct(Boolean, [], function () {})
              ),
              !0
            );
          } catch (e) {
            return !1;
          }
        })();
        return function () {
          var r,
            n = c(e);
          if (t) {
            var o = c(this).constructor;
            r = Reflect.construct(n, arguments, o);
          } else r = n.apply(this, arguments);
          return s(this, r);
        };
      }
      Object.defineProperty(t, "__esModule", { value: !0 }),
      var y = (function (e) {
          if (e && e.__esModule) return e;
          var t = {};
          if (null != e)
            for (var r in e)
              if (Object.prototype.hasOwnProperty.call(e, r)) {
                var n =
                  Object.defineProperty && Object.getOwnPropertyDescriptor
                    ? Object.getOwnPropertyDescriptor(e, r)
                    : {};
                n.get || n.set ? Object.defineProperty(t, r, n) : (t[r] = e[r]);
              }
          return (t.default = e), t;
      function M(e, t, r, n, o, a, i) {
        try {
          var u = e[a](i),
            c = u.value;
        } catch (l) {
          return void r(l);
        }
        u.done ? t(c) : Promise.resolve(c).then(n, o);
      }
      function T(e) {
        return function () {
          var t = this,
            r = arguments;
          return new Promise(function (n, o) {
            var a = e.apply(t, r);
            function i(e) {
              M(a, n, o, i, u, "next", e);
            }
            function u(e) {
              M(a, n, o, i, u, "throw", e);
            }
            i(void 0);
          });
        };
      }
      function L(e, t, r) {
        return (
          t in e
            ? Object.defineProperty(e, t, {
                value: r,
                enumerable: !0,
                configurable: !0,
                writable: !0,
              })
            : (e[t] = r),
          e
        );
      }
      function I(e) {
        return e && e.__esModule ? e : { default: e };
      }
      function N(e) {
        for (
          var t = arguments,
            r = function (r) {
              var n = null != t[r] ? t[r] : {},
                o = Object.keys(n);
              "function" === typeof Object.getOwnPropertySymbols &&
                (o = o.concat(
                  Object.getOwnPropertySymbols(n).filter(function (e) {
                    return Object.getOwnPropertyDescriptor(n, e).enumerable;
                  })
                )),
                o.forEach(function (t) {
                  L(e, t, n[t]);
                });
            },
            n = 1;
          n < arguments.length;
          n++
        )
          r(n);
        return e;
      }
        K = (function (e) {
          !(function (e, t) {
            if ("function" !== typeof t && null !== t)
              throw new TypeError(
                "Super expression must either be null or a function"
              );
            (e.prototype = Object.create(t && t.prototype, {
              constructor: { value: e, writable: !0, configurable: !0 },
            })),
              t && f(e, t);
          })(a, e);
          var t,
            r,
            n,
            o = h(a);
          function a() {
            return i(this, a), o.apply(this, arguments);
          }
        ("function" === typeof t.default ||
          ("object" === typeof t.default && null !== t.default)) &&
          "undefined" === typeof t.default.__esModule &&
          (Object.defineProperty(t.default, "__esModule", { value: !0 }),
          Object.assign(t.default, t),
          (e.exports = t.default));

(the one above is repeated many many times)

     "use strict";
      function n(e, t) {
        (null == t || t > e.length) && (t = e.length);
        for (var r = 0, n = new Array(t); r < t; r++) n[r] = e[r];
        return n;
      }
      function o(e, t) {
        return (
          (function (e) {
            if (Array.isArray(e)) return e;
          })(e) ||
          (function (e, t) {
            var r =
              null == e
                ? null
                : ("undefined" !== typeof Symbol && e[Symbol.iterator]) ||
                  e["@@iterator"];
            if (null != r) {
              var n,
                o,
                a = [],
                i = !0,
                u = !1;
              try {
                for (
                  r = r.call(e);
                  !(i = (n = r.next()).done) &&
                  (a.push(n.value), !t || a.length !== t);
                  i = !0
                );
              } catch (c) {
                (u = !0), (o = c);
              } finally {
                try {
                  i || null == r.return || r.return();
                } finally {
                  if (u) throw o;
                }
              }
              return a;
            }
          })(e, t) ||
          (function (e, t) {
            if (!e) return;
            if ("string" === typeof e) return n(e, t);
            var r = Object.prototype.toString.call(e).slice(8, -1);
            "Object" === r && e.constructor && (r = e.constructor.name);
            if ("Map" === r || "Set" === r) return Array.from(r);
            if (
              "Arguments" === r ||
              /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)
            )
              return n(e, t);
          })(e, t) ||
          (function () {
            throw new TypeError(
              "Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
            );
          })()
        );
      }
      Object.defineProperty(t, "__esModule", { value: !0 }),
        (t.Portal = void 0);
      var a,
        i = (a = r(7294)) && a.__esModule ? a : { default: a },
        u = r(3935);
      "use strict";
      function n(e, t) {
        (null == t || t > e.length) && (t = e.length);
        for (var r = 0, n = new Array(t); r < t; r++) n[r] = e[r];
        return n;
      }
      function o(e, t) {
        return (
          (function (e) {
            if (Array.isArray(e)) return e;
          })(e) ||
          (function (e, t) {
            var r =
              null == e
                ? null
                : ("undefined" !== typeof Symbol && e[Symbol.iterator]) ||
                  e["@@iterator"];
            if (null != r) {
              var n,
                o,
                a = [],
                i = !0,
                u = !1;
              try {
                for (
                  r = r.call(e);
                  !(i = (n = r.next()).done) &&
                  (a.push(n.value), !t || a.length !== t);
                  i = !0
                );
              } catch (c) {
                (u = !0), (o = c);
              } finally {
                try {
                  i || null == r.return || r.return();
                } finally {
                  if (u) throw o;
                }
              }
              return a;
            }
          })(e, t) ||
          (function (e, t) {
            if (!e) return;
            if ("string" === typeof e) return n(e, t);
            var r = Object.prototype.toString.call(e).slice(8, -1);
            "Object" === r && e.constructor && (r = e.constructor.name);
            if ("Map" === r || "Set" === r) return Array.from(r);
            if (
              "Arguments" === r ||
              /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)
            )
              return n(e, t);
          })(e, t) ||
          (function () {
            throw new TypeError(
              "Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
            );
          })()
        );
      }
      Object.defineProperty(t, "__esModule", { value: !0 }),
     function n(e, t) {
        (null == t || t > e.length) && (t = e.length);
        for (var r = 0, n = new Array(t); r < t; r++) n[r] = e[r];
        return n;
      }
      function o() {
        if ("undefined" === typeof Reflect || !Reflect.construct) return !1;
        if (Reflect.construct.sham) return !1;
        if ("function" === typeof Proxy) return !0;
        try {
          return (
            Date.prototype.toString.call(
              Reflect.construct(Date, [], function () {})
            ),
            !0
          );
        } catch (e) {
          return !1;
        }
      }
      function a(e, t, r) {
        return (a = o()
          ? Reflect.construct
          : function (e, t, r) {
              var n = [null];
              n.push.apply(n, t);
              var o = new (Function.bind.apply(e, n))();
              return r && i(o, r.prototype), o;
            }).apply(null, arguments);
      }
      function i(e, t) {
        return (i =
          Object.setPrototypeOf ||
          function (e, t) {
            return (e.__proto__ = t), e;
          })(e, t);
      }
      function u(e) {
        return (
          (function (e) {
            if (Array.isArray(e)) return n(e);
          })(e) ||
          (function (e) {
            if (
              ("undefined" !== typeof Symbol && null != e[Symbol.iterator]) ||
              null != e["@@iterator"]
            )
              return Array.from(e);
          })(e) ||
          (function (e, t) {
            if (!e) return;
            if ("string" === typeof e) return n(e, t);
            var r = Object.prototype.toString.call(e).slice(8, -1);
            "Object" === r && e.constructor && (r = e.constructor.name);
            if ("Map" === r || "Set" === r) return Array.from(r);
            if (
              "Arguments" === r ||
              /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)
            )
              return n(e, t);
          })(e) ||
          (function () {
            throw new TypeError(
              "Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
            );
          })()
        );
      }

I presume that some of this is classes, some is destructuring, some is module system, and some is async/await. I think it would be great if:

  • Framework code should either use modern features sparingly or should be compiled loosely by default (I don't think Next.js needs fully spec behavior for its built-in classes or uses of iterables). Minimal compiled code is the goal.
  • If there have to be compiled helpers for some reason, they should be shared between modules, not duplicated many times.

Expected Behavior

No repetitive and inefficient compilation artifacts in the default Next.js production bundle.

To Reproduce

Create a new Next.js project and build it.

@gaearon gaearon added the bug Issue was opened via the bug report template. label May 23, 2022
@ijjk
Copy link
Member

ijjk commented May 23, 2022

Hi, we have an experimental config to make the transpilation more specific to the browser requirements in the latest canary of Next.js it can be enabled with:

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  experimental: {
    legacyBrowsers: false,
    browsersListForSwc: true
  }
}

module.exports = nextConfig

The browserslist used with the above config can be seen here

export const MODERN_BROWSERSLIST_TARGET = [

Related RFC #33227

@gaearon
Copy link
Author

gaearon commented May 23, 2022

Awesome, thanks! I'll try this as a stopgap. It's still pretty bad the output is so bloated/duplicated for the older browsers though. Do you think this is worth fixing on its own? Sharing the helpers in a single module like Babel does would go a long way.

@gaearon
Copy link
Author

gaearon commented May 23, 2022

To clarify, some of the patterns I've quotes are repeated many times throughout the bundle. Not sure if it's per class, per module, or per await/spread usage.

@ijjk
Copy link
Member

ijjk commented May 23, 2022

Yeah there's definitely room for improvement here separate of the features being transpiled which we can investigate!

@gaearon
Copy link
Author

gaearon commented May 23, 2022

For the approach in #37142 (comment), is the browsers list configurable?

@ijjk
Copy link
Member

ijjk commented May 23, 2022

Yeah the above config will honor a custom browserslist config if present instead of the default provided.

@gaearon
Copy link
Author

gaearon commented May 23, 2022

If I use the config you've suggested, the output is much better!

Some repeated unfortunate patterns which I presume are from module system:

        ("function" === typeof t.default ||
          ("object" === typeof t.default && null !== t.default)) &&
          "undefined" === typeof t.default.__esModule &&
          (Object.defineProperty(t.default, "__esModule", { value: !0 }),
          Object.assign(t.default, t),
          (e.exports = t.default));
    },
  var n = (function (e) {
          if (e && e.__esModule) return e;
          var t = {};
          if (null != e)
            for (var r in e)
              if (Object.prototype.hasOwnProperty.call(e, r)) {
                var n =
                  Object.defineProperty && Object.getOwnPropertyDescriptor
                    ? Object.getOwnPropertyDescriptor(e, r)
                    : {};
                n.get || n.set ? Object.defineProperty(t, r, n) : (t[r] = e[r]);
              }
          return (t.default = e),

@ijjk
Copy link
Member

ijjk commented May 24, 2022

The duplication in helpers noticed here should be fixed by #37150

@ku8ar
Copy link
Contributor

ku8ar commented May 31, 2022

Why we can't just manually add .swcrc to configure browsersList, loose mode etc as we wish?
SWC by default transpiles to some ancient ES5. E.g. template literals have Object.freeze in their initialization. In projects with styled-components it slows down code.

@flieks
Copy link

flieks commented Jun 9, 2022

like @ku8ar i also would like to add an .swcrc to turn on topLevelAwait
using custom babel config i can't get that to work

@mytchdot
Copy link

Per @ku8ar 's comment, wouldn't it be equally as practical to kill two birds with one stone here and allow the custom browserlist through the .swcrc...?

@mvarendorff
Copy link

For those lurking: Support for the experimental config mentioned in this comment has been released in stable 12.2.0!

@jankaifer
Copy link
Contributor

What is the current status of this issue?
Are there more optimizations needed for older browsers or was that fixed here #37142 (comment)?

@github-actions github-actions bot added the linear: next Confirmed issue that is tracked by the Next.js team. label Jan 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team.
Projects
None yet
Development

No branches or pull requests

8 participants