Comment empêcher moment.js de charger des locales avec webpack?

199

Est-il possible d'arrêter le moment.jschargement de tous les paramètres régionaux (j'ai juste besoin d'anglais) lorsque vous utilisez webpack? Je regarde la source et il semble que si hasModuleest défini, ce qui est pour webpack, alors il essaie toujours de require()tous les paramètres régionaux. Je suis presque sûr que cela a besoin d'une demande de tirage pour corriger. Mais existe-t-il un moyen de résoudre ce problème avec la configuration du webpack?

Voici ma configuration webpack pour charger momentjs:

resolve: {
            alias: {
                moment: path.join(__dirname, "src/lib/bower/moment/moment.js")
            },
        },

Ensuite, partout où j'en ai besoin, je le fais require('moment'). Cela fonctionne, mais cela ajoute environ 250 Ko de fichiers de langue inutiles à mon bundle. J'utilise également la version bower de momentjs et gulp.

De plus, si cela ne peut pas être corrigé par la configuration du webpack, voici un lien vers la fonction où il charge les locales . J'ai essayé d'ajouter && module.exports.loadLocalesà la ifdéclaration, mais je suppose que le webpack ne fonctionne pas réellement d'une manière où cela fonctionnerait. C'est juste requirequoi qu'il arrive. Je pense qu'il utilise un regex maintenant, donc je ne sais pas vraiment comment vous pourriez y remédier.

epelc
la source
Avez-vous essayé d'utiliser moment via nmpau lieu de bower?
Andreas Köberle
J'utilise bower pour toutes mes bibliothèques clientes et npm pour tous mes outils de construction. Je veux que cela reste ainsi en raison de la façon dont mes projets sont organisés. De plus, si vous regardez la dernière réponse de github.com/moment/moment/issues/1866, j'ai résolu mon propre problème mais cela nécessite une modification de source mineure. Je ne sais toujours pas comment résoudre ce problème de la bonne manière, car je ne sais pas comment vous distingueriez le nœud et le webpack.
epelc

Réponses:

305

Le code require('./locale/' + name)peut utiliser tous les fichiers dulocale . Webpack inclut donc chaque fichier en tant que module dans votre bundle. Il ne peut pas savoir quelle langue vous utilisez.

Il existe deux plugins qui sont utiles pour donner au webpack plus d'informations sur le module à inclure dans votre bundle: ContextReplacementPluginet IgnorePlugin.

require('./locale/' + name)est appelé un contexte (un besoin qui contient une expression). webpack déduit certaines informations de ce fragment de code: un répertoire et une expression régulière. Ici: directory = ".../moment/locale" regular expression = /^.*$/. Donc, par défaut, chaque fichier dulocale répertoire est inclus.

le ContextReplacementPlugin permet de remplacer les informations déduites, c'est-à-dire de fournir une nouvelle expression régulière (pour choisir les langues que vous souhaitez inclure).

Une autre approche consiste à ignorer l'exigence avec le IgnorePlugin .

Voici un exemple:

var webpack = require("webpack");
module.exports = {
  // ...
  plugins: [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /de|fr|hu/)
    // new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
  ]
};
Tobias K.
la source
3
Pouvez-vous expliquer comment utiliser le chargeur ignore? J'ai essayé `new webpackreg.IgnorePlugin (/\.\/ locale \ /.+. Js $ /, [])` mais cela n'a pas fonctionné. De plus, le contextReplacementPlugin incluait toujours les fichiers dans mon bundle, je pense juste qu'il ne les utilisait pas.
epelc
9
Vous pouvez jeter un œil à ce problème ( github.com/webpack/webpack/issues/198 ) qui contient une discussion détaillée sur moment + webpack.
Tobias K.
2
Merci, je pense que new webpack.IgnorePlugin(/^\.\/lang$/, /moment$/)votre commentaire sur github fonctionnera.
epelc
16
Dans les documents du webpack, le deuxième argument est un tableau d'expressions régulières. J'ai essayé plugins: [ new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]) ],ce qui a très bien fonctionné.
Alex K
6
@AlexKinnee La notation des crochets dans les documents signifie que c'est un argument facultatif, pas un tableau.
yangmillstheory
8

Dans notre projet, j'inclus un moment comme celui-ci: import moment from 'moment/src/moment';et cela semble faire l'affaire. Notre utilisation de moment est cependant très simple, donc je ne sais pas s'il y aura des incohérences avec le SDK. Je pense que cela fonctionne parce que WebPack ne sait pas comment trouver les fichiers de paramètres régionaux de manière statique, vous obtenez donc un avertissement (qui est facile à masquer en ajoutant un dossier vide à moment/src/lib/locale/locale), mais aucun paramètre régional ne comprend.

Adam McCormick
la source
1
Je ne sais pas trop comment cela fonctionne pour vous ... J'ai juste essayé de combattre ce github.com/angular/angular-cli/issues/6137 et j'ai fini par utiliser github.com/ksloan/moment-mini . La momentbibliothèque modulaire appropriée proposera la version 3 github.com/moment/moment/milestone/15 à un moment donné.
kuncevic.dev
3

La momentbibliothèque modulaire appropriée proposera la version 3 à un moment donné, donc actuellement, comme j'utilise angular-cli sans que --ejectje finisse par utiliser https://github.com/ksloan/moment-mini commeimport * as moment from 'moment-mini';

kuncevic.dev
la source
2

D'après la réponse d'Adam McCrmick, vous étiez proche, changez votre alias en:

resolve: {
    alias: {
        moment: 'moment/src/moment'
    },
},
bigopon
la source
1
Juste un mot d'avertissement, cela changera le comportement de tous les modules que vous incluez et pourrait causer des problèmes intéressants avec les bibliothèques tierces. Cela devrait fonctionner en général cependant
Adam McCormick
1
Peux-tu élaborer ? Je ne connais pas tous les cas d'utilisation d'alias. À ma connaissance, cela n'aurait d'importance que si vous avez touché ce module, dans ce cas, «moment»
bigopon
3
Lorsque vous définissez des alias de résolution, ils s'appliquent à toute utilisation d'importation ou requise dans votre système (y compris les bibliothèques dont vous dépendez). Donc, si un module dont vous dépendez du moment requis, vous changeriez également le résultat pour ce module. Cela apparaît si vous définissez un alias qui entre en conflit avec un module de noeud dans votre arborescence de dépendances (comme "événements" par exemple si vos dépendances utilisent cette bibliothèque). Dans la pratique, je n'ai rencontré que des conflits de noms, pas des améliorations de comportement comme celle-ci, mais c'est une approche plus dangereuse que de changer une seule instruction d'importation.
Adam McCormick
2

Avec webpack2les versions récentes de moment, vous pouvez faire:

import {fn as moment} from 'moment'

Et puis en webpack.config.jsvous:

resolve: {
    packageMains: ['jsnext:main', 'main']
}
Kevin
la source
1
Je suppose que tu veux diremainFields: ...
Guillermo Grau
Regardez webpack2, presque sûr que le nom du champ a changé.
Kevin