前言:
作为一个现代 JavaScript 应用程序的静态模块打包器(module bundler),Webpack 凭借其强大的功能和灵活性,成为了前端开发者的首选工具。今天,我们就来深入探讨 Webpack 的几个核心概念,帮助你更好地理解和使用这个强大的工具。
webpack官网:点击<<<
1.使用webpack
1.1 初始化项目
首先我们先要创建一个空的文件夹。
打开该文件的终端,输入npm init命令创建package.json。输入命令后一直点Enter回车,就可以创建package.json。
这时候我们就可以开始创建目录了。目录结构如下:
我们在index.html文件中引入app.js。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="./src/app.js "></script>
<body>
</body>
</html>
common.js文件内容:
export default function(){
console.log('common模块')
}
util.js文件内容:
export default function(){
console.log('util模块')
}
在app.js中引入两个模块,并调用。
import common from "./components/common";
import util from "./components/util";
common()
util()
这时候我们运行index.html文件时会发现报错,这时候也必定会报错。遇到报错情况时我们应该冷静分析。
从报错结果我们可以分析出来,该报错应该会与import有关,其实不然,这是因为浏览器是不支持import,因此这时候我们要去使用webpack。
1.2 安装webpack
因为webpack是一个工具,我们先是要去安装它。
输入该命令,装webpack工具的同时,也要将webpack的脚手架一同安装,它可以命令式的执行webpack。-D表示的是开发环境。
1.3 命令式使用webpack
输入npx webpack ./src/app.js命令,npx是先从本地找到相应的资源,找不到再下载,所以使用npx就可以避免执行命令时编写过长的文件路径。
构建完之后会生成一个dist文件,注意:我们构建的文件一定是在dist中。可以看到dist文件里面有一个main.js文件。
main.js里面的内容为:
(()=>{"use strict";console.log("common模块"),console.log("util模块")})();
刚刚我们在输入命令后,弹出了一行警告。
该警告的意思是我们没有给它一个环境,是开发环境或者是生产环境。我们这边输入选择开发环境。输入命令npx webpack ./src/app.js --mode development,再构建一次。这时候就没有警告了,再点击main.js,可以看到文件内容发送了变化。这边要注意的是我们的配置文件应该是cmd。
如果不是的话我们点击旁边的下拉按钮,选择默认配置文件,修改为cmd,其他的会有权限问题。
1.4 配置式使用webpack
到这一步时,我们可以看到上面的命令式的使用webpack会比较麻烦,需要手动的输入参数来告诉webpack我们需要的打包环境,需要打包的文件等,每次打包都需要输入命令。
所以webpack就提供了可以将参数配置化,需要在原有的基础上新增一个webpack配置文件,此时的目录如下:
在项目的根目录新增一个webpack.config.js文件。所有配置我们都在这个文件中,我们给该文件写一个最简单的配置。
module.exports = {
entry:'./src/app.js',
mode:'development',
}
entry和mode都是webpack的核心配置文件,当然也不止这两种。entry表示的是入口文件,也就是需要打包的文件。mode表示的是打包环境,根据打包后的环境来加载不同的打包规则,development是开发环境,production是生产环境。
然后再使用npx webpack --config ./webpack.config.js执行即可。我们也可以将改命令放入到package.json文件中,让它来帮我们去执行。
到这里我们就可以去运行了,在终端中输入npm run dev。这时候就打包好了
在index.html中,使用webpack打包后引入的一定是dist打包后的代码文件,而不是源文件,这时候我们不是直接去引用app.js文件,而是要去引用我们打包后的文件,也就是main.js文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<!-- <script src="./src/app.js "></script> -->
<script src="./dist/main.js"></script>
<body>
</body>
</html>
到这里再去运行一下index.html文件,可以看到已经打印上去了,这样我们就可以正常的使用webpack对我们的js文件进行一个打包。
2.webpack的配置
2.1 基本配置
entry:表示webpack的入口,指定打包的文件,可以是一个或者多个。
mode:表示打包环境,可设置development或production值。
output:表示输出文件的路径和文件名。
我们就在webpack.config.js配置文件中添加output这个核心配置,说白了这个配置的作用是打包的文件放在哪里,叫什么名字。
const path = require('path')
module.exports = {
entry: './src/app.js',
mode: 'development',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js',
clean: true,
},
}
output核心配置中有几个参数,path表示输出的路径,因此我们要引入path插件,使用path的resolve方法,它可以去解析路径,就是把路径拼起来。filename表示的是输出的文件名。clean表示的是打包前是否清空之前的dist目录中的文件
2.2 loader
这个配置非常重要,它可以实现源码的转换,因此它是以源码做为参数的。因为webpack只能支持对js文件和json文件进行打包,其他文件是不支持的,我们就要配置对应的loader对其他文件里面的内容进行解析转化,从而让webpack可以对其他的文件进行打包。 说白了就是将其他文件转换为js文件或者json文件。
2.2.1 处理css
我们先创建一个css文件夹,在里面添加一个index.css文件,然后写上一些样式,目录如下:
就比方说随便写一个样式:
.box{
width: 200px;
height: 200px;
background-color: brown;
}
在index.html中添加一个类名为box的元素。
我们需要将我们写的样式文件引入到app.js中,注意:我们在使用模块引入css的时候是不需要变量去接收它的,直接import后面接上路径就可以了。
import './css/index.css'
引入过后我们在终端中输入npm run dev再构建一次,会发现报错了。
报错的原因刚刚也提到过,这是因为webpack是不支持对css文件进行打包的,因此我们要把css文件转换为js文件,让webpack能够进行打包。
我们就需要通过loader来将css文件转换为js文件,处理css需要用到css-loader和style-loader.
css-loader的作用是将css文件转换为js文件。
style-loader的作用是将css文件转换的js文件引入到项目中。
我们需要安装这两个命令:
npm i css-loader style-loader -D
这时候我们就可以在webpack.config.js配置文件中来配置loader,我们需要在module中进行配置,代码如下:
const path = require('path')
module.exports = {
entry: './src/app.js',
mode: 'development',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js',
clean: true,
},
module:{
// 配置loader解析css文件
rules:[
{
test: /\.css$/,
use:['style-loader','css-loader']
}
]
}
}
注意点:test后面接的是正则表达式,use后面loader的加载顺序,它是从后往前执行的,因此先执行的应该写在后面,这点要记住,很容易记混。
配置完之后,我们在终端中再使用npm run dev命令构建一次,可以看到并没有报错。
这时候我们就可以运行index.html文件了,可以看到样式正常的渲染到页面上了。
因此,在处理css资源时,css-loader和style-loader两者缺一不可。
2.2.2 处理sass和less
首先我们先在css文件目录里面创建一个sass文件和一个less文件。
注意:因为sass文件它的写法是不可忍受的,因此后面出了个scss,我们这边使用的是scss。
然后再在index.html文件中创几个盒子,在less和sass文件中分布添加样式。注意:less文件在保存时会直接生成一个css文件,当该目录有同名的css文件会将其覆盖,因此我们这边在less中添加样式保存后,我们要去css里面还原我们之前的样式。
在app.js中引入我们刚刚创的文件。
import './css/index.less'
import './css/index.scss'
跟css的情况同理,webpack也不认识less的文件,sass文件,构建后它还是会报错。
这时我们需要同时安装less和sass,以便能够将less和sass编译成css,然后对css进行操作,输入以下命令安装less和sass:
npm i less less-loader sass sass-loader -D
less-loader/sass-loader的作用是将less/sass文件转化为css,然后通过css-loader和style-loader再进行接下来的操作。
less/sass的作用是给我们的代码提供一个less/sass的运行环境。
安装完之后我们就需要在配置文件中去配置loader。配置代码如下:
// 处理css文件
{
test: /\.css$/,
use:['style-loader','css-loader']
},
// 处理less文件
{
test: /\.less$/,
use:['style-loader','css-loader','less-loader']
},
// 处理sass文件
{
test: /\.s[ac]ss$/,
use:['style-loader','css-loader','sass-loader']
}
因为刚刚说了loader的加载顺序是从后往前执行的,这里我们需要先将less/sass文件先转换为css文件,因此应该写在最后面。
sass需要写成s[ac]ss的形式,这表示的样式是这里既可以是sass文件,也可以是scss文件。
然后我们在终端中构建一次,再运行index.html文件可以看到less文件和sass文件里的样式都渲染到页面上了。
2.2.3 处理图片
首先我们在项目中的src下新建一个images文件夹,在其中引入图片。
然后在index.html文件中添加一个div,在给该div添加样式和背景图片。
在配置文件中处理图片。
{
test:/\.(jpe?g|png|gif|webp|svg)$/,
type:'asset'
}
因为图片的后缀名有很多,我们都需要考虑到,在处理图片时我们不需要使用到loader,我们只需要配置它的类型,这边我配置了一个asset类型。可配置的类型如下:
我们还可以给图片配置一个parser。代码如下:
{
test:/\.(jpe?g|png|gif|webp|svg)$/,
type:'asset',
parser:{
dataUrlCondition:{
maxSize: 10 * 1024
}
}
}
这里maxSize的意思是超过10k就作为图片引入,否则转换为Base64。
上面可以看到,图片打包后输出目录与main.js在同一目录,如果想把图片打包放到dist/static/images目录下,那么就要使用到generator字段。代码如下:
{
test:/\.(jpe?g|png|gif|webp|svg)$/,
type:'asset',
parser:{
dataUrlCondition:{
maxSize: 10 * 1024
}
},
generator:{
filename:"static/images/[hash][ext][query]"
}
}
generator中的filename指定了存放的目录
[hash]:表示hash值,后面可携带自定义位数。
[ext]:原文件扩展名
[query]:添加之前的query参数
2.2.4 处理字体图标
跟上面一样,在src下新建一个fonts文件夹,然后我们就可以去阿里巴巴矢量图标库任意下载一个图标,将下载好的图标放到fonts文件夹中,将下载的iconfont.css在app.js中引入,并在index.html文件中新增标签。
import './fonts/iconfont.css'
<span class="iconfont icon-new"></span>
在终端中构建,运行index.html就可以看到字体图标已经渲染上去了。
如何没生效的话,可以去检查下iconfont.css中的路径是否对的上。
最后在配置文件中新增配置,代码如下:
// 处理字体图标文件
{
test:/\.(ttf|woff|woff2)$/,
type:'asset/resource',
generator:{
filename:"static/font/[hash][ext][query]"
}
}
asset/resource 能够将资源原封不动的输出到指定位置。
在webpack早期版本中,所有webpack不支持打包的文件都要用到loader,在webpack5中把一些常用的资源,将它们给内置了,不要我们再去手动下载并配置loader了。
2.2.5 处理css兼容性
兼容性问题一直是前端比较头疼的问题,但是在webpack中可以通过loader,将一些比较新的css语法能够在低版本的浏览器中使用,就需要下载postcss-loader,但这个loader还依赖postcss和postcss-preset-env,因此需要安装三个模块。命令如下:
npm i postcss-loader postcss postcss-preset-env -D
在配置文件中修改webpack的配置如下:
// 处理css文件
{
test: /\.css$/,
use:[
'style-loader',
'css-loader',
{
loader:'postcss-loader',
options:{
postcssOptions:{
plugins:['postcss-preset-env']
}
}
}
]
},
// 处理less文件
{
test: /\.less$/,
use:[
'style-loader',
'css-loader',
{
loader:'postcss-loader',
options:{
postcssOptions:{
plugins:['postcss-preset-env']
}
}
},
'less-loader'
]
},
处理sass同理,要在将less/sass文件转换为css文件后在处理。
除了以上配置外,还需要在package.json中新增"browserslist":["ie >= 7"],去兼容IE浏览器。
我们可以在index.css里面加一个display:flex测试一下,打包后可以看到做了兼容性处理。
2.2.6 处理js兼容性
es6推出了许多新的语法,刚刚推出了的时候,浏览器这边不可能直接就去兼容新语法,它需要时间去兼容。但是在工程化项目中是可以放心大胆的使用的,可以通过loader,可以将js语法在较低的浏览器版本中使用,主要是通过babel,同时也要去安装三个模块,一个loader,一个核心库,一个虚设,分布就是babel-loader、@babel/core、@babel/preset-env,安装命令如下:
npm i babel-loader @babel/core @babel/preset-env -D
- babel-loader:将es6的语法转换为es5。
- @babel/core:Babel编译的核心包。
- @babel/preset-env:Babel编译的预设,可以理解为Bable插件的超集。
安装完后在配置文件中新增loader配置如下:
// 处理js兼容问题
{
test:/\.js$/,
exclude:/node_modules/,
use:['babel-loader']
}
要使用exclude去排除node_modules下的文件,不排除的话,它会对node_modules下的所有文件转换为低版本的js,node_modules中有大量的文件,这些代码也不需要我们去转换,因此我们要去排除node_modules。
到这一步还没有完,@babel/preset-env才是主要转换代码的东西,为了后面方便的修改,在项目的根目录新建一个babel.config.js配置文件,这个是babel专用的配置文件,配置代码如下:
module.exports = {
presets:['@babel/preset-env']
}
如何我们就可以测试一下,在开始创建的common.js文件中添加一个剩余参数运算符,然后打印,代码如下:
export default function(...arr){
console.log('common模块',arr)
}
然后在app.js文件中任意添加参数,代码如下:
common('html','css','js');
构建之后运行index.html,打开控制台。
说白了babel-loader就是将高版本的js语法转换为低版本的js语法,这样我们写代码时候就可以放心的去写,不用担心兼容性的问题。
2.3 Plugin
刚刚的loader就是将webpack不支持的文件转换为js文件,这样webpack就可以去对这些文件进行打包。
loader使webpack能够转化文件,而plugin则使webpack能够拥有压缩、提取等强大的功能。
2.3.1 提取css为单独的文件:
loader处理的css文件,是将其转换为js文件直接插入到html中,不是用引入链接的方式,这样在访问页面时从解析js到解析完成会有一个突然出现的效果,会影响用户体验。
可以通过MiniCssExtractPlugin插件将css提取到单独的文件中。
相关文档:HtmlWebpackPlugin
首先我们要去安装这个插件,命令如下:
npm i mini-css-extract-plugin -D
安装好之后,在配置文件中引入我们安装好的插件。代码如下:
// 引入抽离css插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
然后将我们之前配置的所有style-loader换成MiniCssExtractPlugin.loader,style-loader的作用是将css文件转换的js文件引入到我们的项目中,这时候我们不需要它去引入了,而是将转换的js文件抽离成一个文件。代码如下:
// 处理css文件
{
test: /\.css$/,
use:[
MiniCssExtractPlugin.loader,
'css-loader',
{
loader:'postcss-loader',
options:{
postcssOptions:{
plugins:['postcss-preset-env']
}
}
}
]
},
less与sass同理,全部换为MiniCssExtractPlugin.loader。还需要在module外面写一个plugins,它是一个数组,可以传多个插件。如下所示:
在里面添加一个new MiniCssExtractPlugin,参数是一个对象,对象中添加地址。代码如下:
plugins:[
// 把css抽离成单独的文件
new MiniCssExtractPlugin({
filename:'static/css/app.css'
})
]
再在终端中构建,可以看到在dist文件夹下的static文件夹,我们就成功将css提取到了单独的文件里了。
但是在index.html还需要我们手动引入。
<link rel="stylesheet" href="./dist/static/css/app.css">
2.3.2 自动引入js和css
上面打包后,不管是将js还是将css打包成单独的文件,在index.html中还需要手动的引入相应的资源,如果修改了webpack打包的js和css文件的路径,那么index.html也需要做相应的修改,比较麻烦。
以上问题可以通过HtmlWebpackPlugin插件解决。
安装该插件,命令如下:
npm i html-webpack-plugin -D
跟上面逻辑是差不多的,安装完之后引入刚刚安装的文件。代码如下:
// 引入自动引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
在plugins中添加自动引入css文件插件,代码如下:
plugins:[
// 把css抽离成单独的文件
new MiniCssExtractPlugin({
filename:'static/css/app.css'
}),
// 自动引入css文件插件
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'index.html')
})
]
然后再在终端中构建,打包后,可看到dist下有一个index.html文件,同时会帮我们引入相关资源,这时可以访问这个新的index.html来查看效果了。
2.3.3 压缩css
在配置文件中将打包环境切换为生产环境。代码如下:
mode: 'production',
再打开我们打包好的css文件。
里面有大量的空格和空行,这都是不需要的,需要用webpack将其抽离到极致,上线后的css应该是压缩后的。
同样的,使用 CssMinimizerWebpackPlugin 这个插件能够将css压缩为一行,减少代码体积。
安装这个插件,命令如下:
npm i css-minimizer-webpack-plugin -D
然后引入我们下载好的插件,代码如下:
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
再在plugins中实例化css压缩插件。代码如下:
// 实例化css压缩插件
new CssMinimizerWebpackPlugin()
只需要new一下就搞定。我们再在终端中构建一次,再返回到打包的css文件中,可以看到此时被压缩成了一行代码。
2.3.4 自动清空打包目录
每次打包的时候,打包的目录都会遗留上次打包的文件,为了保持目录的纯净,我们需要在打包前将打包目录清空。
这里使用到了 clean-webpack-plugin 插件来实现
安装插件,命令为:
npm i clean-webpack-plugin -D
引入我们安装好的插件,注意有个细节,引入时要用花括号包起来了。代码如下:
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
在plugins中实例化清除构建插件。代码如下
然后在终端中构建,我们也看不出有什么变化,这个插件的作用就是在打包前将打包目录清空,我们也可以手动清空一下,再构建一次,构建完之后文件仍然打包了。
3.小结
通过本章博客希望对您有所帮助,对webpack有所理解。上面通过处理各种资源来介绍 webpack 的配置使用,但只介绍了其中一部分,更多的 loader,plugins 等使用方法还是得到官方文档查询。