webpack5基础

368 阅读10分钟

一、为什么需要打包工具

开发时,我们会使用vue、react等框架,ES6语法,less/sass等css预处理器等等这些语法进行开发。这样的代码必须要编译成浏览器可以识别的js、css等语法,才能运行,所以需要打包工具帮我们做这些事。除此之外,打包工具还能压缩代码、做兼容处理、提升代码性能等。

1、 有哪些打包工具

  1. Grunt
  2. Gulp
  3. Parcel
  4. Webpack
  5. Rollup
  6. Vite ...

2、 webpack是什么

webpack是一个静态资源打包工具。

它会以一个或多个文件作为打包的入口,将我们整个项目所有文件编译成一个或多个文件输出。

输出的文件叫做bundle,可以运行在浏览器端。

二、基本使用

使用webpack将多个模块打包

开始使用

1、目录结构

webpack_code # 项目根目录(执行npm init -y时会以该文件名作为name属性的值)
    └── src # 项目源码目录
        ├── js # js文件目录
        │   ├── count.js
        │   └── sum.js
        └── main.js # 项目主文件

2、创建文件

count.js

export default function count(x, y) {
  return x - y
}

sum.js

export default function sum(...args) {
  return args.reduce((p, c) => p + c, 0)
}

main.js

import count from './js/count'
import sum from './js/sum'

console.log(count(2, 1))
console.log(sum(1, 2, 3, 4))

3、下载依赖

这里要注意,package.jsonname字段的值不能是webpack,否则会报错

npm i webpack webpack-cli -D

4、启用webpack

npx和npm的区别:

  1. npx侧重执行,智能识别模块,如果有就使用;没有就临时下载,用完删除。
  2. npm侧重安装和卸载模块
  3. npx相比npm,运行一个本地的安装包时,不用配置路径

配置package.json

  "scripts": {
    "dev": "npx webpack ./src/main.js --mode=development",
    "prod": "npx webpack ./src/main.js --mode=production"
  },

开发模式:

npm run dev

生产模式:

npm run prod

5、输出文件

执行webpack命令,会将多个文件打包,输出到dist文件夹下,此时dist文件夹下的main.js就可以在浏览器环境中使用了。

但是要注意,webpack本身功能较少,只能处理js文件,一旦遇到css等资源会报错,还需要学习如何处理其他资源。

三、基本配置

1、五大核心概念

  1. entry(入口) 指示webpack从哪个文件开始打包

  2. output(输出) 指示webpack打包完的文件输出到哪里去,如何命名

  3. loader(加载器) webpack本身只能处理js、json等资源,其他资源需要借助loader才能解析

  4. plugins(插件) 扩展webpack的功能

  5. mode(模式) 主要有两种模式:

  • 开发模式:development
  • 生产模式:production

2、webpack配置文件

在项目根目录下创建文件:webpack.config.js

const path = require('path')
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  module: {
    rules: []
  },
  plugins: [],
  mode: 'development'
  // mode: 'production',
}

运行指令:npx webpack 会自动在根目录下找到webpack.config.js文件,按照配置项进行打包

四、开发模式介绍

开发时使用的模式mode: 'development'

这个模式下主要做两件事:

  1. 编译代码,使浏览器能够识别运行(开发时有样式资源、字体图标、图片资源、html资源等,webpack默认都不能处理这些资源,需要加载配置来编译这些资源)
  2. 代码质量检查,树立代码规范

五、处理样式资源

介绍

前面已经多次提到,webpack本身是不能识别样式资源的,所以我们要借助loader来帮助webpack解析样式资源

1、处理css资源

1. 下载包

npm i css-loader style-loader -D
  • css-loader:负责将css文件编译成webpack能识别的模块
  • style-loader:动态创建一个style标签,里面放置webpack中css模块内容

2. 配置

  module: {
    rules: [
      {
        test: /\.css$/, // 匹配 .css 结尾的文件
        use: ['style-loader', 'css-loader'] // 执行顺序:从右到左
      }
    ]
  }

3. 添加css资源

scr/css/index.css

.box {
  width: 100px;
  height: 100px;
  background-color: yellowgreen;
}

scr/main.js

// 引入 css 资源,Webpack才会对其打包
import "./css/index.css"

public/index.html

    <div class='box'></div>

4. 运行指令

npx webpack

webpack找到.css结尾的文件,会首先通过css-loader将css文件编译成commonjs模块到js中,然后通过style-loader创建一个style标签,插入到head标签中,style标签中放的就是css-loader编译后的模块内容

2、处理less资源

1. 下载包

npm i less less-loader -D
  • less:less-loader依赖less进行编译
  • less-loader:将less文件编译成css文件

2. 配置

      {
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader']
      }

3. 添加less资源

src/less/index.less

@color: greenyellow;
.less-box {
  width: 100px;
  height: 100px;
  background-color: @color;
  > p {
    color: red;
  }
}

4. 运行指令

npx webpack

webpack找到.less结尾的文件,首先通过less-loader将less文件转为css文件,再用css-loader将css文件转为webpack可识别的commonjs模块,再用style-loader创建一个style标签将css放进去

3、处理sass和scss资源

1. 下载包

npm i sass sass-loader -D
  • sass:sass-loader依赖sass进行编译
  • sass-loader:将sass文件编译成css文件

2. 配置

      {
        test: /\.s[ac]ss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      }

3. 添加sass资源

src/sass/index.sass

$purple: purple
.sass-box
  width: 100px
  height: 100px
  background-color: $purple
  > p
    color: red

src/sass/index.scss

$deeppink: deeppink;
.scss-box {
  width: 100px;
  height: 100px;
  background-color: $deeppink;
  > p {
    color: red;
  }
}

src/main.js

import './sass/index.sass'
import './sass/index.scss'

public/index.html

    <div class="sass-box"><p>段落</p></div>
    <div class="scss-box"><p>段落</p></div>

4. 运行指令

npx webpack

webpack找到.sass.scss结尾的文件,首先通过sass-loader将sass/scss文件转为css文件,再用css-loader将css文件转为webpack可识别的commonjs模块,再用style-loader创建一个style标签将css放进去

4、处理styl资源

1. 下载包

npm i stylus stylus-loader -D
  • stylus:stylus-loader依赖stylus进行编译
  • stylus-loader:将styl文件编译成css文件

2. 配置

      {
        test: /\.styl$/,
        use: ['style-loader', 'css-loader', 'stylus-loader']
      }

3. 添加styl资源

src/styl/index.styl

/* 可以省略大括号、冒号、分号 */
.styl-box
  width 100px
  height 100px
  background-color red

src/main.js

import './styl/index.styl'

4. 运行指令

npx webpack

webpack找到.styl结尾的文件,首先通过stylus-loader将styl文件转为css文件,再用css-loader将css文件转为webpack可识别的commonjs模块,再用style-loader创建一个style标签将css放进去

六、处理图片资源

在webpack4时,图片资源通过file-loaderurl-loader处理。在webpack5中,这两个功能内置到webpack中了,只需要简单配置即可处理图片资源

1. 配置

      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: 'asset'
      }

2. 添加图片资源

  • src/images/1.jpeg(4.85kb)
  • src/images/2.png(194kb)
  • src/images/3.gif(128kb)

3. 使用图片资源

src/css/index.css

.box {
  width: 100px;
  height: 100px;
  background-image: url('../images/1.jpeg');
  background-size: contain;
}

src/less/index.less

.less-box {
  width: 100px;
  height: 100px;
  background-image: url('../images/2.png');
  background-size: contain;
}

src/sass/index.scss

.scss-box {
  width: 100px;
  height: 100px;
  background-image: url('../images/3.gif');
  background-size: contain;
}

4. 运行指令

npx webpack

效果: image.png

5. 输出资源情况

此时查看dist目录,会发现多了两张图片资源,因为webpack会将所有打包好的资源输出到dist目录下。

为什么没有样式资源?

因为经过style-loader的处理,样式资源打包到main.js中去了,没有额外输出出来

6. 对图片资源进行优化

配置:

      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
          }
        }
      }

好像webpack5默认已经对小于10kb的图片自动转为base64了。现在我尝试将10改为130,将dist目录删除,执行npx webpack,输出的dist目录中只有一张图片,2.png,1.jgeg和3.gif都转为base64了,这2张图片以dataUrl形式内置到js中了

image.png

image.png

image.png

优点:减少请求数量 缺点:体积变得更大

七、修改输出资源的名称和路径

1、配置

  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'static/js/main.js' // 将js文件输出到 static/js 目录中
  }
  
  
        {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 130 * 1024 // 小于130kb的图片会被base64处理
          }
        },
        generator: {
          filename: 'static/imgs/[hash:8][ext][query]'
        }
      }
  1. filename: 'static/imgs/[hash:8][ext][query]' 将图片文件输出到 static/imgs 目录中
  2. [hash:8][ext][query] 图片命名
  3. [hash:8]:hash值取8位
  4. [ext]:使用之前的文件扩展名
  5. [query]:添加之前的query参数

2、修改index.html

    <script src="../dist/static/js/main.js"></script>

3、运行指令

npx webpack

生成目录如下:

├── dist
    └── static
         ├── imgs
         │    └── 7003350e.png
         └── js
              └── main.js

八、自动清空上次打包资源

配置:

  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'static/js/main.js', // 将js文件输出到 static/js 目录中
    clean: true
  }

九、处理字体图标资源

1. 配置

      {
        test: /\.(ttf|woff2?)$/,
        type: 'asset/resource',
        generator: {
          filename: 'static/media/[hash:8][ext][query]'
        }
      }

type: 'asset/resource'type: 'asset'的区别:

  1. type: 'asset/resource'相当于file-loader,将文件转化为webpack能识别的资源,其他不做处理
  2. type: 'asset'相当于url-loader,将文件转化为webpack能识别的资源,同时小于某个大小的资源会处理成dataUrl形式

2. 添加字体图标资源

打开阿里巴巴矢量图标库,下载一个项目

将解压缩后的文件复制到src/fonts中

image.png

src/main.js

import './fonts/iconfont.css'

public/index.html

    <style>
      .icon::before {
        content: '\e61f';
        font-family: 'iconfont';
      }
    </style>
    <i class="iconfont icon-home"></i>
    <i class="iconfont icon-download"></i>
    <i class="iconfont icon-invert"></i>
    <i class="iconfont">&#xe61f;</i>
    <div class="icon"></div>

3. 运行指令

npx webpack

十、处理其他资源

1. 配置

      {
        test: /\.(ttf|woff2?|mp4|mp3|avi)$/,
        type: 'asset/resource',
        generator: {
          filename: 'static/media/[hash:8][ext][query]'
        }
      }

就是在处理字体图标资源基础上添加其他文件类型,统一处理即可

2. 运行指令

npx webpack

十一、处理js资源

前面不是介绍了webpack可以用来处理js资源了吗,为什么还要处理js资源?

这是因为webpack对js处理是有限的,只能编译js中ES模块语法,不能编译其他语句,导致js不能再IE上运行,所以需要对兼容性做一些处理。

其次在开发中,团队对代码格式有要求,不能由肉眼去检查格式,需要使用专业的工具来检查。

  • 针对代码格式,使用eslint来完成
  • 针对js兼容性处理,使用babel来完成

eslint

eslint是可组装的js和jsx检查工具。可组装意思是可以扩展配置各项功能

1. eslint配置文件

1.1 可以在项目根目录创建.eslintrc/.eslintrc.js/.eslintrc.json(任选其一),或者在package.json中添加eslintConfig

1.2 以.eslintrc.js配置文件为例:

module.exports = {
  // 解析选项
  parserOptions: {
    ecmaVersion: 6, // ES 语法版本
    sourceType: 'module', // ES 模块化
    // ecmaFeatures: { jsx: true } // ES 其他特性,如果是react项目,就需要开启jsx语法
  },
  extends: ['eslint:recommended'], // 继承eslint官方规则
  env: {
    node: true, // 启用node中全局变量
    browser: true // 启用浏览器中全局变量
  },
  // 具体检查规则
  rules: {
    'no-var': 2 // 不允许使用var定义变量
  }
  // ...
}

1.3 rules具体规则

  1. 'off'0:关闭检测
  2. 'warn'1:开启检测,警告级别,不会导致程序退出
  3. 'error'2:开启检测,错误级别,会导致程序退出

1.4 extends继承

开发中一点点写rules规则太麻烦了,可以继承现有的规则,如:

  1. eslint官方的规则:eslint:recommended
  2. vuecli官方的规则:plugin:vue/essential
  3. reactcli官方的规则:react-app

2. 在webpack中使用

2.1 下载包

npm i eslint-webpack-plugin eslint -D

2.2 定义eslint配置文件

.eslintrc.js

module.exports = {
  // 解析选项
  parserOptions: {
    ecmaVersion: 6, // ES 语法版本
    sourceType: 'module', // ES 模块化
    // ecmaFeatures: { jsx: true } // ES 其他特性,如果是react项目,就需要开启jsx语法
  },
  extends: ['eslint:recommended'], // 继承eslint官方规则
  env: {
    node: true, // 启用node中全局变量
    browser: true // 启用浏览器中全局变量
  },
  // 具体检查规则
  rules: {
    semi: 0, // 禁止使用分号
    'array-callback-return': 'warn', // 要求数组方法的回调中有return语句,否则警告
    eqeqeq: [
      1, // 要求使用 === 和 !==,否则警告
      'smart' // 除了少数情况下不会有警告
    ],
    'no-var': 2 // 不允许使用var定义变量
  }
  // ...
}

2.3 webpack.config.js中添加eslint配置

const ESLineWebpackPlugin = require('eslint-webpack-plugin')

...

  plugins: [
    new ESLineWebpackPlugin({
      context: path.resolve(__dirname, 'src') // 检测src目录下的文件
    })
  ]

2.4 运行指令

src/main.js

var res1 = count(2, 1)
var res2 = sum(1, 2, 3, 4, 5)
console.log(res1)
console.log(res2)

此时执行npx webpack,会自动去项目根目录下找到.eslintrc.js,因为设置了'no-var': 2,又使用了var,所以控制台会报错:

image.png

2.5 vscode eslint插件

以上,是在npx webpack后才发现有不符合eslint规范的代码。我们可以在vscode中下载eslint插件: image.png

可以看到,当vscode检测到不符合规范的代码,会直接给出提示: image.png

但此时,dist下的js文件也会被eslint插件检测,其实这里的代码并不需要检测,可以在项目根目录下创建.eslintignore

# 忽略dist目录下所有文件
**/dist

2.6 eslint禁用

多行代码/单行代码的错误/警告提示便会消失

/* eslint-disable */
var res1 = count(2, 1)
var res2 = sum(1, 2, 3, 4, 5)
/* eslint-enable */
console.log(res1)
console.log(res2)

console.log(1 == '1') // eslint-disable-line

babel

js编译器,将es6语法编译为更低版本的js语法,以便能够运行在旧版本的浏览器中

1. babel配置文件

1.1 可以在项目根目录创建babel.config.js/babel.config.json/.babelrc/.babelrc.js/.babelrc.json(任选其一),或者在package.json中添加babel

1.2 以babel.config.js配置文件为例:

module.exports = {
  presets: ['@babel/preset-env']
}

2. 在webpack中使用

2.1 下载包

npm i babel-loader @babel/core @babel/preset-env -D

2.2 定义babel配置文件

babel.config.js

module.exports = {
  presets: ['@babel/preset-env']
}

2.3 webpack.config.js中添加babel配置

      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules
        loader: 'babel-loader'
      }

2.4 运行指令

npx webpack

打包后的dist/static/js/main.js文件,可以看到,箭头函数等es6语法已经转换了

十二、html-webpack-plugin处理html资源,根据html模板生成一个自动引入js的html

以一个html文件作为模板,经过webpack打包后在dist目录中生成一个index.html文件

1. 下载包

npm i html-webpack-plugin -D

2. 准备一个html文件

public/template.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>html-webpack-plugin</title>
    <style>
      .icon::before {
        content: '\e61f';
        font-family: 'iconfont';
      }
    </style>
  </head>
  <body>
    <div class="box"></div>
    <div class="less-box"><p>段落</p></div>
    <div class="sass-box"><p>段落</p></div>
    <div class="scss-box"><p>段落</p></div>
    <div class="styl-box"><p>段落</p></div>
    <i class="iconfont icon-home"></i>
    <i class="iconfont icon-download"></i>
    <i class="iconfont icon-invert"></i>
    <i class="iconfont">&#xe61f;</i>
    <div class="icon"></div>
    <!-- <script src="../dist/static/js/main.js"></script> -->
  </body>
</html>

html中不需要引入js,html-webpack-plugin插件在打包时会自动引入

3. 配置

const HtmlWebpackPlugin = require('html-webpack-plugin')

...

    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'public/template.html')
    })

4. 运行指令

npx webpack

会在dist中输出一个index.html文件,并且js已经自动引入了

image.png

十三、开发服务器&自动化

以上,每次写完代码,打包时都需要运行指令npx webpack,太麻烦了,可以借助webpack-dev-server进行自动化编译

1. 下载包

npm i webpack-dev-server -D

2. 配置

  devServer: {
    host: 'localhost', // 启动服务器域名
    port: 3000, // 启动服务器端口
    open: true // 是否自动打开浏览器
  }

3. 运行指令

npx webpack serve

当使用开发服务器时,所有代码都会在内存中编译打包,不会输出到dist目录下。开发时我们只关心代码能否运行,有效果即可,至于代码会编译成什么样,我们并不需要知道

a.gif

十四、生产模式介绍

生产模式是开发完成后,将打包后的代码部署上线,这个模式下的代码需要性能更高一点

1. 准备工作

原webpack.config.js文件不需要了,根目录下创建config目录

config/webpack.dev.js

const path = require('path')
const ESLineWebpackPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: './src/main.js',
  output: {
    path: undefined, // 开发模式没有输出,不需要指定输出目录
    filename: 'static/js/main.js', // 将js文件输出到 static/js 目录中
    // clean: true // 开发模式没有输出,不需要清空输出结果
  },
  module: {
    rules: [
      {
        test: /\.css$/, // 匹配 .css 结尾的文件
        use: ['style-loader', 'css-loader'] // 执行顺序:从右到左
      },
      {
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader']
      },
      {
        test: /\.s[ac]ss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.styl$/,
        use: ['style-loader', 'css-loader', 'stylus-loader']
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 130 * 1024 // 小于130kb的图片会被base64处理
          }
        },
        generator: {
          filename: 'static/imgs/[hash:8][ext][query]'
        }
      },
      {
        test: /\.(ttf|woff2?|mp4|mp3|avi)$/,
        type: 'asset/resource',
        generator: {
          filename: 'static/media/[hash:8][ext][query]'
        }
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules
        loader: 'babel-loader'
      }
    ]
  },
  plugins: [
    new ESLineWebpackPlugin({
      context: path.resolve(__dirname, '../src') // 检测src目录下的文件
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '../public/template.html')
    })
  ],
  devServer: {
    host: 'localhost', // 启动服务器域名
    port: 3000, // 启动服务器端口
    open: true // 是否自动打开浏览器
  },
  mode: 'development'
}

config/webpack.prod.js

const path = require('path')
const ESLineWebpackPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: 'static/js/main.js', // 将js文件输出到 static/js 目录中
    clean: true
  },
  module: {
    rules: [
      {
        test: /\.css$/, // 匹配 .css 结尾的文件
        use: ['style-loader', 'css-loader'] // 执行顺序:从右到左
      },
      {
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader']
      },
      {
        test: /\.s[ac]ss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.styl$/,
        use: ['style-loader', 'css-loader', 'stylus-loader']
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 130 * 1024 // 小于130kb的图片会被base64处理
          }
        },
        generator: {
          filename: 'static/imgs/[hash:8][ext][query]'
        }
      },
      {
        test: /\.(ttf|woff2?|mp4|mp3|avi)$/,
        type: 'asset/resource',
        generator: {
          filename: 'static/media/[hash:8][ext][query]'
        }
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules
        loader: 'babel-loader'
      }
    ]
  },
  plugins: [
    new ESLineWebpackPlugin({
      context: path.resolve(__dirname, '../src') // 检测src目录下的文件
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '../public/template.html')
    })
  ],
  mode: 'production'
}

2. 运行指令

开发模式

npx webpack serve --config ./config/webpack.dev.js

生产模式

npx webpack --config ./config/webpack.prod.js

生产模式默认开启了html压缩和js压缩,但未开启css压缩,css压缩需要手动开启

3. 配置运行指令

package.json

  "scripts": {
    "start": "npm run dev",
    "dev": "npx webpack serve --config ./config/webpack.dev.js",
    "prod": "npx webpack --config ./config/webpack.prod.js"
  }

现在,启动指令:

  • 开发模式:npm start或npm run dev
  • 生产模式:npm run prod

十五、css处理

1、提取css生成单独的css文件

以上,css文件是经过css-loader将css编译后再经过style-loader创建style标签来存放样式,这样一来,如果style标签很多,会造成闪屏现象,通用的做法是将css提取出来,生成单独的css文件,通过link标签加载进来 image.png

1. 下载包

npm i mini-css-extract-plugin -D

2. 配置

webpack.prod.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const { loader: miniCssLoader } = MiniCssExtractPlugin

...

    new MiniCssExtractPlugin({
      filename: 'static/css/main.css'
    })

还要将style-loader替换为miniCssLoader

      {
        test: /\.css$/, // 匹配 .css 结尾的文件
        use: [miniCssLoader, 'css-loader'] // 执行顺序:从右到左
      }

2、css兼容性处理

1. 下载包

npm i postcss-loader postcss postcss-preset-env -D

2. 配置

webpack.prod.js

      {
        test: /\.css$/, // 匹配 .css 结尾的文件
        use: [miniCssLoader, 'css-loader', {
          loader: 'postcss-loader',
          options: {
            postcssOptions: { plugins: ['postcss-preset-env'] }
          }
        }] // 执行顺序:从右到左
      },
      {
        test: /\.less$/,
        use: [miniCssLoader, 'css-loader', {
          loader: 'postcss-loader',
          options: {
            postcssOptions: { plugins: ['postcss-preset-env'] }
          }
        }, 'less-loader']
      },
      {
        test: /\.s[ac]ss$/,
        use: [miniCssLoader, 'css-loader', {
          loader: 'postcss-loader',
          options: {
            postcssOptions: { plugins: ['postcss-preset-env'] }
          }
        }, 'sass-loader']
      },
      {
        test: /\.styl$/,
        use: [miniCssLoader, 'css-loader', {
          loader: 'postcss-loader',
          options: {
            postcssOptions: { plugins: ['postcss-preset-env'] }
          }
        }, 'stylus-loader']
      }

合并配置:

const getStyleLoaders = (loaderName) => [
  miniCssLoader,
  'css-loader',
  {
    loader: 'postcss-loader',
    options: {
      postcssOptions: { plugins: ['postcss-preset-env'] }
    },
  },
  loaderName
].filter(Boolean)


      {
        test: /\.css$/, // 匹配 .css 结尾的文件
        use: getStyleLoaders() // 执行顺序:从右到左
      },
      {
        test: /\.less$/,
        use: getStyleLoaders('less-loader')
      },
      {
        test: /\.s[ac]ss$/,
        use: getStyleLoaders('sass-loader')
      },
      {
        test: /\.styl$/,
        use: getStyleLoaders('stylus-loader')
      }

3. 控制兼容性

package.json

兼容ie8及以上

  "browserslist": ["ie >= 8"]

实际开发中一般不考虑旧版浏览器,可以设置为:

  "browserslist": ["last 2 version", "> 1%", "not dead"]

4. 运行指令

npm run prod

3、css压缩

1. 下载包

npm i css-minimizer-webpack-plugin -D

2. 配置

webpack.prod.js

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')


    new CssMinimizerPlugin()

3. 运行指令

npm run prod

十六、总结

1、以上,为什么要使用webpack?

当我们使用了vue/react等框架,使用了es6语法,使用了less/sass预处理语言等,这些语法浏览器是不认识的,还有一些浏览器版本较低,有些新的语法又不支持,因此,需要使用webpack将项目代码打包

此外,webpack还可以进行代码压缩,性能方面的提升

2、webpack有几种模式

模式对应的文件名运行指令是否输出dist目录用途
1. 开发模式webpack.dev.jsnpx webpack serve --config ./config/webpack.dev.js不输出dist目录可以借助开发服务器webpack-dev-server进行实时编译,vscode中保存时可以在浏览器端立即看到效果
2. 生产模式webpack.prod.jsnpx webpack --config ./config/webpack.prod.js输出dist目录对代码进行合并、压缩、兼容性处理等操作

开发模式和生产模式区分开后,运行指令会比较长,可以在package.json中配置运行指令

3、webpack五个核心概念

  1. entry
  2. output
  3. loader
  4. plugin
  5. mode