返回介绍

四、配置 loader

发布于 2024-09-07 12:24:19 字数 6183 浏览 0 评论 0 收藏 0

4.1 loader 匹配规则

当我们需要配置 loader 时,都是在 module.rules 中添加新的配置项,在该字段中,每一项被视为一条匹配使用 loader 的规则

module.exports = {
  // ...
  module: {
    rules: [ 
      {
        test: /\.jsx?/, // 条件
        include: [ 
          path.resolve(__dirname, 'src'),
        ], // 条件
        use: 'babel-loader', // 规则应用结果
      }, // 一个 object 即一条规则
      // ...
    ],
  },
}...

loader 的匹配规则中有两个最关键的因素:一个是匹配条件,一个是匹配规则后的应用

4.2 规则条件配置

大多数情况下,配置 loader 的匹配条件时,只要使用 test 字段就好了,很多时候都只需要匹配文件后缀名来决定使用什么 loader ,但也不排除在某些特殊场景下,我们需要配置比较复杂的匹配条件。webpack 的规则提供了多种配置形式…

  • { test: ... } 匹配特定条件
  • { include: ... } 匹配特定路径
  • { exclude: ... } 排除特定路径
  • { and: [...] } 必须匹配数组中所有条件
  • { or: [...] } 匹配数组中任意一个条件
  • { not: [...] } 排除匹配数组中所有条件…

上述的所谓条件的值可以是:

  • 字符串:必须以提供的字符串开始,所以是字符串的话,这里我们需要提供绝对路径
  • 正则表达式:调用正则的 test 方法来判断匹配
  • 函数: (path) => boolean ,返回 true 表示匹配
  • 数组:至少包含一个条件的数组
  • 对象:匹配所有属性值的条件…
rules: [
  {
    test: /\.jsx?/, // 正则
    include: [
      path.resolve(__dirname, 'src'), // 字符串,注意是绝对路径
    ], // 数组
    // ...
  },
  {
    test: {
      js: /\.js/,
      jsx: /\.jsx/,
    }, // 对象,不建议使用
    not: [
      (value) => { /* ... */ return true; }, // 函数,通常需要高度自定义时才会使用
    ],
  },
],...

4.3 使用 loader 配置

module.rules 的匹配规则最重要的还是用于配置 loader ,我们可以使用 use 字段

rules: [
  {
    test: /\.less/,
    use: [
      'style-loader', // 直接使用字符串表示 loader
      {
        loader: 'css-loader',
        options: {
          importLoaders: 1
        },
      }, // 用对象表示 loader,可以传递 loader 配置等
      {
        loader: 'less-loader',
        options: {
          noIeCompat: true
        }, // 传递 loader 配置
      },
    ],
  },
],...

use 字段可以是一个数组,也可以是一个字符串或者表示 loader 的对象。如果只需要一个 loader ,也可以这样: use: { loader: 'babel-loader' , options: { ... } }

4.4 loader 应用顺序

  • 对于上面的 less 规则配置,一个 style.less 文件会途径 less-loadercss-loaderstyle-loader 处理,成为一个可以打包的模块。
  • loader 的应用顺序在配置多个 loader 一起工作时很重要,通常会使用在 CSS 配置上,除了 style-loadercss-loader ,你可能还要配置 less-loader 然后再加个 postcssautoprefixer 等。
  • 上述从后到前的顺序是在同一个 rule 中进行的,那如果多个 rule 匹配了同一个模块文件, loader 的应用顺序又是怎样的呢?看一份这样的配置…
rules: [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: "eslint-loader",
  },
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: "babel-loader",
  },
],...

这样无法法保证 eslint-loaderbabel-loader 应用前执行。 webpack 在 r ules 中提供了一个 enforce 的字段来配置当前 ruleloader 类型,没配置的话是普通类型,我们可以配置 prepost ,分别对应前置类型或后置类型的 loader

  • 所有的 loader 按照前置 -> 内 -> 普通 -> 后置 的顺序执行。所以当我们要确保 eslint-loaderbabel-loader 之前执行时,可以如下添加 enforce 配置
rules: [
  {
    enforce: 'pre', // 指定为前置类型
    test: /\.js$/,
    exclude: /node_modules/,
    loader: "eslint-loader",
  },
]...

当项目文件类型和应用的 loader 不是特别复杂的时候,通常建议把要应用的同一类型 loader 都写在同一个匹配规则中,这样更好维护和控制

4.5 完整代码

const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
  entry: './src/index',

  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js',
  },

  module: {
    rules: [
      {
        enforce: 'pre', // 指定为前置类型
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: "eslint-loader",
      },
      {
        test: /\.jsx?$/,
        include: [
          path.resolve(__dirname, 'src'),
        ],
        use: 'babel-loader',
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            'css-loader',
          ],
        }),
      },
      {
        test: /\.less$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            'css-loader',
            'less-loader',
          ],
        }),
      },
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader'
          },
        ],
      },
    ],
  },

  resolve: {
    alias: {
      utils: path.resolve(__dirname, 'src/utils'), // 这里使用 path.resolve 和 __dirname 来获取绝对路径
      log$: path.resolve(__dirname, 'src/utils/log.js') // 只匹配 log
    },
    extensions: ['.js', '.json', '.jsx', '.css', '.less'],
    modules: [
      path.resolve(__dirname, 'node_modules'), // 指定当前目录下的 node_modules 优先查找
    ],
  },

  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', // 配置输出文件名和路径
      template: 'src/index.html', // 配置文件模板
    }),
    new ExtractTextPlugin('[name].css'),
    new webpack.DefinePlugin({
      TWO: '1+1',
      CONSTANTS: {
        APP_VERSION: JSON.stringify('1.1.2'), // const CONSTANTS = { APP_VERSION: '1.1.2' }
      },
    }),
    new CopyWebpackPlugin([
      { from: 'src/assets/favicon.ico', to: 'favicon.ico', }, // 顾名思义,from 配置来源,to 配置目标路径
    ]),
    new webpack.ProvidePlugin({
      _: 'lodash',
    }),
  ],

  devServer: {
    port: '1234',
    before(app){
      app.get('/api/test.json', function(req, res) { // 当访问 /some/path 路径时,返回自定义的 json 数据
        res.json({ code: 200, message: 'hello world' })
      })
    }
  },
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文