Как запретить моменту.js загружать локали с помощью веб-пакета?

199

Можно ли как-нибудь остановить moment.jsзагрузку всех локалей (мне просто нужен английский) при использовании веб-пакета? Я смотрю на источник, и кажется, что если hasModuleопределено, что это для веб-пакета, то он всегда пытается в require()каждой локали. Я почти уверен, что для исправления требуется запрос на удаление. Но есть ли способ исправить это с помощью конфигурации веб-пакета?

Вот мой конфиг веб-пакета для загрузки моментов:

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

Тогда везде, где мне это нужно, я просто делаю require('moment'). Это работает, но он добавляет около 250 КБ ненужных языковых файлов в мой комплект. Также я использую бауэр-версию момента и глотка.

Также, если это не может быть исправлено конфигурацией веб-пакета, здесь есть ссылка на функцию, в которую он загружает локали . Я попытался добавить && module.exports.loadLocalesк ifзаявлению, но я думаю, что веб-пакет на самом деле не работает так, как это будет работать. Это просто requireне смотря ни на что. Я думаю, что сейчас используется регулярное выражение, поэтому я не знаю, как бы вы его исправили.

epelc
источник
Вы пытались использовать момент через nmpвместо bower?
Андреас Кёберле
Я использую bower для всех моих клиентских библиотек и npm для всех моих инструментов сборки. Я хочу сохранить это так, потому что мои проекты размечены. Также, если вы посмотрите последний ответ github.com/moment/moment/issues/1866, я решил свою собственную проблему, но она требует незначительного редактирования исходного кода. Я до сих пор не знаю, как исправить это правильно, так как я не знаю, как бы вы различали узел и веб-пакет.
epelc

Ответы:

305

Код require('./locale/' + name)может использовать каждый файл вlocale директории. Таким образом, веб-пакет включает в себя каждый файл как модуль в вашем комплекте. Он не может знать, какой язык вы используете.

Есть два плагина , которые полезны, чтобы дать веб-пакету больше информации о том, какой модуль должен быть включен в ваш пакет: ContextReplacementPluginи IgnorePlugin.

require('./locale/' + name)называется контекстом (требование, которое содержит выражение). Webpack выводит некоторую информацию из этого фрагмента кода: каталог и регулярное выражение. Здесь: directory = ".../moment/locale" regular expression = /^.*$/. Таким образом, по умолчанию каждый файл в localeкаталоге включен.

ContextReplacementPluginПозволяет переопределить выведенную информацию т.е. обеспечить новое регулярное выражение (выбрать языки , которые вы хотите включить).

Другой подход заключается в игнорировании потребности с IgnorePlugin .

Вот пример:

var webpack = require("webpack");
module.exports = {
  // ...
  plugins: [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /de|fr|hu/)
    // new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
  ]
};
Тобиас К.
источник
3
Можете ли вы объяснить, как использовать игнорировать загрузчик? Я пробовал `новый webpackreg.IgnorePlugin (/\.\/ locale \ /.+. Js $ /, [])`, но это не сработало. Кроме того, contextReplacementPlugin по-прежнему включал файлы в мой комплект, я просто думаю, что он их не использовал.
epelc
9
Вы можете взглянуть на эту проблему ( github.com/webpack/webpack/issues/198 ), в которой подробно обсуждается момент + веб-пакет.
Тобиас К.
2
Спасибо, я думаю, new webpack.IgnorePlugin(/^\.\/lang$/, /moment$/)из вашего комментария на GitHub будет работать.
epelc
16
В документах webpack второй аргумент - это массив регулярных выражений. Я пытался, plugins: [ new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]) ],который работал просто отлично.
Алекс К
6
@AlexKinnee Обозначение в скобках в документации означает, что это необязательный аргумент, а не массив.
yangmillstheory
8

В нашем проекте я включаю момент, подобный этому: import moment from 'moment/src/moment';и это, кажется, делает свое дело. Наше использование момента очень простое, поэтому я не уверен, будут ли какие-либо несоответствия с SDK. Я думаю, что это работает, потому что WebPack не знает, как статически найти файлы локали, поэтому вы получаете предупреждение (его легко скрыть, добавив пустую папку в moment/src/lib/locale/locale), но ни одна локаль не включает.

Адам Маккормик
источник
1
Не уверен, ребята, как этот работает для вас ... Я просто пытался бороться с этим github.com/angular/angular-cli/issues/6137, а затем просто закончил с использованием github.com/ksloan/moment-mini . Надлежащая модульная momentбиблиотека выйдет с версией 3 github.com/moment/moment/milestone/15 в какой-то момент.
kuncevic.dev
3

Надлежащая модульная momentбиблиотека в какой-то момент выйдет с версией 3, так что в настоящее время я использую angular-cli без --ejectиспользования только https://github.com/ksloan/moment-mini likeimport * as moment from 'moment-mini';

kuncevic.dev
источник
2

Основываясь на ответе Адама Маккрмика, вы были близки, измените свой псевдоним на:

resolve: {
    alias: {
        moment: 'moment/src/moment'
    },
},
bigopon
источник
1
Просто предупреждаю, что это изменит поведение всех включенных вами модулей и может вызвать интересные проблемы со сторонними библиотеками. Это должно работать в целом, хотя
Адам Маккормик
1
Можете ли вы уточнить? Я не опытный со всеми вариантами использования псевдонима. В моем понимании, было бы важно, если бы вы коснулись этого модуля, в данном случае «момент»
bigopon
3
Когда вы устанавливаете псевдонимы разрешения, они применяются при любом использовании импорта или требования в вашей системе (включая библиотеки, от которых вы зависите). Таким образом, если модуль зависит от требуемого момента, вы изменили бы результат и для этого модуля. Это происходит, если вы случайно установили псевдоним, который конфликтует с модулем узла в вашем дереве зависимостей (например, «события», например, если ваши зависимости используют эту библиотеку). На практике у меня возникла проблема только с конфликтами имен, а не с такими уточнениями поведения, но это более опасный подход, чем изменение одного оператора импорта.
Адам Маккормик
2

С webpack2последними версиями вы можете сделать:

import {fn as moment} from 'moment'

И тогда в webpack.config.jsвас делают:

resolve: {
    packageMains: ['jsnext:main', 'main']
}
Kevin
источник
1
Я предполагаю, что вы имеете в видуmainFields: ...
Гильермо Грау
Посмотрите на webpack2, уверен, что имя поля изменилось.
Кевин