Closed mountiny closed 11 months ago
Triggered auto assignment to @anmurali (NewFeature
), see https://stackoverflowteams.com/c/expensify/questions/14418#:~:text=BugZero%20process%20steps%20for%20feature%20requests for more details.
No need to action here now Anu, Callstack will work on this
Hey! It's Bartek from Callstack - expert contributor group - I'll be working on this one.
Thanks, please, first post a plan of how to exectute this migration before you go ahead.
@burczu would you be bale to share a plan for this project and some ETA, thanks!
Hey @mountiny! Sorry for being silent in this issue - I'm 100% involved in the Secure Logins issue (migration to use accountID's instead of emails in personal details) right now and had no time for anything else. I'll do my best to share some plan for this issue today or on Monday.
Ok, @mountiny my plan is simple actually:
moment
librarymoment
lib with date-fns
library (I think it is the best choice because of its popularity in the community)In terms of ETA, it depends on how much tests I will need to add as it's the most time consuming task in this plan. I would say more once I check the current coverage.
What do you think?
@burczu thanks for the update, I like including the unit tests, the plan sounds great to me.
Interested in seeing this one as well, as I am looking at the minute at performance issues with momentjs code (which I'd like to replace by date-fns).
This will continue after the secure logins bugs are fixed
I've been working on the first step of my plan today, and identified all the places where we use the moment
library in the app. Here are my findings:
Places where moment
is used and how:
components/NewDatePicker/index.js
components/AutoUpdateTime.js
DateUtils
utility is usedcomponents/CalendarPicker/index.js
moment
library (formatting, setting etc.) - this file needs to be 100% covered by testslibs/DateUtils.js
moment
library - this file needs to be 100% covered by testsmoment
object and used outside:
getLocalMomentFromDateTime
method, returns moment
object, used in:
components/AutoUpdateTime.js
- used to get timezone name (string)components/ReportActionItem/ChronosOOOListAction.js
- formatingcomponents/pages/home/report/ParticipantLocalTime.js
- formattinglibs/EmojiUtils.js
libs/Navigation/AppNavigator/AuthScreens.js
libs/ReportActionsUtils.js
libs/ValidationUtils.js
moment
library - this file needs to be 100% covered by testsmoment
object and used outsidelibs/actions/App.js
libs/actions/User.js
libs/fileDownload/FileUtils.js
pages/EnablePayments/AdditonalDetailsStep.js
pages/ReimbursementAccount/IdentityForm.js
pages/settings/Profile/PersonalDetails/DateOfBirthPage.js
pages/settings/Profile/TimezoneInitialPage.js
pages/settings/Profile/TimezoneSelectPage.js
pages/wallet/WalletStatementPage.js
Tomorrow, I think I'll start working on writing unit tests for places I've marked in bold (CalendarPicker
component, DateUtils
and ValidationUtils
) - I think these files should be 100% covered.
Looks like something related to react-navigation
may have been mentioned in this issue discussion.
As a reminder, please make sure that all proposals are not workarounds and that any and all attempt to fix the issue holistically have been made before proceeding with a solution. Proposals to change our DeprecatedCustomActions.js
files should not be accepted.
Feel free to drop a note in #expensify-open-source with any questions.
Nice, CalendarPicker will be refactored soon not sure if it would be important, but something to keep an eye on
Not overdue: I made some progress in writing tests I've planned, but I had to switch to another issue for now. I think I'll be able to get back to this one next week.
@burczu - do you have an update?
@anmurali I'm sorry, I had no time for this issue last week - hopefully this week will look better
Update: I've done some progress today, but I'll be OOO starting on Monday till July 25th - once I'll be back, I think I'll have the time to 100% focus on this issue because my other issues will be taken over by other Callstackers.
Bartek has been ooo this week
Update: Covered main files with tests, updated DateUtils and ValidationUtils with date-fns.
@waterim Thats great! Would you be able to open a draft PR? it would also be better to dived this up to couple of smaller PRs to avoid having a large PR which will be super hard to review.
@mountiny Sure! Will create a PR after fixing timezone issues I have now after switching from moment. I think 1-2 hours
@mountiny Sorry about the delay, got stuck in one test with rewriting from moment()
@mountiny Here is adding a draft PR Still some moment in tests and it will be deleted asap, but utils were rewrote fully. I have one question regarding these "a few seconds ago" from moment default moment(date).fromNow() and "less than a minute ago" from date-fns default formatDistanceToNow(new Date(date), {addSuffix: true}); Question is: Do I need to adjust date-fns to return exactly the same messages as a default function from moment did?
@waterim Could we do that in some config or it would require a patch? if we can do this in some config, than yes, but I dont thing this is work making a patch
@mountiny We can add some custom function instead of date-fns formatDistanceToNow
to achieve exact same strings as moment did.
But Im not sure that the difference in a default behaviour is crucial, like "a minute ago" and "1 minute ago"
Date-fns is not supporting some custom configs for formatDistanceToNow
function unfortunately.
All it has: addSuffix, includeSeconds and locale
@waterim where is this used in the app?
@mountiny Just here And after passing to LocaleContext.Provider
Hello @mountiny!
My upate: removed fully moment from utils functions and tests, resolved all comments on my PR.
Now after I started testing the app I found that there are a lot of places in the code where we are using Moment Object functions which on top of the utils functions.
Something like this:
currentUserLocalTime = DateUtils.getLocalDateFromDatetime(props.preferredLocale, null, props.timezone.selected)
And after we are using:
currentUserLocalTime.zoneAbbr()
where zoneAbbr()
is a Moment function.
Now Im going file by file, line by line to change all these Moment Object functions to date-fns functions.
@waterim Could we make sure we can split this up to smaller PRs so before we continue working further I think it would be great to get the PR which sets up the date-fns in the app and adds all the tests in place. Then we can start to slowly migrate over all the usages of Moment and eventually deprecate it and add some ESLint rule which will prohibit people of adding it back
@mountiny yes, sure, agree that it will be easier and safer. Will redo my PR tomorrow to have only tests and new library
@waterim appreciate it 🙇
@mountiny Hello Vit, can you please assign me to this task?
And here is my PR just with tests and new library added, and without any date-fns inside of the code.
@waterim Thank you 🙇 assigned and merged, I think we are good to work on the other prs.
@mountiny great, thank you) For the next PR I think we can go with rewriting ValidationUtils to date-fns and all files which are using it
@waterim lets do that
Another one merged 🚀
@mountiny nice to hear 🙃
@mountiny My update: Moving all usage of moment functions outside of the utils to the DateUtils. I mean all formattings, using of the moment.zoneAbbr() etc. Doing that to have all in one place, for the future it can help with rewriting or changing code related to timezones and dates.
Added c+ to the issue and PR
Merged, great job everyone, lets hope there wont be any issues with it
@waterim @burczu should we consider addig some rule for preventing people re-introducing moment
Regression: https://github.com/Expensify/App/issues/25650
@mountiny Here is a PR with tz.guess and polyfills, please test it too :)
This issue has not been updated in over 15 days. @burczu, @anmurali, @allroundexperts, @mountiny, @waterim eroding to Monthly issue.
P.S. Is everyone reading this sure this is really a near-term priority? Be brave: if you disagree, go ahead and close it out. If someone disagrees, they'll reopen it, and if they don't: one less thing to do!
@waterim is still working on this one and there is couple of prs left to get us over the finish line and remove moment from the app
@mountiny actually I have an update, I have enough capacity on Friday and today to proceed and will create PR today/tomorrow with new changes
There are a lot of hidden usages and all the time app is crashing after even a small change, but step by step is working fine
Heads-up: PR which linked this issue caused regression - https://github.com/Expensify/App/issues/28315 (old: https://github.com/Expensify/App/issues/26719) It was fixed in https://github.com/Expensify/App/pull/26902 but reverted in https://github.com/Expensify/App/pull/26248.
@mountiny PR is open, last PR will be with datepicker and moment will be removed FULLY from the project!
After my last changes, 2 years of history will disappear into oblivion
For the last changes will be:
Problem
Coming from this Slack thread and Callstack proposal.
The
moment
library is a powerful library but has performance disadvantages that comes from its OOP design. This design makes it fail working with tree-shaking, so it’s bundle size it’s huge (especially with internalisation or timezone support enabled) - this impacts mostly the web version of Expensify app.Moreover, the
moment
library is now a “legacy project in maintenance mode” so it is not actively developed anymore.More about above here: https://momentjs.com/docs/#/-project-status/
Solution
There are some other powerful yet lightweight date libraries like
day.js
(the most lightweight) ordate-fns
(supports tree-shaking) that could successfully replace the moment library in our app. My personal preference isdate-fns
because of its support for tree-shaking and wider popularity among community, but usingday.js
may be easier from the Expensify codebase perspective because of its API that is quite similar to the moment one (e.g. parsing date strings using constructor or day/month/year getters etc. - please check the link I’ve posted below for more details).Context/Examples/Screenshots/Notes: More about the subject, containing the comparison of the most popular moment replacements can be found here: https://github.com/you-dont-need/You-Dont-Need-Momentjs/blob/master/README.md