webpack中loader原理之概念和执行顺序

一、什么是loader

Webpack中的loader是用于处理一些非JavaScript`文件的代码转换器,例如将ES6/ES7转换成ES5将SCSS/Sass/less转换成CSS。loader可以让webpack支持更多的文件类型,并且也可以通过loader将一些资源打包成JS文件中。

loader是针对module级别的,即针对每个待打包的文件进行转换处理,并最终输出打包后的文件。在webpack.config.js文件中配置loader,可以指定不同的文件类型使用不同的loader进行处理,也可以通过链式调用多个loader完成某种特定的处理。例如:

module: {
    rules: [
        {
            test: /\.scss$/, 
            use: ['style-loader', 'css-loader', 'sass-loader'] //链式调用loader
        },
        {
            test: /\.js$/, 
            exclude: /node_modules/, 
            loader: 'babel-loader' //单一loader
        }
    ]
}

以上代码中,第一个rule用于处理.scss文件,使用了三个不同的loader,分别是style-loader、css-loader和sass-loader链式调用实现了将scss文件转换成浏览器可识别的CSS文件。第二个rule用于处理.js文件,只使用了一个babel-loader将ES6/ES7转换成ES5,这里的exclude选项用于排除node_modules目录下的文件。

二、常见loader

  1. babel-loader: 用于将ES6、ES7等高级语法转换为ES5语法,以便于浏览器兼容。
  2. css-loader: 用于处理CSS文件中的import、url等导入语法。
  3. file-loader: 用于将文件以特定格式打包处理,支持将文件重命名、分离等多种操作。
  4. url-loader: 类似于file-loader, 但将小于指定大小的文件转换为base64格式,以减少请求量。
  5. image-loader: 用于处理图片文件,支持压缩、解析等多种功能。
  6. json-loader: 用于处理JSON格式的文件,支持import导入语法。
  7. xml-loader: 用于处理XML格式的文件。
  8. csv-loader: 用于处理CSV格式的文件。

三、loader分类

Webpack中的loader可以分为两类普通loaderenforce-loader。普通loader是指在webpack配置文件中没有设置enforce属性的loader,而enforce-loader是指在webpack配置文件中设置了enforce属性的loader

普通loader执行的顺序是从右向左,从下往上。也就是说,在webpack配置文件中,最后一次加入的loader会最先执行,然后依次向上执行。

而enforce-loader则有更高的优先级,会先于普通loader执行。enforce属性可设置为pre或post,如果设置为pre,表示在普通loader之前执行;如果设置为post,表示在普通loader之后执行。这样就可以确保enforce-loader在所有loader中优先执行,并且能够准确地对文件进行处理。

常用的enforce-loader有以下几种:

  1. pre-loader:在执行普通loader之前处理文件,常用于代码检查和格式化等操作;

  2. post-loader:在执行普通loader之后处理文件,常用于对文件进行压缩、优化等操作;

  3. noParse-loader:当文件匹配指定规则时,忽略指定文件的递归解析和处理,提升webpack性能;

  4. ignore-loader:忽略指定文件的解析和处理。

四、普通loader执行顺序举例

Webpack中普通loader的执行顺序是从右到左、从下到上的。也就是说,在webpack配置文件中,loader的引入是按照从右到左的顺序进行的,loader的执行顺序是从下到上的。

举个例子,假设我们在webpack的配置文件中使用了以下loader:

module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env']
        }
      }
    },
    {
      test: /\.css$/,
      use: ['style-loader', 'css-loader']
    }
  ]
}

从上面的配置代码可以看出,在解析js文件的时候,使用了babel-loader转换成浏览器兼容的代码,然后在加载css文件的时候,使用style-loader和css-loader进行处理。

从loader的配置顺序来看,先解析js文件的babel-loader要放到后面,即在css-loader和style-loader的前面。另外,由于loader的执行顺序是从下到上的,所以css-loader要放在style-loader的前面,才能正确地将css代码转换为JavaScript代码。

五、enforce-loader应用

在 webpack 中,loader 是用来处理各种类型的文件的工具。而 enforce-loader 是一个特殊的 loader,它可以强制在之前的 loader 执行后、下一个 loader 执行之前执行。

在 webpack 中,loader 的执行顺序是从右到左、从下往上的。也就是说,当一个模块需要被多个 loader 处理时,它的代码会被从下往上、从右往左依次传递给这些 loader。而在这个过程中,每一个 loader 都可以对该模块进行处理。但是,如果使用了 enforce-loader,那么它会被直接放在 loader 的最前面执行。

举个例子,假如我想使用 Babel 对我的 JavaScript 代码进行编译。那么,我需要安装 babel-loader,并在 webpack.config.js 中进行配置:

module: {
  rules: [
    {
      test: /\.js$/,
      loader: 'babel-loader',
    },
  ],
},

这段代码表示,当 webpack 遇到 js 文件时,会使用 babel-loader 进行编译。但是,如果我的代码中有些部分是不需要编译的,比如说我想保持某个模块的代码不变。这时候可以使用 enforce-loader:

module: {
  rules: [
    {
      test: /\.js$/,
      enforce: 'pre', // 注意这里
      loader: 'some-other-loader',
    },
    {
      test: /\.js$/,
      loader: 'babel-loader',
    },
  ],
},

这段代码中,我把 enforce-loader 放在了 babel-loader 的前面。这就意味着,在执行 babel-loader 前,我的代码会被先传递给 enforce-loader。如果 enforce-loader 不对该模块进行处理,那么它会继续向下传递给 babel-loader。反之,如果 enforce-loader 对该模块进行了处理,那么它就会直接把处理后的代码传递给下一个 loader,而不会再让 babel-loader 对其进行处理。这样,我就可以通过 enforce-loader 来控制哪些模块需要编译,哪些模块不需要编译。

你可能感兴趣的:(webpack,webpack,javascript,前端)