webpack配置
webpack 是代码编译工具,有入口、出口、loader 和插件。webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具。当 webpack 处理应用程序时,它会在内部构建一个依赖图(dependency graph),此依赖图对应映射到项目所需的每个模块,并生成一个或多个 bundle。
同时还发现导入了很多个JS的文件
这就是我们之前做项目的时候所导入的依赖包,这么做有什么问题没有?
首先要知道 webpack
就是打包工具,它可以将我们的所用到的资源进行合理的整合,它相当于一个项目经理,合理的整和资源 ,分配资源,最后生成资源
常用的打包工具
就目前来说,打包工具不仅仅只有webpack
还有其它的一些,我们现在认识一下常用的打包工具
webpack
这一个是2022之前非常火的一个打包工具,目前最新的版本已经到5了,它使用起来非常方便,并且功能强大,后期的vue、react,angular,sevlte
都会使用它grunt
打包工具,Grunt 是一个基于任务的JavaScript工程命令行构建工具。它了是第一代构建工具,目前基本上已经被淘汰了,不再使用了,它所实现的功能与webpack
相似gulp
打包工具,gulp 将开发流程中让人痛苦或耗时的任务自动化,从而减少你所浪费的时间、创造更大价值。这个东西本来应该也过时了,但是现在又活过了,后期面有一个叫vite
的打包工具借鉴它的思路形成了另一个工具vite
打包工具,vite是下一代前端开发与构建工具。 [1] Vite意在提供开箱即用的配置,同时它的插件API和JavaScript API 带来了高度的可扩展性,并有完整的类型支持。【我们后面就主要去使用它了,就不再去使用webpack
了】
vite
是唯一的一款国产打包工具,好用,文档齐全,并且与vue
实现高度整合,无需任何配置就可以实现vue
的脚手架
上面所有的打包工具都有一些共同的特征,所有的打包工具应该都有配置文件 ,并且配置文件里面必须有四个部分
webpack打包工具的核心点
https://webpack.docschina.org/
- 入口
- 出口
loader
- 插件
plugins
目前所存在的问题
Person.js
class Person {
constructor(userName) {
this.userName = userName;
}
sayHello() {
setTimeout(() => {
console.log(`大家好,我叫${this.userName}`);
}, 1000);
}
}
//现在用的是ESModule,不是CommonJS模块
export default Person;
Student.js
import Person from "./Person.js";
class Student extends Person{
constructor(userName,sex){
super(userName)
this.sex = sex;
}
study(){
console.log(`${this.sex}学生在学习`);
}
}
export default Student;
index.js
import Student from "./Student.js";
let s = new Student("张珊","女");
s.sayHello();
s.study();
当我们把所有的js
文件写好了以后,我们在index.html
的网页里去调用
<script src="js/index.js" type="module"></script>
我们现清楚的看到了这个代码的运行
表面上看是没有任何问题
- 因为我们现在使用的是
ESModule
的方式在使用模块化,所以在script
的标签上面,我们使用了type="module"
这个属性,但是这个属性它是在新版本的浏览器里才支持,旧版本是不支持,所以会有兼容性 - 我们在
js
里面大量使用了class,extends
以及箭头函数等ES6的语法,但是这些语法也是有兼容性的,在低版本的浏览器里面,ES6是不被支持的 - 现在我们打开的网页是以
http
协议打开 的,当我们双击文件直接打开的时候,这个时候就会报错了
上面的三个问题就是目前所存在的问题,如果想解决上面的问题,我们可以直接使用webapck
打包个,生成一个新的文件就可以了
webapck工具的安装
webpack是nodejs平台下面的一个包,我们可以直接通过npm
来进行安装
$ npm install webpack webpack-cli --save-dev
webpack的配置文件
webpack只是一个工具,它需要参照一定的规则来处理事情,这个规则就是配置文件,它的配置文件是固定格式,具体可以参考它的官方文档
概念 | webpack 中文文档 (docschina.org)
我们在当前的项目下面新建一个webpack.config.js
的文件 ,然后配置如下
const path = require("path");
/**
* @type {import("webpack").Configuration}
*/
const config = {
// 入口
entry: "./js/index.js",
// 出口
output: {
path: path.join(__dirname, "./dist"),
filename: "bundle.js"
}
//loader
//插件
}
module.exports = config;
当我们把配置文件写好了以后,我们就可以启动webpack
的打包工具,然后开始打包,在打包之前我们还要知道怎么样启动webpack
webpack的启动
在package.json
下面的scripts
目录配置启动命令
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config ./webpack.config.js"
},
现在我们就来启动一下刚刚配置的命令
$ npm run build
使用babel
插件来处理JS的兼容性
它是webpack
的一个插件,作用就是将ES6
的代码转换成兼容性比较高的ES5
代码
在这之前我们使用webpack
进行打包的时候,我们都发现我们的JS代码虽然完成了打包合并 ,但是最大的问题它没有提高兼容性,仍然是ES6的代码,如果这些代码要是在浏览器里面运行很可能会有兼容性的问题
在设置这一页里面,我们可以找到webpack
的配置
第一步:安装babel
的需要的依赖包
npm install --save-dev babel-loader @babel/core
第二步:配置webpack中的babel插件
//省略部分代码......
module: {
//你在import的时候会导入不同的文件 ,我们要根据不同的文件来制定不同的规则
rules:[
{
//如果我在import的时候发现你的后缀名是.js的文件,那么我就要使用babel去转换一下,
//将你转换成es5的代码
test:/\.js$/,
exclude: /node_modules/,exclude: /node_modules/,
// use:["babel-loader"]
use:[
{
loader:"babel-loader"
}
]
}
]
},
第三步:指定babel
的转换规则
在上面的截图里面,我们可以看到它使用了@babel/preset-env
的规则,这个规则是根据你所配置的环境来决定转换规则
环境也就是开发环境,就是根据我们自己的开发环境来决定怎么转换
它提示我们需要安装一个包,那么我们现在就安装
$ yarn add @babel/preset-env --dev
当包安装完成以后,我们可以在刚刚创建的配置文件里面写入转换规则了
再我们再次去启动的时候,我们发现仍然没有执行转换规则 ,这是为什么呢?因为我们还指定JS的运行环境
在设置preset的时候,我们需要第三方的插件,分别是下面三个包
@babel/preset-env
这个包的作用是环境配置环境来决定怎么样转换JS代码@babel/polyfill
这个包主要的作用就是实现ES6中的一些扩展功能,如Map
,Set
,Symbol
…core-js
这个包主要的作用就是用于实现Generater function生成器函数的功能,以及async/await/Promise
$ yarn add @babel/polyfill core-js --dev
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": "3",
"targets": {
"browsers": [
"last 2 version",
"> 1%",
"not dead",
"ie 8"
]
}
}
]
]
}
代码说明:
useBuiltIns
我们的预设里面有很多转换规则,usage
需要哪些就使用哪些corejs
后面的3代表的是当前安装的版本是多少targets
这个指js转换以后的目标平台 ,我们看到这里是browsers
代表js
在浏览器里面运行,后面有一个数组
last 2 version
代表要支持到浏览的的最后2个版本> 1%
浏览器的使用市份额大于1%
就可以了not dead
没有死的浏览器都支持
当然 们把所有的东西都弄完了以后,最后在webpack.config.js
的配置文件上面添加如下代码就可以实现最终的ES6转ES5了
const config = {
target:["web","es5"]
}
配置html-webpack-plugin
这个插件的作用就是帮助我们在这个地方将生成好的JS与CSS插入到HTML文件当中去
安装这个插件
$ yarn add html-webpack-plugin --dev
配置html-webpack-plugin插件
//插件
plugins: [
new HTMLWebpackPlugin({
// 源文件
template: path.join(__dirname, "index.html"),
// 生成的目标文件的名称
filename: "index.html",
// 把打包的js文件或后期的css文件也通过标签链接进去
inject: true
})
]
配置Clean-Webpack-Plugin
在刚刚的代码里面,我们可以看到,我们每次生成的东西都会在dist
的目录下面,但是有些文件我们是不需要的,所以我们希望在每次生成的时候都将目标目录dist
清空,这个时候就需要使用Clean-Webpack-Plugin
安装
$ yarn add clean-webpack-plugin --dev
配置插件
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
//配置文件
plugins:[
//省略部分代码
new CleanWebpackPlugin()
]
上面的插件在
webpack5
里面已经被自带了
const config= {
//省略部分代码
output:{
clean:true
}
}
webpack处理CSS文件
首先要弄清楚 一个问题,webpack只能够处理js
,但是我们可以通过不同的loader
来让wepback加载不同的文件
当我们向js文件里面导入一个css
的时候文件,如下所示
import "../css/index.css";
这个时候再去编译我们就会报错
它提示我们需要一个loader
去处理这样类似于css的文件
安装第三方loader
$ yarn add css-loader style-loader --dev
- 第一个
css-loader
代表可以让webpack
处理以css
结尾的文件style-loader
可以让导入的css
的样式文件以<style>
标签的形式插入到网页当中
配置loader
{
test: /\.css$/,
use: [
"style-loader",
"css-loader"
]
}
配置postcss
处理兼容性
安装
$ yarn add postcss-loader --dev
配置postcss-loader
{
test: /\.css$/,
use: [
"style-loader",
"css-loader",
"postcss-loader"
]
}
当我们去配置好postcss-loader
以后应该是不会生效的,因为我们还没有指定转换规则
指定转换规则
在指定转换规则的时候 ,我们要安装postcss
的插件,它常用的插件有三个
postcss-import
postcss-cssnext
cssnano
$ yarn add postcss-import postcss-cssnext cssnano --dev
然后再当前项目下面创建一个postcss.config.js
的文件,去配置插件
//这里就是postcss的配置文件
module.exports = {
plugins: [
require("postcss-import"),
require("postcss-cssnext"),
require("cssnano")
]
}
当配置完成以后,我们还要在package.json
里面去配置它们的转换规则
"browserslist": [
"last 2 version",
"> 1%",
"ie 6"
]
如果在编译的时候报
true is not Postcss Plugin
是因为postcss
的版本过低,我们要手动的提升版本
$ yarn add postcss@8 --dev
CSS文件分离
当我们处理好CSS的兼容性以后,我们发现我们的CSS代码是在JS
里面的,我们要将CSS的代码从JS里面的分离出来
如果我们要分离CSS,又要使用一个包,这外叫叫mini-css-extract-plugin
安装
$ yarn add mini-css-extract-plugin --dev
配置这个包
const path = require("path");
const HTMLWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
//压缩CSS,并分离CSS为一个单独的文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
/**
* @type {import("webpack").Configuration}
*/
const config = {
target: ["web", "es5"],
mode: "development",
// 入口
entry: "./js/index.js",
// 出口
output: {
path: path.join(__dirname, "./dist"),
filename: "js/bundle.[hash:8].js",
publicPath: "./"
// 自带的清除
// clean:true
},
//模块,也就是加载器loader,当你去import一个文件时候 就会触发这个module里面的loader
module: {
//你在import的时候会导入不同的文件 ,我们要根据不同的文件来制定不同的规则
rules: [
{
//如果我在import的时候发现你的后缀名是.js的文件,那么我就要使用babel去转换一下,
//将你转换成es5的代码
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader"
}
]
}, {
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
importLoaders: 1
}
},
"postcss-loader"
]
}
]
},
//插件
plugins: [
new HTMLWebpackPlugin({
// 源文件
template: path.join(__dirname, "index.html"),
// 生成的目标文件的名称
filename: "index.html",
// 把打包的js文件或后期的css文件也通过标签链接进去
inject: true
}),
new CleanWebpackPlugin(),
//配置CSS的分离插件
new MiniCssExtractPlugin({
filename: "css/index.[hash:8].css",
ignoreOrder: false
})
]
}
module.exports = config;
const path = require("path");
const HTMLWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
//压缩CSS,并分离CSS为一个单独的文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
/**
* @type {import("webpack").Configuration}
*/
const config = {
target: ["web", "es5"],
mode: "development",
// 入口
entry: "./js/index.js",
// 出口
output: {
path: path.join(__dirname, "./dist"),
filename: "js/bundle.[hash:8].js",
publicPath: "./"
// 自带的清除
// clean:true
},
//模块,也就是加载器loader,当你去import一个文件时候 就会触发这个module里面的loader
module: {
//你在import的时候会导入不同的文件 ,我们要根据不同的文件来制定不同的规则
rules: [
{
//如果我在import的时候发现你的后缀名是.js的文件,那么我就要使用babel去转换一下,
//将你转换成es5的代码
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader"
}
]
}, {
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
importLoaders: 1
}
},
"postcss-loader"
]
}
]
},
//插件
plugins: [
new HTMLWebpackPlugin({
// 源文件
template: path.join(__dirname, "index.html"),
// 生成的目标文件的名称
filename: "index.html",
// 把打包的js文件或后期的css文件也通过标签链接进去
inject: true
}),
new CleanWebpackPlugin(),
//配置CSS的分离插件
new MiniCssExtractPlugin({
filename: "css/index.[hash:8].css",
ignoreOrder: false
})
]
}
module.exports = config;
配置sass
的loader
sass的编译是依赖于第三方的环境,所以我们需要安装第三方的包
$ yarn add sass sass-loader --dev
配置sass-loader
,{
test:/\.s[ca]ss$/,
use:[
MiniCssExtractPlugin.loader,
{
loader:"css-loader",
options:{
importLoaders: 2
}
},
"postcss-loader",
"sass-loader"
]
}
webpack处理图片
在webpack里面,如果我们在css里面引入了图片以后,这个时候就会出山现问题,如下所示
.box {
width: 200px;
height: 200px;
border: 2px solid black;
display: flex;
justify-content: center;
align-items: center;
transform: rotateZ(45deg);
opacity: 0.4;
background-color: deeppink;
background-image: url("../img/dijia.jpg");
}
我们在这个地方使用了background-image
的属性,它使用了一个文件 ,这个时候我们再去执行yarn run build
的时候就会报错,原因就是因为webpack
不能实现图片的加载【默认情况下webpack只能加载js
文件,如果要加载其它的文件就需要有相应的loader
来实现】
现在我们就需要使用2个loader
来处理文件的加载
安装
$ yarn add url-loader file-loader --dev
上面所安装的2个loader就是用于加载文件的,我们现在在
webpack.config.js
里面去配置一下
{
test: /\.(jpe?g|png|svg|bmp|gif)$/,
use: [
{
loader: "url-loader",
options: {
limit: 8 * 1024,
name: "[name].[hash:8].[ext]",
outputPath: "img/",
esModule: false,
}
}
],
type: "javascript/auto"
},
上面的配置就是用于处理图片的,但是这个时候还要注意,如果我们这个时候直接进行打包,图片仍然是不能显示的,效果如下所示
我们可以看到,这个时候虽然已经生成了图片,但是背景图片没有显示,这是为什么呢?
我们再去看看生成的文件的结构
这个时候我们可以看到,生成的css与图片img并不在同目录下面,所以在background-image
里面直接使用url("./img")
是找不到这个img
目录的,应该使用../img
才可以找到这个目录
这个问题应该怎么解决呢
解决这个问题的方法有2处
第一种,在mini-css-extract-plugin里面配置,如下所示
在原来配置MiniCssExtractPlugin
的地方指定一个publicPath
的属性,让分离出来的的CSS的里面的路由前面都加上../
。这样就可以了,我们现在去看一下效果
这个时候我们可以看到,图片已经正常显示了,因为背景图片的路径已经正常了
第二种解决方法
这一种解决方法与上面的相似,也是要配置publicPath
,但是不是在MiniCssExtractPlugin
这个插件上面配置,而是在url-loader
这个插件上面配置,如下所示
这个时候我们可以看到效果如下图所示
webpack处理字体
在使用CSS的时候,我们有时候也会使用第三方的字体,如iconfont
图标字体,如一些第三方的文字的字体,我们可以通过 @font-face
来引自,这个处理过程与处理图片原理是一样的,仍然是使用url-laoder
与file-loader
是一样的,配置如下
{
test: /\.(ttf|eot|woff|woff2)$/,
use: [
{
loader: "url-loader",
options: {
limit: 8 * 1024,
name: "[name].[hash:8].[ext]",
outputPath: "fonts/",
esModule: false,
publicPath:"../fonts"
}
}
],
type: "javascript/auto"
}
扩展yarn包管理工具
以前我们在安装第三方模块的时候我们使用的是npm
来进行安装,但是这个东西并不是很完美,因为npm
每次都要从服务器去下载包,这样做非常浪费流量,也非常耗时,所以我们要推荐第三方的包管理工具yarn
安装
$ npm install yarn -g
配置镜像地址
yarn每次去下载包的时候也是从国外的服务器下载的,我们仍然要配置国内的镜像地址
$ yarn config set registry https://registry.npmmirror.com
配置缓存的目录
因为yarn会缓存每一次下载过的包,它的缓存目录默认是在C盘,我们要将这个缓存的目录重新设置一下
$ yarn config set cache-folder D:\yarn_cache
yarn也是一个包管理工具,所以它也可以安装包,也可以卸载包,也可以生成依赖文件
yarn命令与npm命令的对比
npm命令 |
yarn 命令 |
---|---|
npm install 包名 |
yarn add 包名 |
npm uninstall 包名 |
yarn remove 包名 |
--save |
不需要,它自动添加 |
--save-dev |
--dev |
npm init |
yarn init |
npm run 脚本 |
yarn run 脚本 |
npm install |
yarn |
当我们如果需要清理缓存目录的时候 ,我们要使用下面的命令
$ yarn cache clean --force