Next-i18next: Bundle size in last version incremented a lot!

Created on 19 Jul 2019  路  19Comments  路  Source: isaachinman/next-i18next

Describe the bug

After migrating to the latest version of this library (0.49.0), my bundle size incremented a lot.

Occurs in next-i18next version

0.49.0

Steps to reproduce

Just migrate to the latest version and run bundle analyzer.

Expected behavior

Smaller bundle.

Screenshots

Before migrate (0.47.0):

image

After migrate from 0.47.0 to 0.49.0:

image

Most helpful comment

Related to discussions in https://github.com/isaachinman/next-i18next/issues/152 and https://github.com/isaachinman/next-i18next/pull/292. Next.js plugins should not build themselves so es5 and they should not add polyfills. Instead, they should provide babel / webpack enhancers to app developers to that required polyfills were added to the app during the _app build_ time (via app's next.config.js and .babelrc). Violating this principle results duplicate dependencies, inability to three-shake and thus bloated bundle size.

All 19 comments

That's mostly core-js. A lot of projects will already require core-js, so their bundle size will be unaffected.

In theory, you should be able to import the build/es target and skip polyfilling if you want.

Should add bundlesize to the simple example and run this step in CI.

Related to discussions in https://github.com/isaachinman/next-i18next/issues/152 and https://github.com/isaachinman/next-i18next/pull/292. Next.js plugins should not build themselves so es5 and they should not add polyfills. Instead, they should provide babel / webpack enhancers to app developers to that required polyfills were added to the app during the _app build_ time (via app's next.config.js and .babelrc). Violating this principle results duplicate dependencies, inability to three-shake and thus bloated bundle size.

I dunno, but I feel that can be improved a lot. Is much bigger than preact itself...

@aralroca The situation should be improved by #408. I've also added bundlesize as a CI step to prevent regression in the future. Could you please upgrade your project to v0.50.0 and post your bundle analyzer output here?

Bundle size is not affected due to the fact that there is no import to the es version in your package.json file.
image

it is better to add module: "path-to-the-es-entry"

I've tried it locally, and it reduced the size:

with "module": "dist/es/index.js",
image

without
image

@felixmosh Not sure of your point. We're specifically discussing the cjs target in this issue. Naturally, the es target will be smaller as it does not target _anything_. The assumption is that if you are consuming the es target, you are transpiling/polyfilling your own deps.

How polyfilling & transpilation targets related to each other?
How do you provide polyfills to the cjs version only?

How polyfilling & transpilation targets related to each other?

They're both steps/actions performed onto raw source code to get it to run in your targeted browser, eg IE 11.

How do you provide polyfills to the cjs version only?

Feel free to take a look at the babelrc.

Let's wait and hear from @aralroca.

No problem,

Why did we removed the module entry here? https://github.com/isaachinman/next-i18next/commit/af3ae6134db2fc433c8249a7ed9a6e41dc669e51#diff-b9cfc7f2cdf78a7f4b91a753d10865a2L8

Because Webpack seems to give preference to module over main, despite the fact that in 99% of cases, node_modules deps are not transpiled. This means that, completely accidentally, our es target was being consumed by most users instead of the cjs target, which broke targets like IE11.

There are open issues in the Webpack and Babel repos, and this is an ongoing community discussion, but for the sake of this package I'd like to keep things simple. This is a NextJs plugin, and the primary use case is inside a Node server _and_ inside a browser. Because of this, a default cjs target makes good sense. Feel free to consume next-i18next/dist/es if you want raw esnext code.

@isaachinman in 0.50.0 is smaller than 0.49.0:

image

However, it still bigger than 0.47.0. But much better than 0.49.0 馃檪

@aralroca That's good to hear, but indeed it looks like we're still pulling in a lot of core-js. Are you able to share the repo that you're getting these outputs from? If so, I can do some testing locally.

We will be going forward with core-js on our cjs target, so it will be a matter of improvement/optimisation from here.

The es target can be consumed by those who want to handle their own transpilation.

@isaachinman Unfortunately, I can't share the original repo... However, I reproduce it in a new repo just to share with you:

The result of the chunks is very similar:

image

I hope it will help!

@aralroca Thanks, that's very helpful. After doing a bit of local testing, I have some promising results. A couple points about my findings:

  1. Between v0.47.0 and now, there will be an unavoidable increase in the (default) raw size of next-i18next in your bundles, as I've changed the default target to be the cjs target. Previously, people were unintentionally importing raw esnext code, resulting in a very small bundle, but poor browser support.
  2. It seems like using core-js v3 is what is pulling in a lot of this added weight. Unfortunately, it appears that a lot of other common deps are still on v2, so if we downgrade to v2, we get the benefit of sharing.

Can you please check out #414 and let me know what you think? Should reduce the actual bundled source of next-i18next to <6kb GZIP.

Regarding point 1, the es target is not aligned with the community, the es version of lib should be transpiled all but module type, that will allow to webpack enable tree-shaking but the code it self will be suitable to es5.

Check what i18next are doing, https://github.com/i18next/i18next/blob/master/rollup.config.js#L29, they are changing only the module type.

If es version was intentionally a modern js version, lets add esm that will do what I've said.

WDYT?

After forcing core-js to v2, I have again the same size than in the version 0.47.0

v.0.50.0:

image

I approved the PR, however meanwhile to workaround this:

  • Add "core-js": "2.6.9", in package.json
  • Add alias resolver in webpack as: 'core-js': path.resolve(__dirname, 'node_modules/core-js')

If it can be smaller than 51,8kb (6,8kb compressed) it's something that I dunno. However, I imagine that doing what @felixmosh said, it can help.

No need for a workaround, this has been released in v0.51.0.

Was this page helpful?
0 / 5 - 0 ratings