什么是webpack

  • 是一个模块打包工具
  • webpack将前端的所有资源文件(js/json/css/img/less…)都看做模块,来进行处理
  • 会根据模块的依赖关系进行分析,生成对应的资源
  • 原生的webpack只可以完成js/json的打包编译,而转换什么的需要其他插件进行完成,比如说es6转es5,箭头函数转换,都需要依赖其他loader或者插件(plugins)

五个核心概念

  1. 入口(entry): 告诉webpack应该使用哪个模块,作为构建内部依赖图的开始,比如vue中我们经常在一个文件夹当中建立index.js或者main.js作为入口文件
  2. 出口(output): 在哪里输出文件,以及如何命名这些文件
    • 比如经常可以看到有些目录有dist build等这些,里面只有js,css,img等一些文件,就是打包输出后的东西
  3. loader:
    • 我们需要注意,原生webpack只支持解析jsjson,其他的需要安装对应的loader,比如处理less就需要less-loader
    • 本身是一个函数,接收源文件作为参数,返回转换结果
    • loader异步以xxx-loader方式命名,xxx代表了这个loader要做的转换功能
  4. 插件(plugins):
    • 执行访问更广的任务,从打包到优化都可以实现
    • 完成一些loader不能完成的功能
  5. 模式(model)
    • 有生产模式production , 开发模式development,主要区别就是是否会将代码进行压缩

安装webpack

  • 当然,离不开npm,所以npm初始化就不多说了,直接npm init -y
  • 安装webpack
    • npm install webpack webpack-cli -g //全局安装
    • npm install webpack webpack-cli -D//局部安装
    • 查看版本webpack --version
    • 还有,除了全局安装,记得也在项目局部也安装下,不然后面可能有莫名其妙的问题引发

处理js和json文件

目录结构如下:

目录结构

代码如下:

index.js

1
2
3
4
5
6
7
8
9
10
11
/**index.js**/

import say from "./module1.js"
import * as other from "./module2.js"
//引入json
import jsonFile from "../json/user.json"

console.log(say());
console.log(other.a);
console.log(other.b);
console.log(jsonFile);

module1.js

1
2
3
4
5
6
/** module1.js **/
// 默认暴露
function sayHello() {
console.log("你好");
};
export default sayHello

module2.js

1
2
3
4
/** module2.js **/
// 分别暴露
export var a = 100;
export var b = 200;

user.json

1
2
3
4
5
/** user.json **/
{
"name":"李白",
"age":"2000"
}

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/** index.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>
hello
<script src="./dist/js/main.js"></script>
<script>
</script>
</body>
</html>

运行命令打包后的文件:

运行:

1
2
3
4
//生产模式打包
webpack ./js/index.js -o ./dist/js --mode=development
//开发模式打包
webpack ./js/index.js -o ./dist/js --mode=development

输出:

编译输出

注意:

  • es6情况下,如果引入的是一个json文件,那么引入这个json文件的时候,这个json文件是默认暴露
1
2
3
4
5
6
7
8
9
相当于你在user.json写的是
{
"name":"李白",
"age":"2000"
}
那么es6就将这个作为默认暴露,类似于 export default {
"name":"李白",
"age":"2000"
}

webpack 和webpack-cli的关系

  • vue中有vue-cli,webpack有webpack-cli , 有时候我就在想,这个没有cli和有cli有什么区别呢?不带cli的可以理解为一个工具,是死的,就如果程序一样,不双击运行永远不会运行,而cli就可以帮助我们去使用这个工具,比如是帮助我们使用vue,帮助我们去使用webpack

  • cli说通俗点就是cli是一个让你在命令行中使用webpack/vue一些工具的辅助程序。

webpack的使用

基本输出操作

  • webpack 要编译的文件 -o 输出的文件 –mode=development或者production
  • 比如 webpack ./js/index.js -o ./dist/js --mode=development 就将 js目录下的index.js文件打包输出到dist/js目录下(开发者模式)

运行后输出

输出

  • 但是原生的webpack只支持js/json,并且不支持es6转换es5,箭头函数转换等等,这些都需要依赖loader或者插件,所以我们后面就来看看怎么使用这些loader或者插件来帮助我们完成

配置文件的使用

前置了解

  • src为程序员写的源码,建立配置文件的时候不要建立在src当中!
  • 为什么需要,每一次输入这么一长段的代码很不方便,我们不可能每次都敲这个命令来完成打包吧?webpack ./js/index.js -o ./dist/js,所以我们可以使用配置文件来帮助我们完成
  • 还有就是,webpack需要对文件进行操作,所以依赖于nodejs运行,所以肯定是CMJ模块化规范!,所以你会看到,一会儿在webpack配置文件中使用require引入模块,一会在src目录下使用import引入模块的操作,一个是CommonJs模块,一个是es6模块规范~
  • 还有就是基本上要用const来接收引入的模块,是防止有人再次定义了被覆盖而导致的错误,这种错误很难找到!
  • 开发依赖和生产依赖
    • 开发依赖,帮助程序员加工处理代码的,比如说less
    • 生产依赖,帮助程序员完成某些功能的代码,比如说lodash,jQuery之类的

建立配置文件并使用

在src外面建立一个文件名字叫 webpack.config.js 的文件,官网详细配置地址

webpack.config.js配置代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* ComJs的模块化规范
*/
const path = require("path");
module.exports = {
//设置模式 development开发模式 production生产模式
mode:"development",
//webpack入口文件
entry:"./src/js/index.js",
//webpack出口(输出)文件
output:{
//设置输出文件输出在哪里 需要设置一个绝对路径!
path:path.resolve(__dirname,"dist"),
//设置出口文件的名称
//如果是 index.js,那么会输出到path目录下,不会创建文件夹
//如果是 js/index.js 就会输出到dist目录下的js目录下
filename:"js/index.js"
}
}
  • 这样子我们就不用输出很长的一段代码
  • 只需要输入webpack就可,会自动寻找当前运行目录下的webpack.config.js配置文件

运行后输出到dist文件的js目录下

解析css文件 css-loader和style-loader

  • 由于webpack不能解析css文件,只能解析js或者是json文件,但是我们想解析css,那么我们需要安装解析css的插件 - css-loader

没有安装css-loader之前,会提示You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

如图

  • 安装插件
    • npm install css-loader style-loader -D

1.首先在主入口当中添加引入css import "./css/index.css"

1
2
3
4
import "../css/index.css";//引入css文件

//当然,也可以自己命令下接收
import css from "../css/index.css";

2.然后配置webpack.config.js

  • use当中的顺序是从右到左的!

  • style-loader作用: 将css-loader解析的内容处理,生成style并挂载到head

    如图,生成style标签,并挂载到head上

  • css-loader作用: css-loader帮我们解析css文件里面的css代码

    • 比如这是在只使用了css-loader的情况下输出接收到的内容,可以看到,css-loader帮我们读取了css的内容

      只使用了css-loader的情况下输出接收到的内容

1
2
3
4
5
6
7
8
9
10
11
//loader的配置项
module: {
rules: [
//解析css
{
test: /\.css$/,
// <= 执行顺序是从右到左的,先css-loader ,再执行style-loader
use: ['style-loader', 'css-loader']
},
]
}

3.就可以直接使用了可以运行webpack命令来看看

解析less文件 less-loader

  • 安装插件
    • npm install less-loader -D

1.首先在主入口当中添加引入less import "./css/index.css"

1
2
3
4
import "../css/index.less";//引入less文件

//当然,也可以自己命令下接收
import cssLess from "../css/index.less";

2.然后修改下webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module: {
rules: [
//解析less
{
test:/\.less$/,
use:['style-loader',"css-loader","less-loader"]
},
]
}

如果想实现复用的话也可以使用 扩展运算符 ...
const styleLoader = ['style-loader',"css-loader"];
{
test: /\.less$/,
use: [...styleLoader, "less-loader"]
},

打包html文件 html-webpack-plugin(插件)

1.首先配置下webpack.config.js文件

  • 注意这里是插件的使用,所以新增加了一个配置项plugins
  • 注意有模板和没有模板的区别!
1
2
3
4
5
6
7
8
9
10
11
12
var HtmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path');

var webpackConfig = {
...
//这个是没有模板的,也就是如果自己的html文件写了内容,是会被覆盖的!
//plugins: [new HtmlWebpackPlugin()]
//这个是有模板的,以自己的html为模板来进行打包html!!!!!!!!!!!!!
// 注意这个要带 . 不然路径不对!
plugins: [new HtmlWebpackPlugin({template:"./src/index.html"})]
...
};

html-loader和html-webpack-plugin冲突导致的报错

前置

之前学习的时候是webpack4为基本,现在到webpack5了,有些问题了,当我们即使用html-webpack-plugin 又使用html-loader的时候,就会发生这个报错(至少在我现在的版本的情况下会报错!)

  • “html-loader”: “^3.1.0”,
  • “html-webpack-plugin”: “^5.5.0”
  • “webpack”: “^5.72.1”,
  • “webpack-cli”: “^4.9.2”
1
2
3
4
ERROR in   Error: Child compilation failed:
Module not found: Error: Can't resolve '../dist/js/index.js' in 'D:\develop\phpstudy_pro\WWW\webpackstudyagain\src':
Error: Can't resolve '../dist/js/index.js' in 'D:\develop\phpstudy_pro\WWW\webpackstudyagain\src'
ModuleNotFoundError: Module not found: Error: Can't resolve '../dist/js/index.js' in 'D:\develop\phpstudy_pro\WWW\webpackstudyagain\src'

冲突报错解决

  • 原来的index.html改名为index.ejs然后webpack.config.js修改下即可
1
2
3
4
5
6
7
8
9
//loader的配置项
module: {
...
//原来的改为即可
//plugins:[new HtmlWebpackPlugin({template:"./src/index.html"}),]
plugins:[new HtmlWebpackPlugin({template:"./src/index.ejs"}),]
...
},

  • 如果想在ejs引入图片文件并实现后期打包的话,就需要使用<%= require('图片位置') %>
1
2
3
4
5
6
<body>
<!-- <img src="./imgs/lh.jpg"> 不用这个-->
<!-- 使用这个代替 -->
<img src=" <%= require('./imgs/lh.jpg')%> ">

</body>

webpack5使用asset module

  • 在webpack5之前,我们url-loader、file-loader、raw-loader来完成操作
  • 现在webpack5自带的asset-module就可以实现以前的功能
  • 之前通过use来使用这些loader,asset module通过type来完成
  • 官网(英文)的介绍

功能替换

  • asset/resource
    • 将资源分割为单独的文件,并导出url,就是之前的 file-loader的功能
    • 官网关于此的api
  • asset/inline
    • 将资源导出为dataURL(url(data:))的形式,之前的 url-loader的功能
  • asset/source
    • 将资源导出为源码(source code). 之前的 raw-loader 功能
  • asset
    • 自动选择导出为单独文件或者 dataURL形式(默认为8KB)

打包样式中的文件-方法1-asset/resource

类似于file-loader相当于只是对文件进行了重命名,不具有转base64功能

设置type为asset/resource

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module: {
rules: [
//配置解析样式中图片
{
test:/\.(png|jpg|gif|bmp|jpeg|webp)$/,
type:'asset/resource',
//配置项目
generator:{
//设置处理输出的路径为 dist下的imags (也就是dist/imags)
//并且设置图片名称为 选取hash值前五位
filename:"imgs/[hash:5][ext]"
}
}
]
},

打包样式中的文件-方法2-asste

类似于url-loader,可以设置图片小于设定的大小后进行base64编码

设置type为asset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
module: {
rules: [
//配置解析样式中图片
{
test:/\.(png|jpg|gif|bmp|jpeg|webp)$/,
type:'asset',
// 转base64的条件
parser: {
// 转base64的条件,当小于8kb的时候就转化为base64
dataUrlCondition: {
maxSize: 8 * 1024, // 8kb
}
},
//配置项目
generator:{
//设置处理输出的路径为 dist下的imags (也就是dist/imags)
//并且设置图片名称为 选取hash值前五位
filename:"imgs/[hash:5][ext]"
}
}
]
},

使用file-loader url-loader的时候会出现多出来一部分

  • 将type设置为javascript/auto
1
2
3
4
5
6
7
8
9
10
11
12
{
test: /\.(jpg|png|gif)$/,
loader: 'url-loader',
options: {
esModule: false, // webpack5默认开启esModule 手动关闭
// 图片大小小于8kb,就会被base64处理
// 优点:减少请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
limit: 8 * 1024,
},
type: 'javascript/auto' // 阻止webpack5中asset
}

处理html文件的图片 html-loader

不处理html文件图片时候打包后的效果

发现并没有将html当中的图片进行打包

没有处理html文件图片

处理步骤和效果

1.首先安装loader: npm install html-loader -D

2.然后配置webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
//loader的配置项
module: {
rules: [
//配置解析html中的图片<img>标签资源
{
test:/\.(html)$/,
use:{
loader:"html-loader",
}
}
]
},

3.然后就可以测试下是否正常了

配置完成后被正确的打包和引入了

打包其他资源(比如说字体图标,mp4等资源)

  • 有时候我们使用了阿里图标字体库,就必须要使用到ttf字体资源,所以我们就要考虑这些资源的打包

webpack5的使用 asset/resource

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module: {
rules: [
//配置解析其他资源文件,比如说图标字体
//与其说是解析,不如说是搬运下
{
//设置排除列表
exclude:/\.(html|less|css|png|jpg|bmp|js|gif|json|jped|webp|ejs)$/,
type:"asset/resource",
generator:{
filename:"media/[hash][ext]"
}
}
]
}

注意

​ 使用这个asset/resource的时候,不知道是不是版本问题还是我配置的问题,老是出现__webpack_public_path__ = __webpack_base_uri__ = htmlWebpackPluginPublicPath; 这个没有用的文件和文件内容,很奇怪,,,,,,

​ 之前用webpack4的时候就没有,可能是因为是我写这个的时候使用的都是asset或者asset/resource来处理,而没有使用file-loaderurl-loader来处理的原因吧

多出来的

webpack使用webpack-dev-server

  • 安装,最好是全局和局部都安装!!!! (带指令集的最好全局安装)
    • npm install webpack-dev-server -D
    • npm install webpack-dev-server -g

1.首先 在配置对象当中添加 devServer 配置选项

  • 热更新(热模替换): 当内容发生变化的时候,只重新编译变化了的部分,而不会引发整体的编译更新
  • 不开启热更新的话,当内容发生变化的时候,就会全部重新编译全部更新

webpack.config.js

1
2
3
4
5
6
7
8
9
module.exports = {
...
devServer:{
port:5000,//开启服务器的端口号,
open:true,//编译完成是否自动打开浏览器
hot:true,//开启模块热更新(热模替换)
},
...
}

2.使用

后面就可以了,要使用这个webpack-dev-server,就只需要把webpack 改为webpack-dev-server即可

使用webpack-dev-server命名

生产环境

  • 之前如果已经配置完成了,那么开发环境就可以用了,开发我们不讲究什么兼容性啊,什么压缩啊,而生产环境就需要
  • 所以我们可以准备二套webpack的配置文件,一套用于生产,一套用于开发
  • 将之前写的配置文件配置为生产环境

准备二套配置文件

  • 建立config文件夹,里面包括二个文件
  • webpack.dev.js文件 用于开发环境
  • webpack.prod.js文件 用于生产环境
wepack.dev.js文件
webpack4的时候(参考下)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

const styleLoader = ['style-loader', 'css-loader'];

module.exports = {
//五大核心概念在这里都会被陆续配置
mode: "development", //开发模式还是生产模式
entry: "./src/js/index.js", //入口文件
//出口文件
output: {
//设置出口文件的输出路径
path: path.resolve(__dirname, "dist"),
//设置出口文件名称
// filename:"index.js"
filename: "js/index.js", //这样子写js文件就会被放入到js当中,注意不能/js/index.js!
},
//里面配置一个个的loader
module: {
rules: [
//css-loader的配置
{
test: /\.css$/, //指明要处理的文件类型
//执行顺序的从右到左的!
// 简写
use: [...styleLoader]
},
// less-loader配置
{
test: /\.less$/,
use: [...styleLoader, "less-loader"]
},
// 配置解析样式中的图片 file-loader
// {
// test:/\.(png|jpg|gif|bmp)$/,
// use:[
// {
// loader:"file-loader",
// options:{
// outputPath:"imgs",//配置图片加工后存放的位置
// name:'[hash:5].[ext]',//配置生成图片的名字 + 后缀,
// }
// }
// ]
// },
// 配置解析样式中的图片 url-loader
{
test: /\.(png|jpg|gif|bmp)$/,
use:[
{
loader:'url-loader',
options:{
outputPath:"imgs",
name:'[hash:5].[ext]',
limit:9*1024,
}
}
]
},
//配置解析html中的图片<img>资源
{
test:/\.(html)$/,
use:{
loader:"html-loader",
}
},
//配置处理其他资源
{
exclude:/\.(html|less|css|png|jpg|jpeg|bmp|js|gif|json)$/,
use:[
{
loader:"file-loader",
options:{
outputPath:"media",
name:"[hash:5].[ext]"
}
}
]
}
]
},
//使用插件
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
}),
],
devServer:{
port:5000,//开启服务器的端口号
open:true,//编译完成自动打开浏览器
hot:true,//开启模块热更新(热模替换)
}
}
webpack5的时候(这里以这套为例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
* ComJs的模块化规范
*/
const path = require("path");
//html打包插件
var HtmlWebpackPlugin = require('html-webpack-plugin');

//复用
const styleLoader = ['style-loader', "css-loader"];
module.exports = {
//设置模式 development开发模式 production生产模式
mode: "development",
//webpack入口文件
entry: "./src/js/index.js",
//webpack出口(输出)文件
output: {
//设置输出文件输出在哪里
path: path.resolve(__dirname, "dist"),
//设置出口文件的名称
//如果是 index.js,那么会输出到path目录下,不会创建文件夹
//如果是 js/index.js 就会输出到dist目录下的js目录下
filename: "js/index.js"
},
//loader的配置项
module: {
rules: [
//解析css
{
test: /\.css$/,

// <= 执行顺序是从右到左的,先css-loader ,再style-loader
use: [...styleLoader],
},
//解析less
{
test: /\.less$/,
use: [...styleLoader, "less-loader"],

},
//配置解析样式中图片
{
test: /\.(png|jpg|gif|bmp|jpeg|webp)$/,
type: 'asset',
// 转base64的条件
parser: {
// 转base64的条件
dataUrlCondition: {
maxSize: 8 * 1024, // 8kb
}
},
//配置项目
generator: {
//设置处理输出的路径为 dist下的imags (也就是dist/imags)
//并且设置图片名称为 选取hash值前五位
filename: "imgs/[hash:5][ext]"
}
},
//配置解析html中的图片<img>标签资源
{
test: /\.(html)$/,
use: {
loader: "html-loader",
}
},
//配置解析其他资源文件,比如说图标字体
//与其说是解析,不如说是搬运下
{
//设置排除列表
exclude: /\.(html|less|css|png|jpg|bmp|js|gif|json|jped|webp|ejs)$/,
type: "asset/resource",
generator: {
filename: "media/[hash][ext]"
}
}
]
},
//插件的配置项
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.ejs"
}),
],
devServer:{
port:5000,//开启服务器的端口号,
open:true,//编译完成是否自动打开浏览器
hot:true,//开启模块热更新(热模替换)
}
}

使用package.json当中运行脚本 这样子就不用每次都输入很长一段代码了

  • 在webpack中,当运行webpack的时候,可以指明配置文件在哪里,使用 --config就可以指明,否者的话就去当前运行目录下寻找是否有webpack.config.js文件!

    • 比如 webpack --config ./config/webpack.dev.js 就指明webpack的配置文件在哪里
  • 在package.json当中添加script配置项

1
2
3
4
"scripts": {
"start": "webpack-dev-server --config ./config/webpack.dev.js",
"build": "webpack --config ./config/webpack.prod.js"
}

​ 后期即可通过npm run start来进行start当中的命令,通过npm run build来运行build命令!

​ 提醒下:~如果script当中是以start的key值,那么可以简写就可以运行命令,直接npm start就可以,而其他的不可以!

提取css为单独的文件 mini-css-extract-plugin

webpack4测试可以css可以结合less使用,webpack5莫名其妙less无法和css结合…我这有问题!!!!!!!!!!!!

webpack4测试可以css可以结合less使用,webpack5莫名其妙less无法和css结合…我这有问题!!!!!!!!!!!!

webpack4测试可以css可以结合less使用,webpack5莫名其妙less无法和css结合…我这有问题!!!!!!!!!!!!

  • 之前的css,都是包含在js了,通过style-loader css-loader来进行解析使用,但是我们后期打包想分离,css就是css,js就是js
  • 就需要使用插件mini-css-extract-plugin
  • 复习下 style-loader的用处, 就是将js当中的css创建生成标签 ,然后插入到head
  • 关于此插件的api

1.安装

1
npm install --save-dev mini-css-extract-plugin

2.配置loader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//引入mini-css-extract-plugin,用于提取css为单独文件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
{
// 处理less资源
test: /\.less$/,
exclude:/node_modules/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
]
},

{
// 处理css资源
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
]
}

3.配置插件

1
2
3
4
5
6
7
8
9
10
11
module.exports = {
...
//插件的配置项
plugins: [
//提取css文件
new MiniCssExtractPlugin({
filename: "./css/index.css",
}),
],
...
}

3.使用 在配置了package.json的情况下,直接npm run build即可

测试正常,没有出现异常

css兼容性处理

  • 注意,修改下打包的配置项目为开发模式 mode = production ,否者不会处理兼容性问题(因为开发模式要什么兼容性,生产环境才要兼容性)

1.安装loader

1
npm install postcss postcss-loader postcss-preset-env -D

**2.定义通用配置 **因为css和less样式文件都要进行兼容性处理,所以我们定义好一个通用的配置:~ (相当于告诉这个工具,要兼容到哪些浏览器) ~!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 配置一个styleLoader,处理less和css时都会使用
const styleLoader = [MiniCssExtractPlugin.loader, 'css-loader', {
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"postcss-preset-env",
{
// Options
},
],
],
},
},
},
];

3.修改css-loader和less-loader配置

1
2
3
4
5
6
7
8
9
10
{
// 处理css资源
test: /\.css$/,
use: [...styleLoader]
},
{
// 处理less资源
test: /\.less$/,
use: [...styleLoader, 'less-loader']
},

4.配置package.json,在其中追加browserslist配置,通过配置加载指定的css兼容性样式

  • browserslist 是一套描述产品目标运行环境的工具,它被广泛用在各种涉及浏览器/移动端的兼容性支持工具中

  • 若出现版本不兼容,或配置不正确的错误,那么需更换依赖包版本: npm i less-loader@5 postcss-loader@3

代码: vue脚手架用的就是这一套~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//注意,package.json不可以有注释,记得删除!
"browserslist": {
// 开发环境
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
// 生产环境:默认是生产环境
"production": [
">0.2%", //兼容市面上99.8%的浏览器
"not dead", //"死去"的浏览器不做兼容,例如IE8
"not op_mini all",//不做opera浏览器mini版的兼容
"ie 10" //兼容IE10
]
}

如图配置完成在package.json中

5.然后重新运行 npm run build 即可

可以看到,这里的display:flex自动添加了前置,就是做了下兼容性处理

js语法转换

  • 概述:将浏览器不能识别的新语法转换成原来识别的旧语法,做浏览器兼容性处理,比如说箭头函数

1.安装loader

1
npm install babel-loader @babel/core @babel/preset-env  -D

2.配置loader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['@babel/preset-env']
}
}
}
]
}

3.就可以啦,然后直接 npm run build就可以了

如图示例转换了箭头函数

js兼容性处理

  • 处理babel无法处理的~,比如说js语法转换无法处理 promise,而如果做了js语法兼容性处理是可以处理promise的,(注:ie11不使用兼容性处理的无法使用promise的!)

  • 注意从 7.4 开始,就不推荐使用 @babel/polyfill 了,但是这里依旧记录下这个库的使用教程和官方推荐

babel7.4+版本的js兼容性处理
1.安装
1
npm install babel-loader @babel/core @babel/preset-env core-js -D
2.使用

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
module.exports = {
mode: "production",
//loader
module: {
rules: [
//处理js文件
{
test: /\.js$/,
exclude: /node_modules/, //排除node_modules
use: [
//js兼容性处理
{
loader: "babel-loader",
options: {
presets: [
//别漏掉了这个括号
["@babel/preset-env",
{
// 按需加载
useBuiltIns: 'usage',
// 指定core-js版本 ,安装的时候我这里为"core-js": "^3.22.8",
corejs: {
version: 3
},
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
]
}
},
]
},
]
},
}
3.注意

如果出现提示To be a valid preset, its name and options should be wrapped in a pair of brackets 或者RROR in ./src/app.ts Module build failed (from ./node_modules/babel-loader/lib/index.js):Error: [BABEL] D:\develop\phpstudy_pro\WWW\tpyescriptStudy\05_snake\src\app.ts: Unknown option: .useBuiltIns. Check out https://babeljs.io/docs/en/babel-core/#options for more information about options.

可能是因为少了括号,这位老哥一语道破

一图道破

我的ts结合babel

ts结合babel

4.效果

打包后相比@babel/poplyfill库明显减少

打包后相比@babel/poplyfill库明显减少

promise语法也正常输出在ie浏览器

promise语法也正常输出

babel7.4以下 js兼容性处理-@babel/polyfill库的使用

**缺点:!**这个插件会将所有的兼容性代码全部引入,会导致打包后文件体积变大!!!!

1.安装
1
npm install @babel/polyfill -D

安装的时候会提示这些,表示@babel/polyfill不推荐使用

1
2
3
npm WARN deprecated @babel/polyfill@7.12.1: 🚨 This package has been deprecated in favor of separate inclusion of a polyfill and regenerator-runtime (when needed). See the @babel/polyfill docs (https://babeljs.io/docs/en/babel-polyfill) for more information.

npm WARN deprecated core-js@2.6.12: core-js@<3.4 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.

官网对于此的介绍: 从 7.4 开始,就不推荐使用 @babel/polyfill 了,但是这里依旧记录下这个库的使用教程

从 7.4 开始,就不推荐使用 @babel/polyfill 了

2.webpack入口文件处引入
  • 比如我webpack的入口是src\js\index.js,那么我就在这文件夹添加import '@babel/polyfill'; // 包含ES6的高级语法的转换 就可以
3.使用

没有js兼容性处理前IE11的输出(promise测试)

没有js兼容性处理前IE11的输出(promise测试)

使用js兼容性处理后IE11的输出(promise测试)

使用js兼容性处理后IE11的输出(promise测试)

4.效果

测试代码

1
2
3
4
5
6
7
setTimeout(() => {
new Promise((resolve, reject) => {
resolve("动感超人" + 900)
}).then((data) => {
console.log(data);
})
}, 900);

不过体积有点大

打包后体积

js语法检查

1.安装loader

1
npm install eslint-loader eslint -D

2.安装检查规则库

备注:eslint-config-airbnb-base定制了一套标准的、常用的js语法检查规则,推荐使用

1
npm install eslint-config-airbnb-base eslint-plugin-import -D

3.配置webpack

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module.exports = {
//loader的配置项
module: {
rules: [
//语法检查功能
{
// 对js进行语法检查
test: /\.js$/,
exclude: /node_modules/,//排除这个文件
// 优先执行
enforce: 'pre',//优先执行 只要webpack启动时 尽可能先执行
loader: 'eslint-loader',
options: {
fix: true //若有问题自动修复,重要!!!!
}
}
]
},
}

4.配置package.json

注意安装语法规则库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
"eslintConfig": {
"extends": "airbnb-base",
"env": {
"browser": true
}
}

//说明
"eslintConfig": {
"extends": "airbnb-base", //直接使用airbnb-base提供的规则 需要下载的
"env": {
"browser": true//如果运行环境不是浏览器 则运行环境为node 此时需要将这个改为false
}
}

5.使用

打包的时候自动运行

如图,我这里检测到的不符合语法规范的问题

检测到的错误

压缩css(对于html,js,webpack4都已经默认压缩了)

1.安装

webpack4的时候使用这个 官网api

1
npm install optimize-css-assets-webpack-plugin -D

webpack5的时候使用这个 官网api

1
npm install css-minimizer-webpack-plugin --save-dev

2.引入插件

webpack4的时候使用这个

1
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');	

webpack5的时候使用这个

1
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

3.配置插件

webpack4的optimize-css-assets-webpack-plugin配置

1
2
3
4
5
6
7
8
9
10
11
module.exports = {
//插件的配置项
plugins: [
//压缩css插件
new OptimizeCssAssetsPlugin({
cssProcessorPluginOptions: {
preset: ['default', { discardComments: { removeAll: true } }],//移出所有注释
},
}),
]
}

webpack5的css-minimizer-webpack-plugin配置

1
2
3
4
5
6
7
8
9
10
11
12
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
optimization: {
minimizer: [
new CssMinimizerPlugin(),
],
},
//使用压缩css插件
plugins: [new MiniCssExtractPlugin()],
};

注意!注意!注意!注意!注意!

​ 在webpack5中,不需要手动引入uglify插件,只需配置modeproduction就可以压缩js代码。但是,如果用了css-minimizer-webpack-plugin插件去压缩css文件,js的压缩就会失效,所以使用terser-webpack-plugin插件去压缩js代码

​ (我这边反正就是二个一起使用是报错``,这里记录下)

我使用的时候报错记录,可能是提取css的时候遗留下来的问题吧,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ERROR in main.css
main.css from Css Minimizer plugin
Error: Unexpected '/'. Escaping special characters with \ may help.
at D:\develop\phpstudy_pro\WWW\webpackstudyagain\main.css:28:1
at Root._error (D:\develop\phpstudy_pro\WWW\webpackstudyagain\node_modules\postcss-selector-parser\dist\parser.js:174:16)
at Root.error (D:\develop\phpstudy_pro\WWW\webpackstudyagain\node_modules\postcss-selector-parser\dist\selectors\root.js:43:19)
at Parser.error (D:\develop\phpstudy_pro\WWW\webpackstudyagain\node_modules\postcss-selector-parser\dist\parser.js:740:21)
at Parser.unexpected (D:\develop\phpstudy_pro\WWW\webpackstudyagain\node_modules\postcss-selector-parser\dist\parser.js:758:17)
at Parser.combinator (D:\develop\phpstudy_pro\WWW\webpackstudyagain\node_modules\postcss-selector-parser\dist\parser.js:656:12)
at Parser.parse (D:\develop\phpstudy_pro\WWW\webpackstudyagain\node_modules\postcss-selector-parser\dist\parser.js:1101:14)
at Parser.loop (D:\develop\phpstudy_pro\WWW\webpackstudyagain\node_modules\postcss-selector-parser\dist\parser.js:1043:12)
at new Parser (D:\develop\phpstudy_pro\WWW\webpackstudyagain\node_modules\postcss-selector-parser\dist\parser.js:164:10)
at Processor._root (D:\develop\phpstudy_pro\WWW\webpackstudyagain\node_modules\postcss-selector-parser\dist\processor.js:53:18)
at Processor._runSync (D:\develop\phpstudy_pro\WWW\webpackstudyagain\node_modules\postcss-selector-parser\dist\processor.js:100:21)

ERROR in ./css/index.css
./css/index.css from Css Minimizer plugin
Error: Unexpected '/'. Escaping special characters with \ may help.
at D:\develop\phpstudy_pro\WWW\webpackstudyagain\css\index.css:28:1
at Root._error (D:\develop\phpstudy_pro\WWW\webpackstudyagain\node_modules\postcs

打包和运行进度条功能

1.安装

1
npm install webpackbar -D

2.引入插件

1
const WebpackBar = require('webpackbar');

3.配置添加到webpack配置文件

1
2
3
4
5
6
7
module.exports = {
//插件的配置项
plugins: [
//webpack打包和运行的时候进度条
new WebpackBar(),
]
}

4.然后就有效果了

进度条效果

webpack当中use的几种形式

  1. use为一个数组

    • 里面可以为一个个的字符串,比如 use:["style-loader","css-loader"]

    • 也可以对象掺杂着字符串,比如 use:[{...},"css-loader"]

    • 也可以全部为对象,比如use:[{...},{...},{...}]

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      module.exports = {
      module:{
      rules:[
      //分割下 use全部为对象
      {
      test: /\.less$/,
      use: [{
      loader: "style-loader"
      }, {
      loader: "css-loader"
      }, {
      loader: "less-loader"
      }]
      },
      ]
      }
      }
  2. use为一个对象,代表使用这一个loader

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    module: {
    rules: [
    //use为一个对象的情况
    {
    test: /\.m?js$/,
    exclude: /node_modules/,
    use: {
    loader: 'babel-loader',
    options: {
    presets: [
    ['@babel/preset-env', { targets: "defaults" }]
    ]
    }
    }
    },
    //其他loader
    ]
    }

webpack配置对象当中的resolve

resolve.extensions

  • 使用 import 引入其他模块时,如果不加上后缀扩展名(extension)且找不到对应的文件时,webpack 就会尝试根据 extensions 数组,依次加上扩展名看看能不能匹配到一个文件,直到找到为止。如果找不到则会报错。

  • 默认值为: ['.js','.json','wasm']

  • 功能就是,不加后缀名的情况下,依次匹配,直到匹配所有的还匹配不到就报错

  • 所以你经常可以看到一些人导入模块不添加后缀名,直接 import xxx from “./abc/a”,就是resolve.extensions起到的作用!

如图,当导入模块import * as all from "./food"的时候,发现模块不存在,会依次去寻找,然后后缀都匹配完了还是找不到就报错

推荐几款好用的npm

rimraf —- 快速删除node_modules文件夹

官网地址

1.安装

1
npm install rimraf -g

2.使用

在所属文件夹下使用cmd指令下,进入所需删除的node_modules文件夹的位置,再输入指令

1
rimraf node_modules

clena-webpack-plugin — 每次打包删除dist目录

官网地址

1.安装

1
npm install --save-dev clean-webpack-plugin

2.使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

const webpackConfig = {
plugins: [
/**
* All files inside webpack's output.path directory will be removed once, but the
* directory itself will not be. If using webpack 4+'s default configuration,
* everything under <PROJECT_DIR>/dist/ will be removed.
* Use cleanOnceBeforeBuildPatterns to override this behavior.
*
* During rebuilds, all webpack assets that are not used anymore
* will be removed automatically.
*
* See `Options and Defaults` for information
*/
new CleanWebpackPlugin(),
],
};

module.exports = webpackConfig;

webpack箭头函数导致第一行xx位置报错

  • 解决 : 添加 environment:{ arrowFunction:false }

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
mode: "production",
entry: "./src/app.ts",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/index.js", //文件名
environment: {
//不使用箭头函数
arrowFunction: false,
//不使用const
const: false
}
},

}

设置前编译

设置前

设置后编译

设置后

loader和plugin作用和区别

  • loader: 是文件加载器,可以加载资源文件,并对这些文件进行一些处理,比如:编译,压缩等,
  • plugin:webpack在运行的生命周期会广播出许多事件,plugin可以监听这些事件,在合适的时机中通过webpack提供的api改变输出结果

区别:

  • loader是将A文件进行编译形成B文件,这里操作的是文件,A.less => A.css
  • plugin是用于在webpack打包编译过程里,在对应的事件节点里执行自定义操作,比如资源管理、bundle文件优化等操作