¿Cómo evitar que moment.js cargue configuraciones regionales con webpack?

199

¿Hay alguna forma de evitar que moment.jscargue todos los entornos locales (solo necesito inglés) cuando usa webpack? Estoy mirando la fuente y parece que si hasModuleestá definido, que es para webpack, siempre trata de require()cada configuración regional. Estoy bastante seguro de que esto necesita una solicitud de extracción para solucionarlo. Pero, ¿hay alguna forma de solucionar esto con la configuración del paquete web?

Aquí está mi configuración de paquete web para cargar momentjs:

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

Luego, donde sea que lo necesite, lo hago require('moment'). Esto funciona pero agrega alrededor de 250 kB de archivos de idiomas innecesarios a mi paquete. También estoy usando la versión Bower de momentjs y trago.

Además, si esto no puede ser solucionado por la configuración del paquete web, aquí hay un enlace a la función donde carga las configuraciones regionales . Traté de agregar && module.exports.loadLocalesa la ifdeclaración, pero supongo que webpack no funciona de una manera que funcionaría. Simplemente requireno importa qué. Creo que ahora usa una expresión regular, así que realmente no sé cómo podrías arreglarlo.

epelc
fuente
¿Has intentado usar moment via en nmplugar de bower?
Andreas Köberle
Estoy usando bower para todas mis librerías de clientes y npm para todas mis herramientas de compilación. Quiero mantenerlo así por cómo se presentan mis proyectos. Además, si miras la última respuesta de github.com/moment/moment/issues/1866 , resolví mi propio problema, pero requiere una edición de fuente menor. Todavía no sé cómo solucionar esto de la manera correcta, ya que no sé cómo distinguirías entre nodo y paquete web.
epelc

Respuestas:

305

El código require('./locale/' + name)puede usar todos los archivos en el localedirectorio. Entonces webpack incluye cada archivo como módulo en su paquete. No puede saber qué idioma está utilizando.

Hay dos complementos que son útiles para dar a webpack más información sobre qué módulo debe incluirse en su paquete: ContextReplacementPluginy IgnorePlugin.

require('./locale/' + name)se llama contexto (un requisito que contiene una expresión). webpack infiere alguna información de este fragmento de código: un directorio y una expresión regular. Aquí: directory = ".../moment/locale" regular expression = /^.*$/. Entonces, de manera predeterminada locale, se incluyen todos los archivos del directorio.

El ContextReplacementPluginpermite sustituir la información inferida es decir, proporcionar una nueva expresión regular (a elegir los idiomas que desea incluir).

Otro enfoque es ignorar el requerimiento con el IgnorePlugin.

Aquí hay un ejemplo:

var webpack = require("webpack");
module.exports = {
  // ...
  plugins: [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /de|fr|hu/)
    // new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
  ]
};
Tobias K.
fuente
3
¿Puedes explicar cómo usar el cargador de ignorar? Intenté `new webpackreg.IgnorePlugin (/\.\/ locale \ /.+. Js $ /, [])` pero eso no funcionó. Además, contextReplacementPlugin todavía incluía los archivos en mi paquete, solo creo que no los estaba usando.
epelc
9
Puede echar un vistazo a este problema ( github.com/webpack/webpack/issues/198 ) que contiene una discusión detallada sobre moment + webpack.
Tobias K.
2
Gracias, creo que new webpack.IgnorePlugin(/^\.\/lang$/, /moment$/)tu comentario sobre github funcionará.
epelc
16
En los documentos del paquete web, el segundo argumento es una matriz de expresiones regulares. Intenté lo plugins: [ new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]) ],que funcionó bien.
Alex K
66
@AlexKinnee La notación de corchetes en los documentos significa que es un argumento opcional, no una matriz.
yangmillstheory
8

En nuestro proyecto, incluyo momentos como este: import moment from 'moment/src/moment';y eso parece ser el truco. Sin embargo, nuestro uso del momento es muy simple, por lo que no estoy seguro de si habrá inconsistencias con el SDK. Creo que esto funciona porque WebPack no sabe cómo encontrar los archivos locales de forma estática, por lo que recibe una advertencia (que es fácil de ocultar al agregar una carpeta vacía en moment/src/lib/locale/locale), pero no incluye la configuración regional.

Adam McCormick
fuente
1
No estoy seguro, muchachos, de cómo les está funcionando ... Acabo de intentar luchar contra ese github.com/angular/angular-cli/issues/6137 y luego terminé usando github.com/ksloan/moment-mini . La momentbiblioteca modular adecuada presentará la Versión 3 github.com/moment/moment/milestone/15 en algún momento.
kuncevic.dev
3

La momentbiblioteca modular adecuada presentará la Versión 3 en algún momento, por lo que actualmente estoy usando angular-cli sin --ejecthaber terminado de usar https://github.com/ksloan/moment-mini comoimport * as moment from 'moment-mini';

kuncevic.dev
fuente
2

Según la respuesta de Adam McCrmick, estabas cerca, cambia tu alias a:

resolve: {
    alias: {
        moment: 'moment/src/moment'
    },
},
bigopon
fuente
1
Solo una advertencia, que esto cambiará el comportamiento de todos los módulos que incluya y podría causar problemas interesantes con las bibliotecas de terceros. Sin embargo
Adam McCormick el
1
Puedes elaborar ? No tengo experiencia con todos los casos de uso de alias. Según tengo entendido, solo importaría si
tocases
3
Cuando configura los alias de resolución, se aplican a cualquier uso de importación o requerido en su sistema (incluidas las bibliotecas de las que depende). Entonces, si un módulo depende del momento requerido, también cambiaría el resultado de ese módulo. Esto aparece si establece un alias que entre en conflicto con un módulo de nodo en su árbol de dependencias (como "eventos", por ejemplo, si sus dependencias usan esa biblioteca). En la práctica, solo he tenido un problema con conflictos de nombres, no con refinamientos de comportamiento como este, pero este es un enfoque más peligroso que cambiar una declaración de importación.
Adam McCormick el
2

Con webpack2y versiones recientes de moment puedes hacer:

import {fn as moment} from 'moment'

Y luego en webpack.config.jsti haces:

resolve: {
    packageMains: ['jsnext:main', 'main']
}
Kevin
fuente
1
Supongo que quiere decirmainFields: ...
Guillermo Grau
Mira webpack2, bastante seguro de que el nombre del campo cambió.
Kevin