TL; DR: это руководство также протестировано на Webpack 3. Рабочий пример здесь

TL; DR: в последнем разделе этой статьи показано, как заставить его работать с Webpack 4. Советую заранее прочитать статью полностью.

Одна из самых неприятных вещей, с которыми я недавно столкнулся, - это попытка настроить пользовательскую семантическую тему пользовательского интерфейса с помощью Webpack. Конечная цель заключалась в том, чтобы иметь возможность создать конфигурацию темы, которая расширила бы настройки Semantic по умолчанию, изменив при этом некоторые переменные, от которых зависят выходные семантические файлы .css. Альтернативой, конечно же, было бы создание файлов .css, которые переопределяли бы декларации CSS по умолчанию для Semantic, но это показалось мне слишком запутанным.

Оказалось, что это намного сложнее, чем должно быть, и, кроме того, нет статьи, посвященной Webpack 2. Таким образом, я решил создать простое руководство о том, как заставить его работать. Прежде чем мы начнем, я хотел бы упомянуть, что некоторые из шагов здесь взяты из руководства neekey, которое вы можете найти здесь:

Установка

Первым шагом будет установка МЕНЬШЕЙ версии семантического пользовательского интерфейса через npm:

npm install --save semantic-ui-less

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

// at the top of your webpack configuration file
const ExtractTextPlugin = require('extract-text-webpack-plugin');
...
module: {
  rules: [
    ...
    // this handles .less translation
    {
      use: ExtractTextPlugin.extract({
        use: ['css-loader', 'less-loader']
      }),
      test: /\.less$/
    },
    ...
  ]
},
plugins: [
   ...
   // this handles the bundled .css output file
   new ExtractTextPlugin({
     filename: '[name].[contenthash].css',
   }),
  ...
]

Конечно, для этого потребуются дополнительные плагины и загрузчики. Если они еще не установлены, вы можете легко добавить их с помощью следующей команды:

npm install --save-dev less css-loader less-loader extract-text-webpack-plugin

Поскольку существует много значков и изображений, вы должны убедиться, что конфигурация вашего веб-пакета знает, как их объединять. Пример конфигурации, которой вы должны следовать, если у вас ничего не настроено, будет следующая:

...
module: {
  rules: [
    ...
    
    // this rule handles images
    {
      test: /\.jpe?g$|\.gif$|\.ico$|\.png$|\.svg$/,
      use: 'file-loader?name=[name].[ext]?[hash]'
    },

    // the following 3 rules handle font extraction
    {
      test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
      loader: 'url-loader?limit=10000&mimetype=application/font-woff'
    },
    
    {
      test: /\.(ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
      loader: 'file-loader'
    },
    {
    test: /\.otf(\?.*)?$/,
    use: 'file-loader?name=/fonts/[name].  [ext]&mimetype=application/font-otf'
    }
  ]
}

Что, конечно, будет зависеть от загрузчиков url-loader и file-loader Webpack. Если они не указаны в ваших зависимостях, вы можете легко добавить их, введя следующее:

npm install --save-dev file-loader url-loader

Создание папки темы

Следующим шагом будет создание папки для нашей темы. В корне вашего проекта, на том же уровне, где находится каталог node_modules, создайте папку и назовите ее my-semantic-theme или как хотите. Внутри него создайте файл и определенно назовите его theme.config (это НЕ файл .js!) . Кроме того, создайте папку (прямо внутри my-semantic-theme) и назовите ее site. Ваш проект будет выглядеть примерно так

...
node_modules/
my-semantic-theme/
  site/
  theme.config

Чтобы наша тема расширила тему семантического пользовательского интерфейса по умолчанию, нам нужно (к сожалению) скопировать и вставить содержимое конфигурации темы по умолчанию, расположенной в node_modules / semantic-ui-less / theme.config.example. Просто откройте его, скопируйте все и вставьте в наш только что созданный файл theme.config. После этого мы должны сделать 3 больших изменения в самом низу файла.

  1. Измените @import "theme.less"; на @import "~semantic-ui-less/theme.less";
  2. Измените @siteFolder : "site"; на @siteFolder : "../../my-semantic-theme/site";, заменив «my-semantic-theme» на имя вашей папки.
  3. Добавьте @fontPath : "../../../themes/@{theme}/assets/fonts"; в самом конце theme.config (в последней строке)

Что мы здесь сделали, так это сопоставить ресурсы Semantic-UI с теми, которые мы создали. Первое изменение гарантирует, что мы импортируем правильный файл theme.less из node_modules. Второе изменение гарантирует, что переменная siteFolder указывает на нашу папку site с начальным каталогом / node_modules / semantic-ui-less / (отсюда относительный путь). Третье изменение гарантирует, что Semantic-UI может найти шрифты, которые уже существуют в темах.

Последний шаг, который мы должны решить (и который на самом деле было труднее всего найти), - это указание Semantic UI использовать наш файл theme.config при создании файлов .css . Поскольку semantic-ui-less не было создано для простого расширения, он всегда ищет файл theme.config в корневом каталоге пакета, используя относительный путь. Что мы должны сделать, он сообщает webpack : «Эй, когда кто-то запрашивает относительный путь к theme.config, сопоставьте его непосредственно с созданным нами theme.config». Для этого мы должны добавить псевдоним. В конфигурации Webpack 2, предположим, что ваш файл конфигурации webpack находится на том же уровне, что и каталог my-semantic-theme, это будет выглядеть так:

// at the top of the webpack config file
const path = require('path');
module.exports = {
   entry: ...,
   output: {
    ... 
   },
   resolve: {
     alias: {
        '../../theme.config$': path.join(__dirname, 'my-semantic-theme/theme.config')  
     }
  },
  module: {
    ...
  }
}

Это указывает webpack разрешить все вызовы импорта «../../theme.config» в наш конкретный файл theme.config.

Вот и все. Теперь в созданной нами папке site вы можете создать все папки, которые есть в обычной теме. Это означает, что ваша папка site, скорее всего, будет содержать следующие папки.

site/
   assets/
   collections/
   elements/
   globals/
   modules/
   views/

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

Чтобы изменения были объединены, вы должны, конечно, импортировать семантическую библиотеку UI .less где-нибудь в пределах вашей точки входа в веб-пакет. Поэтому, если ваша точка входа - app.js, просто добавьте следующую строку вверху файла:

import "semantic-ui-less/semantic.less"; // ES6
or
require("semantic-ui-less/semantic.less") // CommonJS

Запуск webpack приведет к созданию правильных файлов CSS, которые вам нужны, в зависимости от вашей темы. Вы можете проверить это, изменив значение переменной, например цвет фона кнопок по умолчанию.

Объединение отдельных компонентов

По умолчанию CSS каждого компонента семантического пользовательского интерфейса создается и объединяется из соответствующих файлов LESS, но бывают случаи, когда вы будете использовать только несколько семантических компонентов в своем проекте. Чтобы уменьшить общий размер ваших пакетов, вы должны объединять CSS только тех компонентов, которые вы будете использовать. Для этого есть 5 простых шагов.

  1. Сначала создайте файл с именем semantic.less в папке my-semantic-theme. Теперь эта папка должна выглядеть примерно так:
...
node_modules/
my-semantic-theme/
  site/
  theme.config
  semantic.less

2. Перейдите к соответствующему файлу библиотеки, расположенному в node_modules / semantic-ui-less / semantic.less, скопируйте все содержимое этого файла и вставьте его в наш только что созданный semantic.less файл. Наш файл должен выглядеть примерно так:

...
...
...
/* Global */
& { @import "definitions/globals/reset"; }
& { @import "definitions/globals/site"; }
/* Elements */
& { @import "definitions/elements/button"; }
& { @import "definitions/elements/container"; }
& { @import "definitions/elements/divider"; }
& { @import "definitions/elements/flag"; }
& { @import "definitions/elements/header"; }
& { @import "definitions/elements/icon"; }
...
...
...

3. Сохраните все строки, соответствующие компонентам, которые вы будете использовать в своем проекте, и удалите все остальные (вы должны оставить глобальные переменные).

4. Заменить все & { @import "definitions/..." на & { @import "~semantic-ui-less/definitions/...".

5. В точке входа вашего веб-пакета вы должны теперь включить вновь созданный semantic.less вместо библиотеки по умолчанию. Следуя той же структуре проекта, это будет достигнуто с помощью следующей команды:

import "../my-semantic-theme/semantic.less"; // ES6
or
require("../my-semantic-theme/semantic.less") // CommonJS

Все готово! Теперь будут созданы и объединены только CSS выбранных вами компонентов!

Вы можете найти полный пример всего вышеперечисленного в этом репо.

Webpack 4 и выше

Приведенный выше код полностью совместим с Webpack 4 и 5, но только потому, что многие пакеты изменили основные версии, нам нужно будет настроить некоторые вещи.

Во-первых, нам нужно заменить ExtractTextPlugin на рекомендованный MiniCSSExtractPlugin (поскольку первый устарел). Кроме того, нам также нужно будет скопировать другой файл (да, еще один) в нашу семантическую папку, поскольку пакеты semantic-ui немного изменились со времени написания этой статьи. Наконец, нам нужно будет убедиться, что пакет less соответствует версии 2.7.3. Давайте начнем:

Сначала измените плагин, который обрабатывает выводимый CSS в вашем веб-пакете:

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
...
...
// used to be ExtractTextPlugin(); 
new MiniCssExtractPlugin();

Во-вторых, измените код, который обрабатывает синтаксический анализ файлов .LESS (опять же в вашем веб-пакете):

// change the code that handles .less translation to the following 
{
  test: /\.less$/,
  use: [
    {
      loader: MiniCssExtractPlugin.loader
    },
    'css-loader',
    'less-loader'
  ]
},

Скопируйте файл theme.less, расположенный в папке /node_modules/semantic-ui-less/theme.less, и поместите его как родственника theme.config в наш репозиторий. Таким образом, форма должна выглядеть так:

....
node_modules/
my-semantic-theme/
  site/
  theme.config
  semantic.less // optional, used to bundle specific modules only
  theme.less

Наконец, убедитесь, что у вас less пакет 2.7.3 или старше.

Ваше здоровье :)

P.S. 👋 Привет, я Аггелос! Если вам это понравилось, подумайте о том, чтобы подписаться на меня в твиттере и поделиться историей со своими друзьями-разработчиками 😀