对于用惯了脚手架的开发人员来说,编写css样式,引入样式,再npm run serve/dev(以vue使用的脚手架为例),再到浏览器运行和调试代码就和喝水一样自然,根本不需要考虑,对吧?那如果要是告诉你,本来不是这样呢?你可能很奇怪“什么?我一直都是这样用,大家也是这样用,难道脚手架不是一直都可以让我们这样编写吗?”向来如此,便对吗? 我接下来要说的话,可能要让有的人要失望了。我在上一文里面提过,vue/react脚手架都是基于webpack的,但是有一个大部分人都不知道的事实就是,webpack对于除了js/json文件可以进行处理之外,其他后缀名的文件向来不是开箱即用——即使是最简单的css文件。是的,.jsx和.vue也不能用。这样又有疑问了,基于webpack的脚手架可以用,为什么webpack不能用了呢。对此,我要说的是,因为脚手架里面配置好了loader,才让基于webpack的它们,可以处理其他类型的文件。是的,loader,让webpack不再“裸奔”。
什么是loader
什么是loader,官方早已给出了答案。 **“loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块, 以供应用程序使用,以及被添加到依赖图中。”**说白了,加上loader之后,webpack就可以去处理其他类型的文件了,这样一来,webpack的可拓展性就很强了,这也是webapck可玩性体现之一。只要有相关的loader,那么在webpack中就可以对其进行配置然后处理相关文件。
**
缺少loader时的报错信息
在这里,使用css文件来示范没有对css对应的loader进行配置时,进行打包会怎样。
1.在打包入口文件(对入口文件不了解看这个)引入css文件,我这里任意编写了一些css,并且使用esm的方式引入。
import "./assets/index.css"
console.log("first")
复制代码
此时webapck的配置文件
const path = require("path")
module.exports={
entry:{
index:"./src/index.js", //index只需要打包的文件,后面指打包的文件所在位置
},
output:{
path:path.resolve(__dirname,"./build"), //生成的文件夹叫做build文件夹
filename:"bundle.js" //生成的打包之后的js文件名称
}
}
复制代码
2.之后使用打包命令对其进行打包,会发现报错信息如下: 意思很明确,你可能需要一个正确的loader去处理这个文件类型,所以我们需要添加对应的loader对css文件类型进行打包时的处理(这里以css为例),下面就来添加loader对其进行处理
对loader进行配置
1.在webpack.config.js中添加以下内容
const path = require("path")
module.exports={
entry:{
main:"./src/main.js", //index只需要打包的文件,后面指打包的文件所在位置
},
output:{
path:path.resolve(__dirname,"./build"), //生成的文件夹叫做build文件夹
filename:"bundle.js" //生成的打包之后的js文件名称
},
module:{
rules:[
//rules中的每一项都是需要配置并且进行处理的文件类型
]
}
}
复制代码
2.下载css-loader
3.在新建部分里面编写css的正则表达式以及对应需要使用到的loader,test选项代表匹配哪种文件,use表示使用哪种loader去处理这种文件,这里展示的use是简化写法,即不对loader有额外配置的时候使用这个方式引入loader
const path = require("path");
module.exports = {
entry: {
main: "./src/main.js", //index只需要打包的文件,后面指打包的文件所在位置
},
output: {
path: path.resolve(__dirname, "./build"), //生成的文件夹叫做build文件夹
filename: "bundle.js", //生成的打包之后的js文件名称
},
module: {
rules: [
{
test: /\.css$/,
use:['css-loader'],
},
/*
配置loader复杂的写法
use: [
{
loader: 'css-loader',
options: {
//这里写loader的配置对象
},
},
],*/
]
},
};
复制代码
再次运行打包命令,发现打包完成,没报错
4.那么我们在打包输出之后的文件夹内新建index.html文件,引入刚刚打包之后的文件。并且添加一些内容来验证刚刚样式有没有生效
编写的html文件
<!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>Document</title>
</head>
<body>
草新要蹦迪
<script src="./bundle.js"></script>
</body>
</html>
复制代码
编写的css文件
这里将字体转换为红色
*{
color: red;
}
复制代码
打开浏览器发现并没有效果,控制台里面也没有相关样式,这是因为css-loader只是加载 CSS 文件并解析 import 的 CSS 文件,并没有将css样式应用起来,要将css样式应用起来,需要再使用style-loader将模块导出的内容作为样式并添加到 DOM 中。 6.添加style-loader到webpack配置中,注意要将style-loader放在css-loader中,因为loader的执行顺序是从右往左。这里是先解析css文件再将css样式应用到dom节点中
const path = require("path");
module.exports = {
entry: {
main: "./src/main.js", //index只需要打包的文件,后面指打包的文件所在位置
},
output: {
path: path.resolve(__dirname, "./build"), //生成的文件夹叫做build文件夹
filename: "bundle.js", //生成的打包之后的js文件名称
},
module: {
rules: [
{
test: /\.css$/,
use:['style-loader','css-loader'],
},
]
},
};
复制代码
再次执行打包命令并且在浏览器上查看index.html,发现样式应用上去了,但是是加在style标签内,如何让css样式文件分离,后续章节会提到 这样,我们在编写代码的时候就可以像引入js文件一样引入css文件了!请记住,无论是脚手架还是webpack,如果没有配置对应的loader,那就是不能处理对应的文件,之所以脚手架对css文件开箱即用,是因为它们帮你配置好了,配置好,并不是与生俱来。
处理其他类型文件
这里再演示一下对图片资源的处理,webpack 5 中,可以使用内置的 Asset Modules对图片等静态资源处理,因此不需要下载对应的loader 1.首先得要有一张图片显示在网站上,因此需要修改打包入口文件,将图片以js的形式显示,在这将其设置为背景
import "./assets/index.css"
import imgSrc from "./assets/image/珠穆朗玛峰.jpg"
const divEl = document.createElement('div');
divEl.textContent = "Hello"
divEl.classList.add("content") //加上类名
document.body.appendChild(divEl)
// 再添加一个div,其样式使用loader来编写
const title = document.createElement("h2")
title.textContent="title"
document.body.appendChild(title)
title.classList.add("title")
const Img = document.createElement("img")
Img.src = imgSrc
document.body.appendChild(Img)
const divBg = document.createElement("div")
document.body.appendChild(divBg)
divBg.classList.add("imgBg")
复制代码
2.对其进行配置,这时候需要注意type的设置问题,关于type,这有几点需要说明
aseet/resource:生成独立文件,打包之后的图片不会包含在js里面,js代码量减少,会再次请求两次网络请求去请求图片。
asset/inline:不会生成独立文件,打包之后的图片会在js里面,但是少了对图片的网络请求
综合优点: 直接设置asset文件,但是对于不同文件大小进行不同处理但是要对图片的大小进行划分,以达到更好的打包效果 这里主要是对图片资源的打包,其他资源也是大同小异,大家可以去webpack官网查看其他的资源类型,比如字体,svg资源等。
{
//在rules里面添加以下内容
test: /\.(png|gif|jpe?g)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 60 * 1024 //对于超过这个尺寸的图片单独打包成一个文件
//还有其他属性大家可以自行去官网上查看
}
},
generator: { //这里设置生成之后的图片
// 使用占位符来对生成图片名字来重新设置
// name:以前图片的名称
// ext:以前资源的后缀名
// hash:生成的hash值,可选择截取几位
filename: "img/[name][hash:8][ext]" //可以添加前缀来生成新的文件夹
}
},
复制代码
3.查看打包之后的效果,可以发现webpack已经可以处理图片了!如果还需要对其他类型资源文件打包,可以下载其他类型资源相对应的loader,配置方式都是差不多。
总结
没想到吧,webpack只能打包js和json文件,对其它类型的文件从来都不是开箱即用的,当没有配置任何loader的时候,它就是“裸奔”状态,但是这就是webpack强大的原因之一,我们可以让他帮我们做什么,而不是它让我们去做什么,这样webpack的可拓展性大大提升了,如果想搭建jsx或者vue的loader,那简直是手拿把掐,是不是感觉脚手架也没有那么远了呢~