为什么需要loader

目前我们打包过的文件都是js文件,如果我们希望打包一个图片文件呢,或者一个css文件,甚至是一个vue呢。
那么就需要loader

概念

:::info loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。
loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。
本质上,webpack loader 将所有类型的文件,转换为应用程序的依赖图(和最终的 bundle)可以直接引用的模块。
如: jpg, png,svg,excel,txt等静态文件 :::

尝试不用loader直接打包

:::warning 当我们的页面使用了除js以外的文件,而不用loader配置就直接打包 :::

结构
image.png

  1. var Header = require('./header.js')
  2. var Sidebar = require('./sidebar.js')
  3. var Content = require('./content.js')
  4. // 使用了图片
  5. var avatar = require('./avatar.jpg')
  6. // import Header from './header.js'
  7. // import Sidebar from './sidebar.js'
  8. // import Content from './content.js'
  9. new Header();
  10. new Sidebar();
  11. new Content();

报错了
image.png

报错的原因很简单: webpack 自身只理解 JavaScript,他默认是知道如何打包js模块的。 但是他不知道jpg这种文件该如何打包

所以我们就要在某个地方告诉webpack,如何打包他不认识的模块,这个地方就是loader

使用loader

:::success 因为当webpack在模块打包的时候,他需要我们告诉他模块该怎么办。
所以在配置项有个module选项,他有一个rules规则属性,loader就是写在rules里面。 :::

// node.js的文件模块
const path = require('path')
module.exports = {
  mode: 'development',
  entry: {
    main: './src/index.js'
  },
  module: {
    // rules可以多个,所以他是个数组
    rules:[
      {
        test: /\.jpg$/, // 表示以jpg结尾的文件
        use:{
          // 表示我们用的是file-loader对jpg结尾的文件进行打包
          // 使用前要安装file-loader  npm install file-loader -D
          loader: 'file-loader'
        }
      }
    ]
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
}

打包完成
image.png
在dist中打包了一张图片
image.png

打包流程

打包成功了,我们看一下他的打包流程

首先在index.js上打印我们的图片

var Header = require('./header.js')
var Sidebar = require('./sidebar.js')
var Content = require('./content.js')
// 使用了图片
var avatar = require('./avatar.jpg')
console.log(avatar)

// import Header from './header.js'
// import Sidebar from './sidebar.js'
// import Content from './content.js'

new Header();
new Sidebar();
new Content();

我们可以发现他打印出来的名字就是打包出来的图片名,同时还返回了图片的地址。
image.png
image.png
通过刚刚的console,我们可以推断出file-loader的底层逻辑

  1. 当他发现我们的代码中引入了图片或者其他文件的时候,首先会把图片打包移动到dist文件
  2. 然后他会生成一个名字,但是这个名字也可以自定义
  3. 当他把图片移到dist目录之后,他会得到这个图片的名称并且返回到我们引入模块的变量之中。

:::info 基于这里,我们也可以推出webpack的打包流程:
1、当我们运行npm run bundle命令的时候,实际上执行的是package.json中的scripts中的bundle命令,
实际也是运行webpack命令
2、这个时候webpack会去找他的配置文件帮我们做打包。
3、当webpack帮我们做打包的时候,如果遇到了js文件,那么他默认就知道如何处理。
4、当他打包到avatar.jpg的时候,webpack就不知道该怎么办了。
5、然后他就会根据配置文件中的loader去找,当然我们已经告诉他怎么办了。
6、如果碰到以jpg结尾的文件,就去使用file-loader去打包 :::

简单的总结

其实,我们可以把loader理解成是一个打包的方案。 他知道对于某个特定的文件,webpack应如何进行打包,本身webpack不知道如何处理的,但是loader知道。

:::success 那file-loader是什么?
如果我们在打包的过程中,想让某个后缀的文件移动dist目录下,同时获取到文件的地址,都可以使用file-loader处理。我们可以理解成是处理不同文件的工具。
但有些文件不能通过file-loader进行处理。 例如:vue

Vue Loader
.vue文件需要通过 vue-loader进行处理
Vue Loader 是一个 webpack 的 loader :::

附上当前的代码:
删掉之前的一些代码
结构
image.png

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>我是主页面</title>
  </head>
  <body>
    <div id = "root"></div>
    <script src="./bundle.js"></script>
  </body>
</html>
import avatar from './avatar.jpg'

var img = new Image();
// 通过file-loader打包后能直接获取地址
img.src = avatar;

var root = document.getElementById('root');
root.append(img)
// node.js的文件模块
const path = require('path')
module.exports = {
  mode: 'development',
  entry: {
    main: './src/index.js'
  },
  module: {
    // rules可以多个,所以他是个数组
    rules:[
      {
        test: /\.jpg$/, // 表示以jpg结尾的文件
        use:{
          // 表示我们用的是file-loader对jpg结尾的文件进行打包
          // 使用前要安装file-loader  npm install file-loader -D
          loader: 'file-loader'
        }
      }
    ]
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
}

打包后
image.png