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

concurrently imports the entire date-fns library without tree-shaking but use only 1 function #329

Closed
guillaumeprevost opened this issue May 31, 2022 · 8 comments

Comments

@guillaumeprevost
Copy link

I have found this issue while investigating why my project still had the entire date-fns library bundled even if I was carefully importing and using only a few functions.

date-fns provides a syntax that will allow bundlers like Webpack to do some "tree-shaking" and only import the needed modules rather than the full library, optimizing greatly the total bundle size.

It seems like concurrently doesn't use this syntax, which causes to import the full date-fns library instead of only the single function used in logging (formatDate in logger.ts and log-timings.ts).

How found this :

I had opened an issue about this originally on the date-fns repo because I thought it came from there.

After some discussions around the issue, someone mentioned here that it could come from another dependency importing all of date-fns by not using tree-shaking syntax. The recommendation was to use npm why date-fns to spot which other dependency may use date-fns.

When running that command, it only listed my own references to date-fns (using the syntax allowing tree-shaking) and the concurrently library.

@gustavohenke
Copy link
Member

The two files you mention are importing a single export from date-fns:

import formatDate from 'date-fns/format';

import formatDate from 'date-fns/format';

What is the problem exactly...?

@guillaumeprevost
Copy link
Author

The problem is that in the final bundle, the entire date-fns library is there , making the bundle much larger than it should be.

Indeed it seems that raised the lines should only import a single function, but that's not the case. Maybe this could work with the suggested syntax in their documentation :

import { formatDate } from 'date-fns'

Or maybe the issue comes from erro in tree-shaking within the date-fns library itself ?

@gustavohenke
Copy link
Member

@guillaumeprevost can you provide a sample repo?
To begin with, I'm not sure how bundling is happening (are you building a desktop app?), so any help for me to understand which changes should be made would be great

@paescuj
Copy link
Collaborator

paescuj commented Jul 7, 2022

# Analyzing the bundle of simple 'concurrently' import with esbuild
tmpdir=$(mktemp -d)
pushd "$tmpdir" >/dev/null
npm install concurrently esbuild >/dev/null

echo "import concurrently from 'concurrently'; concurrently(['echo test']);" | \
npx esbuild --bundle --platform=node --analyze --outfile=/dev/null 2> >(grep date-fns)

popd >/dev/null
rm -r "$tmpdir"
   ├ node_modules/date-fns/_lib/format/formatters/index.js                           19.5kb    2.5%
   ├ node_modules/date-fns/format/index.js                                            4.8kb    0.6%
   ├ node_modules/date-fns/locale/en-US/_lib/localize/index.js                        4.0kb    0.5%
   ├ node_modules/date-fns/locale/en-US/_lib/match/index.js                           3.8kb    0.5%
   ├ node_modules/date-fns/_lib/format/longFormatters/index.js                        2.4kb    0.3%
   ├ node_modules/date-fns/locale/en-US/_lib/formatDistance/index.js                  2.4kb    0.3%
   ├ node_modules/date-fns/_lib/format/lightFormatters/index.js                       2.3kb    0.3%
   ├ node_modules/date-fns/_lib/getUTCWeekYear/index.js                               2.2kb    0.3%
   ├ node_modules/date-fns/locale/_lib/buildMatchFn/index.js                          1.8kb    0.2%
   ├ node_modules/date-fns/_lib/protectedTokens/index.js                              1.6kb    0.2%
   ├ node_modules/date-fns/_lib/startOfUTCWeekYear/index.js                           1.5kb    0.2%
   ├ node_modules/date-fns/_lib/getUTCISOWeekYear/index.js                            1.5kb    0.2%
   ├ node_modules/date-fns/_lib/startOfUTCWeek/index.js                               1.5kb    0.2%
   ├ node_modules/date-fns/locale/en-US/_lib/formatLong/index.js                      1.3kb    0.2%
   ├ node_modules/date-fns/toDate/index.js                                            1.2kb    0.2%
   ├ node_modules/date-fns/locale/_lib/buildLocalizeFn/index.js                       1.2kb    0.2%
   ├ node_modules/date-fns/locale/en-US/index.js                                      1.0kb    0.1%
   ├ node_modules/date-fns/locale/_lib/buildMatchPatternFn/index.js                   1.0kb    0.1%
   ├ node_modules/date-fns/_lib/getUTCWeek/index.js                                  1012b     0.1%
   ├ node_modules/date-fns/_lib/getUTCISOWeek/index.js                               1003b     0.1%
   ├ node_modules/date-fns/_lib/startOfUTCISOWeekYear/index.js                        993b     0.1%
   ├ node_modules/date-fns/_lib/getUTCDayOfYear/index.js                              984b     0.1%
   ├ node_modules/date-fns/_lib/startOfUTCISOWeek/index.js                            916b     0.1%
   ├ node_modules/date-fns/addMilliseconds/index.js                                   857b     0.1%
   ├ node_modules/date-fns/isValid/index.js                                           842b     0.1%
   ├ node_modules/date-fns/subMilliseconds/index.js                                   813b     0.1%
   ├ node_modules/date-fns/locale/en-US/_lib/formatRelative/index.js                  716b     0.1%
   ├ node_modules/date-fns/_lib/getTimezoneOffsetInMilliseconds/index.js              678b     0.1%
   ├ node_modules/date-fns/locale/_lib/buildFormatLongFn/index.js                     663b     0.1%
   ├ node_modules/date-fns/isDate/index.js                                            646b     0.1%
   ├ node_modules/date-fns/_lib/toInteger/index.js                                    601b     0.1%
   ├ node_modules/date-fns/_lib/addLeadingZeros/index.js                              559b     0.1%
   ├ node_modules/date-fns/_lib/requiredArgs/index.js                                 518b     0.1%

It seems to me that only the required files are bundled... Am I wrong?


Besides that, the suggested import syntax doesn't work:

src/logger.ts:3:10 - error TS2305: Module '"date-fns"' has no exported member 'formatDate'.

3 import { formatDate } from 'date-fns';

@paescuj
Copy link
Collaborator

paescuj commented Jul 11, 2022

Closing this as I don't see any room for improvement here on our side. Please open a new issue with a reproduction if this is still a problem.

@paescuj paescuj closed this as completed Jul 11, 2022
@guillaumeprevost
Copy link
Author

Hi, yes that's fair enough.. I did not have any free time to work on a minimal reproduction of this issue.
Thank you

@jpolo
Copy link

jpolo commented Jan 29, 2023

I've been investigating why node_modules is so heavy on some of my projects. Many libraries could be the cause but concurrently is on top of it. The main reason is that concurrently uses rxjs and date-fns as dependency. Those packages weight more than 10mo each. This could be problematic, especially in a CI environment...

There might be improvement from concurrently to be "lighter".

@paescuj
Copy link
Collaborator

paescuj commented Jan 29, 2023

I've been investigating why node_modules is so heavy on some of my projects. Many libraries could be the cause but concurrently is on top of it. The main reason is that concurrently uses rxjs and date-fns as dependency. Those packages weight more than 10mo each. This could be problematic, especially in a CI environment...

There might be improvement from concurrently to be "lighter".

Yeah, this is actually another reason why I came up with #366 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants