[{"data":1,"prerenderedAt":469},["ShallowReactive",2],{"blog-\u002Fblog\u002F2023-01-17-momentjs-avec-nuxt3":3,"surround-\u002Fblog\u002F2023-01-17-momentjs-avec-nuxt3":463},{"id":4,"title":5,"body":6,"createdAt":449,"description":450,"extension":451,"meta":452,"navigation":142,"path":453,"pinned":454,"readingTime":455,"seo":460,"stem":461,"__hash__":462},"blog\u002Fblog\u002F2023-01-17-momentjs-avec-nuxt3.md","Utiliser moment.js avec Nuxt 3",{"type":7,"value":8,"toc":447},"minimark",[9,21,30,37,47,56,65,371,374,380,389,392,410,413,416,429,443],[10,11,12,13,20],"p",{},"Vous avez peut-être remarqué que le module ",[14,15,19],"a",{"href":16,"rel":17},"https:\u002F\u002Fgithub.com\u002Fnuxt-community\u002Fmoment-module",[18],"nofollow","@nuxtjs\u002Fmoment"," n'est pas compatible avec Nuxt 3.",[10,22,23,24,29],{},"Vous vous demandez sans doute pourquoi a-t-on besoin d'un module pour utiliser ",[14,25,28],{"href":26,"rel":27},"https:\u002F\u002Fmomentjs.com\u002F",[18],"moment.js"," dans Nuxt ?",[10,31,32,33,36],{},"Dans Nuxt 2, lorsque vous utilisez ",[34,35,28],"code",{},", Webpack importe toutes les locales par défaut. Cela équivaut à plus d'une centaine de locales qui sont importées alors que vous n'avez probablement besoin que d'une ou deux d'entre elles.",[10,38,39,40,42,43,46],{},"Voilà où entre en jeu ",[34,41,19],{},"; celui-ci se charge de supprimer les locales inutiles en utilisant ",[34,44,45],{},"moment-locales-webpack-plugin"," afin de réduire la taille du bundle de votre application.",[10,48,49,50,55],{},"Si vous avez suivi l'actualité, vous savez peut-être que Nuxt 3 utilise maintenant ",[14,51,54],{"href":52,"rel":53},"https:\u002F\u002Fvitejs.dev\u002F",[18],"Vite.js"," au lieu de Webpack afin de bundler votre application. Il n'est donc plus nécessaire de supprimer les locales inutilisées du bundle puisque Vite.js s'en charge déjà grâce à son meilleur support du tree-shaking.",[10,57,58,59,64],{},"Voici comment créer votre propre plugin pour utiliser moment.js directement dans une application multilingue utilisant ",[14,60,63],{"href":61,"rel":62},"https:\u002F\u002Fv8.i18n.nuxtjs.org\u002F",[18],"@nuxtjs\u002Fi18n"," et TypeScript dans Nuxt 3.",[66,67,75],"pre",{"className":68,"code":69,"filename":70,"highlights":71,"language":73,"meta":74,"style":74},"language-js shiki shiki-themes solarized-light solarized-dark","import moment from 'moment';\nimport 'moment\u002Flocale\u002Ffr-ca';\nimport type { NuxtApp } from '#app';\n\nexport default defineNuxtPlugin((nuxtApp) => {\n    const locale = nuxtApp.$i18n.locale.value;\n    moment.locale(locale);\n\n    nuxtApp.$i18n.onBeforeLanguageSwitch = (\n        oldLocale: string,\n        newLocale: string,\n        isInitialSetup: boolean,\n        nuxtApp: NuxtApp\n    ) => {\n        moment.locale(newLocale);\n    };\n\n    return {\n        provide: {\n            moment,\n        },\n    };\n});\n","plugins\u002Fmoment.ts",[72],2,"js","",[34,76,77,101,112,137,144,166,199,217,222,242,257,269,282,294,304,321,327,332,340,346,354,360,365],{"__ignoreMap":74},[78,79,82,86,90,93,97],"span",{"class":80,"line":81},"line",1,[78,83,85],{"class":84},"sxPyI","import",[78,87,89],{"class":88},"sCW-z"," moment",[78,91,92],{"class":84}," from",[78,94,96],{"class":95},"sNx9Q"," 'moment'",[78,98,100],{"class":99},"skhcD",";\n",[78,102,105,107,110],{"class":103,"line":72},[80,104],"highlight",[78,106,85],{"class":84},[78,108,109],{"class":95}," 'moment\u002Flocale\u002Ffr-ca'",[78,111,100],{"class":99},[78,113,115,117,120,123,126,129,132,135],{"class":80,"line":114},3,[78,116,85],{"class":84},[78,118,119],{"class":84}," type",[78,121,122],{"class":99}," { ",[78,124,125],{"class":88},"NuxtApp",[78,127,128],{"class":99}," } ",[78,130,131],{"class":84},"from",[78,133,134],{"class":95}," '#app'",[78,136,100],{"class":99},[78,138,140],{"class":80,"line":139},4,[78,141,143],{"emptyLinePlaceholder":142},true,"\n",[78,145,147,150,153,156,159,163],{"class":80,"line":146},5,[78,148,149],{"class":84},"export",[78,151,152],{"class":84}," default",[78,154,155],{"class":88}," defineNuxtPlugin",[78,157,158],{"class":99},"((nuxtApp) ",[78,160,162],{"class":161},"sNKNx","=>",[78,164,165],{"class":99}," {\n",[78,167,169,172,175,178,181,184,187,189,192,194,197],{"class":80,"line":168},6,[78,170,171],{"class":161},"    const",[78,173,174],{"class":88}," locale",[78,176,177],{"class":84}," =",[78,179,180],{"class":88}," nuxtApp",[78,182,183],{"class":99},".",[78,185,186],{"class":88},"$i18n",[78,188,183],{"class":99},[78,190,191],{"class":88},"locale",[78,193,183],{"class":99},[78,195,196],{"class":88},"value",[78,198,100],{"class":99},[78,200,202,205,207,209,212,214],{"class":80,"line":201},7,[78,203,204],{"class":88},"    moment",[78,206,183],{"class":99},[78,208,191],{"class":88},[78,210,211],{"class":99},"(",[78,213,191],{"class":88},[78,215,216],{"class":99},");\n",[78,218,220],{"class":80,"line":219},8,[78,221,143],{"emptyLinePlaceholder":142},[78,223,225,228,230,232,234,237,239],{"class":80,"line":224},9,[78,226,227],{"class":88},"    nuxtApp",[78,229,183],{"class":99},[78,231,186],{"class":88},[78,233,183],{"class":99},[78,235,236],{"class":88},"onBeforeLanguageSwitch",[78,238,177],{"class":84},[78,240,241],{"class":99}," (\n",[78,243,245,248,251,254],{"class":80,"line":244},10,[78,246,247],{"class":99},"        oldLocale",[78,249,250],{"class":84},":",[78,252,253],{"class":84}," string",[78,255,256],{"class":99},",\n",[78,258,260,263,265,267],{"class":80,"line":259},11,[78,261,262],{"class":99},"        newLocale",[78,264,250],{"class":84},[78,266,253],{"class":84},[78,268,256],{"class":99},[78,270,272,275,277,280],{"class":80,"line":271},12,[78,273,274],{"class":99},"        isInitialSetup",[78,276,250],{"class":84},[78,278,279],{"class":84}," boolean",[78,281,256],{"class":99},[78,283,285,288,290],{"class":80,"line":284},13,[78,286,287],{"class":99},"        nuxtApp",[78,289,250],{"class":84},[78,291,293],{"class":292},"s7NzM"," NuxtApp\n",[78,295,297,300,302],{"class":80,"line":296},14,[78,298,299],{"class":99},"    ) ",[78,301,162],{"class":161},[78,303,165],{"class":99},[78,305,307,310,312,314,316,319],{"class":80,"line":306},15,[78,308,309],{"class":88},"        moment",[78,311,183],{"class":99},[78,313,191],{"class":88},[78,315,211],{"class":99},[78,317,318],{"class":88},"newLocale",[78,320,216],{"class":99},[78,322,324],{"class":80,"line":323},16,[78,325,326],{"class":99},"    };\n",[78,328,330],{"class":80,"line":329},17,[78,331,143],{"emptyLinePlaceholder":142},[78,333,335,338],{"class":80,"line":334},18,[78,336,337],{"class":84},"    return",[78,339,165],{"class":99},[78,341,343],{"class":80,"line":342},19,[78,344,345],{"class":99},"        provide: {\n",[78,347,349,352],{"class":80,"line":348},20,[78,350,351],{"class":88},"            moment",[78,353,256],{"class":99},[78,355,357],{"class":80,"line":356},21,[78,358,359],{"class":99},"        },\n",[78,361,363],{"class":80,"line":362},22,[78,364,326],{"class":99},[78,366,368],{"class":80,"line":367},23,[78,369,370],{"class":99},"});\n",[10,372,373],{},"À première vue, ce code d'importation (ligne 1 et 2) qui provient de la documentation officielle de moment.js devrait fonctionner.\nPar contre, si vous avez utilisé ce code directement, vous aurez remarqué cette erreur lors de la compilation:",[375,376,377],"blockquote",{},[10,378,379],{},"Uncaught TypeError: Cannot read properties of undefined (reading 'defineLocale')",[10,381,382,383,388],{},"Il s'agit d'une erreur déroutante que j'ai pris bien du temps à corriger, mais grâce à cette ",[14,384,387],{"href":385,"rel":386},"https:\u002F\u002Fgithub.com\u002Fmoment\u002Fmoment\u002Fissues\u002F5926#issuecomment-1056785251",[18],"issue"," GitHub, j'ai finalement réussi à régler le problème et à compléter la migration vers Nuxt 3 de mon application.",[10,390,391],{},"Avec Vite.js, il faut simplement changer l'import des locales comme ceci:",[66,393,397],{"className":394,"code":395,"language":396,"meta":74,"style":74},"language-diff shiki shiki-themes solarized-light solarized-dark","- import 'moment\u002Flocale\u002Ffr-ca';\n+ import 'moment\u002Fdist\u002Flocale\u002Ffr-ca';\n","diff",[34,398,399,405],{"__ignoreMap":74},[78,400,401],{"class":80,"line":81},[78,402,404],{"class":403},"s_nZe","- import 'moment\u002Flocale\u002Ffr-ca';\n",[78,406,407],{"class":80,"line":72},[78,408,409],{"class":84},"+ import 'moment\u002Fdist\u002Flocale\u002Ffr-ca';\n",[10,411,412],{},"Malheureusement, ne vous attendez pas à une correction de la part de moment.js puisque le projet est en mode maintenance et ne recevra de mises à jour que si une faille de sécurité majeure est découverte.",[10,414,415],{},"Vous pouvez migrer vers une alternative plus moderne à moment.js, mais dans mon cas, je devais migrer une code base utilisant largement moment.js en Nuxt 3.",[10,417,418,419,424,425,428],{},"J'ai bien tenté de migrer vers ",[14,420,423],{"href":421,"rel":422},"https:\u002F\u002Fday.js.org\u002F",[18],"Day.js",", qui a une API rétrocompatible et l'avantage d'une approche modulaire et un code plus moderne lui permettant d'avoir un poids réduit (7kb vs 61kb) en prenant avantage des dernières fonctionnalités d'internationalisation d'ECMAScript, mais j'ai fait face à une fonctionnalité manquante en lien avec le parsing des heures (Ex. ",[34,426,427],{},"10:00:00",") sans date associée.",[10,430,431,432,437,438,442],{},"Heureusement, je pourrai peut-être faire la migration éventuellement puisqu'une ",[14,433,436],{"href":434,"rel":435},"https:\u002F\u002Fgithub.com\u002Fiamkun\u002Fdayjs\u002Fpull\u002F2197",[18],"pull request"," afin d'apporter cette fonctionnalité à Day.js a été ouverte après que j'ai ouvert l'",[14,439,387],{"href":440,"rel":441},"https:\u002F\u002Fgithub.com\u002Fiamkun\u002Fdayjs\u002Fissues\u002F2179",[18]," sur GitHub afin de signaler ce manquement par rapport à moment.js.",[444,445,446],"style",{},"html pre.shiki code .sxPyI, html code.shiki .sxPyI{--shiki-default:#859900;--shiki-dark:#859900}html pre.shiki code .sCW-z, html code.shiki .sCW-z{--shiki-default:#268BD2;--shiki-dark:#268BD2}html pre.shiki code .sNx9Q, html code.shiki .sNx9Q{--shiki-default:#2AA198;--shiki-dark:#2AA198}html pre.shiki code .skhcD, html code.shiki .skhcD{--shiki-default:#657B83;--shiki-dark:#839496}html pre.shiki code .sNKNx, html code.shiki .sNKNx{--shiki-default:#586E75;--shiki-default-font-weight:bold;--shiki-dark:#93A1A1;--shiki-dark-font-weight:bold}html pre.shiki code .s7NzM, html code.shiki .s7NzM{--shiki-default:#CB4B16;--shiki-dark:#CB4B16}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s_nZe, html code.shiki .s_nZe{--shiki-default:#DC322F;--shiki-dark:#DC322F}",{"title":74,"searchDepth":72,"depth":72,"links":448},[],"2023-01-17","Vous avez peut-être remarqué que le module @nuxtjs\u002Fmoment n'est pas compatible avec Nuxt 3.","md",{},"\u002Fblog\u002F2023-01-17-momentjs-avec-nuxt3",false,{"text":456,"minutes":457,"time":458,"words":459},"3 min read",2.41,144600,482,{"title":5,"description":450},"blog\u002F2023-01-17-momentjs-avec-nuxt3","IIbirBMD5d0NJZHSDa5SVT8YPRNhl502O1vX7UINzms",[464,468],{"title":465,"path":466,"stem":467,"children":-1},"Bienvenue sur mon nouveau site web !","\u002Fblog\u002F2023-01-01-mots-de-bienvenue","blog\u002F2023-01-01-mots-de-bienvenue",null,1792907962263]