MiniCssExtractPlugin

免责声明 MiniCssExtractPlugin是一个由社区成员维护的第三方包,它可能不具备与 webpack 相同的支持、安全策略或许可证,并且不受 webpack 维护。

npm node tests coverage discussion size

此插件将 CSS 提取到单独的文件中。它为每个包含 CSS 的 JS 文件创建一个 CSS 文件。它支持 CSS 的按需加载和 Source Map。

它基于 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-plugincss-loader 结合使用。

然后将 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"],
      },
    ],
  },
};

[!警告]

请注意,如果你从 webpack 入口点导入 CSS 或在初始 chunk 中导入样式,mini-css-extract-plugin 不会自动将此 CSS 加载到页面中。请使用 html-webpack-plugin 自动生成 link 标签,或手动在你的 index.html 文件中包含一个 <link> 标签。

[!警告]

Source map 仅适用于 source-map/nosources-source-map/hidden-nosources-source-map/hidden-source-map 值,因为 CSS 仅支持带有 sourceMappingURL 注释的 source map(即 //# sourceMappingURL=style.css.map)。如果你需要将 devtool 设置为其他值,可以通过为 css-loader 使用 sourceMap: true 来启用提取 CSS 的 source map 生成。

选项

插件选项

filename

类型

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

默认值:[name].css

此选项决定每个输出 CSS 文件的名称。

作用类似于 output.filename

chunkFilename

类型

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

默认值:基于 filename

chunkFilename 指定为 function 仅在 webpack@5 中可用

此选项决定非入口 chunk 文件的名称。

作用类似于 output.chunkFilename

ignoreOrder

类型

type ignoreOrder = boolean;

默认值:false

移除顺序警告。更多详情请参阅示例

insert

类型

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

默认值:document.head.appendChild(linkTag);

在给定位置为非初始(异步) CSS chunk 插入 link 标签

[!警告]

仅适用于非初始(异步) chunk。

默认情况下,mini-css-extract-plugin 将样式(<link> 元素)附加到当前 windowdocument.head 中。

然而,在某些情况下,可能需要更精细地控制追加目标,甚至延迟 link 元素的插入。例如,当你异步加载在 iframe 中运行的应用程序的样式时,就是这种情况。在这种情况下,insert 可以配置为一个函数或一个自定义选择器。

如果你目标是 iframe,请确保父文档有足够的访问权限来进入帧文档并向其追加元素。

string

允许设置自定义的 查询选择器。新的 <link> 元素将插入到找到的项之后。

webpack.config.js

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

新的 <link> 标签将插入到 ID 为 some-element 的元素之后。

function

允许覆盖默认行为并在任何位置插入样式。

⚠ 不要忘记此代码将在浏览器中与你的应用程序一起运行。由于并非所有浏览器都支持最新的 ECMA 特性,例如 letconstarrow function expression 等,我们建议你仅使用 ECMA 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>};

默认值:{}

[!警告]

仅适用于非初始(异步) chunk。

如果定义,mini-css-extract-plugin 将在 <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 chunk。如果你想修改 HTML 文件中的 <link> 属性,请使用 html-webpack-plugin

linkType

类型

type linkType = string | boolean;

默认值:text/css

此选项允许使用自定义链接类型加载异步 chunk,例如 <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 完全禁用 link 的 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

允许启用/禁用运行时生成。CSS 仍将被提取,并可用于自定义加载方法。例如,你可以使用 assets-webpack-plugin 来检索它们,然后使用自己的运行时代码在需要时下载资产。

设置为 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

如果未明确启用(即 truefalse 允许你显式控制此选项)且新 API 可用(至少需要 webpack 5.52.0)时,此选项默认启用。布尔值自版本 5.33.2 起可用,但你需要启用 experiments.executeModule(从 webpack 5.52.0 起不再需要)。

使用新的 webpack API 来执行模块而不是子编译器,显著提升性能和内存使用。

experiments.layers 结合使用时,这会为 loader 选项添加一个 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"],
      },
    ],
  },
};

Loader 选项

publicPath

类型

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

默认值:webpackOptions.output 中的 publicPath

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 生成使用 ES 模块语法的 JS 模块。在某些情况下,使用 ES 模块是有益的,例如模块连接摇树优化

你可以通过以下方式启用 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

[!注意]

此选项仅在你将 css-loader 中的 namedExport 设置为 true 时才有效。

默认情况下,mini-css-extract-plugin 根据 css-loader 中的 esModulenamedExport 选项生成 JS 模块。使用 esModulenamedExport 选项将使你能够更好地优化代码。如果你为 css-loader 设置 esModule: truenamedExport: truemini-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 构建,建议从你的 bundle 中提取 CSS,以便之后能够并行加载 CSS/JS 资源。这可以通过使用 mini-css-extract-plugin 实现,因为它创建单独的 CSS 文件。对于 development 模式(包括 webpack-dev-server),你可以使用 style-loader,因为它使用多种方式将 CSS 注入到 DOM 中并且工作速度更快。

重要提示:不要同时使用 style-loadermini-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

⚠ 不允许在 CSS 类名中使用 JavaScript 保留字。

css-loader 中的 esModulemodules.namedExport 选项应该被启用。

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 选项

你可以将 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",
        ],
      },
    ],
  },
};

高级配置示例

此插件不应与 loader 链中的 style-loader 一起使用。

这是一个示例,可以在 development 环境中启用 HMR,并在 production 构建中将样式提取到文件中。

(为清晰起见,省略了 Loader 选项,请根据你的需求进行调整。)

如果你正在使用 webpack-dev-server,则不应使用 HotModuleReplacementPlugin 插件。webpack-dev-server 使用 hot 选项来启用/禁用 HMR。

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)

[!注意]

webpack 5 中已自动支持 HMR。无需配置。跳过以下内容

mini-css-extract-plugin 支持在开发环境中对实际 CSS 文件进行热重载。提供了一些选项来启用标准样式表以及局部作用域 CSS 或 CSS 模块的 HMR。以下是 mini-css 与 CSS 模块结合使用 HMR 的配置示例。

如果你正在使用 webpack-dev-server,则不应使用 HotModuleReplacementPlugin 插件。webpack-dev-server 使用 hot 选项来启用/禁用 HMR。

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 o keep JS minimizers and add CSS minimizer:
      // `...`,
      new CssMinimizerPlugin(),
    ],
  },
};
  • 默认情况下,CSS 压缩在生产模式下运行。
  • 如果你想在开发环境中也运行它,请将 optimization.minimize 选项设置为 true

使用预加载或内联 CSS

运行时代码会检测通过 <link><style> 标签已添加的 CSS,并避免重复加载 CSS。

  • 这在服务器端渲染(SSR)时注入 CSS 非常有用。
  • <link> 标签的 href 必须与用于加载 CSS chunk 的 URL 匹配。
  • data-href 属性可用于 <link><style> 元素。
  • 内联 CSS 时必须使用 data-href

将所有 CSS 提取到单个文件中

可以使用 optimization.splitChunks.cacheGroups 并将 type 设置为 "css/mini-extract" 来将 CSS 提取到一个 CSS 文件中。

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"],
      },
    ],
  },
};

请注意,在 Webpack 5 中应该使用 type 而不是 test,否则除了 .css 文件之外还会生成一个额外的 .js 文件。这是因为 test 不知道哪些模块应该被删除(在这种情况下,它不会检测到 .js 应该被删除)。

基于入口提取 CSS

你也可以根据 webpack 入口名称提取 CSS。如果你动态导入路由但希望根据入口打包 CSS,这会特别有用。这也能解决使用 ExtractTextPlugin 时出现的 CSS 重复问题。

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 选项,你可以使用 chunk 数据自定义文件名。这在处理多个入口点并希望更好地控制给定入口点/chunk 的文件名时特别有用。在下面的示例中,我们将使用 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 Modules)来解决 CSS 排序问题的项目,可以通过将插件的 ignoreOrder 标志设置为 true 来禁用 CSS 顺序警告。

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"],
      },
    ],
  },
};

多主题

通过使用查询参数有条件地加载不同的 SCSS 变体来切换主题。

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>

媒体查询插件

如果你想从提取的 CSS 中提取媒体查询(以便移动用户不再需要加载桌面或平板专用 CSS),你应该使用以下插件之一:

钩子

mini-css-extract-plugin 提供了钩子(hooks),以满足你的扩展需求。

beforeTagInsert

SyncWaterfallHook

在为 link 标签注入插入代码之前调用。应该返回一个字符串。

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

贡献

我们欢迎所有贡献!如果您是新用户,请在提交问题或拉取请求之前花一些时间阅读我们的贡献指南。

贡献

许可证

MIT