Jak uniemożliwić moment.js ładowanie ustawień regionalnych za pomocą pakietu WebPack?

199

Czy jest jakiś sposób, aby zatrzymać moment.jsładowanie wszystkich ustawień narodowych (potrzebuję tylko angielskiego) podczas korzystania z pakietu WebPack? Patrzę na źródło i wygląda na to, że jeśli hasModulejest zdefiniowane, to jest dla webpacka, to zawsze próbuje require()wszystkich ustawień regionalnych. Jestem prawie pewien, że to wymaga żądania ściągnięcia, aby to naprawić. Ale czy jest jakiś sposób, aby to naprawić za pomocą konfiguracji webpacka?

Oto moja konfiguracja webpacka, aby załadować momentjs:

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

Potem, gdziekolwiek tego potrzebuję, po prostu potrzebuję require('moment'). To działa, ale dodaje około 250 kB niepotrzebnych plików językowych do mojego pakietu. Używam też altanowej wersji momentjs i łyka.

Również jeśli konfiguracja webpack nie może tego naprawić, tutaj jest link do funkcji, w której ładuje ustawienia narodowe . Próbowałem dodać && module.exports.loadLocalesdo ifinstrukcji, ale wydaje mi się, że webpack tak naprawdę nie działa w taki sposób, aby działało. Po prostu requirenie ważne co. Myślę, że używa teraz wyrażenia regularnego, więc tak naprawdę nie wiem, jak byś to zrobił.

epelc
źródło
Czy próbowałeś użyć chwili nmpzamiast bower?
Andreas Köberle,
Używam bower do wszystkich moich bibliotek klienta i npm do wszystkich moich narzędzi do budowania. Chcę to utrzymać w ten sposób, ponieważ moje projekty są ułożone. Również, jeśli spojrzysz na ostatnią odpowiedź na github.com/moment/moment/issues/1866 , rozwiązałem własny problem, ale wymaga on niewielkiej edycji źródła. Nadal nie wiem, jak to naprawić we właściwy sposób, ponieważ nie wiem, jak odróżnić węzeł od pakietu WWW.
epelc

Odpowiedzi:

305

Kod require('./locale/' + name)może wykorzystywać każdy plik w katalogu locale. Tak więc webpack zawiera każdy plik jako moduł w pakiecie. Nie może wiedzieć, którego języka używasz.

Istnieją dwie wtyczki, które są przydatne, aby przekazać pakietowi internetowemu więcej informacji o tym, który moduł powinien zostać zawarty w pakiecie: ContextReplacementPlugini IgnorePlugin.

require('./locale/' + name)nazywa się kontekstem (wymaganie zawierające wyrażenie). webpack pobiera pewne informacje z tego fragmentu kodu: Katalog i wyrażenie regularne. Tutaj: directory = ".../moment/locale" regular expression = /^.*$/. Tak więc domyślnie każdy plik w localekatalogu jest dołączony.

ContextReplacementPluginPozwala zastąpić wywieść informacje tj dostarczyć nowe wyrażenie regularne (do wyboru języki, które chcesz dołączyć).

Innym podejściem jest zignorowanie wymagania za pomocą IgnorePlugin.

Oto przykład:

var webpack = require("webpack");
module.exports = {
  // ...
  plugins: [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /de|fr|hu/)
    // new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
  ]
};
Tobias K.
źródło
3
Czy możesz wyjaśnić, jak korzystać z modułu ładującego ignorowanie? Próbowałem `new webpackreg.IgnorePlugin (/\.\/ locale \ /.+. Js $ /, [])`, ale to nie zadziałało. Również contextReplacementPlugin nadal zawierał pliki w moim pakiecie, myślę, że ich nie używał.
epelc
9
Możesz rzucić okiem na ten problem ( github.com/webpack/webpack/issues/198 ), który zawiera szczegółową dyskusję na temat momentu + webpack.
Tobias K.,
2
Dziękuję, myślę, że new webpack.IgnorePlugin(/^\.\/lang$/, /moment$/)z twojego komentarza na github zadziała.
epelc
16
W dokumentacji pakietu webpack drugim argumentem jest tablica wyrażeń regularnych. Próbowałem, plugins: [ new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]) ],który działał dobrze.
Alex K
6
@AlexKinnee Notacja w nawiasach w dokumentach oznacza, że ​​jest to opcjonalny argument, a nie tablica.
yangmillstheory
8

W naszym projekcie uwzględniam taki moment: import moment from 'moment/src/moment';i to wydaje się załatwić sprawę. Używanie chwili jest jednak bardzo proste, więc nie jestem pewien, czy będą jakieś niespójności z SDK. Myślę, że to działa, ponieważ WebPack nie wie, jak znaleźć pliki ustawień regionalnych, więc pojawia się ostrzeżenie (można to łatwo ukryć, dodając pusty folder w moment/src/lib/locale/locale), ale nie zawiera ustawień regionalnych.

Adam McCormick
źródło
1
Nie jestem pewien, jak to działa dla ciebie ... Właśnie próbowałem walczyć z tym github.com/angular/angular-cli/issues/6137, a potem skończyłem z użyciem github.com/ksloan/moment-mini . Właściwa momentbiblioteka modułowa pojawi się w wersji 3 github.com/moment/moment/milestone/15 .
kuncevic.dev
2

Na podstawie odpowiedzi Adama McCrmicka byłeś blisko, zmień swój alias na:

resolve: {
    alias: {
        moment: 'moment/src/moment'
    },
},
bigopon
źródło
1
Wystarczy ostrzeżenie, że zmieni to zachowanie wszystkich modułów, które dołączasz, i może powodować ciekawe problemy z bibliotekami stron trzecich. Powinno jednak działać ogólnie
Adam McCormick
1
Czy możesz rozwinąć ? Nie mam doświadczenia ze wszystkimi przypadkami użycia aliasów. W moim rozumieniu
miałoby
3
Gdy ustawisz aliasy rozpoznawania, mają one zastosowanie do dowolnego użycia importu lub wymagają w twoim systemie (w tym bibliotek, od których zależysz). Więc jeśli moduł zależy od wymaganego momentu, zmieniłbyś również wynik dla tego modułu. Pojawia się to, jeśli zdarzy ci się ustawić alias, który powoduje konflikt z modułem węzła w twoim drzewie zależności (np. „Zdarzenia”, na przykład, jeśli twoje zależności korzystają z tej biblioteki). W praktyce miałem tylko problem z konfliktami nazw, a nie takimi udoskonaleniami zachowania, ale jest to bardziej niebezpieczne podejście niż zmiana jednej instrukcji importu.
Adam McCormick
2

Dzięki webpack2najnowszym wersjom chwili możesz:

import {fn as moment} from 'moment'

A potem w webpack.config.jstobie:

resolve: {
    packageMains: ['jsnext:main', 'main']
}
Kevin
źródło
1
Chyba masz na myślimainFields: ...
Guillermo Grau
Spójrz na webpack2, całkiem pewny, że nazwa pola uległa zmianie.
Kevin