Printable

babel-loader

This README is for babel-loader v8 + Babel v7 Check the 7.x branch for docs with Babel v6

NPM Status codecov

此 package 允许你使用 Babelwebpack 转译 JavaScript 文件。

注意:请在 Babel Issues tracker 上报告输出时遇到的问题。

安装

webpack 4.x | babel-loader 8.x | babel 7.x

npm install -D babel-loader @babel/core @babel/preset-env webpack

用法

webpack 文档:Loaders

在 webpack 配置对象中,需要将 babel-loader 添加到 module 列表中,就像下面这样:

module: {
  rules: [
    {
      test: /\.m?js$/,
      exclude: /(node_modules|bower_components)/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env'],
        },
      },
    },
  ];
}

选项

查看 babel 选项

你可以使用 options 属性,来向 loader 传递 options 选项

module: {
  rules: [
    {
      test: /\.m?js$/,
      exclude: /(node_modules|bower_components)/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env'],
          plugins: ['@babel/plugin-proposal-object-rest-spread'],
        },
      },
    },
  ];
}

此 loader 也支持下面这些 loader 特有的选项:

  • cacheDirectory:默认值为 false。当有设置时,指定的目录将用来缓存 loader 的执行结果。之后的 webpack 构建,将会尝试读取缓存,来避免在每次执行时,可能产生的、高性能消耗的 Babel 重新编译过程(recompilation process)。如果设置了一个空值 (loader: 'babel-loader?cacheDirectory') 或者 true (loader: 'babel-loader?cacheDirectory=true'),loader 将使用默认的缓存目录 node_modules/.cache/babel-loader,如果在任何根目录下都没有找到 node_modules 目录,将会降级回退到操作系统默认的临时文件目录。

  • cacheIdentifier:默认是由 @babel/core 版本号,babel-loader 版本号,.babelrc 文件内容(存在的情况下),环境变量 BABEL_ENV 的值(没有时降级到 NODE_ENV)组成的一个字符串。可以设置为一个自定义的值,在 identifier 改变后,来强制缓存失效。

  • cacheCompression:默认值为 true。当设置此值时,会使用 Gzip 压缩每个 Babel transform 输出。如果你想要退出缓存压缩,将它设置为 false -- 如果你的项目中有数千个文件需要压缩转译,那么设置此选项可能会从中收益。

  • customize: 默认值为 null。导出 custom 回调函数的模块路径,例如传入 .custom() 的 callback 函数。由于你必须创建一个新文件才能使用它,建议改为使用 .custom 来创建一个包装 loader。只有在你必须继续直接使用 babel-loader 但又想自定义的情况下,才使用这项配置。

疑难解答

babel-loader 很慢!

确保转译尽可能少的文件。你可能使用 /\.m?js$/ 来匹配,这样也许会去转译 node_modules 目录或者其他不需要的源代码。

要排除 node_modules,参考文档中的 loaders 配置的 exclude 选项。

你也可以通过使用 cacheDirectory 选项,将 babel-loader 提速至少两倍。这会将转译的结果缓存到文件系统中。

Babel 在每个文件都插入了辅助代码,使代码体积过大!

Babel 对一些公共方法使用了非常小的辅助代码,比如 _extend。默认情况下会被添加到每一个需要它的文件中。

你可以引入 Babel runtime 作为一个独立模块,来避免重复引入。

下面的配置禁用了 Babel 自动对每个文件的 runtime 注入,而是引入 @babel/plugin-transform-runtime 并且使所有辅助代码从这里引用。

更多信息请查看 文档

注意:你必须执行 npm install -D @babel/plugin-transform-runtime 来把它包含到你的项目中,然后使用 npm install @babel/runtime@babel/runtime 安装为一个依赖。

rules: [
  // 'transform-runtime' 插件告诉 Babel
  // 要引用 runtime 来代替注入。
  {
    test: /\.m?js$/,
    exclude: /(node_modules|bower_components)/,
    use: {
      loader: 'babel-loader',
      options: {
        presets: ['@babel/preset-env'],
        plugins: ['@babel/plugin-transform-runtime'],
      },
    },
  },
];

注意:transform-runtime 和自定义 polyfills (例如 Promise library)

由于 @babel/plugin-transform-runtime 包含了一个 polyfill,含有自定义的 regenerator-runtimecore-js, 下面使用 webpack.ProvidePlugin 来配置 shimming 的常用方法将没有作用:

// ...
        new webpack.ProvidePlugin({
            'Promise': 'bluebird'
        }),
// ...

下面这样的写法也没有作用:

require('@babel/runtime/core-js/promise').default = require('bluebird');

var promise = new Promise();

它其实会生成下面这样 (使用了 runtime 后):

'use strict';

var _Promise = require('@babel/runtime/core-js/promise')['default'];

require('@babel/runtime/core-js/promise')['default'] = require('bluebird');

var promise = new _Promise();

前面的 Promise library 在被覆盖前已经被引用和使用了。

一种可行的办法是,在你的应用程序中加入一个“引导(bootstrap)”步骤,在应用程序开始前先覆盖默认的全局变量。

// bootstrap.js

require('@babel/runtime/core-js/promise').default = require('bluebird');

// ...

require('./app');

babel 的 Node.js API 已经被移到 babel-core 中。

如果你收到这个信息,这说明你有一个已经安装的 babel npm package,并且在 webpack 配置中使用 loader 简写方式(在 webpack 2.x 版本中将不再支持这种方式):

  {
    test: /\.m?js$/,
    loader: 'babel',
  }

webpack 将尝试读取 babel package 而不是 babel-loader

想要修复这个问题,你需要卸载 babel npm package,因为它在 Babel v6 中已经被废除。(安装 @babel/cli 或者 @babel/core 来替代它) 在另一种场景中,如果你的依赖于 babel 而无法删除它,可以在 webpack 配置中使用完整的 loader 名称来解决:

  {
    test: /\.m?js$/,
    loader: 'babel-loader',
  }

排除不应参与转码的库

core-jswebpack/buildin 如果被 Babel 转码会发生错误。

你需要在 babel-loader 中排除它们:

{
  "loader": "babel-loader",
  "options": {
    "exclude": [
      // \\ for Windows, \/ for Mac OS and Linux
      /node_modules[\\\/]core-js/,
      /node_modules[\\\/]webpack[\\\/]buildin/,
    ],
    "presets": [
      "@babel/preset-env"
    ]
  }
}

根据 webpack 部署目标(target)的自定义配置

Webpack 支持打包成多种 部署目标 。例如,当需要为不同的部署目标(例如 webnode)指定不同的 Babel 配置时, babel-loader 通过 Babel 的caller API 提供了 target属性。

例如,根据 webpack 的部署目标改变传给@babel/preset-env的 targets 选项

// babel.config.js

module.exports = (api) => {
  return {
    plugins: [
      '@babel/plugin-proposal-nullish-coalescing-operator',
      '@babel/plugin-proposal-optional-chaining',
    ],
    presets: [
      [
        '@babel/preset-env',
        {
          useBuiltIns: 'entry',
          // caller.target 等于 webpack 配置的 target 选项
          targets: api.caller((caller) => caller && caller.target === 'node')
            ? { node: 'current' }
            : { chrome: '58', ie: '11' },
        },
      ],
    ],
  };
};

自定义 loader

babel-loader 提供了一个 loader-builder 工具函数, 允许用户为 Babel 处理过的每个文件添加自定义处理选项

.custom 接收一个 callback 函数, 它将被调用,并传入 loader 中的 babel 实例, 因此,此工具函数才能够完全确保它使用与 loader 的 @babel/core 相同的实例。

如果你想自定义,但实际上某个文件又不想调用 .custom, 可以向 customize 选项传入一个字符串, 此字符串指向一个导出 custom 回调函数的文件。

示例

// 从 "./my-custom-loader.js" 中导出,或者任何你想要的文件中导出。
module.exports = require('babel-loader').custom((babel) => {
  function myPlugin() {
    return {
      visitor: {},
    };
  }

  return {
    // 传给 loader 的选项。
    customOptions({ opt1, opt2, ...loader }) {
      return {
        // 获取 loader 可能会有的自定义选项
        custom: { opt1, opt2 },

        // 传入"移除了两个自定义选项"后的选项
        loader,
      };
    },

    // 提供 Babel 的 'PartialConfig' 对象
    config(cfg) {
      if (cfg.hasFilesystemConfig()) {
        // 使用正常的配置
        return cfg.options;
      }

      return {
        ...cfg.options,
        plugins: [
          ...(cfg.options.plugins || []),

          // 在选项中包含自定义 plugin
          myPlugin,
        ],
      };
    },

    result(result) {
      return {
        ...result,
        code: result.code + '\n// 自定义loader生成',
      };
    },
  };
});
// 然后,在你的 webpack config 文件中
module.exports = {
  // ..
  module: {
    rules: [
      {
        // ...
        loader: path.join(__dirname, 'my-custom-loader.js'),
        // ...
      },
    ],
  },
};

customOptions(options: Object): { custom: Object, loader: Object }

指定的 loader 的选项, 从 babel-loader 选项中分离出自定义选项。

config(cfg: PartialConfig): Object

指定的 Babel 的 PartialConfig 对象, 返回应该被传递给 babel.transformoption 对象。

result(result: Result): Result

指定的 Babel 结果对象,允许 loaders 对它进行额外的调整。

License

MIT

coffee-loader

npm node deps tests coverage chat size

Compile CoffeeScript to JavaScript.

起步

安装 coffeescriptcoffee-loader

npm install --save-dev coffeescript coffee-loader

然后添加 plugin 到 webpack 配置文件. 例:

file.coffee

# 任务:
number   = 42
opposite = true

# 条件:
number = -42 if opposite

# 函数:
square = (x) -> x * x

# 数组:
list = [1, 2, 3, 4, 5]

# 对象:
math =
  root:   Math.sqrt
  square: square
  cube:   (x) -> x * square x

# Splats:
race = (winner, runners...) ->
  print winner, runners

# 存在性:
alert "I knew it!" if elvis?

# 数组推导(comprehensions):
cubes = (math.cube num for num in list)

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.coffee$/,
        loader: "coffee-loader",
      },
    ],
  },
};

替代方案:

import coffee from "coffee-loader!./file.coffee";

然后按偏好运行 webpack

选项

类型:Object 默认:{ bare: true }

所有 coffeescript 选项的文档 点击查看.

transpile 选项的文档 点击查看.

ℹ️ sourceMap 选项从 compiler.devtool 中选取一个值作为默认值。

ℹ️ filename 选项从 webpack loader API 中选取一个值。 选项值将被忽略。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.coffee$/,
        loader: "coffee-loader",
        options: {
          bare: false,
          transpile: {
            presets: ["@babel/env"],
          },
        },
      },
    ],
  },
};

示例

CoffeeScript 与 Babel

来自 CoffeeScript 2 的文档:

CoffeeScript 2 使用最新的句法生成 JavaScript。 代码运行所在的运行时或浏览器有可能无法支持全部相关句法。 这种情况下,新的 JavaScript 句法将被转换为旧的 JavaScript 句法,以便在较低版本 Node 环境或浏览器中运行这些代码。比如将 { a } = obj 转换为 a = obj.a。 这个转换的过程是由一些诸如 Babel, Bublé or Traceur Compiler 等转换工具完成的。

安装 @babel/core@babel/preset-env 然后创建配置文件:

npm install --save-dev @babel/core @babel/preset-env
echo '{ "presets": ["@babel/env"] }' > .babelrc

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.coffee$/,
        loader: "coffee-loader",
        options: {
          transpile: {
            presets: ["@babel/env"],
          },
        },
      },
    ],
  },
};

Literate CoffeeScript

开启 Literate CoffeeScript 时需要设置:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.coffee$/,
        loader: "coffee-loader",
        options: {
          literate: true,
        },
      },
    ],
  },
};

贡献

如果您尚未了解,建议您阅读以下贡献指引。

CONTRIBUTING

许可

MIT

css-loader

npm node deps tests coverage chat size

css-loader 会对 @importurl() 进行处理,就像 js 解析 import/require() 一样。

快速开始

如果要使用 css-loader,你需要安装 webpack@5

首先,你需要先安装 css-loader

npm install --save-dev css-loader

然后把 loader 引用到你 webpack 的配置中。如下所示:

file.js

import css from 'file.css';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
};

然后运行 webpack

如果由于某种原因你需要将 CSS 提取为一个文件(即不要将 CSS 存储在 JS 模块中),你可能想要查看 推荐示例

配置项

名称类型默认值描述
url{Boolean|Function}true启用/禁用 url()/image-set() 函数处理
import{Boolean|Function}true启用/禁用 @import 规则进行处理
modules{Boolean|String|Object}{auto: true}启用/禁用 CSS 模块及其配置
sourceMap{Boolean}compiler.devtool启用/禁用生成 SourceMap
importLoaders{Number}0启用/禁用或者设置在 css-loader 前应用的 loader 数量
esModule{Boolean}true使用 ES 模块语法
exportType{'array' | 'string' | 'css-style-sheet'}array允许导出样式为模块数组、字符串或者 可构造样式(即 CSSStyleSheet

url

类型: Boolean|Object 默认值: true

启用/禁用 url/image-set 函数进行处理。 如果设置为 falsecss-loader 将不会解析 url 或者 image-set 中的任何路径。 还可以传递给一个函数基于资源的路径动态地控制这种行为。 绝对路径和根目录的相对 URL 现在会被解析(版本 4.0.0

示例解决方案:

url(image.png) => require('./image.png')
url('image.png') => require('./image.png')
url(./image.png) => require('./image.png')
url('./image.png') => require('./image.png')
url('http://dontwritehorriblecode.com/2112.png') => require('http://dontwritehorriblecode.com/2112.png')
image-set(url('image2x.png') 1x, url('image1x.png') 2x) => require('./image1x.png') and require('./image2x.png')

要从 node_modules 目录(包括 resolve.modules)导入资源,而对于 alias,请加上一个前缀 ~

url(~module/image.png) => require('module/image.png')
url('~module/image.png') => require('module/image.png')
url(~aliasDirectory/image.png) => require('otherDirectory/image.png')

Boolean

启用/禁用 url() 解析。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          url: true,
        },
      },
    ],
  },
};

Object

允许过滤 url()。所有过滤的内容 url() 都不会解析(保留编写时的代码)。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          url: {
            filter: (url, resourcePath) => {
              // resourcePath - css 文件的路径

              // 不处理 `img.png` url
              if (url.includes('img.png')) {
                return false;
              }

              return true;
            },
          },
        },
      },
    ],
  },
};

import

类型: Boolean|Object 默认值: true

启用/禁用 @import 规则进行处理。 控制 @import 的解析。@import 中的绝对 URL 会被直接移到运行时去处理。

示例解决方案:

@import 'style.css' => require('./style.css')
@import url(style.css) => require('./style.css')
@import url('style.css') => require('./style.css')
@import './style.css' => require('./style.css')
@import url(./style.css) => require('./style.css')
@import url('./style.css') => require('./style.css')
@import url('http://dontwritehorriblecode.com/style.css') => @import url('http://dontwritehorriblecode.com/style.css') in runtime

要从 node_modules 目录(包括 resolve.modules)导入样式,而对于 alias,请加上一个前缀 ~

@import url(~module/style.css) => require('module/style.css')
@import url('~module/style.css') => require('module/style.css')
@import url(~aliasDirectory/style.css) => require('otherDirectory/style.css')

Boolean

启用/禁用 @import 解析。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          import: true,
        },
      },
    ],
  },
};

Object

名称类型默认值描述
filter{Function}undefined允许过滤 @import
filter

类型:Function 默认值:undefined

允许过滤 @import。所有过滤的内容 @import 都不会解析(保留编写时的代码)。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          import: {
            filter: (url, media, resourcePath) => {
              // resourcePath - css 文件路径

              // 不处理 `style.css` 的导入
              if (url.includes('style.css')) {
                return false;
              }

              return true;
            },
          },
        },
      },
    ],
  },
};

modules

类型:Boolean|String|Object 默认值:undefined

启用/禁用 CSS 模块或者 ICSS 及其配置:

  • undefined - 为所有匹配 /\.module\.\w+$/i.test(filename)/\.icss\.\w+$/i.test(filename) 正则表达式的文件启用 CSS 模块。
  • true - 对所有文件启用 CSS 模块。
  • false - 对所有文件禁用 CSS 模块。
  • string - 对所有文件禁用 CSS 模块并设置 mode 配置项,你可以在 这里 获得更多信息。
  • object - 如果没有配置 modules.auto 则对所有文件启用 CSS 模块,否则 modules.auto 配置项则会决定其是否为 CSS 模块,你可以在 这里 获得更多信息。

modules 选项启用/禁用 CSS 模块 规范并且设置基本的行为。

设置为 false 值会提升性能,因为避免了 CSS Modules 特性的解析,这对于使用普通 CSS 或者其他技术的开发人员是非常有用的。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: true,
        },
      },
    ],
  },
};

Features

Scope

使用 local 值要求你指定 :global 类。 使用 global 值要求你指定 :local 类。 使用 pure 值则要求必须至少包含一个局部类或者 id。

你可以点击 此处 了解更多。

样式可以在局部作用域中,避免影响全局作用域的样式。

语法 :local(.className) 可以被用来在局部作用域中声明 className。局部的作用域标识符会以模块形式暴露出去。

使用 :local(无括号)可以为此选择器启用局部模式。 :global(.className) 可以用来声明一个明确的全局选择器。 使用 :global(无括号)可以将此选择器切换至全局模式。

loader 会用唯一的标识符 (identifier) 来替换局部选择器。所选择的唯一标识符以模块形式暴露出去。

:local(.className) {
  background: red;
}
:local .className {
  color: green;
}
:local(.className .subClass) {
  color: green;
}
:local .className .subClass :global(.global-class-name) {
  color: blue;
}
._23_aKvs-b8bW2Vg3fwHozO {
  background: red;
}
._23_aKvs-b8bW2Vg3fwHozO {
  color: green;
}
._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 {
  color: green;
}
._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 .global-class-name {
  color: blue;
}

ℹ️ 被导出的标识符

exports.locals = {
  className: '_23_aKvs-b8bW2Vg3fwHozO',
  subClass: '_13LGdX8RMStbBE9w-t0gZ1',
};

本地选择器推荐使用驼峰命名。它们在导入的 JS 模块中更容易使用。

你也可以使用 :local(#someId),但这并不推荐。应该使用类去代替 id。

Composing

声明本地类名时,可以从另一个本地类名组成一个本地类。

:local(.className) {
  background: red;
  color: yellow;
}

:local(.subClass) {
  composes: className;
  background: blue;
}

这不会导致 CSS 本身发生任何变化,但是会导出多个类名。

exports.locals = {
  className: '_23_aKvs-b8bW2Vg3fwHozO',
  subClass: '_13LGdX8RMStbBE9w-t0gZ1 _23_aKvs-b8bW2Vg3fwHozO',
};
._23_aKvs-b8bW2Vg3fwHozO {
  background: red;
  color: yellow;
}

._13LGdX8RMStbBE9w-t0gZ1 {
  background: blue;
}
Importing

从另一个模块导入本地类名。

我强烈建议您在导入文件时指定扩展名,因为可以导入具有任何扩展名的文件,而且事先并不能知道要使用哪个文件。

:local(.continueButton) {
  composes: button from 'library/button.css';
  background: red;
}
:local(.nameEdit) {
  composes: edit highlight from './edit.css';
  background: red;
}

要从多个模块导入,请使用多个 composes: 规则。

:local(.className) {
  composes: edit hightlight from './edit.css';
  composes: button from 'module/button.css';
  composes: classFromThisModule;
  background: red;
}
Values

可以使用 @value 来指定在整个文档中都能被重复使用的值,

我们推荐对特定的值使用 v- 的前缀,给选择器使用 s- 的前缀,并且为媒体规则使用 m- 前缀。

@value v-primary: #BF4040;
@value s-black: black-selector;
@value m-large: (min-width: 960px);

.header {
  color: v-primary;
  padding: 0 10px;
}

.s-black {
  color: black;
}

@media m-large {
  .header {
    padding: 0 20px;
  }
}

Boolean

启用 CSS 模块 功能。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: true,
        },
      },
    ],
  },
};

String

启用 CSS 模块 功能和设置 mode

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          // 使用 `local` 同使用 `modules: true` 的效果是一样的
          modules: 'global',
        },
      },
    ],
  },
};

Object

启用 CSS 模块 功能和设置选项。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            mode: 'local',
            auto: true,
            exportGlobals: true,
            localIdentName: '[path][name]__[local]--[hash:base64:5]',
            localIdentContext: path.resolve(__dirname, 'src'),
            localIdentHashSalt: 'my-custom-hash',
            namedExport: true,
            exportLocalsConvention: 'camelCase',
            exportOnlyLocals: false,
          },
        },
      },
    ],
  },
};
auto

类型:Boolean|RegExp|Function 默认值:undefined

modules 配置项为对象时允许基于文件名自动启用 CSS 模块或者 ICSS。

有效值:

  • undefined - 为所有文件启用 CSS 模块。
  • true - 为所有匹配 /\.module\.\w+$/i.test(filename)/\.icss\.\w+$/i.test(filename) 正则表达式的文件启用 CSS 模块。
  • false - 禁用 CSS 模块。
  • RegExp - 为所有匹配 /RegExp/i.test(filename) 正则表达式的文件禁用 CSS 模块。
  • function - 为所有通过基于文件名的过滤函数校验的文件启用 CSS 模块。
Boolean

可能的值:

  • true - 启用 CSS 模块或者可交互 CSS 格式,为所有满足 /\.module(s)?\.\w+$/i.test(filename) 条件的文件设置 modules.mode 选项为 local,或者为所有满足 /\.icss\.\w+$/i.test(filename) 条件的文件设置 modules.mode 选项为 icss
  • false - 禁用 css 模块或者基于文件名的可交互 CSS 格式

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            auto: true,
          },
        },
      },
    ],
  },
};
RegExp

根据正则表达式检查文件名,为匹配的文件启用 css 模块。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            auto: /\.custom-module\.\w+$/i,
          },
        },
      },
    ],
  },
};
Function

根据过滤器检查文件名,为满足过滤要求的文件启用 css 模块。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            auto: (resourcePath) => resourcePath.endsWith('.custom-module.css'),
          },
        },
      },
    ],
  },
};
mode

类型:String|Function 默认:'local'

设置 mode 选项。需要 local 模式时可以忽略该值。

控制应用于输入样式的编译级别。

localglobalpure 处理 classid 域以及 @value 值。 icss 只会编译底层的 Interoperable CSS 格式,用于声明 CSS 和其他语言之间的 :import:export 依赖关系。

ICSS 提供 CSS Module 支持,并且为其他工具提供了一个底层语法,以实现它们自己的 css-module 变体。

String

可选值 - localglobalpureicss

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            mode: 'global',
          },
        },
      },
    ],
  },
};
Function

允许根据文件名设置不同的 mode 选项值。

可能的返回值 - localglobalpureicss

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            // 回调必须返回 `local`,`global`,或者 `pure`
            mode: (resourcePath) => {
              if (/pure.css$/i.test(resourcePath)) {
                return 'pure';
              }

              if (/global.css$/i.test(resourcePath)) {
                return 'global';
              }

              return 'local';
            },
          },
        },
      },
    ],
  },
};
localIdentName

类型:String 默认:'[hash:base64]'

允许配置生成的本地标识符(ident)。

更多关于配置项的信息可以查看:

支持的模板字符串:

  • [name] 源文件名称
  • [folder] 文件夹相对于 compiler.context 或者 modules.localIdentContext 配置项的相对路径。
  • [path] 源文件相对于 compiler.context 或者 modules.localIdentContext 配置项的相对路径。
  • [file] - 文件名和路径。
  • [ext] - 文件拓展名。
  • [hash] - 字符串的哈希值。基于 localIdentHashSaltlocalIdentHashFunctionlocalIdentHashDigestlocalIdentHashDigestLengthlocalIdentContextresourcePathexportName 生成。
  • [<hashFunction>:hash:<hashDigest>:<hashDigestLength>] - 带有哈希设置的哈希。
  • [local] - 原始类名。

建议:

  • 开发环境使用 '[path][name]__[local]'
  • 生产环境使用 '[hash:base64]'

[local] 占位符包含原始的类。

**注意:**所有保留 (<>:"/\|?*) 和控制文件系统字符 (不包括 [local] 占位符) 都将转换为 -

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            localIdentName: '[path][name]__[local]--[hash:base64:5]',
          },
        },
      },
    ],
  },
};
localIdentContext

类型:String 默认:compiler.context

允许为本地标识符名称重新定义基本的 loader 上下文。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            localIdentContext: path.resolve(__dirname, 'src'),
          },
        },
      },
    ],
  },
};
localIdentHashSalt

类型:String 默认:undefined

允许添加自定义哈希值以生成更多唯一类。 更多信息请查看 output.hashSalt

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            localIdentHashSalt: 'hash',
          },
        },
      },
    ],
  },
};
localIdentHashFunction

类型:String 默认值:md4

允许设置生成 class 的哈希函数。 更多信息请查看 output.hashFunction

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            localIdentHashFunction: 'md4',
          },
        },
      },
    ],
  },
};
localIdentHashDigest

类型:String 默认值:hex

允许设置生成 class 的哈希摘要。 更多信息请查看 output.hashDigest

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            localIdentHashDigest: 'base64',
          },
        },
      },
    ],
  },
};
localIdentHashDigestLength $#localidentHashdigestlength$

类型:Number 默认值:20

允许设置生成 class 的哈希摘要长度。 更多信息请查看 output.hashDigestLength

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            localIdentHashDigestLength: 5,
          },
        },
      },
    ],
  },
};
localIdentRegExp

类型:String|RegExp 默认:undefined

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            localIdentRegExp: /page-(.*)\.css/i,
          },
        },
      },
    ],
  },
};
getLocalIdent

类型:Function 默认:undefined

可以指定自定义 getLocalIdent 函数的绝对路径,以基于不同的架构生成类名。 默认情况下,我们使用内置函数来生成 classname。 如果自定义函数返回 null 或者 undefined, 我们将降级使用内置函数来生成 classname。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            getLocalIdent: (context, localIdentName, localName, options) => {
              return 'whatever_random_class_name';
            },
          },
        },
      },
    ],
  },
};
namedExport

类型:Boolean 默认:false

本地环境启用/禁用 export 的 ES 模块。

⚠ 本地环境的命名将转换为驼峰格式,即 exportLocalsConvention 选项默认设置了 camelCaseOnly

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

styles.css

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

index.js

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

console.log(fooBaz, bar);

可以使用以下命令启用 export 的 ES 模块:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          esModule: true,
          modules: {
            namedExport: true,
          },
        },
      },
    ],
  },
};

可以为 namedExport 设置一个自定义名称,可以使用 exportLocalsConvention 配置项作为一个函数。 可前往 examples 章节查看示例。

exportGlobals

类型:Boolean 默认:false

允许 css-loader 从全局类或 ID 导出名称,因此您可以将其用作本地名称。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            exportGlobals: true,
          },
        },
      },
    ],
  },
};
exportLocalsConvention

类型:String|Function 默认:取决于 modules.namedExport 选项值,如果为 true 则对应的是 camelCaseOnly,反之对应的是 asIs

导出的类名称的样式。

String

默认情况下,导出的 JSON 密钥反映了类名(即 asIs 值)。

⚠ 如果你设置 namedExporttrue 那么只有 camelCaseOnly 被允许。

名称类型描述
'asIs'{String}类名将按原样导出。
'camelCase'{String}类名将被驼峰化,原类名不会从局部环境删除
'camelCaseOnly'{String}类名将被驼峰化,原类名从局部环境删除
'dashes'{String}类名中只有破折号会被驼峰化
'dashesOnly'{String}类名中破折号会被驼峰,原类名从局部环境删除

file.css

.class-name {
}

file.js

import { className } from 'file.css';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            exportLocalsConvention: 'camelCase',
          },
        },
      },
    ],
  },
};
Function

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            exportLocalsConvention: function (name) {
              return name.replace(/-/g, '_');
            },
          },
        },
      },
    ],
  },
};

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            exportLocalsConvention: function (name) {
              return [
                name.replace(/-/g, '_'),
                // dashesCamelCase
                name.replace(/-+(\w)/g, (match, firstLetter) =>
                  firstLetter.toUpperCase()
                ),
              ];
            },
          },
        },
      },
    ],
  },
};
exportOnlyLocals

类型:Boolean 默认:false

仅导出局部环境。

使用 css 模块 进行预渲染(例如 SSR)时很有用。 要进行预渲染,预渲染包 应使用 mini-css-extract-plugin 选项而不是 style-loader!css-loader。 它不嵌入 CSS,而仅导出标识符映射。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            exportOnlyLocals: true,
          },
        },
      },
    ],
  },
};

importLoaders

类型:Number 默认:0

允许为 @import 样式规则、CSS 模块或者 ICSS 启用/禁用或设置在 CSS loader 之前应用的 loader 的数量,例如:@import/composes/@value value from './values.css' 等。

importLoaders 选项允许你配置在 css-loader 之前有多少 loader 应用于 @imported 资源与 CSS 模块/ICSS 导入。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2,
              // 0 => no loaders (default);
              // 1 => postcss-loader;
              // 2 => postcss-loader, sass-loader
            },
          },
          'postcss-loader',
          'sass-loader',
        ],
      },
    ],
  },
};

当模块系统(即 webpack)支持按来源匹配 loader 时,这种情况将来可能会改变。

sourceMap

类型:Boolean 默认值:取决于 compiler.devtool

source map 的生成默认依赖 devtool 配置项。除了 evalfalse 之外的值都会启用 source map。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          sourceMap: true,
        },
      },
    ],
  },
};

esModule

类型:Boolean 默认:true

默认情况下,css-loader 生成使用 ES 模块语法的 JS 模块。 在某些情况下,使用 ES 模块是有益的,例如在模块串联tree shaking 时。

你可以使用以下方式启用 CommonJS 模块语法:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          esModule: false,
        },
      },
    ],
  },
};

exportType

类型:'array' | 'string' | 'css-style-sheet' 默认值:'array'

允许导出样式为模块数组、字符串或者 可构造样式(即 CSSStyleSheet)。 默认值为 'array',即 loader 导出具有特定 API 的模块数组,用于 style-loader 或其他。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        assert: { type: 'css' },
        loader: 'css-loader',
        options: {
          exportType: 'css-style-sheet',
        },
      },
    ],
  },
};

src/index.js

import sheet from './styles.css' assert { type: 'css' };

document.adoptedStyleSheets = [sheet];
shadowRoot.adoptedStyleSheets = [sheet];

'array'

loader 导出具有特定 API 的模块数组,用于 style-loader 或其他。

webpack.config.js

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

src/index.js

// `style-loader` applies styles to DOM
import './styles.css';

'string'

⚠ 你不再需要 style-loader,请移除它。 ⚠ 如果你想使用 CSS modules,应该启用 esModules 配置项,默认情况下,本地变量会被 具名导出

默认导出为 string

webpack.config.js

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

src/index.js

import sheet from './styles.css';

console.log(sheet);

'css-style-sheet'

⚠ 不再允许使用 @import 规则,更多 信息 ⚠ 你不再需要 style-loader,请移除它。 ⚠ 如果你想使用 CSS modules,应该启用 esModules 配置项,默认情况下,本地变量会被 具名导出。 ⚠ 目前在 Chrome 中不支持 Source maps,因为有该 bug

默认导出是一个 可构造样式 (即 CSSStyleSheet)。

自定义元素 以及 shadow DOM 有用处。

更多信息:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        assert: { type: 'css' },
        loader: 'css-loader',
        options: {
          exportType: 'css-style-sheet',
        },
      },

      // For Sass/SCSS:
      //
      // {
      //   assert: { type: "css" },
      //   rules: [
      //     {
      //       loader: "css-loader",
      //       options: {
      //         exportType: "css-style-sheet",
      //         // Other options
      //       },
      //     },
      //     {
      //       loader: "sass-loader",
      //       options: {
      //         // Other options
      //       },
      //     },
      //   ],
      // },
    ],
  },
};

src/index.js

// Example for Sass/SCSS:
// import sheet from "./styles.scss" assert { type: "css" };

// Example for CSS modules:
// import sheet, { myClass } from "./styles.scss" assert { type: "css" };

// Example for CSS:
import sheet from './styles.css' assert { type: 'css' };

document.adoptedStyleSheets = [sheet];
shadowRoot.adoptedStyleSheets = [sheet];

对于迁移,你可以使用以下配置:

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        oneOf: [
          {
            assert: { type: 'css' },
            loader: 'css-loader',
            options: {
              exportType: 'css-style-sheet',
              // Other options
            },
          },
          {
            use: [
              'style-loader',
              {
                loader: 'css-loader',
                options: {
                  // Other options
                },
              },
            ],
          },
        ],
      },
    ],
  },
};

示例

推荐

推荐 production 环境的构建将 CSS 从你的 bundle 中分离出来,这样可以使用 CSS/JS 文件的并行加载。 这可以通过使用 mini-css-extract-plugin 来实现,因为它可以创建单独的 CSS 文件。 对于 development 模式(包括 webpack-dev-server),你可以使用 style-loader,因为它可以使用多个 标签将 CSS 插入到 DOM 中,并且反应会更快。

i 不要同时使用 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: [
      {
        test: /\.(sa|sc|c)ss$/i,
        use: [
          devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader',
        ],
      },
    ],
  },
  plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
};

使用 /* webpackIgnore: true */ 注释禁用 url 解析

有了 /* webpackIgnore: true */ 注释,可以禁用对规则和单个声明的源处理。

/* webpackIgnore: true */
@import url(./basic.css);
@import /* webpackIgnore: true */ url(./imported.css);

.class {
  /* 对 'background' 声明中的所有 url 禁用 url 处理 */
  color: red;
  /* webpackIgnore: true */
  background: url('./url/img.png'), url('./url/img.png');
}

.class {
  /* 对 'background' 声明中第一个 url 禁用 url 处理 */
  color: red;
  background:
    /* webpackIgnore: true */ url('./url/img.png'), url('./url/img.png');
}

.class {
  /* 对 'background' 声明中第二个 url 禁用 url 处理 */
  color: red;
  background: url('./url/img.png'),
    /* webpackIgnore: true */ url('./url/img.png');
}

/* prettier-ignore */
.class {
  /* 对 'background' 声明中第二个 url 禁用 url 处理 */
  color: red;
  background: url("./url/img.png"),
    /* webpackIgnore: true */
    url("./url/img.png");
}

/* prettier-ignore */
.class {
  /* 对 'background-image' 声明中第三和第六个 url 禁用 url 处理 */
  background-image: image-set(
    url(./url/img.png) 2x,
    url(./url/img.png) 3x,
    /* webpackIgnore:  true */ url(./url/img.png) 4x,
    url(./url/img.png) 5x,
    url(./url/img.png) 6x,
    /* webpackIgnore:  true */
    url(./url/img.png) 7x
  );
}

Assets

如下配置的 webpack.config.js 可以加载 CSS 文件,嵌入小的 PNG/JPG/GIF/SVG 图片以及字体作为数据 URL,并将较大的文件复制到输出目录。

对于 webpack v5:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i,
        // 更多信息请点击这里 https://webpack.js.org/guides/asset-modules/
        type: 'asset',
      },
    ],
  },
};

Extract

For production builds it's recommended to extract the CSS from your bundle being able to use parallel loading of CSS/JS resources later on.

  • This can be achieved by using the mini-css-extract-plugin to extract the CSS when running in production mode.

  • As an alternative, if seeking better development performance and css outputs that mimic production. extract-css-chunks-webpack-plugin offers a hot module reload friendly, extended version of mini-css-extract-plugin. HMR real CSS files in dev, works like mini-css in non-dev

纯 CSS,CSS 模块和 PostCSS

如果项目中没有纯 CSS(没有 CSS 模块),CSS 模块和 PostCSS,则可以使用以下设置:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        // 对于 pure CSS - /\.css$/i,
        // 对于 Sass/SCSS - /\.((c|sa|sc)ss)$/i,
        // 对于 Less - /\.((c|le)ss)$/i,
        test: /\.((c|sa|sc)ss)$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              // 每一个 CSS 的 `@import` 与 CSS 模块/ICSS 都会运行 `postcss-loader`,不要忘了 `sass-loader` 将不属于 CSS 的 `@import` 编译到一个文件中
              // 如果您需要在每个 CSS 的 `@import` 上运行 `sass-loader` 和 `postcss-loader`,请将其设置为 `2`。
              importLoaders: 1,
            },
          },
          {
            loader: 'postcss-loader',
            options: { plugins: () => [postcssPresetEnv({ stage: 0 })] },
          },
          // 也可能是 `less-loader`
          {
            loader: 'sass-loader',
          },
        ],
      },
      // 对于 webpack v5
      {
        test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i,
        // More information here https://webpack.js.org/guides/asset-modules/
        type: 'asset',
      },
    ],
  },
};

使用别名解析未解析的 URL

index.css

.class {
  background: url(/assets/unresolved/img.png);
}

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
  resolve: {
    alias: {
      '/assets/unresolved/img.png': path.resolve(
        __dirname,
        'assets/real-path-to-img/img.png'
      ),
    },
  },
};

Named export with custom export names

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'css-loader',
        options: {
          modules: {
            namedExport: true,
            exportLocalsConvention: function (name) {
              return name.replace(/-/g, '_');
            },
          },
        },
      },
    ],
  },
};

只允许 可交互的 CSS 使其与 CSS Module 特性分离

下面是有关配置的示例代码,通过为所有未匹配到 *.module.scss 命名约定文件设置 mode 选项,只允许使用 可交互的 CSS 特性(如 :import:export),而不使用其他的 CSS Module 特性。此处仅供参考,因为在 v4 之前,css-loader 默认将 ICSS 特性应用于所有文件。 同时,在本示例中,匹配到 *.module.scss 的所有文件都将被视为 CSS Modules

假设项目中有这样一个需求,要求 canvas 绘制使用的变量与 CSS 同步,换句话说就是 canvas 绘制使用的颜色(在 JavaScript 中设置的颜色名)与 HTML 背景(在 CSS 中通过 class 设置)相同。

webpack.config.js

module.exports = {
  module: {
    rules: [
      // ...
      // --------
      // SCSS ALL EXCEPT MODULES
      {
        test: /\.scss$/i,
        exclude: /\.module\.scss$/i,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              modules: {
                mode: 'icss',
              },
            },
          },
          {
            loader: 'sass-loader',
          },
        ],
      },
      // --------
      // SCSS MODULES
      {
        test: /\.module\.scss$/i,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              modules: {
                mode: 'local',
              },
            },
          },
          {
            loader: 'sass-loader',
          },
        ],
      },
      // --------
      // ...
    ],
  },
};

variables.scss

文件被视为仅使用 ICSS

$colorBackground: red;
:export {
  colorBackgroundCanvas: $colorBackground;
}

Component.module.scss

文件被视为 CSS Module

@import 'variables.scss';
.componentClass {
  background-color: $colorBackground;
}

Component.jsx

在 JavaScript 中直接使用 CSS Module 的特性以及 SCSS 声明的变量。

import svars from 'variables.scss';
import styles from 'Component.module.scss';

// Render DOM with CSS modules class name
// <div className={styles.componentClass}>
//   <canvas ref={mountsCanvas}/>
// </div>

// Somewhere in JavaScript canvas drawing code use the variable directly
// const ctx = mountsCanvas.current.getContext('2d',{alpha: false});
ctx.fillStyle = `${svars.colorBackgroundCanvas}`;

Contributing

如果您还没有阅读,请花一点时间阅读我们的贡献指南。

贡献

License

MIT

exports-loader

npm node deps tests coverage chat size

允许对源文件设置 module.exports/export

当源文件不包含 exports 或者有一些内容没有 export 时是有用的。

想要获取有关兼容性的进一步提示,请查看官方文档中的 Shimming

⚠ 默认情况下,loader 生成具名的 ES module。

⚠ 请注意,原始代码中现有的 exports(export/module.exports/exports)和导出新值可能会导致失败。

快速开始

首先,你需要安装 exports-loader

npm install exports-loader --save-dev

内联

可以使用 | 或者 %20(空格)分隔 export 中的 syntaxnamealias。 可以在这里获取文档和语法实例。

%20 是查询字符串中的空格,因为你不能在 URL 中使用空格

然后将 loader 添加到所需的 import 语句或 require 调用中。例如:

import { myFunction } from 'exports-loader?exports=myFunction!./file.js';
// 向源文件中添加如下代码:
//
// ...
// Code
// ...
//
// export { myFunction }

myFunction('Hello world');
import {
  myVariable,
  myFunction,
} from 'exports-loader?exports=myVariable,myFunction!./file.js';
// 向源文件中添加如下代码:
//
// ...
// Code
// ...
//
// export { myVariable, myFunction };

const newVariable = myVariable + '!!!';

console.log(newVariable);

myFunction('Hello world');
const {
  myFunction,
} = require('exports-loader?type=commonjs&exports=myFunction!./file.js');
// 向源文件中添加如下代码:
//
// ...
// Code
// ...
//
// module.exports = { myFunction }

myFunction('Hello world');
// 替换语法:
// import myFunction from 'exports-loader?exports=default%20myFunction!./file.js';
import myFunction from 'exports-loader?exports=default|myFunction!./file.js';
// `%20` 是查询字符串中的空格,等同于 `default myFunction`
// 向源文件中添加如下代码:
//
// ...
// Code
// ...
//
// exports default myFunction;

myFunction('Hello world');
const myFunction = require('exports-loader?type=commonjs&exports=single|myFunction!./file.js');
// `|` 是查询字符串中的分隔符, 等同于 `single|myFunction`
// 向源文件中添加如下代码:
//
// ...
// Code
// ...
//
// module.exports = myFunction;

myFunction('Hello world');
import { myFunctionAlias } from 'exports-loader?exports=named|myFunction|myFunctionAlias!./file.js';
// `|` 是查询字符串中的分隔符, 等同于 `named|myFunction|myFunctionAlias`
// 向源文件中添加如下代码:
//
// ...
// Code
// ...
//
// exports { myFunction as myFunctionAlias };

myFunctionAlias('Hello world');

可以在下面的文档中找到字段值的含义。

使用配置文件

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        // 你可以使用 `regexp`
        // test: /vendor\.js/$
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          exports: 'myFunction',
        },
      },
    ],
  },
};

然后用你喜欢的方式运行 webpack

配置项

NameTypeDefaultDescription
type{String}module生成导出的格式
exports{String|Object|Array<String|Object>}undefined导出的列表

type

类型:String 默认值:module

生成导出的格式

可选值 - commonjs(CommonJS 模块语法)和 module(ES 模块语法)。

commonjs

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          type: 'commonjs',
          exports: 'Foo',
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

module.exports = { Foo };

module

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          type: 'module',
          exports: 'Foo',
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

export { Foo };

exports

类型:String|Array 默认值:undefined

导出的列表。

String

允许使用一个字符串来描述导出。

Syntax

可以使用 | 或者 %20(空格)分隔 export 中的 syntaxnamealias

字符串语法 - [[syntax] [name] [alias]] 或者 [[syntax]|[name]|[alias]],含义如下:

  • [syntax] (可以省略) -

    • 如果 typemodule- 可以是 defaultnamed,
    • 如果 typecommonjs- 可以使 singlemultiple
  • [name] - 导出值的名称 (必填项)

  • [alias] - 导出值的别名 (可以省略)

Examples:

  • [Foo] - 生成 export { Foo };.
  • [default Foo] - 生成 export default Foo;.
  • [named Foo] - 生成 export { Foo };.
  • [named Foo FooA] - 生成 export { Foo as FooA };.
  • [single Foo] - 生成 module.exports = Foo;.
  • [multiple Foo] - 生成 module.exports = { Foo };.
  • [multiple Foo FooA] - 生成 module.exports = { 'FooA': Foo };.
  • [named [name] [name]Alias] - 生成名为 exports 的 ES 模块,并导出等于另一个名称下的文件名的值., 对于 single.js 将会是 single and 和singleAlias, 生成 export { single as singleAlias };.

⚠ 你需要设置 type: "commonjs" 才能使用 single 或者 multiple 语法。

⚠ 别名不能与 default 或者 single 语法一起使用。

示例
ES Module Default Export

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          exports: 'default Foo',
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

export default Foo;
ES Module Named Exports

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          exports: 'named Foo FooA',
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

export { Foo as FooA };
CommonJS Single Export

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          type: 'commonjs',
          exports: 'single Foo',
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

module.exports = Foo;
CommonJS 导出多个

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          type: 'commonjs',
          exports: 'multiple Foo FooA',
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

module.exports = { FooA: Foo };

Object

允许使用对象来描述导出。

属性:

  • syntax - 对于 module 类型(ES modules 模块格式)可以是 default 或者 named,对于 commonjs 类型(CommonJS 模块格式)可以是 single 或者 multiple可以省略
  • name - 导出值的名称 (required)
  • alias - 导出值的别名 (may be omitted)
示例
ES Module 默认导出

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          exports: {
            syntax: 'default',
            name: 'Foo',
          },
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

export default Foo;
ES Module 重命名导出

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          exports: {
            syntax: 'named',
            name: 'Foo',
            alias: 'FooA',
          },
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

export { Foo as FooA };
CommonJS 单个导出

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          type: 'commonjs',
          exports: {
            syntax: 'single',
            name: 'Foo',
          },
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

module.exports = Foo;
CommonJS 导出多个

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          type: 'commonjs',
          exports: {
            syntax: 'multiple',
            name: 'Foo',
            alias: 'FooA',
          },
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

module.exports = { FooA: Foo };

Array

允许指定多个导出。 每一个可以是 string 或者 object.

⚠ 因为 CommonJS 格式限制,不能将 singlemultiple 语法一起使用。

⚠ 因为 ES module 格式限制,不能导出多个 default 值。

⚠ 因为 CommonJS 格式限制,不能导出多个 single 值。

示例
CommonJS 导出多个

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          type: 'commonjs',
          exports: ['Foo', 'multiple Bar', 'multiple Baz BazA'],
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

module.exports = { Foo, Bar, BazA: Bar };
ES 默认导出与导出重命名

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          exports: ['default Foo', 'named Bar BarA'],
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

export default Foo;
export { Bar as BarA };
导出重命名

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/vendor.js'),
        loader: 'exports-loader',
        options: {
          exports: [
            { syntax: 'named', name: 'Foo', alias: 'FooA' },
            { syntax: 'named', name: 'Bar' },
            'Baz',
          ],
        },
      },
    ],
  },
};

生成的输出结果:

// ...
// Code
// ...

export { Foo as FooA, Bar, Baz };

贡献

如果您还没有阅读,请花一点时间阅读我们的贡献指南。

CONTRIBUTING

License

MIT

expose-loader

npm node deps tests coverage chat size

expose-loader 允许暴露一个模块(整体或者部分)给全局对象(selfwindowglobal)。

想要获取有关兼容性的进一步提示,请查看官方文档中的 Shimming

快速开始

首先,你需要安装 expose-loader

npm install expose-loader --save-dev

(如果你在使用 webpack4,请安装 expose-loader@1 并按照 相应说明 进行配置。)

然后你可以用两种方法来用 expose-loader

内联

可以使用 | 或者 %20(空格)分隔 expose 中的 globalNamemoduleLocalNameoverride。 可以在这里获取文档和语法实例。

%20 是查询字符串中的空格,因为你不能在 URL 中使用空格

import $ from 'expose-loader?exposes=$,jQuery!jquery';
//
// 将 `jquery` 添加到全局对象中,其名称为 `$` 和 `jQuery`
import { concat } from 'expose-loader?exposes=_.concat!lodash/concat';
//
// 将 `lodash/concat` 添加到全局对象中,其名称为 `_.concat`
import {
  map,
  reduce,
} from 'expose-loader?exposes=_.map|map,_.reduce|reduce!underscore';
//
// 将 `underscore` 中的 `map` 和 `reduce` 方法分别添加到全局对象中,其名称为 `_.map` 和 `_.reduce`

使用配置文件

src/index.js

import $ from 'jquery';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('jquery'),
        loader: 'expose-loader',
        options: {
          exposes: ['$', 'jQuery'],
        },
      },
      {
        test: require.resolve('underscore'),
        loader: 'expose-loader',
        options: {
          exposes: [
            '_.map|map',
            {
              globalName: '_.reduce',
              moduleLocalName: 'reduce',
            },
            {
              globalName: ['_', 'filter'],
              moduleLocalName: 'filter',
            },
          ],
        },
      },
    ],
  },
};

require.resolve 调用是一个 Node.js 函数(和 webpack 进程中的 require.resolve 无关)。 require.resolve 给出模块的绝对路径 ("/.../app/node_modules/jquery/dist/jquery.js")。 所以 expose 只应用于 jquery 模块。并且只会在 bundle 中使用时才会被暴露。

然后用你喜欢的方式运行 webpack

配置项

NameTypeDefaultDescription
exposes{String|Object|Array<String|Object>}undefinedList of exposes

exposes

类型:String|Object|Array<String|Object> 默认值:undefined

List of exposes.

String

允许用一个 string 来描述 expose。

Syntax

可以使用 | 或者 %20(空格)分隔 expose 中的 globalNamemoduleLocalNameoverride

字符串语法 - [[globalName] [moduleLocalName] [override]] 或者 [[globalName]|[moduleLocalName]|[override]],含义如下:

  • globalName - 全局对象的名称,比如 window.$ 用于浏览器环境(必填项
  • moduleLocalName - 模块的方法/变量/等的名称(该模块必须导出它)(可以省略
  • override - 允许覆盖在全局对象中存在的值(可以省略

如果 moduleLocalName 没有指定,它将整个模块暴露给全局对象,否则它只暴露 moduleLocalName 的值。

src/index.js

import _ from 'underscore';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('jquery'),
        loader: 'expose-loader',
        options: {
          // 对于 `underscore`,它可以是 `_.map map` 或者 `_.map|map`
          exposes: 'jquery',
        },
      },
    ],
  },
};

Object

允许用一个对象来描述 expose。

globalName

类型:String|Array<String> 默认值:undefined

全局对象中的名字。(必填项)。

src/index.js

import _ from 'underscore';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('underscore'),
        loader: 'expose-loader',
        options: {
          exposes: {
            // 可以是 `['_', 'filter']`
            globalName: '_.filter',
            moduleLocalName: 'filter',
          },
        },
      },
    ],
  },
};
moduleLocalName

类型:String 默认值:undefined

模块中的方法/变量/等的名称(该模块必须导出它)。 如果指定了 moduleLocalName,它只暴露 moduleLocalName 的值。

src/index.js

import _ from 'underscore';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('underscore'),
        loader: 'expose-loader',
        options: {
          exposes: {
            globalName: '_.filter',
            moduleLocalName: 'filter',
          },
        },
      },
    ],
  },
};
override

类型:Boolean 默认值:false

默认情况下,loader 不会覆盖全局对象中的现有值,因为它是不安全的。 在 development 模式下,如果值已经出现在全局对象中则抛出一个错误。 但是你可以使用此选项配置 loader 以覆盖全局对象中的现有值。

为了强制覆盖已经存在在全局对象中的现有值,你可以设置 override 选项值为 true

src/index.js

import $ from 'jquery';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('jquery'),
        loader: 'expose-loader',
        options: {
          exposes: {
            globalName: '$',
            override: true,
          },
        },
      },
    ],
  },
};

Array

src/index.js

import _ from 'underscore';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('underscore'),
        loader: 'expose-loader',
        options: {
          exposes: [
            '_.map map',
            {
              globalName: '_.filter',
              moduleLocalName: 'filter',
            },
            {
              globalName: ['_', 'find'],
              moduleLocalName: 'myNameForFind',
            },
          ],
        },
      },
    ],
  },
};

它将 暴露 mapfilterfind 方法(名称为 myNameForFind) 给全局对象。

在浏览器中,这些方法可以在 windows._.map(..args)windows._.filter(...args)windows._.myNameForFind(...args) 下使用。

贡献

如果你还没有阅读,请花一点时间阅读我们的贡献指南。

CONTRIBUTING

License

MIT

html-loader

npm node deps tests coverage chat size

将 HTML 导出为字符串。当编译器需要时,将压缩 HTML 字符串。

快速开始

首先,你需要安装 html-loader

npm install --save-dev html-loader

然后将插件添加到你的 webpack 配置中。例如:

file.js

import html from './file.html';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
      },
    ],
  },
};

选项

名称类型默认值描述
sources{Boolean|Object}true启用/禁用 sources 处理
preprocessor{Function}undefined允许在处理前对内容进行预处理
minimize{Boolean|Object}在生产模式下为 true,其他情况为 false通知 html-loader 压缩 HTML
esModule{Boolean}true启用/禁用 ES modules 语法

sources

类型: Boolean|Object 默认值: true

默认情况下,每个可加载属性(例如 - <img src="image.png"/> )都将被导入( const img = require ('./image.png')import img from "./image.png"" )。 你可能需要为配置中的图片指定 loader(推荐使用 asset modules)。

支持的标签和属性:

  • audio 标签的 src 属性
  • embed 标签的 src 属性
  • img 标签的 src 属性
  • img 标签的 srcset 属性
  • input 标签的 src 属性
  • object 标签的 data 属性
  • script 标签的 src 属性
  • script 标签的 href 属性
  • script 标签的 xlink:href 属性
  • source 标签的 src 属性
  • source 标签的 srcset 属性
  • track 标签的 src 属性
  • video 标签的 poster 属性
  • video 标签的 src 属性
  • image 标签的 xlink:href 属性
  • image 标签的 href 属性
  • use 标签的 xlink:href 属性
  • use 标签的 href 属性
  • rel 属性值包含 stylesheeticonshortcut iconmask-iconapple-touch-iconapple-touch-icon-precomposedapple-touch-startup-imagemanifestprefetchpreload 或者当 itemprop 属性为 imagelogoscreenshotthumbnailurlcontenturldownloadurlduringmediaembedurlinstallurllayoutimage 时,支持 link 标签的 href 属性
  • rel 属性值包含 stylesheeticonshortcut iconmask-iconapple-touch-iconapple-touch-icon-precomposedapple-touch-startup-imagemanifestprefetchpreload时,支持 link 标签的 imagesrcset 属性
  • name 属性为 msapplication-tileimagemsapplication-square70x70logomsapplication-square150x150logomsapplication-wide310x150logomsapplication-square310x310logomsapplication-configtwitter:image 或者当 property 属性为 og:imageog:image:urlog:image:secure_urlog:audioog:audio:secure_urlog:videoog:video:secure_urlvk:image,支持 meta 标签的 content 属性。
  • name 属性为 msapplication-task 时,支持 meta 标签的 content 属性中的 icon-uri 值组件

Boolean

当设置为 true 时,则启用所有默认元素和属性的处理,而 false 则禁用所有属性的处理。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
        options: {
          // Disables attributes processing
          sources: false,
        },
      },
    ],
  },
};

Object

你可以配置要处理的标签和属性,来过滤它们,过滤 URL 并处理以 / 开头的资源地址。

例如:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
        options: {
          sources: {
            list: [
              // All default supported tags and attributes
              '...',
              {
                tag: 'img',
                attribute: 'data-src',
                type: 'src',
              },
              {
                tag: 'img',
                attribute: 'data-srcset',
                type: 'srcset',
              },
            ],
            urlFilter: (attribute, value, resourcePath) => {
              // `attribute` 参数包含一个 HTML 属性的名称。
              // `value` 参数包含一个 HTML 属性的值。
              // `resourcePath` 参数包含一个已加载 HTML 文件的路径。

              if (/example\.pdf$/.test(value)) {
                return false;
              }

              return true;
            },
          },
        },
      },
    ],
  },
};

list

类型:Array 默认值:支持的标签和属性列表

允许设置要处理的标签和属性以及处理方式,以及过滤其中一些标签和属性的能力。

使用 ... 语法可以使用所有默认支持的标签和属性

例如:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
        options: {
          sources: {
            list: [
              // All default supported tags and attributes
              '...',
              {
                tag: 'img',
                attribute: 'data-src',
                type: 'src',
              },
              {
                tag: 'img',
                attribute: 'data-srcset',
                type: 'srcset',
              },
              {
                // Tag name
                tag: 'link',
                // Attribute name
                attribute: 'href',
                // Type of processing, can be `src` or `scrset`
                type: 'src',
                // Allow to filter some attributes
                filter: (tag, attribute, attributes, resourcePath) => {
                  // The `tag` argument contains a name of the HTML tag.
                  // The `attribute` argument contains a name of the HTML attribute.
                  // The `attributes` argument contains all attributes of the tag.
                  // The `resourcePath` argument contains a path to the loaded HTML file.

                  if (/my-html\.html$/.test(resourcePath)) {
                    return false;
                  }

                  if (!/stylesheet/i.test(attributes.rel)) {
                    return false;
                  }

                  if (
                    attributes.type &&
                    attributes.type.trim().toLowerCase() !== 'text/css'
                  ) {
                    return false;
                  }

                  return true;
                },
              },
            ],
          },
        },
      },
    ],
  },
};

如果未指定标签名称,它将处理所有标签。

你可以使用自定义过滤器指定要处理的 html 元素。

例如:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
        options: {
          sources: {
            list: [
              {
                // Attribute name
                attribute: 'src',
                // Type of processing, can be `src` or `scrset`
                type: 'src',
                // Allow to filter some attributes (optional)
                filter: (tag, attribute, attributes, resourcePath) => {
                  // The `tag` argument contains a name of the HTML tag.
                  // The `attribute` argument contains a name of the HTML attribute.
                  // The `attributes` argument contains all attributes of the tag.
                  // The `resourcePath` argument contains a path to the loaded HTML file.

                  // choose all HTML tags except img tag
                  return tag.toLowerCase() !== 'img';
                },
              },
            ],
          },
        },
      },
    ],
  },
};

filter 也可以用来扩展支持的元素和属性。

例如,filter 可以帮助处理引用资源的 meta 标签:

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
        options: {
          sources: {
            list: [
              {
                tag: 'meta',
                attribute: 'content',
                type: 'src',
                filter: (tag, attribute, attributes, resourcePath) => {
                  if (
                    attributes.value === 'og:image' ||
                    attributes.name === 'twitter:image'
                  ) {
                    return true;
                  }

                  return false;
                },
              },
            ],
          },
        },
      },
    ],
  },
};

请注意: 带有 tag 配置项的 source 优先级要比没有 tag 配置项的高。

filter 可以用于禁用默认 source。

示例:

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
        options: {
          sources: {
            list: [
              '...',
              {
                tag: 'img',
                attribute: 'src',
                type: 'src',
                filter: () => false,
              },
            ],
          },
        },
      },
    ],
  },
};

urlFilter

类型:Function 默认值: undefined

允许配置要过滤的 url。所有过滤的 url 都参与解析(会保持原样)。 默认情况下,所有非请求资源类型的值(例如 <img src="javascript:void (0)" /> )都不处理。

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
        options: {
          sources: {
            urlFilter: (attribute, value, resourcePath) => {
              // The `attribute` argument contains a name of the HTML attribute.
              // The `value` argument contains a value of the HTML attribute.
              // The `resourcePath` argument contains a path to the loaded HTML file.

              if (/example\.pdf$/.test(value)) {
                return false;
              }

              return true;
            },
          },
        },
      },
    ],
  },
};

preprocessor

类型:Function 默认值:undefined

允许在处理之前对内容进行预处理。

⚠ 你应该始终返回有效的 HTML

file.hbs

<div>
  <p>{{firstname}} {{lastname}}</p>
  <img src="image.png" alt="alt" />
<div>

Function

你可以将 preprocessor 选项设置为 Function 实例。

webpack.config.js

const Handlebars = require('handlebars');

module.exports = {
  module: {
    rules: [
      {
        test: /\.hbs$/i,
        loader: 'html-loader',
        options: {
          preprocessor: (content, loaderContext) => {
            let result;

            try {
              result = Handlebars.compile(content)({
                firstname: 'Value',
                lastname: 'OtherValue',
              });
            } catch (error) {
              loaderContext.emitError(error);

              return content;
            }

            return result;
          },
        },
      },
    ],
  },
};

你还可以将 preprocessor 选项设置为异步函数实例。

例如:

webpack.config.js

const Handlebars = require('handlebars');

module.exports = {
  module: {
    rules: [
      {
        test: /\.hbs$/i,
        loader: 'html-loader',
        options: {
          preprocessor: async (content, loaderContext) => {
            let result;

            try {
              result = await Handlebars.compile(content)({
                firstname: 'Value',
                lastname: 'OtherValue',
              });
            } catch (error) {
              await loaderContext.emitError(error);

              return content;
            }

            return result;
          },
        },
      },
    ],
  },
};

minimize

类型:Boolean|Object 默认值:在生产模式下为 true ,否则为 false

告诉 html-loader 编译时需要压缩 HTML 字符串。

Boolean

默认情况下,启用压缩的规则如下:

({
  caseSensitive: true,
  collapseWhitespace: true,
  conservativeCollapse: true,
  keepClosingSlash: true,
  minifyCSS: true,
  minifyJS: true,
  removeComments: true,
  removeRedundantAttributes: true,
  removeScriptTypeAttributes: true,
  removeStyleLinkTypeAttributes: true,
});

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
        options: {
          minimize: true,
        },
      },
    ],
  },
};

Object

webpack.config.js

关于可用选项的更多信息,请参阅 html-minifier-terser 文档。

可以在 webpack.conf.js 中使用以下选项来禁用规则

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
        options: {
          minimize: {
            removeComments: false,
            collapseWhitespace: false,
          },
        },
      },
    ],
  },
};

esModule

类型:Boolean 默认值:false

默认情况下, html-loader 生成使用 ES modules 语法的 JS 模块。 在某些情况下,使用 ES modules 会更好,例如在进行模块合并tree shaking 时。

你可以使用以下方法启用 CommonJS 模块语法:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
        options: {
          esModule: false,
        },
      },
    ],
  },
};

示例

使用 <!-- webpackIgnore: true --> 注释禁用 url 解析

通过 <!-- webpackIgnore: true --> 注释,可以禁止处理下一个标签的源。

<!-- 禁止对 src 属性进行 url 处理 -->
<!-- webpackIgnore: true -->
<img src="image.png" />

<!-- 禁止对 src 与 srcset 属性进行 url 处理 -->
<!-- webpackIgnore: true -->
<img
  srcset="image.png 480w, image.png 768w"
  src="image.png"
  alt="Elva dressed as a fairy"
/>

<!-- 禁止对 content 属性进行 url 处理 -->
<!-- webpackIgnore: true -->
<meta itemprop="image" content="./image.png" />

<!-- 禁止对 href 属性进行 url 处理 -->
<!-- webpackIgnore: true -->
<link rel="icon" type="image/png" sizes="192x192" href="./image.png" />

roots

使用 resolve.roots 可以指定解析相对服务端的 URL(以 '/' 开头)请求的目录列表。

webpack.config.js

module.exports = {
  context: __dirname,
  module: {
    rules: [
      {
        test: /\.html$/i,
        loader: 'html-loader',
        options: {},
      },
      {
        test: /\.jpg$/,
        type: 'asset/resource',
      },
    ],
  },
  resolve: {
    roots: [path.resolve(__dirname, 'fixtures')],
  },
};

file.html

<img src="/image.jpg" />
// => image.jpg in __dirname/fixtures will be resolved

CDN

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.jpg$/,
        type: 'asset/resource',
      },
      {
        test: /\.png$/,
        type: 'asset/inline',
      },
    ],
  },
  output: {
    publicPath: 'http://cdn.example.com/[fullhash]/',
  },
};

file.html

<img src="image.jpg" data-src="image2x.png" />

index.js

require('html-loader!./file.html');

// => '<img src="http://cdn.example.com/49eba9f/a992ca.jpg" data-src="image2x.png"/>'
require('html-loader?{"sources":{"list":[{"tag":"img","attribute":"data-src","type":"src"}]}}!./file.html');

// => '<img src="image.jpg" data-src="data:image/png;base64,..." />'
require('html-loader?{"sources":{"list":[{"tag":"img","attribute":"src","type":"src"},{"tag":"img","attribute":"data-src","type":"src"}]}}!./file.html');

// => '<img src="http://cdn.example.com/49eba9f/a992ca.jpg" data-src="data:image/png;base64,..." />'

处理 scriptlink 标签

script.file.js

console.log(document);

style.file.css

a {
  color: red;
}

file.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Title of the document</title>
    <link rel="stylesheet" type="text/css" href="./style.file.css" />
  </head>
  <body>
    Content of the document......
    <script src="./script.file.js"></script>
  </body>
</html>

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/,
        type: 'asset/resource',
        generator: {
          filename: '[name][ext]',
        },
      },
      {
        test: /\.html$/i,
        use: ['extract-loader', 'html-loader'],
      },
      {
        test: /\.js$/i,
        exclude: /\.file.js$/i,
        loader: 'babel-loader',
      },
      {
        test: /\.file.js$/i,
        type: 'asset/resource',
      },
      {
        test: /\.css$/i,
        exclude: /\.file.css$/i,
        loader: 'css-loader',
      },
      {
        test: /\.file.css$/i,
        type: 'asset/resource',
      },
    ],
  },
};

模板

你可以使用任何模板系统。以下是 handlebars 的示例。

file.hbs

<div>
  <p>{{firstname}} {{lastname}}</p>
  <img src="image.png" alt="alt" />
<div>

webpack.config.js

const Handlebars = require('handlebars');

module.exports = {
  module: {
    rules: [
      {
        test: /\.hbs$/i,
        loader: 'html-loader',
        options: {
          preprocessor: (content, loaderContext) => {
            let result;

            try {
              result = Handlebars.compile(content)({
                firstname: 'Value',
                lastname: 'OtherValue',
              });
            } catch (error) {
              loaderContext.emitError(error);

              return content;
            }

            return result;
          },
        },
      },
    ],
  },
};

PostHTML

你可以使用 PostHTML 而无需任何其他加载程序。

file.html

<img src="image.jpg" />

webpack.config.js

const posthtml = require('posthtml');
const posthtmlWebp = require('posthtml-webp');

module.exports = {
  module: {
    rules: [
      {
        test: /\.hbs$/i,
        loader: 'html-loader',
        options: {
          preprocessor: (content, loaderContext) => {
            let result;

            try {
              result = posthtml().use(plugin).process(content, { sync: true });
            } catch (error) {
              loaderContext.emitError(error);

              return content;
            }

            return result.html;
          },
        },
      },
    ],
  },
};

导出为 HTML 文件

一种非常常见的情况是将 HTML 导出到自己的 .html 文件中,以直接使用, 而非注入到 javascript。 可以使用以下 2 种 loader 的组合来实现:

还有 asset modules

html-loader 将解析 URL,同时引入图片以及你需要的所有内容。 extract loader 会将 javascript 解析为正确的 html 文件, 然后确保图片被引入且路径正确, asset modules 会为你生成 .html 文件。例如:

webpack.config.js

module.exports = {
  output: {
    assetModuleFilename: '[name][ext]',
  },
  module: {
    rules: [
      {
        test: /\.html$/,
        type: 'asset/resource',
        generator: {
          filename: '[name][ext]',
        },
      },
      {
        test: /\.html$/i,
        use: ['extract-loader', 'html-loader'],
      },
    ],
  },
};

贡献

如果你还没有阅读,请花一点时间阅读我们的贡献指南。

贡献

许可证

MIT

imports-loader

npm node deps tests cover chat size

imports loader 允许使用依赖于特定全局变量的模块。

这对于依赖 window 对象下的全局变量(比如 $this )的第三方模块非常有用。 imports loader 可以添加必要的 require('whatever') 调用,因此这些模块可以与 webpack 一起使用。

有关兼容性问题的进一步提示,可以查看官方文档中的 Shimming

⚠ 默认情况下,loader 生成具名 ES module。

⚠ 请注意,在原始代码中已存在的 imports(import/require)与引入新值会导致失败。

快速开始

首先,你需要安装 imports-loader

npm install imports-loader --save-dev

如果你有这个文件:

example.js

$('img').doSomeAwesomeJqueryPluginStuff();

然后你可以使用两个方法来配置 imports-loader,就可以把 jquery 值注入到模块中。

内联

可以使用 | 或者 %20(空格)分隔 import 语句中的 syntaxmoduleNamenamealias。 可以在 这里 获取文档和语法示例。

%20 是查询字符串中的空格,因为你不能在 URL 中使用空格。

// 可供选择的语法:
//
// import myLib from 'imports-loader?imports=default%20jquery%20$!./example.js';
//
// `%20` 是查询字符串中的空格,相当于 `default jquery $`
import myLib from 'imports-loader?imports=default|jquery|$!./example.js';
// 在 example.js 的开头添加如下代码:
//
// import $ from "jquery";
//
// ...
// Code
// ...
import myLib from 'imports-loader?imports=default|jquery|$,angular!./example.js';
// `|` 是查询字符串中的分隔符,相当于 `default|jquery|$` 与 `angular`
// 在 example.js 的开头添加如下代码:
//
// import $ from "jquery";
// import angular from "angular";
//
// ...
// Code
// ...
import myLib from 'imports-loader?imports=named|library|myMethod,angular!./example.js';
// `|` 是查询字符串中的分隔符,相当于 `named|library|myMethod` 与 `angular`
// 在 example.js 的开头添加如下代码:
//
// import { myMethod } from "library";
// import angular from "angular";
//
// ...
// Code
// ...
const myLib = require(`imports-loader?type=commonjs&imports=single|jquery|$,angular!./example.js`);
// `|` 是查询字符串中的分隔符,相当于 `single|jquery|$` 与 `angular`
// 在 example.js 的开头添加如下代码:
//
// var $ = require("jquery");
// var angular = require("angular");
//
// ...
// Code
// ...
const myLib = require(`imports-loader?type=commonjs&imports=single|myLib|myMethod&wrapper=window&!./example.js`);
// `|` 是查询字符串中的分隔符,相当于 `single|myLib|myMethod` 与 `angular`
// 在 example.js 中添加如下代码:
//
// const myMethod = require('myLib');
//
// (function () {
// ...
// Code
// ...
// }.call(window));
import myLib from 'imports-loader?additionalCode=var%20myVariable%20=%20false;!./example.js';
// 在 example.js 的开头添加如下代码:
//
// var myVariable = false;
//
// ...
// Code
// ...

使用配置项

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        // 你可以使用 `regexp`
        // test: /example\.js/$
        test: require.resolve('example.js'),
        use: [
          {
            loader: 'imports-loader',
            options: {
              imports: [
                'default jquery $',
                'default lib_2 lib_2_default',
                'named lib_3 lib2_method_1',
                'named lib_3 lib2_method_2 lib_2_method_2_short',
                'namespace lib_4 my_namespace',
                'side-effects lib_5',
                {
                  syntax: 'default',
                  moduleName: 'angular',
                  name: 'angular',
                },
              ],
            },
          },
        ],
      },
    ],
  },
};

生成输出:

import $ from 'jquery';
import lib_2_default from 'lib_2';
import { lib2_method_1, lib2_method_2 as lib_2_method_2_short } from 'lib_3';
import * as my_namespace from 'lib_4';
import 'lib_5';
import angular from 'angular';

然后用你喜欢的方式运行 webpack

配置项

NameTypeDefaultDescription
type{String}module生成 import 的格式
imports{String|Object|Array<String|Object>}undefinedimport 列表
wrapper{Boolean|String|Object}undefined关闭函数中的模块代码 ((function () { ... }).call();)
additionalCode{String}undefined添加自定义代码

type

类型:String 默认值:module

生成 exports 的格式。

可选值 - commonjs (CommonJS module 语法) 和 module (ES module 语法)。

commonjs

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('example.js'),
        loader: 'imports-loader',
        options: {
          syntax: 'default',
          type: 'commonjs',
          imports: 'Foo',
        },
      },
    ],
  },
};

生成输出:

var Foo = require('Foo');

// ...
// Code
// ...

module

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('example.js'),
        loader: 'imports-loader',
        options: {
          type: 'module',
          imports: 'Foo',
        },
      },
    ],
  },
};

生成输出:

import Foo from 'Foo';

// ...
// Code
// ...

imports

类型:String|Object|Array<String|Object> 默认值:undefined

import 列表。

String

允许使用字符串描述 export

Syntax

使用 | 或者 %20(空格)分隔 import 中的 syntaxmoduleNamenamealias

字符串语法 - [[syntax] [moduleName] [name] [alias]] 或者 [[syntax]|[moduleName]|[name]|[alias]],其含义为:

  • [syntax] (可以被省略):

    • 如果 type 值为 module- 可以是 defaultnamednamespace 或者 side-effects,默认值为 default
    • 如果 type 值为 commonjs- 可以是 singlemultiple 或者 pure,默认值为 single
  • [moduleName] - 被导入模块的名称(必填)

  • [name] - 被导入值的名称(必填)

  • [alias] - 被导入值的别名(可以被省略)

示例:

如果 type 值为 module

  • [Foo] - 生成 import Foo from "Foo";.
  • [default Foo] - 生成 import Foo from "Foo";.
  • [default ./my-lib Foo] - 生成 import Foo from "./my-lib";.
  • [named Foo FooA] - 生成 import { FooA } from "Foo";.
  • [named Foo FooA Bar] - 生成 import { FooA as Bar } from "Foo";.
  • [namespace Foo FooA] - 生成 import * as FooA from "Foo";.
  • [side-effects Foo] - 生成 import "Foo";.

如果 type 值为 commonjs

  • [Foo] - 生成 const Foo = require("Foo");.
  • [single Foo] - 生成 const Foo = require("Foo");.
  • [single ./my-lib Foo] - 生成 const Foo = require("./my-lib");.
  • [multiple Foo FooA Bar] - 生成 const { FooA: Bar } = require("Foo");.
  • [pure Foo] - 生成 require("Foo");.

⚠ 你需要设置 type: "commonjs" 以使用 singlemultiplepure 语法。

⚠ Aliases 不能与 defaultnamespaceside-effectssinglepure 语法同时使用。

示例
ES Module 默认导入

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/example.js'),
        loader: 'imports-loader',
        options: {
          imports: 'default lib myName',
        },
      },
    ],
  },
};

生成输出:

import myName from 'lib';

// ...
// Code
// ...
CommonJS Single Import

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('./path/to/example.js'),
        loader: 'imports-loader',
        options: {
          type: 'commonjs',
          imports: 'single lib myName',
        },
      },
    ],
  },
};

生成输出:

var myName = require('lib');

// ...
// Code
// ...

Object

允许使用一个对象来描述 import

属性:

  • syntax:

    • 如果 type 值为 module- 可以是 defaultnamednamespaceside-effects
    • 如果 type 值为 commonjs- 可以是 singlemultiplepure`
  • moduleName - 被导入模块的名称 (必填)

  • name - 被导入值的名称 (必填)

  • alias - 被导入值的别名 (可以被省略)

⚠ Alias 不能与 defaultnamespaceside-effectssinglepure 语法同时使用。

示例

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('example.js'),
        use: [
          {
            loader: 'imports-loader',
            options: {
              imports: {
                syntax: 'named',
                moduleName: 'lib_2',
                name: 'lib2_method_2',
                alias: 'lib_2_method_2_alias',
              },
            },
          },
        ],
      },
    ],
  },
};

生成输出:

import { lib2_method_2 as lib_2_method_2_alias } from 'lib_2';

// ...
// Code
// ...

Array

允许指定多个导入。 每一项可以为 string 或者 object

示例

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('example.js'),
        use: [
          {
            loader: 'imports-loader',
            options: {
              imports: [
                {
                  moduleName: 'angular',
                },
                {
                  syntax: 'default',
                  moduleName: 'jquery',
                  name: '$',
                },
                'default lib_2 lib_2_default',
                'named lib_2 lib2_method_1',
                'named lib_2 lib2_method_2 lib_2_method_2_alias',
                'namespace lib_3 lib_3_all',
                'side-effects lib_4',
              ],
            },
          },
        ],
      },
    ],
  },
};

生成输出:

import angular from 'angular';
import $ from 'jquery';
import lib_2_default from 'lib_2';
import { lib2_method_1, lib2_method_2 as lib_2_method_2_alias } from 'lib_2';
import * as lib_3_all from 'lib_3';
import 'lib_4';

// ...
// Code
// ...

wrapper

类型:Boolean|String|Object 默认值:undefined

用给定的 thisArgargs 关闭函数中的模块代码 ((function () { ... }).call();)。

⚠ 如果源码中包含 ES module import 的话,请不要使用该配置。

Boolean

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('example.js'),
        use: [
          {
            loader: 'imports-loader',
            options: {
              imports: {
                moduleName: 'jquery',
                name: '$',
              },
              wrapper: true,
            },
          },
        ],
      },
    ],
  },
};

生成输出:

import $ from 'jquery';

(function () {
  // ...
  // Code
  // ...
}.call());

String

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('example.js'),
        use: [
          {
            loader: 'imports-loader',
            options: {
              imports: {
                moduleName: 'jquery',
                name: '$',
              },
              wrapper: 'window',
            },
          },
        ],
      },
    ],
  },
};

生成输出:

import $ from 'jquery';

(function () {
  // ...
  // Code
  // ...
}.call(window));

Object

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('example.js'),
        use: [
          {
            loader: 'imports-loader',
            options: {
              imports: {
                moduleName: 'jquery',
                name: '$',
              },
              wrapper: {
                thisArg: 'window',
                args: ['myVariable', 'myOtherVariable'],
              },
            },
          },
        ],
      },
    ],
  },
};

生成输出:

import $ from 'jquery';

(function (myVariable, myOtherVariable) {
  // ...
  // Code
  // ...
}.call(window, myVariable, myOtherVariable));

Object with different parameter names

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('example.js'),
        use: [
          {
            loader: 'imports-loader',
            options: {
              imports: {
                moduleName: 'jquery',
                name: '$',
              },
              wrapper: {
                thisArg: 'window',
                args: {
                  myVariable: 'var1',
                  myOtherVariable: 'var2',
                },
              },
            },
          },
        ],
      },
    ],
  },
};

生成输出:

import $ from 'jquery';

(function (var1, var2) {
  // ...
  // Code
  // ...
}.call(window, myVariable, myOtherVariable));

additionalCode

类型:String 默认值:undefined

在模块代码之前添加自定义代码作为前导。

Examples

定义自定义变量

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('example.js'),
        use: [
          {
            loader: 'imports-loader',
            options: {
              imports: {
                moduleName: 'jquery',
                name: '$',
              },
              additionalCode: 'var myVariable = false;',
            },
          },
        ],
      },
    ],
  },
};

生成输出:

import $ from 'jquery';

var myVariable = false;

// ...
// Code
// ...
Disable AMD Import Syntax

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('example.js'),
        use: [
          {
            loader: 'imports-loader',
            options: {
              imports: {
                moduleName: 'jquery',
                name: '$',
              },
              additionalCode:
                'var define = false; /* Disable AMD for misbehaving libraries */',
            },
          },
        ],
      },
    ],
  },
};

生成输出:

import $ from 'jquery';

var define = false; /* Disable AMD for misbehaving libraries */

// ...
// Code
// ...

Contributing

如果你还没有阅读,请花一点时间阅读我们的贡献指南。

贡献指南

License

MIT

Loaders

Webpack 支持使用 loader 对文件进行预处理。你可以构建包括 JavaScript 在内的任何静态资源。并且可以使用 Node.js 轻松编写自己的 loader。

require() 语句中使用 loadername! 作为前缀的方式来使用 loader,或者在 webpack 配置中配置 regex 来自动应用它们 - 请参阅 配置

文件

  • val-loader 将代码作为模块执行,并将其导出为 JS 代码
  • ref-loader 用于手动建立文件之间的依赖关系

JSON

语法转换

模板

样式

框架

Awesome

有关更多第三方 loader,请参阅 awesome-webpack 中的列表。

less-loader

npm node deps tests cover chat size

webpack 将 Less 编译为 CSS 的 loader。

快速开始

首先,你需要先安装 lessless-loader

npm install less less-loader --save-dev

然后将该 loader 添加到 webpack 的配置中去,例如:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          // compiles Less to CSS
          'style-loader',
          'css-loader',
          'less-loader',
        ],
      },
    ],
  },
};

接着使用你习惯的方式运行 webpack

可选项

名称类型默认值描述
lessOptions{Object|Function}{ relativeUrls: true }Less 的可选项。
additionalData{String|Function}undefined在入口文件起始或末尾添加 Less 代码。
sourceMap{Boolean}compiler.devtool是否生成 source map。
webpackImporter{Boolean}true是否启用默认的 webpack importer。
implementation{Object|String}less配置 Less 使用的实现库

lessOptions

类型: Object|Function 默认值: { relativeUrls: true }

通过 lessOptions 属性,你可以设置 loader options 中的任意特定的选项值给 less-loader。所有可用的选项值请参看 Less 命令行可选参数文档。由于我们是通过编程的方式将这些选项传递给 Less,因此您需要将破折号(dash-case)转换为驼峰值(camelCase)后传递它们。

Object

使用对象(Object)的形式传递 options 给 Less。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
          {
            loader: 'less-loader',
            options: {
              lessOptions: {
                strictMath: true,
              },
            },
          },
        ],
      },
    ],
  },
};

Function

允许根据 loader 的 context 来设置 options,再传递给 Less。

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              lessOptions: (loaderContext) => {
                // 更多可用的属性见 https://webpack.js.org/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === 'styles/foo.less') {
                  return {
                    paths: ['absolute/path/c', 'absolute/path/d'],
                  };
                }

                return {
                  paths: ['absolute/path/a', 'absolute/path/b'],
                };
              },
            },
          },
        ],
      },
    ],
  },
};

additionalData

类型: String|Function 默认值: undefined

在实际入口文件的起始位置添加 Less 代码。 这种情况下,less-loader 只会追加并不会覆盖文件内容。

当你的 Less 变量依赖环境变量时这个属性将非常有用:

ℹ 由于你注入了代码,因此它将破坏入口文件的源映射关系。通常有比这更简单的解决方案,例如多个 Less 入口文件。

String

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              additionalData: `@env: ${process.env.NODE_ENV};`,
            },
          },
        ],
      },
    ],
  },
};

Function

Sync
module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              additionalData: (content, loaderContext) => {
                // 更多可用的属性见 https://webpack.js.org/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === 'styles/foo.less') {
                  return '@value: 100px;' + content;
                }

                return '@value: 200px;' + content;
              },
            },
          },
        ],
      },
    ],
  },
};
Async
module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              additionalData: async (content, loaderContext) => {
                // More information about available properties https://webpack.js.org/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === 'styles/foo.less') {
                  return '@value: 100px;' + content;
                }

                return '@value: 200px;' + content;
              },
            },
          },
        ],
      },
    ],
  },
};

sourceMap

类型: Boolean 默认值: 取决于 compiler.devtool 的值

默认生成的 source map 取决于 compiler.devtool 的值。除了值等于 evalfalse 外,其他值都能生成 source map

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
            },
          },
          {
            loader: 'less-loader',
            options: {
              sourceMap: true,
            },
          },
        ],
      },
    ],
  },
};

webpackImporter

类型:Boolean 默认值:true

启用/禁用 webpack 默认的 importer。

在某些情况下,这样做可以提高性能,但是请慎用,因为可能会使得 aliases 和以 ~ 开头的 @import 规则失效。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              webpackImporter: false,
            },
          },
        ],
      },
    ],
  },
};

implementation

类型:Object | String

⚠ less-loader 已兼容 Less 3 和 Less 4。

特殊的 implementation 选项决定使用 Less 的哪个实现。重载本地安装的 lesspeerDependency 版本。

此选项只对下游的工具作者有效,以便于 Less 3 到 Less 4 的过渡。

Object

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              implementation: require('less'),
            },
          },
        ],
      },
    ],
  },
};

String

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              implementation: require.resolve('less'),
            },
          },
        ],
      },
    ],
  },
};

示例

常规用法

less-loadercss-loaderstyle-loader 串联起来使用可立即将所有样式应用于 DOM。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          {
            loader: 'style-loader', // 从 JS 中创建样式节点
          },
          {
            loader: 'css-loader', // 转化 CSS 为 CommonJS
          },
          {
            loader: 'less-loader', // 编译 Less 为 CSS
          },
        ],
      },
    ],
  },
};

不幸的是,Less 并没有将所有选项 1 对 1 映射为 camelCase(驼峰值)。如有疑问,请检查执行文件并搜索破折号选项。

Source maps

为了生成 CSS 的 source map, 你需要在 loader 的可选项中设置 sourceMap 属性。如果没设置的话 loader 将会继承你 webpack 中为生成 source map 设置的属性值 devtool

webpack.config.js

module.exports = {
  devtool: 'source-map', // 任何类似于 "source-map" 的  devtool 值都可以
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
            },
          },
          {
            loader: 'less-loader',
            options: {
              sourceMap: true,
            },
          },
        ],
      },
    ],
  },
};

如果你想在 Chrome 中修改原始的 Less 文件,可以参考这篇不错的博客。这篇博客虽然写的 Sass,但也适合于 Less。

生产环境

在生产环境中推荐使用 MiniCssExtractPlugin 来提取样式表到专门的文件中,这样你的样式就不需要依赖 JavaScript。

导入

首先我们会尝试使用内置 less 解析逻辑,然后再使用 webpack 解析逻辑(alias 和 ~)。

webpack 解析器

webpack 提供了一种 解析文件的高级机制。如果 less 不能解析 @import 的话,less-loader 作为 Less 的插件将所有的查询结果传递给 webpack 解析器。因此你可以从 node_modules 中导入 Less 模块。

@import 'bootstrap/less/bootstrap';

~ 用法已被废弃,可以从代码中删除(我们建议这么做),但是我们会因为一些历史原因一直支持这种写法。 为什么你可以移除它呢?loader 首先会尝试以相对路径解析 @import,如果它不能被解析,loader 将会尝试在 node_modules 中解析 @import。 只要在包名前加上 ~,告诉 webpack 在 modules 中进行查找。

@import '~bootstrap/less/bootstrap';

可以通过 resolve.byDependency 修改默认解析器配置:

webpack.config.js

module.exports = {
  devtool: 'source-map', // "source-map" 类的 devtool 都是可以的
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: ['style-loader', 'css-loader', 'less-loader'],
      },
    ],
  },
  resolve: {
    byDependency: {
      // 更多的配置项可以在这里找到 https://webpack.js.org/configuration/resolve/
      less: {
        mainFiles: ['custom'],
      },
    },
  },
};

在其前面加上 很关键,因为 〜/ 会解析到根目录。webpack 需要区分 bootstrap〜bootstrap,因为 CSS 和 Less 文件没有用于导入相对路径文件的特殊语法。写 @import“ file” 等同于 @import“ ./file”;

Less Resolver

如果指定 paths 选项,将从指定的 paths 中搜索模块,这是 less 的默认行为。paths 应该是具有绝对路径的数组:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
          {
            loader: 'less-loader',
            options: {
              lessOptions: {
                paths: [path.resolve(__dirname, 'node_modules')],
              },
            },
          },
        ],
      },
    ],
  },
};

插件

想要使用 插件,只需要简单设置下 plugins 选项即可, 具体配置如下:

webpack.config.js

const CleanCSSPlugin = require('less-plugin-clean-css');

module.exports = {
  ...
    {
      loader: 'less-loader',
      options: {
        lessOptions: {
          plugins: [
            new CleanCSSPlugin({ advanced: true }),
          ],
        },
      },
    },
  ...
};

ℹ️ 使用 pluginManager.webpackLoaderContext 属性可以访问自定义插件中的 loader context

module.exports = {
  install: function (less, pluginManager, functions) {
    functions.add('pi', function () {
      // Loader context is available in `pluginManager.webpackLoaderContext`

      return Math.PI;
    });
  },
};

提取样式

通过 webpack 打包 CSS 有很多好处,比如给引用图片和字体文件路径添加 hash, 在开发环境可以 模块热替换。另一方面,在生产环境,根据 JS 来控制应用样式表不是一个好的方式,可能会导致延迟渲染,甚至可能会出现闪烁现象。因此,在你最终的生产环境中将它们拆分成单独的文件来存放通常是比较好的选择。

有两种从 bundle 中提取样式表的方式:

CSS modules 陷阱

Less 和 CSS modules 有一个已知的问题,关于 url(...) 语句中的相对文件路径,看下这个问题的解释

贡献

如果你还没有看过我们的贡献者指南请先花点时间看一下。

CONTRIBUTING

许可

MIT

node-loader

npm node deps tests coverage chat size

处理 Node.js 插件(add-ons) 的 loader。

允许使用 .node 拓展名与原生 node module 相关联。

node-loader 只对 node/electron-main/electron-main/electron-renderer/electron-preload 生效。

快速开始

首先,你需要安装 node-loader

npm install node-loader --save-dev

设置 target 配置项为 node/async-node/electron-main/electron-renderer/electron-preload,并且需禁用 __dirname 全局变量。

webpack.config.js

module.exports = {
  target: 'node',
  node: {
    __dirname: false,
  },
  module: {
    rules: [
      {
        test: /\.node$/,
        loader: 'node-loader',
      },
    ],
  },
};

内联

index.js

import node from 'node-loader!./file.node';

然后通过你喜欢的方式运行 webpack

配置

index.js

import node from 'file.node';

然后在你的 webpack 配置中添加该 loader。例如:

webpack.config.js

module.exports = {
  target: 'node',
  node: {
    __dirname: false,
  },
  module: {
    rules: [
      {
        test: /\.node$/,
        loader: 'node-loader',
      },
    ],
  },
};

然后通过你喜欢的方式运行 webpack

选项

NameTypeDefaultDescription
flags{Number}undefined启用/禁用 url/image-set 函数处理
name{String|Function}'[contenthash].[ext]'指定一个或多个目标文件的自定义文件名模板。

flags

类型:Number 默认值:undefined

flags 参数是一个允许指定 dlopen 行为的整数。 请查阅 process.dlopen 文档了解更多。

index.js

import node from 'file.node';

webpack.config.js

const os = require('os');

module.exports = {
  target: 'node',
  node: {
    __dirname: false,
  },
  module: {
    rules: [
      {
        test: /\.node$/,
        loader: 'node-loader',
        options: {
          flags: os.constants.dlopen.RTLD_NOW,
        },
      },
    ],
  },
};

name

类型:String|Function 默认值:'[contenthash].[ext]'

指定一个或多个目标文件的自定义文件名模板。

String

webpack.config.js

module.exports = {
  target: 'node',
  node: {
    __dirname: false,
  },
  module: {
    rules: [
      {
        test: /\.node$/,
        loader: 'node-loader',
        options: {
          name: '[path][name].[ext]',
        },
      },
    ],
  },
};

Function

webpack.config.js

module.exports = {
  target: 'node',
  node: {
    __dirname: false,
  },
  module: {
    rules: [
      {
        test: /\.node$/,
        loader: 'node-loader',
        options: {
          name(resourcePath, resourceQuery) {
            // `resourcePath` - `/absolute/path/to/file.js`
            // `resourceQuery` - `?foo=bar`

            if (process.env.NODE_ENV === 'development') {
              return '[path][name].[ext]';
            }

            return '[contenthash].[ext]';
          },
        },
      },
    ],
  },
};

贡献

如果你还未阅读贡献指南,请抽时间进行阅读。

贡献指南

License

MIT

postcss-loader

npm node deps tests coverage size

Webpack chat: chat

PostCSS chat: chat-postcss

使用 PostCSS 处理 CSS 的 loader。

快速开始

如果要使用最新版本的话,你需要使用 webpack v5。如果使用 webpack v4 的话,你需要安装 postcss-loader v4。

为了使用本 loader,你需要安装 postcss-loaderpostcss

npm install --save-dev postcss-loader postcss

然后添加本 loader 的相关配置到你的 webpack 的配置文件。例如:

In the following configuration the plugin postcss-preset-env is used, which is not installed by default.

file.js

import css from 'file.css';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  [
                    'postcss-preset-env',
                    {
                      // 其他选项
                    },
                  ],
                ],
              },
            },
          },
        ],
      },
    ],
  },
};

或者使用 PostCSS 本身的 配置文件

postcss.config.js

module.exports = {
  plugins: [
    [
      'postcss-preset-env',
      {
        // 其他选项
      },
    ],
  ],
};

Loader 将会自动搜索配置文件。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader', 'postcss-loader'],
      },
    ],
  },
};

最后,通过你喜欢的方式运行 webpack

选项

名称类型默认值描述
execute{Boolean}undefinedCSS-in-JS 中启动 PostCSS Parser 支持
postcssOptions{Object|Function}Postcss.process的默认值设置 PostCSS 选项与插件
sourceMap{Boolean}compiler.devtool开启 / 关闭 source map 的生成
implementation{Function|String}postcss为 PostCSS 设置对应实现并使用

execute

类型:Boolean 默认值:undefined

如果你在 JS 文件中编写样式,请使用 postcss-js parser,并且添加 execute 选项。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.style.js$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                parser: 'postcss-js',
              },
              execute: true,
            },
          },
        ],
      },
    ],
  },
};

postcssOptions

类型:Object|Function 默认值:undefined

允许设置 PostCSS 选项 和插件。

支持所有的 PostCSS 选项。 这是配置文件中特殊的 配置 选项。它如何工作、如何配置再接下来的部分将会有详细的描述。

因为可能会导致 source map 中错误的文件路径,我们不推荐使用指定的 fromtomap 选项。 如果你需要 source map,请使用 sourcemap 选项。

Object

设置 plugins

webpack.config.js (recommended)

const myOtherPostcssPlugin = require('postcss-my-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.sss$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            plugins: [
              'postcss-import',
              ['postcss-short', { prefix: 'x' }],
              require.resolve('my-postcss-plugin'),
              myOtherPostcssPlugin({ myOption: true }),
              // 废弃的,将会在下一个主要版本中移除
              { 'postcss-nested': { preserveEmpty: true } },
            ],
          },
        },
      },
    ],
  },
};

webpack.config.js废弃的,将会在下一个主要版本中移除)

module.exports = {
  module: {
    rules: [
      {
        test: /\.sss$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            plugins: {
              'postcss-import': {},
              'postcss-short': { prefix: 'x' },
            },
          },
        },
      },
    ],
  },
};

设置 syntax

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.sss$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            // 可以是 `String`
            syntax: 'sugarss',
            // 可以是 `Object`
            syntax: require('sugarss'),
          },
        },
      },
    ],
  },
};

设置 parser

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.sss$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            // 可以是 `String`
            parser: 'sugarss',
            // 可以是 `Object`
            parser: require('sugarss'),
            // 可以是 `Function`
            parser: require('sugarss').parse,
          },
        },
      },
    ],
  },
};

设置 stringifier

webpack.config.js

const Midas = require('midas');
const midas = new Midas();

module.exports = {
  module: {
    rules: [
      {
        test: /\.sss$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            // 可以是 `String`
            stringifier: 'sugarss',
            // 可以是 `Object`
            stringifier: require('sugarss'),
            // 可以是 `Function`
            stringifier: midas.stringifier,
          },
        },
      },
    ],
  },
};

Function

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.(css|sss)$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: (loaderContext) => {
            if (/\.sss$/.test(loaderContext.resourcePath)) {
              return {
                parser: 'sugarss',
                plugins: [
                  ['postcss-short', { prefix: 'x' }],
                  'postcss-preset-env',
                ],
              };
            }

            return {
              plugins: [
                ['postcss-short', { prefix: 'x' }],
                'postcss-preset-env',
              ],
            };
          },
        },
      },
    ],
  },
};

config

类型:Boolean|String 默认值:undefined

允许使用配置文件设置选项。 在配置文件中指定的选项将会和 loader option 进行合并,并且 loader option 将会覆盖配置文件中的选项。

配置文件

Loader 将会从下面几个地方搜索目录树来寻找配置文件:

  • package.json 中的 postcss 属性
  • JSON 或者 YAML 格式的 .postcssrc 文件
  • .postcss.json.postcss.yaml.postcss.yml.postcss.js 或者 .postcss.cjs 文件
  • postcss.config.js 或者 postcss.config.cjs 导出一个对象的 CommonJS 模块(推荐
配置文件示例

使用 Object

postcss.config.js推荐

module.exports = {
  // 你可以指定下面提到的所有选项 https://postcss.org/api/#processoptions
  // parser: 'sugarss',
  plugins: [
    // PostCSS 插件
    ['postcss-short', { prefix: 'x' }],
    'postcss-preset-env',
  ],
};

使用 Function

postcss.config.js推荐

module.exports = (api) => {
  // `api.file` - 文件路径
  // `api.mode` - webpack 的 `mode` 属性值,请查阅 https://webpack.js.org/configuration/mode/
  // `api.webpackLoaderContext` - 在复杂情况下使用的 loader 上下文
  // `api.env` - `api.mode` 的别名,与 `postcss-cli` 兼容
  // `api.options` - `postcssOptions` 的选项

  if (/\.sss$/.test(api.file)) {
    return {
      //你可以指定下面提到的所有选项 https://postcss.org/api/#processoptions here
      parser: 'sugarss',
      plugins: [
        // PostCSS 插件
        ['postcss-short', { prefix: 'x' }],
        'postcss-preset-env',
      ],
    };
  }

  return {
    // 你可以指定下面提到的所有选项 https://postcss.org/api/#processoptions
    plugins: [
      // PostCSS 插件
      ['postcss-short', { prefix: 'x' }],
      'postcss-preset-env',
    ],
  };
};

postcss.config.js废弃的,将会在下一个主要版本中移除)

module.exports = {
  // 你可以指定下面提到的所有选项 https://postcss.org/api/#processoptions
  // parser: 'sugarss',
  plugins: {
    // PostCSS 插件
    'postcss-short': { prefix: 'x' },
    'postcss-preset-env': {},
  },
};
配置级联

你可以在不同的目录中使用不同的 postcss.config.js 文件。 配置文件的寻找从 path.dirname(file) 开始根据文件树向上寻找,直至找到一个配置文件。

|– components
| |– component
| | |– index.js
| | |– index.png
| | |– style.css (1)
| | |– postcss.config.js (1)
| |– component
| | |– index.js
| | |– image.png
| | |– style.css (2)
|
|– postcss.config.js (1 && 2 (recommended))
|– webpack.config.js
|
|package.json

在设置 postcss.config.js 之后,将 postcss-loader 添加到 webpack.config.js 中。 你可以单独使用它,或者与 css-loader 结合使用(推荐)。

css-loaderstyle-loader 之前使用它,但是在其他预处理器(例如:sass|less|stylus-loader之后使用 (因为 webpack loader 从右到左 / 从底到顶执行)。

webpack.config.js推荐

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
            },
          },
          'postcss-loader',
        ],
      },
    ],
  },
};

Boolean

开启 / 关闭自动加载配置。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            config: false,
          },
        },
      },
    ],
  },
};

String

允许指定配置文件路径。

webpack.config.js

const path = require('path');

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            config: path.resolve(__dirname, 'custom.config.js'),
          },
        },
      },
    ],
  },
};

sourceMap

类型:Boolean 默认值:依赖于 compiler.devtool 的值

默认情况下 source map 的生成依赖于 devtool选项。 除 evalfalse 外,其他的值都将打开 source map 生成。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          { loader: 'style-loader' },
          { loader: 'css-loader', options: { sourceMap: true } },
          { loader: 'postcss-loader', options: { sourceMap: true } },
          { loader: 'sass-loader', options: { sourceMap: true } },
        ],
      },
    ],
  },
};

替代设置:

webpack.config.js

module.exports = {
  devtool: 'source-map',
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          { loader: 'style-loader' },
          { loader: 'css-loader' },
          { loader: 'postcss-loader' },
          { loader: 'sass-loader' },
        ],
      },
    ],
  },
};

implementation

类型:Function | String 默认值:postcss

特殊的 implementation 选项决定使用 PostCSS 哪个实现。重载本地安装的 postcsspeerDependency 版本。

此选项只对底层工具的作者有效,以便于 PostCSS 7 到 PostCSS 8 的过渡。

Function

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          { loader: 'style-loader' },
          { loader: 'css-loader' },
          {
            loader: 'postcss-loader',
            options: { implementation: require('postcss') },
          },
          { loader: 'sass-loader' },
        ],
      },
    ],
  },
};

String

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          { loader: 'style-loader' },
          { loader: 'css-loader' },
          {
            loader: 'postcss-loader',
            options: { implementation: require.resolve('postcss') },
          },
          { loader: 'sass-loader' },
        ],
      },
    ],
  },
};

例子

SugarSS

你需要安装 sugarss

npm install --save-dev sugarss

使用 SugarSS 句法分析器。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.sss$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: { importLoaders: 1 },
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                parser: 'sugarss',
              },
            },
          },
        ],
      },
    ],
  },
};

Autoprefixer

你需要安装 autoprefixer

npm install --save-dev autoprefixer

使用 autoprefixer 添加厂商前缀。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: { importLoaders: 1 },
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  [
                    'autoprefixer',
                    {
                      // 选项
                    },
                  ],
                ],
              },
            },
          },
        ],
      },
    ],
  },
};

⚠️ postcss-preset-env 包含 autoprefixer,因此如果你已经使用了 preset 就无需单独添加它了。更多 信息

PostCSS Preset Env

你需要安装 postcss-preset-env

npm install --save-dev postcss-preset-env

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: { importLoaders: 1 },
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  [
                    'postcss-preset-env',
                    {
                      // 选项
                    },
                  ],
                ],
              },
            },
          },
        ],
      },
    ],
  },
};

CSS Modules

什么是 CSS Modules?请 阅读

postcss-loader 中没有额外的设置。 为了使他们正常工作,请添加 css-loaderimportLoaders 选项。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
              importLoaders: 1,
            },
          },
          'postcss-loader',
        ],
      },
    ],
  },
};

CSS-in-JS and postcss-js

你需要安装 postcss-js

npm install --save-dev postcss-js

如果你想处理写在 JavaScript 中的样式,那么你需要使用 postcss-js parser。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.style.js$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2,
            },
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                parser: 'postcss-js',
              },
              execute: true,
            },
          },
          'babel-loader',
        ],
      },
    ],
  },
};

接下来你就可以像下面这样书写样式了

import colors from './styles/colors';

export default {
  '.menu': {
    color: colors.main,
    height: 25,
    '&_link': {
      color: 'white',
    },
  },
};

⚠️ 如果你正在使用 Babel 且为了程序正常工作,你需要进行下面的步骤:

  1. 添加 babel-plugin-add-module-exports 到你的配置中。
  2. 你需要在每一个样式模块中有一个默认导出。

提取 CSS

使用 mini-css-extract-plugin

webpack.config.js

const isProductionMode = process.env.NODE_ENV === 'production';

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

module.exports = {
  mode: isProductionMode ? 'production' : 'development',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          isProductionMode ? MiniCssExtractPlugin.loader : 'style-loader',
          'css-loader',
          'postcss-loader',
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: isProductionMode ? '[name].[contenthash].css' : '[name].css',
    }),
  ],
};

触发资源打包

要将资源从 PostCSS 插件写到 webpack,需要向 result.messages 中添加一条消息。

一条符合规范的消息应该包含下面的字段:

  • type = asset - 消息类型(必需字段,并且应该为 asset
  • file - 文件名称(必需)
  • content - 文件内容(必需)
  • sourceMap - sourceMap
  • info - 资源信息

webpack.config.js

const customPlugin = () => (css, result) => {
  result.messages.push({
    type: 'asset',
    file: 'sprite.svg',
    content: '<svg>...</svg>',
  });
};

const postcssPlugin = postcss.plugin('postcss-assets', customPlugin);

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [postcssPlugin()],
              },
            },
          },
        ],
      },
    ],
  },
};

添加 dependencies、contextDependencies、buildDependencies、missingDependencies

当需要在文件变化时进行重新编译时,webpack 为了理解这样的操作需要添加必要的依赖。

由两种方式添加依赖:

  1. (推荐)。插件在 result.messages 中触发消息。

消息应该包含下面两个字段:

  • type = dependency - 消息类型(必需字段,并且应该为 dependencycontext-dependencybuild-dependencymissing-dependency
  • file - 文件的绝对路径(必需)

webpack.config.js

const path = require('path');

const customPlugin = () => (css, result) => {
  result.messages.push({
    type: 'dependency',
    file: path.resolve(__dirname, 'path', 'to', 'file'),
  });
};

const postcssPlugin = postcss.plugin('postcss-assets', customPlugin);

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [postcssPlugin()],
              },
            },
          },
        ],
      },
    ],
  },
};
  1. 在插件中传递 loaderContext

webpack.config.js

const path = require('path');

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                config: path.resolve(__dirname, 'path/to/postcss.config.js'),
              },
            },
          },
        ],
      },
    ],
  },
};

postcss.config.js

module.exports = (api) => ({
  plugins: [
    require('path/to/customPlugin')({
      loaderContext: api.webpackLoaderContext,
    }),
  ],
});

customPlugin.js

const path = require('path');

const customPlugin = (loaderContext) => (css, result) => {
  loaderContext.webpack.addDependency(
    path.resolve(__dirname, 'path', 'to', 'file')
  );
};

module.exports = postcss.plugin('postcss-assets', customPlugin);

贡献

如果你还没有读过我们的贡献指南,请花一点时间阅读它。

CONTRIBUTING

License

MIT

pug-loader

404: Not Found

remark-loader

npm node deps tests cover chat size

通过 remark 加载 markdown。

用法

只需将 loader 添加到您的配置中,并设置 options。

import md from "markdown-file.md";
console.log(md);

webpack.config.js

import RemarkHTML from "remark-html";

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.md$/,
        use: [
          {
            loader: "html-loader",
          },
          {
            loader: "remark-loader",
            options: {
              remarkOptions: {
                plugins: [RemarkHTML],
              },
            },
          },
        ],
      },
    ],
  },
};

下面是 remark plugins 的完整列表。

我们不再支持任何 react 的特殊功能。 如果您对在 JSX 中使用 Markdown 感兴趣,请参阅很棒的 MDX 项目。

Options

NameTypeDefaultDescription
remarkOptions{Object}{}Remark options
removeFrontMatter{Boolean}trueRemove removeFrontMatter

remarkOptions

NameTypeDefaultDescription
pluginsArray<String|Array>[]Allows to connect remark plugins
settings{Object}undefinedRemark settings
data{Object}undefinedInformation available to all plugins

plugins

Type: Array<String|Array> Default: []

可以和 remark plugins 一起使用

String

webpack.config.js

import RemarkFrontmatter from "remark-frontmatter";

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.md$/,
        use: [
          {
            loader: "remark-loader",
            options: {
              remarkOptions: {
                plugins: [RemarkFrontmatter],
              },
            },
          },
        ],
      },
    ],
  },
};
Array

如果需要为插件指定 options,可以使用数组传递插件,其中第二个参数就是将要设置的 options。

webpack.config.js

import RemarkFrontmatter from "remark-frontmatter";
import RemarkBookmarks from "remark-bookmarks";

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.md$/,
        use: [
          {
            loader: "remark-loader",
            options: {
              remarkOptions: {
                plugins: [
                  RemarkFrontmatter,
                  [
                    RemarkBookmarks,
                    {
                      bookmarks: {
                        npm: "https://npmjs.com/package/remark-bookmarks",
                      },
                    },
                  ],
                ],
              },
            },
          },
        ],
      },
    ],
  },
};

settings

Type: Object Default: undefined

remark-stringify options 选项和 remark-parse options 选项传递给 remark

webpack.config.js

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.md$/,
        use: [
          {
            loader: "remark-loader",
            options: {
              remarkOptions: {
                settings: {
                  bullet: "+",
                  listItemIndent: "1",
                },
              },
            },
          },
        ],
      },
    ],
  },
};

data

Type: Object Default: undefined

使用所有插件通用的配置 remark。 配置信息存储在内存中的键值存储中。

webpack.config.js

function examplePluginUsingData() {
  console.log(this.data);
  // { alpha: 'bravo', charlie: 'delta' }
}

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.md$/,
        use: [
          {
            loader: "remark-loader",
            options: {
              remarkOptions: {
                plugins: [examplePluginUsingData],
                data: {
                  alpha: "bravo",
                  charlie: "delta",
                },
              },
            },
          },
        ],
      },
    ],
  },
};

removeFrontMatter

Type: Boolean Default: true

默认情况下,refortmatter 是被移除的。 如果要覆盖这个配置,需要在插件中添加 remark-frontmatter,并设置 removeFrontMatterfalse

webpack.config.js

import RemarkFrontmatter from "remark-frontmatter";

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.md$/,
        use: [
          {
            loader: "remark-loader",
            options: {
              removeFrontMatter: false,
              remarkOptions: {
                plugins: [RemarkFrontmatter],
              },
            },
          },
        ],
      },
    ],
  },
};

启发

这个项目收到了以下开源作品的启发:

示例

Markdown 转为 HTML

要获得 html,需要在 remark 插件中添加 remark-html,并在 webpack.config 中添加 html-loader

import md from "markdown-file.md";
console.log(md);

webpack.config.js

import RemarkHTML from "remark-html";

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.md$/,
        use: [
          {
            loader: "html-loader",
          },
          {
            loader: "remark-loader",
            options: {
              remarkOptions: {
                plugins: [RemarkHTML],
              },
            },
          },
        ],
      },
    ],
  },
};

Markdown 转为 Markdown

index.js

import md from "markdown-file.md";
console.log(md);

webpack.config.js

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.md$/,
        use: [
          {
            loader: "remark-loader",
          },
        ],
      },
    ],
  },
};

贡献

如果您还没有贡献代码,请花点时间阅读我们的贡献指南。

CONTRIBUTING

License

MIT

sass-loader

npm node deps tests coverage chat size

加载 Sass/SCSS 文件并将他们编译为 CSS。

快速开始

首先,你需要安装 sass-loader

npm install sass-loader sass webpack --save-dev

sass-loader 需要预先安装 Dart SassNode Sass(可以在这两个链接中找到更多的资料)。这可以控制所有依赖的版本, 并自由的选择使用的 Sass 实现。

这样可以控制所有依赖项的版本,并选择要使用的 Sass 实现。

ℹ️ 我们推荐使用 Dart Sass

Node Sass 不能与 Yarn PnP 特性一起正常工作,并且不支持 @use rule

sass-loadercss-loaderstyle-loader 进行链式调用,可以将样式以 style 标签的形式插入 DOM 中,或者使用 mini-css-extract-plugin 将样式输出到独立的文件中。

然后将本 loader 添加到你的 Webpack 配置中。例如:

app.js

import './style.scss';

style.scss

$body-color: red;

body {
  color: $body-color;
}

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          // 将 JS 字符串生成为 style 节点
          'style-loader',
          // 将 CSS 转化成 CommonJS 模块
          'css-loader',
          // 将 Sass 编译成 CSS
          'sass-loader',
        ],
      },
    ],
  },
};

最后通过你喜欢的方式运行 webpack

解析 import 的规则

Webpack 提供一种 解析文件的高级机制

sass-loader 使用 Sass 提供的 custom importer 特性,将所有 query 传递给 Webpack 解析引擎。 因此你可以从 node_modules 中引入 Sass modules。

@import "bootstrap";

~ 用法已被废弃,可以从代码中删除(我们建议这么做),但是我们会因为一些历史原因一直支持这种写法。 为什么你可以移除它呢?loader 首先会尝试以相对路径解析 @import,如果它不能被解析,loader 将会尝试在 node_modules 中解析 @import

在包名前加上 ~ 就会告诉 Webpack 在 modules 中进行查找。

@import "~bootstrap";

重要的是,只在前面加上 ~,因为~/ 将会解析到用户的主目录(home directory)。 因为 CSS 和 Sass 文件没有用于导入相关文件的特殊语法,所以 Webpack 需要区分 bootstrap~bootstrap@import "style.scss"@import "./style.scss"; 两种写法是相同的。

url(...) 的问题

由于 Sass 的实现没有提供 url 重写的功能,所以相关的资源都必须是相对于输出文件(ouput)而言的。

  • 如果生成的 CSS 传递给了 css-loader,则所有的 url 规则都必须是相对于入口文件的(例如:main.scss)。
  • 如果仅仅生成了 CSS 文件,没有将其传递给 css-loader,那么所有的 url 都是相对于网站的根目录的。

第一种情况可能会带来一些困扰。通常情况下我们希望相对路径引用的解析是相对于声明它的 .sass/.scss 文件(如同在 .css 文件中一样)。

幸运的是,有两种方法可以解决这个问题:

  • resolve-url-loader 设置于 loader 链中的 sass-loader 之前,就可以重写 url。
  • Library 作者一般都会提供变量,用来设置资源路径。比如 bootstrap-sass 可以通过 $icon-font-path 进行设置。

配置选项

名称类型默认值Description
implementation{Object|String}sass设置使用的 Sass 的实现。
sassOptions{Object|Function}Sass 实现的默认值Sass 自身选项。
sourceMap{Boolean}compiler.devtool启用 / 禁用 source maps 的生成。
additionalData{String|Function}undefined在实际的输入文件之前添加 Sass /SCSS 代码。
webpackImporter{Boolean}true启用 / 禁用默认的 Webpack importer。
warnRuleAsWarning{Boolean}false@warn 规则视为 webpack 警告。

implementation

类型: Object | String 默认值: sass

特殊的 implementation 选项确定要使用的 Sass 实现。

默认情况下,loader 将会根据你的依赖解析需要使用的实现。 只需将必需的实现添加到 package.jsonsassnode-sass 包)中并安装依赖项即可。

示例,此时 sass-loader 将会使用 sassdart-sass)实现:

package.json

{
  "devDependencies": {
    "sass-loader": "^7.2.0",
    "sass": "^1.22.10"
  }
}

示例,此时 sass-loader 将会使用 node-sass 实现:

package.json

{
  "devDependencies": {
    "sass-loader": "^7.2.0",
    "node-sass": "^5.0.0"
  }
}

需注意同时安装 node-sasssass 的情况!默认情况下,sass-loader 会选择 sass。 为了避免这种情况,你可以使用 implementation 选项。

implementation 选项可以以模块的形式接受 sassDart Sass)或 node-sass

Object

例如,为了使用 Dart Sass,你应该传递:

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              // `dart-sass` 是首选
              implementation: require('sass'),
            },
          },
        ],
      },
    ],
  },
};

String

例如,为了使用 Dart Sass,你应该传递:

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              // Prefer `dart-sass`
              implementation: require.resolve('sass'),
            },
          },
        ],
      },
    ],
  },
};

需要注意的是,当使用 sassDart Sass)时,由于异步回调的开销,通常情况下同步编译的速度是异步编译速度的两倍。 为了避免这种开销,你可以使用 fibers 包从同步代码中调用异步导入程序。

如果可能,我们会为小于 v16.0.0 的 Node.js 自动注入 fibers 软件包(设置 sassOptions.fiber)(当然需要你安装 fibers 包)。

Fibers 不兼容 Node.js v16.0.0 以及更高的版本(查看介绍)。

package.json

{
  "devDependencies": {
    "sass-loader": "^7.2.0",
    "sass": "^1.22.10",
    "fibers": "^4.0.1"
  }
}

你可以通过向 sassOptions.fiber 传递 false 参数关闭自动注入的 fibers 包。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              implementation: require('sass'),
              sassOptions: {
                fiber: false,
              },
            },
          },
        ],
      },
    ],
  },
};

你还可以通过一下代码传递 fiber

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              implementation: require('sass'),
              sassOptions: {
                fiber: require('fibers'),
              },
            },
          },
        ],
      },
    ],
  },
};

sassOptions

类型:Object|Function 默认值:Sass 实现的默认值

Dart Sass 或者 Node Sass 实现的选项。

ℹ️ dart-sasscharset 选项默认为 true,我们强烈建议你将其改为 false,因为 webpack 并不支持 utf-8 以外的文件。

ℹ️ indentedSyntax 选项值为 true,是对 sass 的扩展。

ℹ️ 像 datafile 这样的选项是不可用的,且会被忽略。

ℹ 我们坚决反对设置 outFilesourceMapContentssourceMapEmbedsourceMapRoot 这些选项,因为当 sourceMaptrue 时,sass-loader 会自动设置这些选项。

ℹ️ 可以使用 this.webpackLoaderContext 属性访问自定义 importer 中的 loader 上下文

sassdart-sass)和 node-sass 之间的选项略有不同。

在使用他们之前,请查阅有关文档:

Object

使用对象设置 Sass 实现的启动选项。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              sassOptions: {
                indentWidth: 4,
                includePaths: ['absolute/path/a', 'absolute/path/b'],
              },
            },
          },
        ],
      },
    ],
  },
};

Function

允许通过 loader 上下文为 Sass 实现设置不同的选项。

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              sassOptions: (loaderContext) => {
                // 有关可用属性的更多信息 https://webpack.js.org/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === 'styles/foo.scss') {
                  return {
                    includePaths: ['absolute/path/c', 'absolute/path/d'],
                  };
                }

                return {
                  includePaths: ['absolute/path/a', 'absolute/path/b'],
                };
              },
            },
          },
        ],
      },
    ],
  },
};

sourceMap

类型:Boolean 默认值:取决于 compiler.devtool 的值

开启/关闭生成 source map。

默认情况下 source maps 的生成取决于 devtool 选项。 除 evalfalse 之外的所有值都将开启 source map 的生成。

ℹ 如果为 true 将会忽略来自 sassOptionssourceMapsourceMapRootsourceMapEmbedsourceMapContentsomitSourceMapUrl 选项。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
            },
          },
          {
            loader: 'sass-loader',
            options: {
              sourceMap: true,
            },
          },
        ],
      },
    ],
  },
};

ℹ 在极少数情况下,node-sass 会输出无效的 source maps(这是 node-sass 的 bug)。

为了避免这种情况,你可以尝试将 node-sass 更新到最新版本,或者可以尝试将 sassOptions 中的 outputStyle 选项设置为 compressed

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              sourceMap: true,
              sassOptions: {
                outputStyle: 'compressed',
              },
            },
          },
        ],
      },
    ],
  },
};

additionalData

类型:String|Function 默认值:undefined

在实际的文件之前要添加的 Sass / SCSS 代码。 在这种情况下,sass-loader 将不会覆盖 data 选项,而只是将它拼接在入口文件内容之前。

当某些 Sass 变量取决于环境时,这非常有用:

String

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              additionalData: '$env: ' + process.env.NODE_ENV + ';',
            },
          },
        ],
      },
    ],
  },
};

Function

Sync
module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              additionalData: (content, loaderContext) => {
                // 有关可用属性的更多信息 https://webpack.js.org/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === 'styles/foo.scss') {
                  return '$value: 100px;' + content;
                }

                return '$value: 200px;' + content;
              },
            },
          },
        ],
      },
    ],
  },
};
Async
module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              additionalData: async (content, loaderContext) => {
                // More information about available properties https://webpack.js.org/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === 'styles/foo.scss') {
                  return '$value: 100px;' + content;
                }

                return '$value: 200px;' + content;
              },
            },
          },
        ],
      },
    ],
  },
};

webpackImporter

类型:Boolean 默认值:true

开启 / 关闭默认的 Webpack importer。

在某些情况下,可以提高性能。但是请谨慎使用,因为 aliases 和以 开头的 @import 规则将不起作用。 你可以传递自己的 importer 来解决这个问题(参阅 importer docs)。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              webpackImporter: false,
            },
          },
        ],
      },
    ],
  },
};

warnRuleAsWarning

Type: Boolean Default: false

@warn 规则视为 webpack 警告。

ℹ️ 在下一个大版本发布中它将默认设置为 true

style.scss

$known-prefixes: webkit, moz, ms, o;

@mixin prefix($property, $value, $prefixes) {
  @each $prefix in $prefixes {
    @if not index($known-prefixes, $prefix) {
      @warn "Unknown prefix #{$prefix}.";
    }

    -#{$prefix}-#{$property}: $value;
  }
  #{$property}: $value;
}

.tilt {
  // Oops, we typo'd "webkit" as "wekbit"!
  @include prefix(transform, rotate(15deg), wekbit ms);
}

给出的代码将抛出 webpack 警告而不是日志。

要忽略不必要的警告,可以使用 ignoreWarnings 配置项。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              warnRuleAsWarning: true,
            },
          },
        ],
      },
    ],
  },
};

示例

提取样式表

对于生产版本,我们建议从 bundle 中提取 CSS,以便之后可以使 CSS/JS 资源并行加载。

从 bundle 中提取样式表,有 2 种实用的方式:

webpack.config.js

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

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          // 在开发过程中回退到 style-loader
          process.env.NODE_ENV !== 'production'
            ? 'style-loader'
            : MiniCssExtractPlugin.loader,
          'css-loader',
          'sass-loader',
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      // 与 webpackOptions.output 中的选项相似
      // 所有的选项都是可选的
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ],
};

Source maps

开启/关闭 source map 的生成。

为了开启 CSS source maps,需要将 sourceMap 选项作为参数,传递给 sass-loadercss-loader

webpack.config.js

module.exports = {
  devtool: "source-map", // 任何类似于 "source-map" 的选项都是支持的
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              sourceMap: true,
            },
          },
          {
            loader: "sass-loader",
            options: {
              sourceMap: true,
            },
          },
        ],
      },
    ],
  },
};

如果你要在 Chrome 中编辑原始的 Sass 文件,建议阅读 这篇不错的博客。具体示例参考 test/sourceMap

贡献

如果你还没有阅读过我们的贡献指南,请花一点时间阅读它。

CONTRIBUTING

License

MIT

source-map-loader

npm node deps tests coverage chat size

从现有的源文件中提取 source maps(从 sourceMappingURL 中提取)。

起步

安装 source-map-loader

npm i -D source-map-loader

添加 plugin 至 webpack 配置。例:

file.js

import css from 'file.css';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        enforce: 'pre',
        use: ['source-map-loader'],
      },
    ],
  },
};

source-map-loader 从 JavaScript 入口提取现有的 source maps. 这些 source maps 既可以是内联的也可以是通过 URL 链接引入的。 所有的 source map 数据都按照选定的 source map style 交给 webpack 处理,这些选定可以在 webpack.config.jsdevtool 选项中配置。 在使用有自己 source maps 的第三方库时,source-map-loader 就显得尤为重要。 如果相关 source map 数据没有按照规范提取、处理并注入 webpack bundle, 浏览器有可能无法正确解读这些数据。source-map-loader 允许 webpack 跨库且持续的维护 source map 数据,因而更易于调试。 source-map-loader 可以从任何 JavaScript 文件中提取,这也包括 node_modules 目录下的 JavaScript 文件。 在设置 includeexclude 规则时,要保证构建性能最优。

最后按偏好运行 webpack 方法。

选项

选项名类型默认值描述
filterSourceMappingUrl{Function}undefined允许控制 SourceMappingURL 的行为

filterSourceMappingUrl

类型:Function 默认值:undefined

允许你为 SourceMappingURL 注释指定 loader 的特定行为。

此函数的返回值必须为下列之一:

  • true'consume' — 使用 source map 并删除 SourceMappingURL 注释(默认行为)
  • false'remove' — 不使用 source map 并删除 SourceMappingURL 注释
  • skip — 不使用 source map 但不删除 SourceMappingURL 注释

示例配置:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        enforce: 'pre',
        use: [
          {
            loader: 'source-map-loader',
            options: {
              filterSourceMappingUrl: (url, resourcePath) => {
                if (/broker-source-map-url\.js$/i.test(url)) {
                  return false;
                }

                if (/keep-source-mapping-url\.js$/i.test(resourcePath)) {
                  return 'skip';
                }

                return true;
              },
            },
          },
        ],
      },
    ],
  },
};

示例

忽略警告

忽略警告可以使用以下配置:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        enforce: 'pre',
        use: ['source-map-loader'],
      },
    ],
  },
  ignoreWarnings: [/Failed to parse source map/],
};

欲了解 ignoreWarnings 的更多信息,请查阅此文

贡献

如果您尚未了解,建议您阅读以下贡献指引。

CONTRIBUTING

许可

MIT

style-loader

npm node deps tests coverage chat size

把 CSS 插入到 DOM 中。

快速开始

首先,你需要安装 style-loader

npm install --save-dev style-loader

推荐将 style-loadercss-loader 一起使用

然后把 loader 添加到你的 webpack 配置中。比如:

style.css

body {
  background: green;
}

component.js

import './style.css';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
};

Options

名称类型默认值描述
injectType{String}styleTag配置把 styles 插入到 DOM 中的方式
attributes{Object}{}添加自定义属性到插入的标签中
insert{String|Function}head在指定的位置插入标签
styleTagTransform{String|Function}undefined当将 'style' 标签插入到 DOM 中时,转换标签和 css
base{Number}true基于 (DLLPlugin) 设置 module ID
esModule{Boolean}false使用 ES modules 语法

injectType

Type: String Default: styleTag

配置把 styles 插入到 DOM 中的方式。

可选值:

  • styleTag
  • singletonStyleTag
  • autoStyleTag
  • lazyStyleTag
  • lazySingletonStyleTag
  • lazyAutoStyleTag
  • linkTag

styleTag

通过使用多个 <style></style> 自动把 styles 插入到 DOM 中。该方式是默认行为。

component.js

import './styles.css';

使用 Locals (CSS Modules) 的例子:

component-with-css-modules.js

import styles from './styles.css';

const divElement = document.createElement('div');
divElement.className = styles['my-class'];

导入的对象保存着所有的 locals (class names)。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          // 由于是默认行为,`injectType` 选项可以省略
          { loader: 'style-loader', options: { injectType: 'styleTag' } },
          'css-loader',
        ],
      },
    ],
  },
};

此 loader 插入的 style 效果如下:

<style>
  .foo {
    color: red;
  }
</style>
<style>
  .bar {
    color: blue;
  }
</style>

singletonStyleTag

通过使用一个 <style></style> 来自动把 styles 插入到 DOM 中。

⚠ Source map 不起作用

component.js

import './styles.css';

component-with-css-modules.js

import styles from './styles.css';

const divElement = document.createElement('div');
divElement.className = styles['my-class'];

导入的对象保存着所有的 locals (class names)。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: { injectType: 'singletonStyleTag' },
          },
          'css-loader',
        ],
      },
    ],
  },
};

loader 插入的 styles 如下:

<style>
  .foo {
    color: red;
  }
  .bar {
    color: blue;
  }
</style>

autoStyleTag

styleTag 相同,但是当代码在 IE6-9 中运行时,请打开 singletonStyleTag 模式。

lazyStyleTag

在需要时使用多个 <style></style> 把 styles 插入到 DOM 中。

推荐 lazy style 遵循使用 .lazy.css 作为后缀的命名约定,style-loader 基本用法是使用 .css 作为文件后缀(其他文件也一样,比如:.lazy.less.less)。

当使用 lazyStyleTag 时,style-loader 将惰性插入 styles,在需要使用 styles 时可以通过 style.use() / style.unuse() 使 style 可用。

⚠️ 调用 unuse 多于 use 时,其表现会不确定。因此,请不要这么做。

component.js

import styles from './styles.lazy.css';

styles.use();
// 要移除 styles 时你可以调用
// styles.unuse();

component-with-css-modules.js

import styles from './styles.lazy.css';

styles.use();

const divElement = document.createElement('div');
divElement.className = styles.locals['my-class'];

导入的对象的 locals 属性保存着所有的 locals (class names)。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        exclude: /\.lazy\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.lazy\.css$/i,
        use: [
          { loader: 'style-loader', options: { injectType: 'lazyStyleTag' } },
          'css-loader',
        ],
      },
    ],
  },
};

此 loader 插入的 style 效果如下:

<style>
  .foo {
    color: red;
  }
</style>
<style>
  .bar {
    color: blue;
  }
</style>

lazySingletonStyleTag

在必要时,使用 <style></style> 把 style 插入的 DOM 中。

推荐 lazy style 遵循使用 .lazy.css 作为后缀的命名约定,style-loader 基本用法是使用 .css 作为文件后缀(其他文件也一样,比如:.lazy.less.less)。

当使用 lazySingletonStyleTag 时,style-loader 将惰性插入 styles,在需要使用 styles 时可以通过 style.use() / style.unuse() 使 style 可用。

⚠️ Source maps 不起作用

⚠️ 调用 unuse 多于 use 时,其表现会不确定。因此,请不要这么做。

component.js

import styles from './styles.css';

styles.use();
// 要移除 styles 时你可以调用
// styles.unuse();

component-with-css-modules.js

import styles from './styles.lazy.css';

styles.use();

const divElement = document.createElement('div');
divElement.className = styles.locals['my-class'];

导入的对象的 locals 属性保存着所有的 locals (class names)。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        exclude: /\.lazy\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.lazy\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: { injectType: 'lazySingletonStyleTag' },
          },
          'css-loader',
        ],
      },
    ],
  },
};

此 loader 生成的代码如下:

<style>
  .foo {
    color: red;
  }
  .bar {
    color: blue;
  }
</style>

lazyAutoStyleTag

lazyStyleTag 相同,但是当代码在 IE6-9 中运行时,请打开 lazySingletonStyleTag 模式。

linkTag

使用多个 <link rel="stylesheet" href="path/to/file.css"> 将 styles 插入到 DOM 中。

ℹ️ 此 loader 会在运行时使用 JavaScript 动态地插入 <link href="path/to/file.css" rel="stylesheet">。要静态插入 <link href="path/to/file.css" rel="stylesheet"> 时请使用MiniCssExtractPlugin

import './styles.css';
import './other-styles.css';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.link\.css$/i,
        use: [
          { loader: 'style-loader', options: { injectType: 'linkTag' } },
          { loader: 'file-loader' },
        ],
      },
    ],
  },
};

此 loader 生成的代码如下:

<link rel="stylesheet" href="path/to/style.css" />
<link rel="stylesheet" href="path/to/other-styles.css" />

attributes

Type: Object Default: {}

如果配置了 attributesstyle-loader 将会在 <style> / <link> 上绑定指定的 attributes 以及它们的值。

component.js

import style from './file.css';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          { loader: 'style-loader', options: { attributes: { id: 'id' } } },
          { loader: 'css-loader' },
        ],
      },
    ],
  },
};
<style id="id"></style>

insert

Type: String|Function Default: head

默认情况下,除非指定 insert,否则 style-loader 会把 <style> / <link> 添加到页面的 <head> 标签尾部。

这会使得 style-loader 创建的 CSS 比 <head> 标签内已经存在的 CSS 拥有更高的优先级。 当默认行为不能满足你的需求时,你可以使用其他值,但我们不推荐这么做。

如果你指定 iframe 作为插入的目标时,请确保你有足够的访问权限,styles 将会被插入到 content document 的 head 标签中。

String

Selector

配置 styles 插入 DOM 的自定义 query selector

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: {
              insert: 'body',
            },
          },
          'css-loader',
        ],
      },
    ],
  },
};
Absolute path to function

允许设置自定义函数的绝对路径,该函数能够覆盖默认行为并且能够在任意位置插入样式。

⚠ 不要忘了这个函数会在浏览器中调用,由于不是所有浏览器都支持最新的 ECMA 特性,如:letconstarrow function expression 等。我们推荐使用 babel-loader 以支持最新的 ECMA 特性。 ⚠ 不要忘了版本较旧的浏览器中某些 DOM 方法并不可用,所以我们推荐只使用 DOM core level 2 properties,但这取决于想要支持的浏览器版本。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: {
              insert: require.resolve('modulePath'),
            },
          },
          'css-loader',
        ],
      },
    ],
  },
};

一个新的 <style><link> 元素将会被插入到 body 标签底部。

Function

允许覆盖默认行为并把 styles 插入到任意位置。

⚠ 不要忘了这个函数会在浏览器中调用,由于不是所有浏览器都支持最新的 ECMA 特性,如:letconstarrow function expression 等,我们推荐只使用 ECMA 5 特性,但这取决于你想要支持的浏览器版本。

⚠ 不要忘了版本较旧的浏览器中某些 DOM 方法并不可用,所以我们推荐只使用 DOM core level 2 properties,但这取决于想要支持的浏览器版本。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: {
              insert: function insertAtTop(element) {
                var parent = document.querySelector('head');
                // eslint-disable-next-line no-underscore-dangle
                var lastInsertedElement =
                  window._lastElementInsertedByStyleLoader;

                if (!lastInsertedElement) {
                  parent.insertBefore(element, parent.firstChild);
                } else if (lastInsertedElement.nextSibling) {
                  parent.insertBefore(element, lastInsertedElement.nextSibling);
                } else {
                  parent.appendChild(element);
                }

                // eslint-disable-next-line no-underscore-dangle
                window._lastElementInsertedByStyleLoader = element;
              },
            },
          },
          'css-loader',
        ],
      },
    ],
  },
};

head 标签顶部插入 styles。

你可以给 style.use(options) 传递任何参数,并且这些值会被传递给 insertstyleTagTransform 函数。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: {
              injectType: 'lazyStyleTag',
              // 不要忘记这些代码会在浏览器中使用,
              // 并且不是所有的浏览器都支持 `let`、`const`、箭头函数表达式等高级 ECMA 特性。
              // 我们建议只使用 ECMA 5 特性,
              // 但是这取决于你想支持的浏览器
              insert: function insertIntoTarget(element, options) {
                var parent = options.target || document.head;

                parent.appendChild(element);
              },
            },
          },
          'css-loader',
        ],
      },
    ],
  },
};

向指定元素添加样式,没有指定时将会插入到 head 标签中。现在你可以向 Shadow DOM 注入样式了(或者其他元素)。

custom-square.css

div {
  width: 50px;
  height: 50px;
  background-color: red;
}

custom-square.js

import customSquareStyles from './custom-square.css';

class CustomSquare extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: 'open' });

    const divElement = document.createElement('div');

    divElement.textContent = 'Text content.';

    this.shadowRoot.appendChild(divElement);

    customSquareStyles.use({ target: this.shadowRoot });

    // 你可以覆盖注入的样式
    const bgPurple = new CSSStyleSheet();
    const width = this.getAttribute('w');
    const height = this.getAttribute('h');

    bgPurple.replace(`div { width: ${width}px; height: ${height}px; }`);

    this.shadowRoot.adoptedStyleSheets = [bgPurple];

    // `divElement` 将会拥有 `100px` 宽,`100px` 高和 `red` 背景颜色
  }
}

customElements.define('custom-square', CustomSquare);

export default CustomSquare;

styleTagTransform

类型:String | Function 默认值:undefined

String

允许设置自定义函数的绝对路径,该函数能够覆盖 styleTagTransform 默认行为。

⚠ 不要忘了这个函数会在浏览器中调用,由于不是所有浏览器都支持最新的 ECMA 特性,如:letconstarrow function expression 等,我们推荐只使用 ECMA 5 特性,但这取决于你想要支持的浏览器版本。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: {
              injectType: 'styleTag',
              styleTagTransform: require.resolve('module-path'),
            },
          },
          'css-loader',
        ],
      },
    ],
  },
};

Function

当将 'style' 标签插入到 DOM 中时,转换标签和 css。

⚠ 不要忘记该代码会在浏览器中使用,并且不是所有的浏览器都支持想 letconst箭头函数 等最新的 ECMA 特性,我们建议仅使用 ECMA5 特性,但这取决于你想支持什么浏览器。 ⚠ 不要忘记有一些 DOM 方法在老的浏览器中是不可用的,我们推荐只使用 DOM core level 2 properties,但这取决于你想支持什么浏览器。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: {
              injectType: 'styleTag',
              styleTagTransform: function (css, style) {
                // Do something ...
                style.innerHTML = `${css}.modify{}\n`;

                document.head.appendChild(style);
              },
            },
          },
          'css-loader',
        ],
      },
    ],
  },
};

base

这个配置主要是作为使用 DllPlugin 时出现 css clashes 问题时的解决方案。base 允许你通过指定一个比 DllPlugin1 使用的 css 模块 id 大的值,来避免应用程序中的 css (或者 DllPlugin2 的 css) 被 DllPlugin1 中的 css 覆盖问题。比如:

webpack.dll1.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
};

webpack.dll2.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          { loader: 'style-loader', options: { base: 1000 } },
          'css-loader',
        ],
      },
    ],
  },
};

webpack.app.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          { loader: 'style-loader', options: { base: 2000 } },
          'css-loader',
        ],
      },
    ],
  },
};

esModule

Type: Boolean Default: true

默认情况下,style-loader 生成使用 ES 模块语法的 JS 模块。在某些情况下使用 ES 模块语法更好,比如:module concatenationtree shaking 时。

你可以使用下面的配置启用 CommonJS 模块语法:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: 'style-loader',
        options: {
          esModule: false,
        },
      },
    ],
  },
};

示例

推荐

对于 production 模式的构建,建议从你的包中提取 CSS,以便以后能够使用 CSS/JS 资源的并行加载。 可以使用 mini-css-extract-plugin 实现,因为它可以创建单独的 css 文件。 对于 development 模式(包括 webpack-dev-server),你可以使用 style-loader,因为他使用多个 <style></style> 将 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: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader',
        ],
      },
    ],
  },
  plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
};

Named export for CSS Modules

⚠ 本地命名导出时,会将其名称转换为 camelCase 的形式。

⚠ 并且不允许在 css 的 class 名中使用 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

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
            options: {
              modules: {
                namedExport: true,
              },
            },
          },
        ],
      },
    ],
  },
};

Source maps

因此,想要生成 source map,则需将 style-loader 之前执行 loader 的 sourceMap 选项设置为true

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          { loader: 'css-loader', options: { sourceMap: true } },
        ],
      },
    ],
  },
};

Nonce

有两种方式使用 nonce

  • 使用 attributes 选项
  • 使用 __webpack_nonce__ 变量

attributes 拥有比 __webpack_nonce__ 更高的优先级

attributes

component.js

import './style.css';

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: {
              attributes: {
                nonce: '12345678',
              },
            },
          },
          'css-loader',
        ],
      },
    ],
  },
};

此 loader 生成代码如下:

<style nonce="12345678">
  .foo {
    color: red;
  }
</style>

webpack_nonce

create-nonce.js

__webpack_nonce__ = '12345678';

component.js

import './create-nonce.js';
import './style.css';

使用 require 的示例:

component.js

__webpack_nonce__ = '12345678';

require('./style.css');

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
};

此 loader 生成代码如下:

<style nonce="12345678">
  .foo {
    color: red;
  }
</style>

Insert styles at top

head 标签顶部插入 style。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: {
              insert: function insertAtTop(element) {
                var parent = document.querySelector('head');
                var lastInsertedElement =
                  window._lastElementInsertedByStyleLoader;

                if (!lastInsertedElement) {
                  parent.insertBefore(element, parent.firstChild);
                } else if (lastInsertedElement.nextSibling) {
                  parent.insertBefore(element, lastInsertedElement.nextSibling);
                } else {
                  parent.appendChild(element);
                }

                window._lastElementInsertedByStyleLoader = element;
              },
            },
          },
          'css-loader',
        ],
      },
    ],
  },
};

在目标元素前插入 style

#id 元素前面插入 style。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: {
              insert: function insertBeforeAt(element) {
                const parent = document.querySelector('head');
                const target = document.querySelector('#id');

                const lastInsertedElement =
                  window._lastElementInsertedByStyleLoader;

                if (!lastInsertedElement) {
                  parent.insertBefore(element, target);
                } else if (lastInsertedElement.nextSibling) {
                  parent.insertBefore(element, lastInsertedElement.nextSibling);
                } else {
                  parent.appendChild(element);
                }

                window._lastElementInsertedByStyleLoader = element;
              },
            },
          },
          'css-loader',
        ],
      },
    ],
  },
};

Custom Elements (Shadow DOM)

你可以为 lazyStyleTag 类型定义自定义目标。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: {
              injectType: 'lazyStyleTag',
              // 不要忘记这些代码会在浏览器中使用,
              // 并且不是所有的浏览器都支持 `let`、`const`、箭头函数表达式等高级 ECMA 特性。
              // 我们建议只使用 ECMA 5 特性,
              // 但是这取决于你想支持的浏览器
              insert: function insertIntoTarget(element, options) {
                var parent = options.target || document.head;

                parent.appendChild(element);
              },
            },
          },
          'css-loader',
        ],
      },
    ],
  },
};

向指定元素添加样式,没有指定时将会插入到 head 标签中。

custom-square.css

div {
  width: 50px;
  height: 50px;
  background-color: red;
}

custom-square.js

import customSquareStyles from './custom-square.css';

class CustomSquare extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: 'open' });

    const divElement = document.createElement('div');

    divElement.textContent = 'Text content.';

    this.shadowRoot.appendChild(divElement);

    customSquareStyles.use({ target: this.shadowRoot });

    // 你可以覆盖注入的样式
    const bgPurple = new CSSStyleSheet();
    const width = this.getAttribute('w');
    const height = this.getAttribute('h');

    bgPurple.replace(`div { width: ${width}px; height: ${height}px; }`);

    this.shadowRoot.adoptedStyleSheets = [bgPurple];

    // `divElement` 将会拥有 `100px` 宽,`100px` 高和 `red` 背景颜色
  }
}

customElements.define('custom-square', CustomSquare);

export default CustomSquare;

Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.

CONTRIBUTING

License

MIT

stylus-loader

npm node deps tests cover chat size

一个 webpack 的 Stylus loader。将 Stylus 文件编译为 CSS。

快速开始

首先,你需要安装 stylusstylus-loader

npm install stylus stylus-loader --save-dev

然后将该 loader 添加到 webpack 配置中。例如:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl$/,
        loader: 'stylus-loader', // 将 Stylus 文件编译为 CSS
      },
    ],
  },
};

接着按照你习惯的方式运行 webpack

可选项

NameTypeDefaultDescription
stylusOptions{Object|Function}{}Stylus 的可选项。
sourceMap{Boolean}compiler.devtool启用/禁用生成 SourceMap。
webpackImporter{Boolean}true启用/禁用默认的 webpack importer。
additionalData{String|Function}undefined在入口文件起始或末尾添加 Stylus 代码。
implementation{String|Function}stylus配置 Stylus 使用的实现库。

stylusOptions

类型:Object|Function 默认值:{}

通过 stylusOptions 属性,你可以给 stylus-loader 配置 loader options 中任意特定的选项值。 所有可用选项可以查看 Stylus 文档。 这些配置项需要将破折号(dash-case)转换为驼峰值(camelCase)后进行设置。

Object

使用对象(Object)的形式传递 options 给 Stylus。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl$/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
          {
            loader: 'stylus-loader',
            options: {
              stylusOptions: {
                /**
                 * 指定要使用的 Stylus 插件。将插件作为
                 * 字符串进行传递,而不是从 Webpack 配置中导入。
                 *
                 * @type {(string|Function)[]}
                 * @default []
                 */
                use: ['nib'],

                /**
                 * 指定 path 的查找路径。
                 *
                 * @type {string[]}
                 * @default []
                 */
                include: [path.join(__dirname, 'src/styl/config')],

                /**
                 * 导入指定的 Stylus 文件或者路径
                 *
                 * @type {string[]}
                 * @default []
                 */
                import: ['nib', path.join(__dirname, 'src/styl/mixins')],

                /**
                 * 定义 Stylus 变量或者函数。
                 *
                 * @type {Array|Object}
                 * @default {}
                 */
                // 定义数组语法的推荐格式:[key, value, raw]
                define: [
                  ['$development', process.env.NODE_ENV === 'development'],
                  ['rawVar', 42, true],
                ],
                // Object 语法已经弃用(不可指定 "raw' 选项)
                // define: {
                //   $development: process.env.NODE_ENV === 'development',
                //   rawVar: 42,
                // },

                /**
                 * 是否包含通过 @import 导入的常规 CSS。
                 *
                 * @type {boolean}
                 * @default false
                 */
                includeCSS: false,

                /**
                 * 解析导入文件中的相对 url()。
                 *
                 * @see https://stylus-lang.com/docs/js.html#stylusresolveroptions
                 *
                 * @type {boolean|Object}
                 * @default { nocheck: true }
                 */
                resolveURL: true,
                // resolveURL: { nocheck: true },

                /**
                 * 生成 CSS 后 注入注释并指定其所在 Stylus 文件行。
                 *
                 * @see https://stylus-lang.com/docs/executable.html
                 *
                 * @type {boolean}
                 * @default false
                 */
                lineNumbers: true,

                /**
                 * 将 @import 和 @charset 移至文件顶部。
                 *
                 * @see https://stylus-lang.com/docs/executable.html
                 *
                 * @type {boolean}
                 * @default false
                 */
                hoistAtrules: true,

                /**
                 * 压缩输出的 CSS。
                 * 生产环境默认值为 `true`
                 *
                 * @see https://stylus-lang.com/docs/executable.html
                 *
                 * @type {boolean}
                 * @default false
                 */
                compress: true,
              },
            },
          },
        ],
      },
    ],
  },
};

Function

允许根据 loader 的 context 来设置 options,再传递给 Stylus。

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'stylus-loader',
            options: {
              stylusOptions: (loaderContext) => {
                // 更多可用的属性参见 https://webpack.js.org/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === 'styles/foo.styl') {
                  return {
                    paths: ['absolute/path/c', 'absolute/path/d'],
                  };
                }

                return {
                  paths: ['absolute/path/a', 'absolute/path/b'],
                };
              },
            },
          },
        ],
      },
    ],
  },
};

sourceMap

类型:Boolean

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
            },
          },
          {
            loader: 'stylus-loader',
            options: {
              sourceMap: true,
            },
          },
        ],
      },
    ],
  },
};

webpackImporter

类型:Boolean 默认值:true

启用/禁用 webpack 默认的 importer。

在某些情况下,这样做可以提高性能。 但是请慎用,因为可能会使得 aliases 和以 ~ 开头的 @import 规则失效。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'stylus-loader',
            options: {
              webpackImporter: false,
            },
          },
        ],
      },
    ],
  },
};

additionalData

类型:String|Function 默认值:undefined

在实际入口文件的起始位置添加 Stylus 代码。 这种情况下,stylus-loader 只会追加并不会覆盖文件内容。

当你的 Stylus 变量依赖环境变量时这个属性将非常有用:

ℹ 由于你注入了代码,因此它将破坏入口文件的源映射关系。通常有比这更简单的解决方案,例如多个 Stylus 入口文件。

String

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'stylus-loader',
            options: {
              additionalData: `@env: ${process.env.NODE_ENV};`,
            },
          },
        ],
      },
    ],
  },
};

Function

Sync
module.exports = {
  module: {
    rules: [
      {
        test: /\.styl/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'stylus-loader',
            options: {
              additionalData: (content, loaderContext) => {
                // 更多可用的属性参见 https://webpack.js.org/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === 'styles/foo.styl') {
                  return 'value = 100px' + content;
                }

                return 'value 200px' + content;
              },
            },
          },
        ],
      },
    ],
  },
};
Async
module.exports = {
  module: {
    rules: [
      {
        test: /\.styl/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'stylus-loader',
            options: {
              additionalData: async (content, loaderContext) => {
                // 更多可用的属性参见 https://webpack.js.org/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === 'styles/foo.styl') {
                  return 'value = 100px' + content;
                }

                return 'value 200px' + content;
              },
            },
          },
        ],
      },
    ],
  },
};

implementation

类型:Function | String

特殊的 implementation 选项决定使用 Stylus 的哪个实现。将会覆盖本地安装的 styluspeerDependency 版本。

Function

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'stylus-loader',
            options: {
              implementation: require('stylus'),
            },
          },
        ],
      },
    ],
  },
};

String

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'stylus-loader',
            options: {
              implementation: require.resolve('stylus'),
            },
          },
        ],
      },
    ],
  },
};

示例

常规用法

stylus-loadercss-loaderstyle-loader 串联起来使用可立即将所有样式更新到 DOM。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl$/,
        use: [
          {
            loader: 'style-loader', // 从 JS 中创建样式节点
          },
          {
            loader: 'css-loader', // 将 CSS 转为 CommonJS
          },
          {
            loader: 'stylus-loader', // 将 Stylus 编译为 CSS
          },
        ],
      },
    ],
  },
};

Source maps

为了生成 CSS 的 source map, 你需要在 loader 的可选项中设置 sourceMap 属性。如果没设置的话 loader 将会继承你 webpack 中为生成 source map 设置的属性值 devtool

webpack.config.js

module.exports = {
  devtool: 'source-map', // 任何类似于 "source-map" 的 devtool 值都可以
  module: {
    rules: [
      {
        test: /\.styl$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
            },
          },
          {
            loader: 'stylus-loader',
            options: {
              sourceMap: true,
            },
          },
        ],
      },
    ],
  },
};

stylus 中使用 nib

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl$/,
        use: [
          {
            loader: 'style-loader', // 从 JS 中创建样式节点
          },
          {
            loader: 'css-loader', // 将 CSS 转为 CommonJS
          },
          {
            loader: 'stylus-loader', // 将 Stylus 编译为 CSS
            options: {
              stylusOptions: {
                use: [require('nib')()],
                import: ['nib'],
              },
            },
          },
        ],
      },
    ],
  },
};

导入 JSON 文件

Stylus 在 json 函数中无效。 因此 webpack 解析器不适用于 .json 文件。 可使用 stylus resolver

index.styl

// 假设文件位置在这里 `node_modules/vars/vars.json`
json('vars.json')

@media queries-small
  body
    display nope

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'stylus-loader',
            options: {
              stylusOptions: {
                // 指定文件查找路径。
                paths: ['node_modules/vars'],
              },
            },
          },
        ],
      },
    ],
  },
};

生产环境

在生产环境中推荐使用 MiniCssExtractPlugin 来提取样式表到专门的文件中,这样你的样式就不需要依赖 JavaScript。

webpack 解析器

webpack 提供了一种 解析文件的高级机制stylus-loader 将所有的查询结果传递给了 webpack 解析器。 因此你可以从 node_modules 中导入 Stylus 模块。

@import 'bootstrap-styl/bootstrap/index.styl';

~ 用法已被废弃,可以从代码中删除(我们建议这么做),但是我们会因为一些历史原因一直支持这种写法。 为什么你可以移除它呢?loader 首先会尝试以相对路径解析 @import,如果它不能被解析,loader 将会尝试在 node_modules 中解析 @import。 只要在包名前加上 ~,告诉 webpack 在 modules 中进行查找。

@import "~bootstrap-styl/bootstrap/index.styl";

重要的是只在它的前面加上 ~,因为 ~/ 会被解析到根目录。 webpack 需要区分 bootstrap~bootstrap,因为 CSS 和 Stylus 文件没有特殊的语法可以导入相对路径的文件。 @import "file"@import "./file"; 写法是等价的。

Stylus resolver

如果指定 paths 选项,将从指定的 paths 中搜索模块。 这是 Stylus 的默认行为。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.styl/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
          {
            loader: 'stylus-loader',
            options: {
              stylusOptions: {
                paths: [path.resolve(__dirname, 'node_modules')],
              },
            },
          },
        ],
      },
    ],
  },
};

提取样式

通过 webpack 打包 CSS 有很多好处,比如给引用图片和字体文件路径添加 hash, 在开发环境可以模块热更新。另一方面,在生产环境,根据 JS 来控制应用样式表不是一个好的方式,可能会导致延迟渲染,甚至可能会出现闪烁现象。因此,在你最终的生产环境中将它们拆分成单独的文件来存放通常是比较好的选择。

有两种从 bundle 中提取样式表的方式:

贡献

如果你还没有看过我们的贡献者指南请先花点时间看一下。

CONTRIBUTING

许可

MIT

thread-loader

npm node deps tests coverage chat size

运行以下 loader 在 worker pool 中。

快速开始

npm install --save-dev thread-loader

使用时,需将此 loader 放置在其他 loader 之前。放置在此 loader 之后的 loader 会在一个独立的 worker 池中运行。

在 worker 池中运行的 loader 是受到限制的。例如:

  • 这些 loader 不能生成新的文件。
  • 这些 loader 不能使用自定义的 loader API(也就是说,不能通过插件来自定义)。
  • 这些 loader 无法获取 webpack 的配置。

每个 worker 都是一个独立的 node.js 进程,其开销大约为 600ms 左右。同时会限制跨进程的数据交换。

请仅在耗时的操作中使用此 loader!

示例

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        include: path.resolve('src'),
        use: [
          "thread-loader",
          // 耗时的 loader (例如 babel-loader)
        ],
      },
    ],
  },
};

with options

use: [
  {
    loader: "thread-loader",
    // 有同样配置的 loader 会共享一个 worker 池
    options: {
      // 产生的 worker 的数量,默认是 (cpu 核心数 - 1),或者,
      // 在 require('os').cpus() 是 undefined 时回退至 1
      workers: 2,

      // 一个 worker 进程中并行执行工作的数量
      // 默认为 20
      workerParallelJobs: 50,

      // 额外的 node.js 参数
      workerNodeArgs: ['--max-old-space-size=1024'],

      // 允许重新生成一个僵死的 work 池
      // 这个过程会降低整体编译速度
      // 并且开发环境应该设置为 false
      poolRespawn: false,

      // 闲置时定时删除 worker 进程
      // 默认为 500(ms)
      // 可以设置为无穷大,这样在监视模式(--watch)下可以保持 worker 持续存在
      poolTimeout: 2000,

      // 池分配给 worker 的工作数量
      // 默认为 200
      // 降低这个数值会降低总体的效率,但是会提升工作分布更均一
      poolParallelJobs: 50,

      // 池的名称
      // 可以修改名称来创建其余选项都一样的池
      name: "my-pool"
    },
  },
  // 耗时的 loader(例如 babel-loader)
];

预警

可以通过预警 worker 池来防止启动 worker 时的高延时。

这会启动池内最大数量的 worker 并把指定的模块加载到 node.js 的模块缓存中。

const threadLoader = require('thread-loader');

threadLoader.warmup(
  {
    // 池选项,例如传递给 loader 选项
    // 必须匹配 loader 选项才能启动正确的池
  },
  [
    // 加载模块
    // 可以是任意模块,例如
    'babel-loader',
    'babel-preset-es2015',
    'sass-loader',
  ]
);

贡献

如果还未阅读贡献指南,请抽时间进行阅读。

CONTRIBUTING

License

MIT

val-loader

npm node deps tests coverage chat size

A webpack loader which executes a given module, and returns the result of the execution at build-time, when the module is required in the bundle. In this way, the loader changes a module from code to a result.

Another way to view val-loader, is that it allows a user a way to make their own custom loader logic, without having to write a custom loader.

The target module is called with two arguments: (options, loaderContext)

  • options: The loader options (for instance provided in the webpack config. See the example below).
  • loaderContext: The loader context.

Getting Started

To begin, you'll need to install val-loader:

npm install val-loader --save-dev

Then add the loader to your webpack config. For example:

target-file.js

module.exports = (options, loaderContext) => {
  return { code: 'module.exports = 42;' };
};

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /target-file.js$/,
        use: [
          {
            loader: `val-loader`,
          },
        ],
      },
    ],
  },
};

src/entry.js

const answer = require('target-file');

And run webpack via your preferred method.

Options

NameTypeDefaultDescription
executableFile{String}undefinedAllows to specify path to the executable file

executableFile

Type: String Default: undefined

Allows to specify path to the executable file

data.json

{
  "years": "10"
}

executable-file.js

module.exports = function yearsInMs(options, loaderContext, content) {
  const { years } = JSON.parse(content);
  const value = years * 365 * 24 * 60 * 60 * 1000;

  return {
    cacheable: true,
    code: 'module.exports = ' + value,
  };
};

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.(json)$/i,
        rules: [
          {
            loader: 'val-loader',
            options: {
              executableFile: path.resolve(
                __dirname,
                'fixtures',
                'executableFile.js'
              ),
            },
          },
        ],
      },
      {
        test: /\.json$/i,
        type: 'asset/resource',
      },
    ],
  },
};

Return Object Properties

Targeted modules of this loader must export a Function that returns an object, or a Promise resolving an object (e.g. async function), containing a code property at a minimum, but can contain any number of additional properties.

code

Type: String|Buffer Default: undefined Required

Code passed along to webpack or the next loader that will replace the module.

sourceMap

Type: Object Default: undefined

A source map passed along to webpack or the next loader.

ast

Type: Array[Object] Default: undefined

An Abstract Syntax Tree that will be passed to the next loader. Useful to speed up the build time if the next loader uses the same AST.

dependencies

Type: Array[String] Default: []

An array of absolute, native paths to file dependencies that should be watched by webpack for changes.

Dependencies can also be added using loaderContext.addDependency(file: string).

contextDependencies

Type: Array[String] Default: []

An array of absolute, native paths to directory dependencies that should be watched by webpack for changes.

Context dependencies can also be added using loaderContext.addContextDependency(directory: string).

buildDependencies

Type: Array[String] Default: []

An array of absolute, native paths to directory dependencies that should be watched by webpack for changes.

Build dependencies can also be added using loaderContext.addBuildDependency(file: string).

cacheable

Type: Boolean Default: false

If true, specifies that the code can be re-used in watch mode if none of the dependencies have changed.

Examples

Simple

In this example the loader is configured to operator on a file name of years-in-ms.js, execute the code, and store the result in the bundle as the result of the execution. This example passes years as an option, which corresponds to the years parameter in the target module exported function:

years-in-ms.js

module.exports = function yearsInMs({ years }) {
  const value = years * 365 * 24 * 60 * 60 * 1000;

  // NOTE: this return value will replace the module in the bundle
  return {
    cacheable: true,
    code: 'module.exports = ' + value,
  };
};

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: require.resolve('src/years-in-ms.js'),
        use: [
          {
            loader: 'val-loader',
            options: {
              years: 10,
            },
          },
        ],
      },
    ],
  },
};

In the bundle, requiring the module then returns:

import tenYearsMs from 'years-in-ms';

console.log(tenYearsMs); // 315360000000

Modernizr

Example shows how to build modernizr.

entry.js

import modenizr from './modernizr.js';

modernizr.js

const modernizr = require('modernizr');

module.exports = function (options) {
  return new Promise(function (resolve) {
    // It is impossible to throw an error because modernizr causes the process.exit(1)
    modernizr.build(options, function (output) {
      resolve({
        cacheable: true,
        code: `var modernizr; var hadGlobal = 'Modernizr' in window; var oldGlobal = window.Modernizr; ${output} modernizr = window.Modernizr; if (hadGlobal) { window.Modernizr = oldGlobal; } else { delete window.Modernizr; } export default modernizr;`,
      });
    });
  });
};

webpack.config.js

const path = require('path');
module.exports = {
  module: {
    rules: [
      {
        test: path.resolve(__dirname, 'src', 'modernizr.js'),
        use: [
          {
            loader: 'val-loader',
            options: {
              minify: false,
              options: ['setClasses'],
              'feature-detects': [
                'test/css/flexbox',
                'test/es6/promises',
                'test/serviceworker',
              ],
            },
          },
        ],
      },
    ],
  },
};

Figlet

Example shows how to build figlet.

entry.js

import { default as figlet } from './figlet.js';

console.log(figlet);

figlet.js

const figlet = require('figlet');

function wrapOutput(output, config) {
  let figletOutput = '';

  if (config.textBefore) {
    figletOutput += encodeURI(`${config.textBefore}\n`);
  }

  output.split('\n').forEach((line) => {
    figletOutput += encodeURI(`${line}\n`);
  });

  if (config.textAfter) {
    figletOutput += encodeURI(`${config.textAfter}\n`);
  }

  return `module.exports = decodeURI("${figletOutput}");`;
}

module.exports = function (options) {
  const defaultConfig = {
    fontOptions: {
      font: 'ANSI Shadow',
      horizontalLayout: 'default',
      kerning: 'default',
      verticalLayout: 'default',
    },
    text: 'FIGLET-LOADER',
    textAfter: null,
    textBefore: null,
  };

  const config = Object.assign({}, defaultConfig, options);

  return new Promise(function (resolve, reject) {
    figlet.text(config.text, config.fontOptions, (error, output) => {
      if (error) {
        return reject(error);
      }

      resolve({
        cacheable: true,
        code: 'module.exports = ' + wrapOutput(output, config),
      });
    });
  });
};

webpack.config.js

const path = require('path');
module.exports = {
  module: {
    rules: [
      {
        test: path.resolve(__dirname, 'src', 'figlet.js'),
        use: [
          {
            loader: 'val-loader',
            options: {
              text: 'FIGLET',
            },
          },
        ],
      },
    ],
  },
};

Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.

CONTRIBUTING

License

MIT

1 位贡献者

webpack