Spec-Zone.ru › webpack 5

MiniCssExtractPlugin

Отказ от ответственности: MiniCssExtractPlugin — это сторонний пакет, поддерживаемый участниками сообщества, у него, вероятно, отсутствует такая же поддержка, политика безопасности или лицензия, как у webpack, и он не поддерживается webpack.

Этот плагин извлекает CSS в отдельные файлы. Он создаёт файл CSS для каждого файла JS, содержащего CSS. Он поддерживает загрузку CSS по требованию и карты исходного кода.

Он основан на новой функции webpack v5 и требует webpack 5 для работы.

По сравнению с extract-text-webpack-plugin:

  • Асинхронная загрузка
  • Отсутствие дублирования компиляции (производительность)
  • Проще в использовании
  • Специально для CSS

Начало работы

Для начала вам необходимо установить mini-css-extract-plugin:

npm install --save-dev mini-css-extract-plugin

или

yarn add -D mini-css-extract-plugin

или

pnpm add -D mini-css-extract-plugin

Рекомендуется комбинировать mini-css-extract-plugin с css-loader

Затем добавьте загрузчик и плагин в вашу конфигурацию webpack. Например:

style.css

body {
  background: green;
}

component.js

import "./style.css";

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

[!ВНИМАНИЕ]

Обратите внимание, что если вы импортируете CSS из вашей точки входа webpack или импортируете стили в начальном блоке начальный, mini-css-extract-plugin не загрузит этот CSS в страницу. Используйте html-webpack-plugin для автоматического создания link тегов или создайте файл index.html с тегом link.

[!ВНИМАНИЕ]

Карты исходного кода работают только для значений source-map/nosources-source-map/hidden-nosources-source-map/hidden-source-map, так как CSS поддерживает карты исходного кода только с комментарием sourceMappingURL, (например, //# sourceMappingURL=style.css.map). Если вам нужно установить devtool в другое значение, вы можете включить генерацию карт исходного кода для извлечённого CSS, используя sourceMap: true для css-loader.

Опции

Опции плагина

  • filename
  • chunkFilename
  • ignoreOrder
  • insert
  • attributes
  • linkType
  • runtime
  • experimentalUseImportModule

filename

Тип:

type filename =
  | string
  | ((pathData: PathData, assetInfo?: AssetInfo) => string);

По умолчанию: [name].css

Эта опция определяет имя каждого выходного файла CSS.

Работает как output.filename

chunkFilename

Тип:

type chunkFilename =
  | string
  | ((pathData: PathData, assetInfo?: AssetInfo) => string);

По умолчанию: based on filename

Указание chunkFilename в качестве function доступно только в webpack@5

Эта опция определяет имя файлов блоков, не являющихся точками входа.

Работает как output.chunkFilename

ignoreOrder

Тип:

type ignoreOrder = boolean;

По умолчанию: false

Убрать предупреждения о порядке. Подробности см. в примерах ниже.

insert

Тип:

type insert = string | ((linkTag: HTMLLinkElement) => void);

По умолчанию: document.head.appendChild(linkTag);

Вставляет тег link в заданную позицию для не-начальных (асинхронных) блоков CSS.

[!ВНИМАНИЕ]

Только для не-начальных (асинхронных) блоков.

По умолчанию плагин добавляет стили (элементы <link> к document.head текущего window.

Однако в некоторых случаях может потребоваться более точный контроль над целевым элементом для добавления или даже задержка добавления элементов link. Например, это необходимо, когда вы асинхронно загружаете стили для приложения, работающего внутри iframe. В таких случаях insert можно настроить на функцию или пользовательский селектор.

Если вы нацеливаетесь на iframe, убедитесь, что у родительского документа есть достаточные права доступа для взаимодействия с документом фрейма и добавления элементов в него.

string

Позволяет настроить пользовательский селектор. Новый элемент <link> будет вставлен после найденного элемента.

webpack.config.js

new MiniCssExtractPlugin({
  insert: "#some-element",
});

Новый элемент <link> будет вставлен после элемента с id some-element.

function

Позволяет переопределить поведение по умолчанию и вставить стили в любой позиции.

⚠ Не забудьте, что этот код будет выполняться в браузере вместе с вашим приложением. Так как не все браузеры поддерживают новейшие возможности ECMAScript, такие как let, const, arrow function expression и т.д., мы рекомендуем использовать только возможности и синтаксис ECMAScript 5.

⚠ Функция insert сериализуется в строку и передаётся в плагин. Это означает, что она не будет иметь доступа к области видимости модуля конфигурации webpack.

webpack.config.js

new MiniCssExtractPlugin({
  insert: function (linkTag) {
    var reference = document.querySelector("#some-element");
    if (reference) {
      reference.parentNode.insertBefore(linkTag, reference);
    }
  },
});

Новый элемент <link> будет вставлен перед элементом с id some-element.

attributes

Тип:

type attributes = Record<string, string>};

По умолчанию: {}

[!ВНИМАНИЕ]

Только для не-начальных (асинхронных) блоков.

Если определено, плагин добавит заданные атрибуты со значениями к элементу <link>.

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      attributes: {
        id: "target",
        "data-target": "example",
      },
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

[!ПРИМЕЧАНИЕ]

Применяется только к динамически загружаемым блокам CSS. Если вы хотите изменить атрибуты ссылок внутри файла html, используйте html-webpack-plugin.

linkType

Тип:

type linkType = string | boolean;

По умолчанию: text/css

Эта опция позволяет загружать асинхронные блоки с типом ссылки, например <link type="text/css" ...>.

string

Возможные значения: text/css

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      linkType: "text/css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};
boolean

false отключает атрибут ссылки type.

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      linkType: false,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

runtime

Тип:

type runtime = boolean;

По умолчанию: true

Позволяет включить/выключить генерацию runtime. CSS всё равно будет извлечён и может быть использован для пользовательских методов загрузки. Например, вы можете использовать assets-webpack-plugin для получения, а затем использовать свой собственный код runtime для загрузки ресурсов по мере необходимости.

false для пропуска.

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      runtime: false,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

experimentalUseImportModule

Тип:

type experimentalUseImportModule = boolean;

По умолчанию: undefined

Включено по умолчанию, если не отключено явно (т.е. true и false позволяют явно контролировать эту опцию) и новый API доступен (требуется как минимум webpack 5.52.0). Булевы значения доступны с версии 5.33.2, но вам нужно включить experiments.executeModule (не требуется с webpack 5.52.0).

Использует новый API webpack для выполнения модулей вместо дочерних компиляторов. Это значительно улучшает производительность и использование памяти.

В сочетании с experiments.layers, это добавляет опцию layer к опциям загрузчика для указания уровня выполнения CSS.

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // You don't need this for `>= 5.52.0` due to the fact that this is enabled by default
      // Required only for `>= 5.33.2 & <= 5.52.0`
      // Not available/unsafe for `<= 5.33.2`
      experimentalUseImportModule: true,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Опции загрузчика

  • publicPath
  • emit
  • esModule
  • defaultExport

publicPath

Тип:

type publicPath =
  | string
  | ((resourcePath: string, rootContext: string) => string);

По умолчанию: publicPath в webpackOptions.output

Устанавливает пользовательский публичный путь для внешних ресурсов, таких как изображения, файлы и т.д., внутри CSS. Работает как output.publicPath

string

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: "/public/path/to/",
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};
function

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: (resourcePath, context) => {
                return path.relative(path.dirname(resourcePath), context) + "/";
              },
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

emit

Тип:

type emit = boolean;

По умолчанию: true

Если true, генерируется файл (записывается файл в файловую систему). Если false, плагин извлечёт CSS, но не сгенерирует файл. Это часто полезно для отключения этой опции для серверных пакетов.

esModule

Тип:

type esModule = boolean;

По умолчанию: true

По умолчанию, mini-css-extract-plugin генерирует JS-модули, использующие синтаксис ES-модулей. Существуют случаи, когда использование ES-модулей выгодно, например, при конкатенации модулей module concatenation и tree shaking.

Вы можете включить синтаксис CommonJS:

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              esModule: false,
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

defaultExport

Тип:

type defaultExport = boolean;

По умолчанию: false

[!ПРИМЕЧАНИЕ]

Эта опция будет работать только когда namedExport установлено на true в css-loader

По умолчанию mini-css-extract-plugin генерирует JS-модули, основанные на параметрах esModule и namedExport в css-loader. Используя опции esModule и namedExport, вы сможете лучше оптимизировать код. Если вы установите esModule: true и namedExport: true для css-loader, mini-css-extract-plugin будет генерировать только именованный экспорт. Наша официальная рекомендация - использовать только именованный экспорт для лучшей совместимости в будущем. Но для некоторых приложений быстро переписать код из стандартного экспорта в именованный экспорт непросто.

В случае необходимости и стандартного, и именованного экспорта, вы можете включить эту опцию:

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              defaultExport: true,
            },
          },
          {
            loader: "css-loader",
            options: {
              esModule: true,
              modules: {
                namedExport: true,
              },
            },
          },
        ],
      },
    ],
  },
};

Примеры

Рекомендуемый

Для сборки production рекомендуется извлекать CSS из вашего пакета, чтобы позже использовать параллельную загрузку CSS/JS-ресурсов. Этого можно добиться с помощью mini-css-extract-plugin, так как он создаёт отдельные файлы CSS. Для режима development (включая webpack-dev-server), вы можете использовать style-loader, так как он вставляет CSS в DOM с использованием множественных и работает быстрее.

Не используйте style-loader и mini-css-extract-plugin вместе.

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";

module.exports = {
  module: {
    rules: [
      {
        // If you enable `experiments.css` or `experiments.futureDefaults`, please uncomment line below
        // type: "javascript/auto",
        test: /\.(sa|sc|c)ss$/,
        use: [
          devMode ? "style-loader" : MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      },
    ],
  },
  plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
};

Минимальный пример

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // all options are optional
      filename: "[name].css",
      chunkFilename: "[id].css",
      ignoreOrder: false, // Enable to remove warnings about conflicting order
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              // you can specify a publicPath here
              // by default it uses publicPath in webpackOptions.output
              publicPath: "../",
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

Именованный экспорт для CSS-модулей

⚠ Имена локалей преобразуются в camelCase.

⚠ Нельзя использовать служебные слова JavaScript в именах классов CSS.

⚠ Параметры esModule и modules.namedExport в css-loader должны быть включены.

styles.css

.foo-baz {
  color: red;
}
.bar {
  color: blue;
}

index.js

import { fooBaz, bar } from "./styles.css";

console.log(fooBaz, bar);

Вы можете включить экспорт модуля ES, используя:

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
          },
          {
            loader: "css-loader",
            options: {
              esModule: true,
              modules: {
                namedExport: true,
                localIdentName: "foo__[name]__[local]",
              },
            },
          },
        ],
      },
    ],
  },
};

Параметр publicPath как функция

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: (resourcePath, context) => {
                // publicPath is the relative path of the resource to the context
                // e.g. for ./css/admin/main.css the publicPath will be ../../
                // while for ./css/main.css the publicPath will be ../
                return path.relative(path.dirname(resourcePath), context) + "/";
              },
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

Пример расширенной конфигурации

Этот плагин не следует использовать с style-loader в цепочке загрузчиков.

Вот пример, чтобы иметь как HMR в development и ваши стили были извлечены в файл для production сборки.

(Опции загрузчиков опущены для ясности, адаптируйте их в соответствии со своими потребностями.)

Вы не должны использовать плагин HotModuleReplacementPlugin если вы используете webpack-dev-server. webpack-dev-server включает / выключает HMR с помощью параметра hot.

webpack.config.js

const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";

const plugins = [
  new MiniCssExtractPlugin({
    // Options similar to the same options in webpackOptions.output
    // both options are optional
    filename: devMode ? "[name].css" : "[name].[contenthash].css",
    chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
  }),
];
if (devMode) {
  // only enable hot in development
  plugins.push(new webpack.HotModuleReplacementPlugin());
}

module.exports = {
  plugins,
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      },
    ],
  },
};

Горячая перезагрузка модулей (HMR)

[!ПРИМЕЧАНИЕ]

HMR автоматически поддерживается в webpack 5. Нет необходимости в настройке. Пропустите следующее:

mini-css-extract-plugin поддерживает горячую перезагрузку фактических файлов CSS в режиме разработки. Предоставлены некоторые параметры для включения HMR как для стандартных таблиц стилей, так и для локально-определенных CSS или CSS-модулей. Ниже приведена примерная конфигурация mini-css для использования HMR с CSS-модулями.

Вы не должны использовать плагин HotModuleReplacementPlugin если вы используете webpack-dev-server. webpack-dev-server включает / выключает HMR с помощью параметра hot.

webpack.config.js

const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const plugins = [
  new MiniCssExtractPlugin({
    // Options similar to the same options in webpackOptions.output
    // both options are optional
    filename: devMode ? "[name].css" : "[name].[contenthash].css",
    chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
  }),
];
if (devMode) {
  // only enable hot in development
  plugins.push(new webpack.HotModuleReplacementPlugin());
}

module.exports = {
  plugins,
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {},
          },
          "css-loader",
        ],
      },
    ],
  },
};

Минификация для производства

Для минификации вывода используйте плагин, такой как css-minimizer-webpack-plugin.

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
  optimization: {
    minimizer: [
      // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
      // `...`,
      new CssMinimizerPlugin(),
    ],
  },
};

Это включит оптимизацию CSS только в режиме производства. Если вы хотите запустить его и в режиме разработки, установите параметр optimization.minimize в значение true.

Использование предварительно загруженного или встроенного CSS

Код выполнения обнаруживает уже добавленный CSS с помощью тега <link> или <style>. Это может быть полезно при вставке CSS на стороне сервера для рендеринга на стороне сервера. Значение атрибута href тега <link> должно совпадать с URL, который будет использоваться для загрузки фрагмента CSS. Атрибут data-href может использоваться для <link> и <style> тоже. При инлайнинге CSS необходимо использовать data-href.

Извлечение всего CSS в один файл

CSS можно извлечь в один файл CSS, используя optimization.splitChunks.cacheGroups.

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: "styles",
          type: "css/mini-extract",
          chunks: "all",
          enforce: true,
        },
      },
    },
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Обратите внимание, что type следует использовать вместо test в Webpack 5, иначе может быть сгенерирован дополнительный файл .js помимо файла .css. Это потому, что test не знает, какие модули следует удалить (в этом случае он не обнаружит, что .js должен быть удалён).

Извлечение CSS на основе входа

Вы также можете извлечь CSS на основе имени входа webpack. Это особенно полезно, если вы динамически импортируете маршруты, но хотите сохранить свой CSS, сгруппированный по входам. Это также предотвращает проблему дублирования CSS, которая существовала с ExtractTextPlugin.

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: {
    foo: path.resolve(__dirname, "src/foo"),
    bar: path.resolve(__dirname, "src/bar"),
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        fooStyles: {
          type: "css/mini-extract",
          name: "styles_foo",
          chunks: (chunk) => {
            return chunk.name === "foo";
          },
          enforce: true,
        },
        barStyles: {
          type: "css/mini-extract",
          name: "styles_bar",
          chunks: (chunk) => {
            return chunk.name === "bar";
          },
          enforce: true,
        },
      },
    },
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Параметр имени файла как функция

С помощью параметра filename вы можете использовать данные фрагмента для настройки имени файла. Это особенно полезно при работе с несколькими точками входа и желании получить больший контроль над именем файла для данной точки входа/фрагмента. В примере ниже мы будем использовать filename для вывода сгенерированного CSS в другой каталог.

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: ({ chunk }) => `${chunk.name.replace("/js/", "/css/")}.css`,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Кэширование на длительный срок

Для кэширования на длительный срок используйте filename: "[contenthash].css". Дополнительно добавьте [name].

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].[contenthash].css",
      chunkFilename: "[id].[contenthash].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Убрать предупреждения о порядке

Для проектов, в которых порядок CSS был смягчен за счёт последовательного использования присвоения области действия или соглашений об именовании, таких как CSS Modules, предупреждения о порядке CSS можно отключить, установив для флага ignoreOrder значение true для плагина.

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      ignoreOrder: true,
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

Несколько тем

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: "./src/index.js",
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        oneOf: [
          {
            resourceQuery: "?dark",
            use: [
              MiniCssExtractPlugin.loader,
              "css-loader",
              {
                loader: "sass-loader",
                options: {
                  additionalData: `@use 'dark-theme/vars' as vars;`,
                },
              },
            ],
          },
          {
            use: [
              MiniCssExtractPlugin.loader,
              "css-loader",
              {
                loader: "sass-loader",
                options: {
                  additionalData: `@use 'light-theme/vars' as vars;`,
                },
              },
            ],
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      attributes: {
        id: "theme",
      },
    }),
  ],
};

src/index.js

import "./style.scss";

let theme = "light";
const themes = {};

themes[theme] = document.querySelector("#theme");

async function loadTheme(newTheme) {
  // eslint-disable-next-line no-console
  console.log(`CHANGE THEME - ${newTheme}`);

  const themeElement = document.querySelector("#theme");

  if (themeElement) {
    themeElement.remove();
  }

  if (themes[newTheme]) {
    // eslint-disable-next-line no-console
    console.log(`THEME ALREADY LOADED - ${newTheme}`);

    document.head.appendChild(themes[newTheme]);

    return;
  }

  if (newTheme === "dark") {
    // eslint-disable-next-line no-console
    console.log(`LOADING THEME - ${newTheme}`);

    import(/* webpackChunkName: "dark" */ "./style.scss?dark").then(() => {
      themes[newTheme] = document.querySelector("#theme");

      // eslint-disable-next-line no-console
      console.log(`LOADED - ${newTheme}`);
    });
  }
}

document.onclick = () => {
  if (theme === "light") {
    theme = "dark";
  } else {
    theme = "light";
  }

  loadTheme(theme);
};

src/dark-theme/_vars.scss

$background: black;

src/light-theme/_vars.scss

$background: white;

src/styles.scss

body {
  background-color: vars.$background;
}

public/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Document</title>
    <link id="theme" rel="stylesheet" type="text/css" href="./main.css" />
  </head>
  <body>
    <script src="./main.js"></script>
  </body>
</html>

Плагин Media Query

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

  • Плагин Media Query
  • Плагин разделения Media Query

Плагины

Плагин mini-css-extract-plugin предоставляет плагины для расширения его возможностей в соответствии с вашими потребностями.

beforeTagInsert

SyncWaterfallHook

Вызывается перед вставкой кода вставки для тега link. Должен вернуть строку.

MiniCssExtractPlugin.getCompilationHooks(compilation).beforeTagInsert.tap(
  "changeHref",
  (source, varNames) =>
    Template.asString([
      source,
      `${varNames.tag}.setAttribute("href", "/plugins/mini-css-extract-plugin/));`,
    ])
);

Содействие

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

CONTRIBUTING

Лицензия

MIT

© JS Foundation and other contributors
Licensed under the Creative Commons Attribution License 4.0.
https://webpack.js.org/plugins/mini-css-extract-plugin

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API