前端与移动开发----webpack----loader

webpack

目标:

  • 能处理css,less文件,解决css的浏览器兼容性配置
  • 能处理图片文件
  • 能处理js降级问题

认识loader的作用

在这里插入图片描述

在webpack看来 一切皆模块,图片,样式文件,js文件… 。 但是webpack默认只能处理js, json模块,对于非js的内容它就需要一些帮手来处理了。这些帮手就是loader

webpack 可以使用 loader 来预处理文件。这允许你打包除 JavaScript 之外的任何静态资源。

如果希望在.html文件中使用style.css样式,我们以前只学习过一种方式:直接在.html中通过link的方式来引入 ,这是传统的做法,在webpack语境下,我们将选择一条不同的道路:在js文件中引入了css。

下面来看一个典型的打包错误: 在入口文件中引用.css文件。

再次,打包代码,会报错。

ERROR in ./src/css/style.css 1:0
Module parse failed: Unexpected character '@' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> @import "public.css";
| div {
|   padding:20px;
 @ ./src/js/main.js 4:0-26

上面报错的原因是:webpack把.css文件内容当作了js代码来运行,那当然会报错了。所以,解决方法是安装相应的loader来处理。

webpack默认只能处理.js文件,它遇到其它类型的文件时,就需要下载相对应的包来帮着处理了。这些帮手就是loader。

处理css文件

我们来具体讨论如何处理.css文件。

基本学习步骤是:

    1. 在源文件(src下的.js)中使用css(直接引入一个css文件)
    1. 打包会出错
    1. 下包css-loader修改配置文件,以解决错误

创建.css文件

在src目录下,再次创建一个css目录及两个css文件,如下:

|-src
|-src/css
|--------public.css
|--------style.css

src/css/public.css的内容如下

body,html{
    
    
  padding:0;
  font-size:14px;
}

src/css/style.css的内容如下

@import "public.css";
div {
    
    
  border:4px solid #ccc;
  width: 50%;
  height: 200px;
  margin:30px auto;
  box-shadow: 3px 3px 3px #ccc;
  background-color: #fff;
  text-align: center;
}

说明:@import语句用来导入另一个css文件。

在.js中导入css

下面,我们修改src/js/main.js,在其中引入css。

import { updateDom } from './tool'

+ import '../css/style.css'
updateDom ('app','index.html')

上面的操作之后,打包会报错。

在这里插入图片描述

安装并使用css-loader

对于所有的loader的使用,其基本步骤是一致的,分成两步:

  1. 安装loader包
  2. 配置webpack.config.js中的module项

安装

npm命令,以开发依赖的方式来安装。

npm i css-loader -D
--------------------
+ [email protected]
added 16 packages from 51 contributors in 14.718s

7 packages are looking for funding

在配置文件中使用

修改webpack.config.js文件,添加module项。module的功能是:为webpack无法识别模块指定帮手

使用modules基本格式是:

module.exports = {
    
    
   // 其它配置 ... 
   module: {
    
    
     // rules: 规则
     rules: [
       {
    
    
         test: 正则, // 用正则匹配后缀名
         use: [loader] // 如果匹配成功,就用use中指定的帮手
       }
     ]
   }
}

下面是具体的配置

const path = require('path')
module.exports = {
  mode: 'development',
  entry:'./src/js/main.js',
  output:{
    path:path.resolve(__dirname, './build'),
    filename:'bundle.js'
  },
+  module:{ // 处理非js模块
+    rules:[ // 规则
+      {
+        test: /\.css$/, 		// 正则测试
+        use: ['css-loader'] 	// loader
+      }
+    ]
+  }
}

再次打包

它不会报错,但是,页面上也并没有出现样式的效果。

检查打包之后得到的目标代码.js文件,发现其包含css代码。但是,它为什么不会显示在页面上呢?

如果我们希望样式生效,最终在.html文件中有两种情况:

  • 有style标签
  • 有link标签

而css-loader只是允许你在.js中通过import来引入.css,如果你希望引入的css代码最终以style标签的方式插入到html页面中,则还需要安装一个loader:style-loader

安装并使用style-loader

安装

npm开发依赖

npm i style-loader -D 
---------------
+ [email protected]
added 4 packages from 6 contributors in 13.086s

8 packages are looking for funding
  run `npm fund` for details

配置

module: {
    
    
  rules: [
    // 每一个对象就是一条规则.
    //  test: 匹配
    //  use: 对匹配到的模块采用对应的loader
    {
    
    
      test: /\.css$/, // 正则匹配 .css文件
      // 匹配成功后(从后向前;从右到左)
      // 1. 先用css-loader去加载.css文件
      // 2. 再用style-loader把样式以style标签的方式嵌入到html中 
      use: ['style-loader', 'css-loader']
    }
  ]
}

注意:在有多个loader的情况下,use数组中的loader执行顺序是从右到左的过程。即:

  • 先用css-loader来处理css
  • 再用style-loader把css代码插入到html中的style标签中。

打包查看效果

index.html

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>index</title>
    <!-- <link rel="stylesheet" href="./css/style.css"> -->
  </head>
  <body>
    <div id="app">
      
    </div>

    <!-- 引入打包之后的js -->
    <script src="../build/main.js"></script>
</body>
</html>

现在就能看到css的效果了 。

在这里插入图片描述

原理是:

  • bundle.js中有一些js代码,它在运行时,会自动在.html文件中追加style标签,并输出样式。

在这里插入图片描述

拓展

你可以分析打包之后代码,来验证style-loader的工作原理。在main.js中,可以找到类似如下的代码:

eval("var api = __webpack_require__(/*! ../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ \"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js

再去node_modules\style-loader\dist\runtime\injectStylesIntoStyleTag.js 找下insertStyleElement这个方法,你就可以发现这个过程。

loader使用小结

loader是webpack非常重要的概念

  • 在webpack看来,一切皆模块: 每一个文件都是一个模块。

  • webpack默认只能处理json和js模块,对于其它的模块它需要对应的loader来处理

  • loader的基本使用是:

    • 安装Loader (npm 包)
    • 配置module中的rules:用loader来处理对应类型的文件

处理less文件

目标:在项目中支持使用less来写css代码。

改进案例

创建less文件

在src目录的css目录下创建 index.less,则内容如下:

@import "style.css";

body{
    
    
  div {
    
    
    padding:50px;
  }
}

在.js中引用.less

在src/js/main.js文件中引入less

// nodejs中的模块化
const { updateDom } = require('./tool')

- import '../css/style.css'
+ import '../css/index.less'
updateDom ('app','index.html')

安装并配置loader包

less less-loader

参考官网

npm i less-loader less -D
-------------------------
+ [email protected]
+ [email protected]
added 50 packages from 123 contributors in 23.883s
  • less 用来把less–>css
  • less-loader用来加载less文件。

配置模块

在rules中添加一个配置,专门针对less文件。

module: {
    
    
  // 规则
  rules: [
    // ...
    {
    
    
      test: /\.less$/,  // 如果这个模块以less结尾
      // 如果在打包的过程遇到了.less,则:从右向左
      // 1. 先用less-loader 读出内容,转成css
      // 2. 用css-loader 读出内容
      // 3. style-loader把读出的内容以style标签的格式
      // 附加在.html文件上
      use: ['style-loader','css-loader', 'less-loader'] // 设置要处理的loader
    }
  ]
}

注意:如上配置中,对于less文件的处理涉及三个loader,其处理顺序是从右到左:less-loader --> css-loader–>style-loader。

  • less-loader:用来加载less文件,并处理成css
  • css-loader:用来加载css文件
  • style-loader:用来将css代码以style标签的格式插入到html文件中

自动添加css样式前缀

问题

大家是否遇到过浏览器兼容的问题?又是怎么处理的?更具体一点:display: flex有兼容性问题吗?

学习postcss-loader之后,就可以自动帮我们来处理这个问题。

tip: caniuse 这个网站可以查看兼容性问题,点击 这里查看flex的兼容性。

步骤

  1. 安装依赖

  2. 在modules中补充设置postcss-loader

  3. 单独设置postcss的autoprefixer插件

安装依赖

npm i postcss postcss-loader autoprefixer -D

补充设置postcss-loader

{
        test: /\.less$/,
        // 匹配成功后(从后向前;从右到左)
        // 1. 先用less-loader去加载.less文件,转成css
        // 2. 用postcss-loader配合autoprofixer加浏览器前缀
        // 3. 先用css-loader去加载css文件
        // 4. 再用style-loader把样式以style标签的方式嵌入到html中 
        use:['style-loader', 'css-loader', 'postcss-loader',  'less-loader']
      }

单独设置 postcss.config.js

const autoprefixer = require('autoprefixer')
module.exports = {
  plugins:[
    autoprefixer({
      // last 2 versions : 浏览器最近的2版本
      // >1% 全球市场占有率在1%以上的浏览器
      overrideBrowserslist: ['last 2 versions', '> 1%']
    })
  ]
}

默认是兼容所有最新版本。

通过npx browserslist命令可以查看当前支持的浏览器的列表

下面是overrideBrowserslist中可以设置的结果

例子 说明
> 1% 全球超过1%人使用的浏览器
> 5% in US 指定国家使用率覆盖
last 2 versions 所有浏览器兼容到最后两个版本根据CanIUse.com追踪的版本
Firefox ESR 火狐最新版本
Firefox > 20 指定浏览器的版本范围
not ie <=8 方向排除部分版本
Firefox 12.1 指定浏览器的兼容到指定版本
unreleased versions 所有浏览器的beta测试版本
unreleased Chrome versions 指定浏览器的测试版本
since 2013 2013年之后发布的所有版本

特别地:对于要支持的浏览器的设置,也可以写在package.json中独立设置browserslist项,同时删除overrideBrowserslist的设置。

{
  // ......
  "browserslist": "ie 10"
}

如果只支持ie 10 ,则flex只会加-ms-前缀

file-loader-处理图片文件

目标:支持在css中引入图片文件

思路:

  • 引入准备好图片
  • webpack打包报错
  • 引入file-loader解决这个报错

在css中引入图片

提前准备图片

src下新增目录:img,并在其下放置两张图片:一张图片大一些,一张图片小一些(可以自己找图片)。

  • webpack.png: 49.4kb
  • webpack.svg: 3kb

在css中引入图片

在style.css中引入图片,作为div标签的background。

@import "public.css";
div {
  border:4px solid #ccc;
  width: 50%;
  height: 200px;
  margin:30px auto;
  box-shadow: 3px 3px 3px #ccc;
  background-color:pink;
  text-align: center;
+  background-image: url('../img/webpack.png')
}
body {
+  background-image: url('../img/webpack.svg')
}

打包,会报错

报错的原因是.svg, .png格式的文件webpack并不能直接处理。

解决错误

安装包:npm i - D file-loader

添加rules

{
    
    
  test: /\.(png|svg|jpg)$/, //
  use: ['file-loader']
}

这样只是简单的拷贝功能。

补充设置路径

use: {
    
    
  loader: 'file-loader',
  options: {
    
    
    outputPath: './img' // 它会在出口文件夹下创建一个img文件夹来保存图片
  }
}

要注意:此时打包得到的图片的路径可能有问题,需要你把src下的index.html手动复制一份到目标文件夹,才能正确看到图片。(后面会改成自动去复制)

文件指纹

用作版本管理时,如果一个项目需要发布,只需要发布修改过的文件指纹;对于没有修改过的文件,用户在访问的时候,依旧可以使用浏览器缓存好的,无需二次加载,加速页面访问。

生成文件指纹的占位符

占位符名称 定义
[ext] 资源后缀名
[name] 文件名称
[path] 文件的相对路径
[folder] 文件所在的文件夹
[contenthash] 根据文件内容来定义hash,文件内容不变,则contenthash不变文,默认是md5生成
[hash] 和整个项目的构建相关,只要项目文件有修改,整个项目构建的hash值就会随之更改,默认是md5生成
[Chunkhash] webpack打包的chunk有关,不同的entry会生成不同的chunkhash

示例:

use: {
  loader: 'file-loader',
  options: {
  	name: '[name]_[hash:8].[ext]',
    outputPath: './img' // 它会在出口文件夹下创建一个msg文件夹来保存图片
  }
}

url-loader处理图片

参考链接:npm官网

问题:如果在你的项目中,出现多次引入很小图片的情况,会有什么后果?要如何解决?

答:会请求多次,加载速度会慢;

解决方案:

  • 精灵图(把很多小图合在一个大图);
  • 字体图标(是用字体来表示图片);
  • 把小图片直接以base64的编码引入

目标:在项目中支持对图片的处理:如果足够小就直接生成对应的base64编码值,否则就直接拷贝到指定位置。

下面,补充一个安装url-loader,并修改配置

npm i url-loader -D

修改后的配置如下:

      {
    
    
        test: /\.(png|svg|jpg)$/, // jpg
        use: {
    
    
          loader: 'url-loader',
          // url-loader是增强版的file-loader
          // 如果图片小于指定的大小,则会转成base64,否则就调用file-loader进行拷贝
          options: {
    
    
            limit: 3*1024, // 如果图片小于3k就转成base64,否则就直接拷贝
            name: '[name].[ext]',
            outputPath: './img' // 它会在出口文件夹下创建一个msg文件夹来保存图片
          }
        }
      }

打包成功后,观察webpack对两张图片的不同处理。

使用babel-loader处理js降级问题

导入

在写js代码时,如果用到了一些比较高级的特性(箭头函数,函数默认参数等)时,可能会存在兼容性问题 ----- 低版本的浏览器(或者是ie系列)不支持,所以需要做降级处理

能够把es6高级内容变为es5的loader名称为 babel-loader

es6/es7/es8等等高级标准有很多(let、箭头函数、对象解构赋值、…展开运算符、字符串模板等等),每个标准都需要一个独立的plugin进行降级处理,如果使用许多高级标准内容,那么势必要为此安装许多plugin,这样工作比较繁琐,系统已经考虑到这点了,其通过preset把许多常用的plugin给做了集合,因此一般性的使用只需要安装preset即可搞定(如果项目应用到了一个生僻的高级标准内容,preset处理不来,就还需要再安装对应的plugin处理)

npm官网: babel-loader

babel官网:https://www.babeljs.cn/setup#installation

步骤:

  1. 安装依赖包

    npm i babel-loader @babel/core @babel/preset-env -D
    
  2. 在tool.js中修改一下函数,使用箭头函数和默认参数值

    const updateDom = (id, content="函数的默认值") =>{
      document.getElementById(id).innerHTML =  content
    }
    
  3. 在webpack.config.js中做如下配置:

    {
          
          
        test: /\.js$/,
        exclude: /node_modules/,  // 排除目录,通知webpack不要管这个目录下的js
        use: [
            {
          
          
                loader:'babel-loader',
                options: {
          
          
                  presets: ['@babel/preset-env']
                }
             }
        ]
        // es6转es5
    }
    

    说明: @babel/preset-env用来指定按什么样的预设来进行降级处理

  4. 打包测试

    打包之后,去打包后的文件中检查是否已经把const和箭头函数这种es6的代码转成了es5的代码。

在这里插入图片描述

小结

  • 一切皆模块,非js模块有对应的loader来处理
  • loader使用的基本步骤
    • 第一步:安装包
    • 第二步:配置rules

如有不足,请多指教,
未完待续,持续更新!
大家一起进步!

猜你喜欢

转载自blog.csdn.net/qq_40440961/article/details/112953131