Webpack入门,预处理器

一个Web工程通常会包含HTML、JS、CSS、图片、字体等多种类型的静态资源,且这些资源之间都存在着某种联系。对于Webpack来说,所有这些静态资源都是模块,开发者可以像加载一个JS文件一样去加载它们。比如在index.js中加载style.css。

// index.js
import "./style.css"

提示

对于初学者,可能会有这样的疑问:从JS中加载CSS文件具有怎样的意义呢?从结果来看,其实和之前并没有什么差别,这个style.css可以被打包并生成在输出资源目录下,对index.js文件也不会产生实质性的影响。这句引用的实际意义是描述了JS文件与CSS文件之间的依赖关系。

loader概述

loader是Webpack中的一个核心概念,可以理解为一个代码转换的工具。每个loader本质上都是一个函数,可以表示为以下形式:out = loader(input)这里的input可能是工程源文件的字符串,也可能是上一个loader转化后的结果,output则包括了转化后的代码、sourcemap和AST对象。如果这是最后一个loader,结果将直接被送到Webpack进行后续处理,否则将作为下一个loader的输入向后传递。loader可以是链式的,开发者可以对一种资源设置多个loader,第一个loader的输入是文件源码,之后所有loader的输入都为上一个loader的输出。用公式表达则为:output = loaderA(loaderB(loaderC(input)))

在Webpack中,本身只认识Javascript,对于其他类型的资源,开发者必须先定义一个或多个loader对其进行转译,输出为Webpack能够接收的形式再继续进行,因此loader做的实际上是一个预处理的工作。

loader的引入

// app.js
import "./style.css"
// style.css
body {
  text-align: center;
  padding: 100px;
  color: #fff;
  background-color: #09c;
}

此时工程中还没有任何loader,如果直接打包会看到报错提示。这是因为Webpack无法处理CSS语法。

如果想让Webpack能够处理CSS语法,需要在工程中引入css-loader。

提示

loader都是一些第三方npm模块,因此使用loader的第一步就是先从npm安装它。

在工程目录下安装css-loader。

npm install css-loader -D

接下来将loader引入工程中,具体配置如下

// webpack.config.js
module.exports = {
  // ...
  module: {
    rules: [{
      test: /\.css$/,
      use: ['css-loader'],
    }]
  }
}

与loader相关的配置都在module对象中,其中module.rule代表了模块的处理规则。每条队则内部可以包含很多配置项,这里我们只使用了最重要的两项:test和use。

  • test可接收一个正则表达式或者一个元素为正则表达式的数组,只有正则匹配上的模块才会使用这条规则。
  • use可接收一个数组,数组包含该规则所使用的loader。在只有一个loader时可以将其简化为字符串“css-loader”。

此时再进行打包,就不会出现报错的情况了。但是CSS的样式没有在页面上生效。这是因为css-loader的作用仅仅是处理CSS的各种加载语法(@import和url()函数等),如果要使样式起作用需要style-loader来把样式插入页面。css-loader与style-loader通常是配合在一起使用的。

提示

Webpack在打包时是按照数组从后往前的顺序将资源交给loader处理的。所以在使用多个loader时,要把最后生效的放在前面。例如在使用style-loader和css-loader时,要把style-loader加到css-loader前面。

loader更多配置

exclude与include

exclude与include用于排除或包含指定目录下的模块,可接收正则表达式或者字符串(文件绝对路径),或者由它们组成的数组。

// webpack.config.js
module.exports = {
  ...
  module: {
    rules:[{
      test: /\.css$/,
      use: ['style-loader','css-loader'],
      exclude: /node_modules/,
    }]
  }
}

上面exclude的含义是,所有被正则匹配到的模块都排除在该规则之外,也就是说,node_modules中的模块不会执行这条规则。该配置项通常是必加的,否则将拖慢整体的打包速度。

与exclude相反,include的含义是只对正则匹配到的模块生效。

温馨提示

当exclude和include同时存在时,exclude的优先级更高。

resource与issuer

resource与issuer用于更加精准地确定模块规则的作用范围。 resource指的是被加载模块,issuer指的是加载者。

请看下面的例子

// index.js
import "./style.css"

在示例中,被加载模块(resource)是style.css,加载者(issuer)是index.js。

test、exclude、include本质上均属于对resource也就是被加载者的配置,如果想要对issuer加载者也增加条件限制,则要额外写一些配置。比如,只想让/src/pages目录下的JS可以引用CSS。

// webpack.config.js
module.exports = {
  ...
  module: {
    rules: [{
     test: /\.css$/,
     use: ['style-loader','style-loader'],
     exclude: /node_modules/,
     issuer: {
       test: /\.js$/,
       include: /src/pages/,
     },
    }]
  }
}

可以看到,添加了issuer配置对象,其形式与之前对resource条件的配置并无太大差异,但只有/src/pages/目录下面的JS文件引用CSS文件,这条规则才会生效。

上面的配置虽然实现了的需求,但是test、exclude、include这些配置项分布于不同的层级上,可读性较差。事实上还可以将它改为另一种等价的形式。

// webpack.config.js
module.exports = {
  ...
  module: {
    rules: [{
      use: ['style-loader','css-loader'],
      resource: {
        test: /\.css$/,
        exclude: /node_modules/,
      },
      issuer: {
        test: /\.js$/,
        exclude: /node_modules/,
      }
    }]
  }
}

上面的配置,分别包裹了resource和issuer中的规则,这样就一目了然了。

enforce

enforce用来指定一个loader的种类,只接收pre或post两种字符串类型的值。

Webpack中的loader按照执行顺序可分为pre、inline、normal、post四种类型。上面的示例中直接定义的loader都属于normal类型,inline形式官方已经不推荐使用,而pre和post则需要使用enforce来指定。

// webpack.config.js
module.exports = {
  ...
  module: {
    rules: [{
      test: /\.js$/,
      enforce: 'pre',
      use: 'eslint-loader',
    }]
  }
}

在上面的配置中,添加了一个eslint-loader来对源码进行质量检测,其enforce的值为pre。表示它将在所有正常loader之前执行,这样可以保证其检测的代码不是被其他loader更改过的。类似地,如果某一个loader需要在所有loader之后执行,可以指定其enforce为post。

温馨提示

事实上,开发者可以不使用enforce而只要保证loader顺序是正确的即可。配置enforce的主要目的是使模块规则更加清晰,可读性更强。在实际工程中,配置文件可能会出现达到上百行的情况,此时开发者很难保证各个loader都按照预想的方式工作,而使用enforce可以强制指定loader的作用顺序。

示例代码仓库

https://gitee.com/zero_79152105/webpack-vblog

原创文章,作者:ZERO,如若转载,请注明出处:https://www.edu24.cn/course/webpack-loader.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
ZEROZERO
上一篇 2022年11月18日
下一篇 2022年11月23日

相关推荐

  • JavaScript 事件委托详解

    基本概念 事件委托,通俗地来讲,就是把一个元素响应事件(click、keydown……)的函数委托到另一个元素; 一般来讲,会把一个或者一组元素的事件委托到…

    2021年3月8日
    1.2K
  • MySQL数据库入门之单表数据记录查询

    简单数据查询 语法形式如下: 在上述语句中,参数fieldn表示所要查询的字段名字,参数table_name表示所要查询数据记录的表名。 当需要查询表中所有字段时,可使用&#822…

    2020年7月15日
    1.5K
  • JavaScript基础知识八问

    JavaScript是前端开发中非常重要的一门语言,浏览器是他主要运行的地方。JavaScript是一个非常有意思的语言,但是他有很多一些概念,大家经常都会忽略。比如说,原型,闭包…

    2020年12月30日
    1.0K
  • 创建JavaScript对象的六种方式

    第一种:Object 构造函数创建 这行代码创建了 Object 引用类型的一个新实例,然后把实例保存在变量 Person 中。 第二种:使用对象字面量表示法 对象字面量是对象定义…

    2020年6月24日
    1.3K
  • js数组去重(区分object、“NaN”、NaN)

    数组去重在前端面试中比较常见,今天来复习复习。 对这样一个数组进行去重,我尝试了几种方法,大多数不能对对象去重,或者不能区分true和”true”、NaN和…

    2021年2月23日
    1.3K
  • JAVA学习之多线程知识点整理

    1、什么是进程?什么是线程? 进程是一个应用程序。线程是一个进程中的执行场景或者执行单元。一个进程可以启动多个线程。进程之间内存独立不共享。同一个进程中的线程之间,堆内存和方法区内…

    2020年6月19日
    1.3K
  • CSS让内容居中的方法总结

    内容水平居中  分行内元素与块级元素两种情况;其中块级元素又分定宽与不定宽两种情况; 行内元素 首先看它的父元素是不是块级元素,如果是,则直接给父元素设置 te…

    2019年6月28日
    3.4K
  • CSS多列等高布局

    在项目开发中,经常遇到需要多列等高布局的需求。解决这种的需求的方法有很多,各有利弊,现总结如下。 方法一:使用flex布局 优点:实现方便,还可以方便实现各种比例 ; 缺点: IE…

    2019年6月11日
    2.2K
  • flex布局详解

    往往在移动端开发过程中,弹性布局是非常实用的一种手段。往往你并不需要去反复的使用媒体查询的。整整的响应式布局是使界面能够自动的根据屏幕进行变化,做到完美的弹性布局,在必要的时候,去…

    2018年9月10日
    2.3K
  • Spring Boot的常用注解

    未来的框架趋势是“约定大于配置”,代码的封装会更加严密。开发人员会将更多的精力放在代码的整体优化和业务逻辑上,所以注解式编程会被更加广泛地使用。那么什么是注解?Spring Boo…

    2024年8月29日
    424