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
Tree shaking issue in 2.17 #2207
Comments
I'm on 2.17, and with the set up above (@babel/preset-env) + tsconfig with and imports that looks like: import { endOfDay, endOfMonth, isDate, parse, sub } from 'date-fns'; Treeshaking works correctly |
It's weird that both my projects have the same behavior on 2.17, but I'll try to figure out if there's something similar to your problem. Thanks for the reply and the pointers. |
I think I am now closer to the issue. Full disclosure: I'm using the functional (fp) flavor of date-fns (which I failed to mention earlier). So, long story short I created a vanilla project, and by importing like this, tree-shaking works correctly. But if I try to import the functional flavor of the same functions tree shaking never happens So, importing them one by one solves the problem and tree shaking is working again
I still think there's an issue here though. |
Something has changed with the format of package in 2.17.0. I've had issues with my Angular 11 project and warnings being thrown that it's using a commonjs version of the date-fns package. Sticking with 2.16.1 for now which worked fine. EDIT: my angular project is target: es5 |
Not sure if this is related, but for me |
2.18.0: still the same issue |
It looks like the 2.16.1 {
"sideEffects": false,
"module": "../esm/format/index.js",
"typings": "../typings.d.ts"
} 2.17.0 {
"sideEffects": false,
"typings": "../typings.d.ts"
} |
Newer versions have a bug which leads to much larger js-chunks date-fns/date-fns#2207
I can confirm tree shaking works with |
Any updates for this? Have the same issue. I have created custom locales file for Ukrainian, English and Russian, with some custom translations. I want lazy load these files via webpack |
Specifically for locale tree-shaking, I think the culprit is this file that ends up exporting every locale explicitly: https://github.com/date-fns/date-fns/blob/master/src/locale/index.js In my app (CRA, Typescript, date-fns 2.19), I managed to work around the issue by importing my locales slightly differently and bypassing that index: I'm not completely sure if this is a webpack bug / new behavior? Maybe the official date-fns docs should encourage this alternative import method, or at least mention it in the ESM/Tree-shaking section? Hope this is helpful! EDIT: |
@martinhiller thanks to you, I think I figured out the root cause and just opened a pull request (#2339) |
Any update on this? The PR from @fturmel has been open and awaiting review almost as long as it took for them to open it in the first place. |
Does the pull request really address the locales issue (I haven't tested)? So lets say you're using babel + webpack and are running in an esm environment.
Then you have a mix of imports from both cjs and esm. And since tree shaking only works in esm the locales bundle is big. I think the fix is the package.json "exports" field. That way the This seems to work if added to
But since some people use subpath imports, those also needs to be added, e.g. |
@mlandalv Yeah, I just verified again and can confirm that #2339 fixes this issue. There is a build step that generates over a thousand nested package.json files and they were all missing their module property because of an async bug. You can't see these files on Github because they are created after the babel transpiling phase in the tmp directory. See the bundle analysis in my project which only imports one locale: With fix from pull request (date-fns 32KB) Version 2.20.2 (date-fns 786KB) |
@antch It's strange that this issue has been ignored considering how it must be significantly impacting the bundle size of tons of projects out there without people noticing. The modular structure / tree-shaking ability of the project is literally the first thing mentioned in their promotional material everywhere and currently that statement is not true anymore if you import from locale and fp. |
@antch, I would like to ask you to stop letting down contributors, especially when you didn't contribute anything to the project or issue. |
@fturmel thank you for your fix. We have to process many incoming issues and pull requests, and unfortunately, this critical issue went unnoticed. |
I will admit this was not the correct forum to vent about that, especially since I even mentioned I am not sure if it even applies this project team. Apologies. |
@antch, no worries, thank you for your reply! |
I've shipped the fix with |
@kossnocorp I am still quite sure that something isn't working as it was intended to. I am working on a project where I upgraded code from The only migration change I made in that bundle is from:
to
and it went from this: to this: I don't think that is intended behaviour. Not sure how many people here are thoroughly watching their bundle sizes but I'd be interested to know if somebody else is experiencing this too. If you would like me to I can spawn a separate issue since the downgrade hasn't helped in my case either. But I felt this belonged here. |
@Freddixx check that 2.16.1 version. It was working for everyone. |
As said above: Downgrading unfortunately didn't solve the issue for me. |
@Freddixx I'm not super experienced with Perhaps it's a project-specific issue (Webpack/Babel config), or simply a misreading of the analyzer output (the paths are different in your images)? I find it interesting that you don't have parsed and gzipped values in your screenshots like mine does, maybe that does hint to something missing in your build step. Are you seeing the same problem for other libraries with esm modules? These might be worth reading: |
Yes, the paths are supposed to be different. Because the esm support is a date-fns v2 feature. The missing gzip and parsed values are due our system architecture. It's a micro-frontend architecture where each component gets packed into its own bundle. For these "virtual" files the bundle analyzer can only output But even if - that doesn't explain the difference between v1 and v2 - after all both scenarios operate under the same conditions 🤔 But really, any input is very much appreciated. |
I really hope I am wrong, but something is strange here @kossnocorp What I did: I spawned a blank CRA (create-react-app) and loaded
date-fns v1: date-fns v2: And since it was suggested that this might be a false reading by date-fns v1: date-fns v2: P.S.: Yes, I tested this on both the latest version and |
@Freddixx I get what you’re saying, there certainly is a significant file size difference. I’m not a date-fns team member and I might certainly be wrong here. I’m just trying to help and make sure my PR didn’t mess anything up. If anyone else wants to jump in feel free. From what I can see, these two methods have changed quite a bit under the hood in v2. The file size difference might simply come from a larger source code implementation and depending on more internal methods. I’m sure there are differences in features and robustness that may not be apparent from the outside. https://github.com/date-fns/date-fns/blob/v1.30.1/src/format/index.js https://github.com/date-fns/date-fns/blob/v1.30.1/src/parse/index.js In v2, you have a few parse and format methods to choose from. If you can for example use I also stumbled on this comment in the source code: The previous So, in my opinion this is unrelated to #2207 and tree-shaking works as intended now. I do however think that you bring an interesting point. Maybe you could propose an effort to reduce the file size of the parse and format methods in a new issue? See if it gains any traction and if it’s even feasible? Or perhaps some additional documentation on v2 migration could’ve helped? If some methods can add 20KB to your bundle size while others only a few, maybe this information could be documented to manage expectation? |
This fixed the problem for me on 2.19.0. Thank you very much!! |
Test results:
|
I'm using date-fns in two projects (without additional locales) and when I upgraded to 2.17 the bundle size went to ~200Kb.
Checked with the webpack bundle analyzer, and all the functions seem to be there. I'm actually using just 7 functions with import syntax (ESM), so nothing changed from my side. If I rollback to 2.16.1, everything is OK again.
Does it have to do with the Typescript addition? My projects are plain js.
The text was updated successfully, but these errors were encountered: