Why is moment-timezone using a lot less space with webpack 4 and/or create react app 4?
Asked Answered
F

3

5

With webpack 3, I was using moment-timezone-data-webpack-plugin to reduce my bundle size and it worked well. Tests showed it reduced the bundle size dramatically. I've now upgraded to webpack 4 and create-react-app 4, and it seems like

  1. this plugin has no impact on the total bundle size
  2. analyzing the bundle, moment-timezone only takes about 7k

As far as I can tell moment-timezone is functioning correctly in my app, so I'm very confused.

Webpack 4 is a lot better at reducing bundle size, but there's no way it can know which timezone data my app needs are runtime, so I can't imagine how that could be part of the answer.

Familiarity answered 31/7, 2021 at 16:34 Comment(5)
Can you tell more about your problem and making some examples or screenshots, I don't get your point.Burkett
Could you show the import you're using? Presumably the answer is tree shaking but I don't see how moment-timezone would be tree-shakable without the plugin...Insolation
why don't you take a look at the actual moment-timezone data in your bundle and check if it includes all timezone data or just what you configured it to?Smokeproof
@Insolation MomentJS is infamously immune to tree-shaking.Stadia
What version of moment and moment-timezone are you using?Stadia
S
4

Apologies for this being a non-answer, but hopefully it saves some time.

MomentJS have been aware of their size for a while, and have taken steps to try to structure their project so it can be stripped down better. They have structured their project, so that the locales are stored separately.

However the trick here is you mentioned CreateReact4, you are not testing this in a clean room, so anything could be taking effect.

Create React 4 document that:

Troubleshooting.md - MomentJS Locales are Missing

If you use a Moment.js, you might notice that only the English locale is available by default. This is because the locale files are large, and you probably only need a subset of all the locales provided by Moment.js.

To add a specific Moment.js locale to your bundle, you need to import it explicitly.

This is because CreateReact4 is configured by default to remove the locales

react-scripts/config/webpack.config.js#L671-L678

  // Moment.js is an extremely popular library that bundles large locale files
  // by default due to how webpack interprets its code. This is a practical
  // solution that requires the user to opt into importing specific locales.
  // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
  // You can remove this if you don't use Moment.js:
  new webpack.IgnorePlugin({
    resourceRegExp: /^\.\/locale$/,
    contextRegExp: /moment$/,
  }),

It's possible you could trim it further using the plugin you mentioned in the question (Have you checked if it's even being invoked / compatible anymore?), but the bulk of the gzipped data really is the locales, not the timezone data, (TZ don't compress as easily).

Moment TZ Data Plugin state on their site that depending on the config gives various savings.

Default                 1164 KiB        105 KiB
Strip locales           959 KiB (~82%)  56 KiB (~53%)
Strip tz data           265 KiB (~23%)  69 KiB (~66%)
Strip locales & tz data 60 KiB (~5%)    20 KiB (~19%)

So CreateReact4's default behaviour of stripping un-needed locales, likely gives a 53% reduction by default(gzipped).

However you state that Moment-js is using 7k... so whilst this is a good breakdown of what could be happening, there's clearly something further at play, even moment.js-min is 18kb.

Stadia answered 31/7, 2021 at 16:34 Comment(0)
S
3

I believe that during an upgrade of moment-timezone, you have gone from one with timezone data, to one without.

https://momentjs.com/timezone/ states that (minified) moment-timezone without data is only 2.8k

Loading the unminified version: https://momentjs.com/downloads/moment-timezone.js and looking at my browsers network tab, shows that it clocks in at around 5.2k

It's my assumption (without additional information/testing and recreating your webpack) that this is the likely culprit.

"But my web app appears to be working" I hear you cry.

moment-timezone falls back to (new) native browser API's, try testing in an older browser:

If you don't need to support old projects / browsers, consider Luxon.

Stadia answered 12/8, 2021 at 9:22 Comment(0)
F
0

I had same feeling when did dune to webpack2 some time ago.

In my experience the answer was: strings of localizations. Before - it took all of them, and know they somehow limited.

Forme answered 10/8, 2021 at 14:4 Comment(2)
pretty sure it has nothing to do with localizations. yes, CRA will automatically prune localizations, but it's a different issue from timezonesFamiliarity
@JohnBachir you rigjt, I deserved my downvoteForme

© 2022 - 2024 — McMap. All rights reserved.