一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
前言
大家好,我是小阵 🔥,一路奔波不停的码字业务员
身为一个前端小菜鸟,总是有一个飞高飞远的梦想,因此,每点小成长,我都想要让它变得更有意义,为了自己,也为了更多值得的人
如果喜欢我的文章,可以关注 ➕ 点赞,与我一同成长吧~😋
加我微信:zzz886885,邀你进群,一起学习交流,摸鱼学习两不误🌟
正文
作为越来越内卷的FE圈中的一员,仿佛你不懂webpack
就跟不懂前端一样??
本着不卷没饭吃的心态,我重温了webpack5
的文档,决定第N
遍手撸一下webpack的基本配置。
来,大家左脚跟右脚一步步跟着迈!(千万不要扯着???🤐)
基本概念
- webpack是一个静态资源模块化打包工具
- 静态资源指
css|js|imgs(jpg|png|gif|webp...)|medio(fonts|mp4|mp3...)
- 模块化指webpack会将每个入口引入的资源作为单独的模块进行打包
- 打包指将我们本地开发环境的各种资源通过webpack的各种loader处理转换成浏览器可识别的资源,当然绝大部分我们还需要很多webpack的plugin参与进来
- 静态资源指
- webpack总体分为四个模块
- entry
- 打包的入口文件,可以单入口,也可以多入口。一切在入口文件中引入的资源都会被webpack打包
- output
- webpack打包之后输出的文件目录,可以单目录也可以多目录
- module
- 主要是用来配置各种
loader
,loader
是webpack的翻译官,负责将webpack不认识的资源转化成webpack认识的资源(webpack只认识js和json,可想而知loader们有多么重要)
- 主要是用来配置各种
- plugins
- 用于拓展webpack打包过程中的其他功能,比如
集成
,压缩
,优化
等
- 用于拓展webpack打包过程中的其他功能,比如
- entry
综上,我们得知了webpack其实就是一个大的node包,这个node包做了什么事情呢? 他将我们在开发过程中引入的各种小包(包括我们自己的工具包、资源包,也包括我们又引入的其他node包)通过构建编译成一个浏览器可以正常识别的资源包
注意⚠️📢:以上的概念都是我经过了自己的理解简单描述的,具体概念细节还请参考别的文章(后续我尽量补上各个概念的具体描述文章链接)
开撸
开开心心学技术大法~~
来了来了,他真的来了~
webpack初体验
首先我们需要准备一下webpack的基本环境,毕竟要用到webpack的command
指令,因此,我们需要「全局安装」 webpack
和webpack-cli
当然,如果你讨厌这种做法,也可以安装到本项目目录,然后通过
package.json
中的script
模块定制你的快捷访问方式,这个后续再说。 也可以使用npx
访问项目内部的包(比如:webpack)
全局安装webpack
和webpack-cli
# 因为这里直接演示webpack5,所以就不指定版本了
npm i webpack webpack-cli -g
当然,你也可以用
pnpm
,cnpm
,或者某tnpm
?😄
之后你需要指定一个webpack的入口文件,我这里在项目根目录下创建了src/index.js
。
随意写上一些代码
// src/index.js 作为webpack的入口文件
function add(x, y){
return x + y;
};
console.log('add:', add(1, 2));
然后终端试执行
webpack ./src/index.js -o ./build/built.js --mode=development
你会发现,在根目录下,生成了一个build
目录,该目录下还有一个built.js
文件,那这个build/built.js
文件其实就是webpack
从入口文件./src/index.js
开始打包,之后输出到./build/built.js
文件。
本次打包的模式是development
,该模式是不压缩的,如果是production
,则默认压缩。
如果感兴趣的话,可以点进./build/built.js
文件看一下,看一下到底生成了个什么玩意儿?😄
css资源引入
接下来我们搞一下其他资源进来试下,比如css
。
注意:前面提到了,webpack默认只认识
js
和json
文件,并不认识其他资源文件,那遇到webpack不认识的资源怎么办?那就需要用loader
处理这些资源,将他们变成webpack认识的js模块
因为要配置loader
,单一的命令行已经不支持我们做更多更复杂的配置了,这个时候就需要一个webpack的配置文件webpack.config.js
,该文件要放在项目的根目录。
我们来写一下webpack.config.js
。
// webpack.config.js webpack的配置文件
const { resolve } = require('path');
module.exports = {
//入口文件配置
entry: './src/index.js',
//输出目录配置
output: {
//输出文件名
filename: 'built.js',
//输出文件目录,最终输出结果会是 目录名 + 文件名
path: resolve(__dirname, 'build') // __dirname是node内置变量,指改文件所在目录,是一个绝对路径,resolve将__dirname和'build'拼接成一个你要输出的绝对目录地址
},
// 模块
module: {
rules: [
{
// 代表匹配以.css结尾的文件
test: /\.css$/,
// use代表需要用到多个loader,而loader的加载顺序是从右到左的,注意:是从右到左,所以这里的顺序是先引入css-loader,再引入style-loader
// 说了引入顺序的问题,这里再说下两个loader的作用
// css-loader:将css代码文件中的内容以字符串的形式打包到js文件中,如果看打包后的js的话,会发现css代码是这样被引入的 eval(xxxx),其中xxx就是css样式
// style-loader:将css字符串从js中抽离到html中,以style标签的形式内嵌到html的head标签中
use: ['style-loader', 'css-loader']
}
]
},
// 插件
plugins: [],
// 打包模式,这里是development,默认不压缩打包后的资源,后续会有production模式的演示
mode: 'development'
}
为了书写方便,也为了大家看着方便,之后只会贴上关键代码
我们从上到下来分析,首先为什么引入包要用require
,因为webpack本质也是一个node包,而node需要遵循commonJs
的模块化标准,所以要用require
。
Q:那为什么我业务开发中用esModule
的import
和require
都可以呢?
A:因为那是webpack帮你处理过了呀😄
你的代码有webpack帮忙处理,而webpack的代码谁来处理?
当然是node
了,那就必须遵循node
的模块化标准嘛~~哎,闭环了,舒服。
想必代码中的注释已经解决了你大部分疑惑了,那关于loader
那部分内容我拿到这里来再提一嘴(要你多嘴🤐笑哭。。)。
首先rules
是一个数组,内部可以包含多个loader
每个loader
都可以有自己的options
,当然,你也可以使用它的默认配置,就比如上面的写法['style-loader','css-loader']
。
如果要定义某个loader的options的话,需要将该loader写成对象的形式,将loader的配置写到options中,我这里以css-loader
举例,代码如下
module:{
rules:[
{
test: /\.css$/,
loader:'css-loader',
options:{
...xxx
}
}
]
}
配置文件我们搞好了,那我们试着用webpack打包下看看吧, 终端运行
# 目录是项目根目录,跟webpack.config.js同目录
# 此时webpack默认去找webpack.config.js作为配置文件
webpack
如果不是同目录或者要运行其他目录下的配置文件,可以用
--config xxx.js
来指定
这个时候我们看终端打包是成功的,没有报错,那怎样看具体是否ok了呢?
好吧,我需要手动在./src
目录下建一个index.html
文件,然后手动引入一下打包好的../build/built.js
文件(也就是上面我们ouput输出的文件),
页面看效果,ok的,没问题
那么我问题来了,我手动创建index.html文件有点low,那我能否允许自己逼格高一点呢?
打包html资源
你可以的,只需要借助webpack的plugins
即可,什么plugin呢?html-webpack-plugin
好,既然用到了,那我们就安装下
npm i -D html-webpack-plugin
接下来上配置代码,该插件的用法也会在代码注释上
// 首先需要通过commonjs的模块化引入插件
// 注意命名要用大驼峰
const HtmlWebpackPlugin = require('html-webpack-plugin')
export.modules = {
...
// 插件
plugins:[
// 实例化html-webpack-plugin,并做下配置
// 自动将webpack打包好的资源引入到模板html中,如果不指定template,会自动生成一个html文件
new HtmlWebpackPlugin({
// 指定以哪一个html作为模板导入打包好的js或其他资源
template:'./src/index.html'
})
],
...
}
搞好插件之后,我们继续webpack一下,发现这个时候哪怕我们不手动在html文件中引入../build/built.js
文件依然是可行的
打包图片资源
继续!
css
搞好了,那我们搞下image
通过上面的一串操作,我想大家已经都了解了怎样写loader了,需要注意的是,解析image只需要用到一个loader,那就是url-loader
,但是因为url-loader
是file-loader
的子集,因此我们需要下载两个包
npm i -D url-loader file-loader
之后需要在webpack.config.js中稍微做下配置,那就废话不多说,直接上代码,解释照例会标注到代码上
...
module.exports = {
...
// 模块
module: {
rules: [
...
{
// 匹配以png、jpg和gif结尾的图片资源
test:/\.(png|jpg|gif)$/,
loader:'url-loader',
options:{
// 图片大小小于8kb的时候会被base64处理
// 优点:减少请求数量(减轻服务器压力,让服务器优先处理其他自资源请求)
// 缺点:图片体积更大(相应的,打包之后体积也会稍大,base64会存到最终的包中)
limit: 8 * 1024,
// 给图片重命名
// hash:10 :因为打包后的图片资源名称默认是一长串hash值,那我们这里取hash值的前十位就可以了,毕竟也不需要那么长的名字,还会加大包大小(蝇子腿再小,那也是肉呀)
// ext:是文件的后缀名,打包前是png,打包后就依然是png,jpg和gif同理
name: '[hash:10].[ext]'
}
}
]
},
...
}
这个时候我们在之前的css文件中引入一张图片,假设引入的是./react.png
,这个时候打包是没问题的,我们打开网页源代码看到的img
标签也是没问题的。
那么问题来了,image
不可能只在css中使用吧,如果我在html
使用呢??
ok,我们来试一下,在./src/index.html
文件中写了个标签
<img src='./react.png' alt='react' />
我继续webpack一下,哦吼?报错了?
我们看提示发现是webpack解析到html文件的时候识别不了./react.png
这个资源。哦?刚才不是说只用url-loader
就可以了吗?你在骗我!
莫慌莫慌,url-loader
只能处理css中的图片资源,那我html中的图片资源还需要另外的loader来处理,什么loader呢?html-loader
是的,你没听错,一个名字取的像是要处理html似的,其实就只是处理html中的image资源。。。
手动狗头。。
那么上代码,我们只需要在原来的基础上加上html-loader
的处理就可以了
{
// 匹配以.html结尾的文件
test:/\.html$/,
// 识别html中的图片资源并引入,之后该资源转交到url-loader手中
loader:'html-loader'
}
然后我接着webpack,哦吼?没有报错,那我们看页面,没出来图片,纳尼!!! 我打开源代码,看到了以下img标签
<img src="[object Module]" alt="" />
为什么呢?
原来html-loader
默认是commonJs
的模块,而
url-loader
使用的是esModule
的模块,那他们之间自然就不能正常解析了,那怎么办呢?
只需要传入url-loader中的一个配置局可以了,什么配置呢?
{
// 匹配以png、jpg和gif结尾的图片资源
test:/\.(png|jpg|gif)$/,
loader:'url-loader',
options:{
...
esModule:false
}
}
是不是很降智?? 不不不,只是人家options提供的好而已。。
打包其他资源
接上,我们image和css都搞好了,那其他资源岂不是都很有限了?
上更多资源,例如font|media|mp4
等
大家看到了,我用了【等】
,是的,没错,接下来我们只需要用一个loader就可以处理除了js
、css
和html
资源以外的任意资源(当然,你的资源一定要是真实存在的,我随便造一个.zzz
后缀的可不行哦^_^)
注意:这次真的只需要一个loader,我们可不兴跟图片资源学习的呀!罒ω罒
这个loader上面已经提到过了,那就是file-loader
,一个强大的loader,好,我们上面已经安装过了,那直接上配置代码
{
// 排除掉css、js和html资源之外的所有资源
exclude: /.\(css|js|html)$/,
// 是的,我就是这么简单,启用默认配置就可以,当然,更多配制会在后面的【生产环境篇】讲解
loader: 'file-loader'
}
验证: 没问题!!赞
注意:记得验证的时候,这些资源一定要在入口文件中引入,否则webpack并不会追踪到这些文件,当然也不会打包
好吧,我从头到尾都没有贴验证结果,只是文字描述了,那是因为我掘金写的时候跟代码不在一个时间段哈哈哈哈。。。
我之后会把代码上传到github,感兴趣的同学可以自己clone一下自己验证下看看,当然,好心又帅气的朋友们也会自觉的点个Star
啊什么的~
结语
往期好文推荐「我不推荐下,大家可能就错过了史上最牛逼vscode插件集合
啦!!!(嘎嘎嘎~)😄」