Less.js: ModifyVars не передается

Созданный на 23 февр. 2018  ·  6Комментарии  ·  Источник: less/less.js

У меня есть файл index.less, который решает, какой файл переменных загружать с помощью переменной, например:

@theme-variant: "a-theme.less";

<strong i="6">@import</strong> "./@{theme-variant}";

У меня меньше файлов, загружаемых в этот индексный файл:

<strong i="10">@import</strong> "~theme-variant-variables";

Я устанавливаю значение переменной в моем файле webpack.config.js :

lessOptions.modifyVars = {
   "theme-variant": `"${v}-theme.less"`
}

Если я перемещу содержимое файла index.less в непосредственно импортированный файл less, все будет работать так, как я ожидаю, я могу переключить файл переменных, выбранный на основе логики конфигурации веб-пакета, к сожалению, если я попытаюсь централизовать эти две строки less в файл, который непосредственно импортирует меньше файлов, сам импортирует, он перестает работать. Я вижу меньше вызовов загрузчика с ожидаемой конфигурацией, поэтому я предполагаю, что компилятор less не распространяет переменные/параметры на меньшее количество импортированных файлов. Это ожидается?

Все 6 Комментарий

Я предполагаю, что это то же самое, что и в # 2772 - см. там середину обсуждения (например, modifyVars имеет эффект определения переменной, но это происходит после того, как интересующий оператор импорта уже оценен ). Но также см. https://github.com/less/less.js/issues/1400#issuecomment -137128461.

Вкратце суть такова: интерполяция переменных в операторах импорта — удобная штука, но она прямо противоречит принципу ленивой оценки. Таким образом, если дело доходит до сложной структуризации, лучше найти другие способы добиться такой настройки (например, использовать разные каталоги для разных файлов темы, а затем установить соответствующую опцию paths для переключения).

Спасибо за ответ. Переменная обновляется в меньшем количестве файлов, которые напрямую импортируются JS, это просто файлы, которые импортируются другими меньшими файлами, переменная которых не обновляется. Ленивая оценка происходит в обоих случаях, конечно? Похоже, что изменение логики/конфигурации var не применяется/передается в менее импортированные файлы. Или я что-то упускаю?

Переменная обновляется в меньшем количестве файлов, которые напрямую импортируются JS, это просто файлы, которые импортируются другими меньшими файлами, переменная которых не обновляется.

Ну, это сложнее, чем это. Обратите внимание, что для работы ленивой оценки компилятор должен оценивать различные языковые объекты (в той же области видимости) по типам , а не в порядке их появления в коде, от более высокого уровня к более низкому, т.е. (примерно): imports -> mixins - > переменные.
Теперь, если у вас есть <strong i="9">@import</strong> "@{var}"; , компилятор вынужден оценивать данную переменную перед импортом (и всеми последующими импортами) - и это все портит (вообще результат такого злоупотребления просто не определен - он работает в одних случаях (в основном очень простых) и не работает в других).

Компилятор не может гарантировать согласованное поведение при объединении двух прямо конфликтующих функций.

Другими словами, дело не в том, что modifyVars не "обновляет переменные" при последующем импорте, а в том, что обновленные значения переменных сами по себе не могут иметь никакого влияния на импорт внешнего уровня (поскольку этот импорт уже "выполнен").


И даже если документы говорят:

Обратите внимание, что до v2.0.0 учитывались только переменные, которые были объявлены в корневой или текущей области, и что при поиске переменной учитывались только текущий файл и вызывающие файлы.

... это не намного лучше после v2. Это действительно улучшило/исправило больше комбинаций/вариантов использования, но не может исправить их все. Для получения более подробной информации см. № 1108 и, в частности, № 2246.


Похоже, что изменение логики/конфигурации var не применяется/передается в менее импортированные файлы.

Нет (просто потому, что в итоге файлы оцениваются все вместе как одна большая строка). Если проблема не в другом, для проверки просто добавьте:
foo {bar: @theme-variant}
к интересующим файлам и посмотреть результат.

Кстати. Для вашего варианта использования (если «*-theme.less» касается только переменных/примесей для конкретной темы), вы можете попробовать что-то вроде:

  • Оставьте значение по умолчанию <strong i="7">@import</strong> "a-theme.less"; явным (т.е. без какой-либо интерполяции) или полностью удалите его.
  • С помощью modifyVars установите сам оператор импорта (например, <strong i="11">@import</strong> "custom-theme.less"; напрямую).

Обратите внимание, что хотя modifyVars делает вид, что речь идет только о переменных бла-бла-бла, на самом деле он ничего не делает, кроме добавления произвольного текста в конец корневого файла. Т.е. в случае lessc реально просто --modify-vars="whatever-less-code foo {bar: baz;}" . Хотя я не знаю, через какие форматы может проходить менее загрузчик веб-пакета, хм... Может быть, lessOptions.modifyVars = "an arbitrary code"; ?

Это, очевидно, хак, но на самом деле это вполне предсказуемый хак (поскольку он злоупотребляет только форматом modifyVars , а не самим языком, как это делает первоначальная комбинация).

Большое спасибо за ваши ответы и идеи @seven-phases-max. Я собираюсь продолжить расследование в течение недели и установил напоминание, чтобы обновить / закрыть эту проблему позже на этой неделе. Спасибо еще раз.

Тогда я закрою это, так как это больше похоже на ожидаемое (в данном случае определяемое как «неопределенное/неуказанное») поведение, а не на проблему, которую можно было бы каким-то образом решить.
Хотя любые идеи по улучшению и особенно PR всегда приветствуются... Я не думаю, что кто-то будет этим заниматься в обозримом будущем.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги