webpack5-基础篇

134 阅读7分钟

关于系统学习webpack5这个Flag立了快一年半了,最近突发觉得要好好完善一下自己的知识体系,终于在今年年底前有了行动。每天学一点,一周一大点。内容偏于基础,有错误的地方欢迎指正

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

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

基本使用

功能介绍

  • 开发模式:仅能编译JS中的ES Module语法
  • 生产模式:能编译JS中的ES Module语法,还能压缩JS代码(性能提升)

本身只能处理JS文件,对其他如样式文件无法处理,所以我们需要了解它更强大的配置

初始化package.json

package.json中的name不能为webpack

npm init -y

下载依赖

npm i webpack webpack-cli -D

启用webpack

  • 开发模式
npx webpack ./src/main.js --mode=development
  • 生产模式
npx webpack ./src/main.js --mode=production

npx webpack:用来运行本地安装的webpack。

./src/main.js:指定webpack从main.js开始打包,不但会打包main.js,还会将其依赖也一起打包进来

--mode=xxx:指定打包环境

基本配置

五大核心概念

entry:指定webpack从哪个文件开始打包

output:指定webpack打包好的文件输出到哪里,如何命名

loader:webpack本身只能处理js,json等资源,其他资源要借助loader才能进行解析

plugins:扩展webpack的功能

mode:生产模式/开发模式

配置文件

⭐ webpack的配置文件,要位于项目的根目录下,并且命名一定是webpack.config.js

const path = require('path'); // nodejs核心模块,专门用来处理路径问题

// Webpack 是基于 Node.js 运行的,所以采用 Common.js 模块化规范
module.exports = {
  // 入口
  entry: './src/main.js', // 相对路径
  // 输出
  output: {
    // 所有文件输出的路径
    // __dirname: nodejs的变量,代表当前文件的文件夹目录
    path: path.resolve(__dirname, 'dist'), // 绝对路径
    // 入口文件打包输出文件名
    filename: 'static/js/main.js',
  },
  // 加载器
  module: {
    rules: [
      // loader的配置
    ],
  },
  // 插件
  plugins: [
    // 三个步骤:下载 引用 new调用
    // plugin的配置
  ],
  // 模式
  mode: 'development',
};

运行

npx webpack

处理样式资源

处理Css资源

处理Css资源需要下载两个loader包

  • css-loader:负责将Css文件编译成webpack能识别的模块
  • style-loader:会动态的创建一个style标签,里面放置webpack中Css模块的内容
// 加载器
  module: {
    rules: [
      // 处理Css资源loader配置
      {
        test: /.css$/i, // 只检测.css文件 --这是一个正则表达式
        // use的执行顺序,从右到左(从下到上)
        use: ['style-loader', 'css-loader'],
      },
    ],
  },

处理Less资源

处理Less资源需要下载三个包(其中有两个是Css资源中需要,不再解释)

如果没有下载less包,则需要下载less包

  • less-loader:将less文件编译成css文件
module: {
  rules: [
  // less资源的loader配置
    {
      test: /.less$/i, // 只检测.less文件 --这是一个正则表达式
      // loader: 'xxxx', 只能使用一个loader,use可以使用多个loader
      // use的执行顺序,从右到左(从下到上)
      use: [
	'style-loader',
	'css-loader',
	'less-loader', // 将less编译成css文件
      ],
    },
  ],
<p align=left>},</p>

处理Sass/Scss资源

处理Sass资源需要下载三个包(其中有两个是Css资源中需要,不再解释)

如果没有下载sass包,则需要下载sass包

  • sass-loader:将sass/scss文件编译成css文件
module: {
	rules: [
		// sass资源的loader配置
		{
			test: /.s[ac]ss$/i, // 只检测.sass/scss文件 --这是一个正则表达式
			// use的执行顺序,从右到左(从下到上)
			use: [
				'style-loader',
				'css-loader',
				'sass-loader', // 将sass/scss编译成css文件
			],
		},
	],
},

处理Styl资源

处理Less资源需要下载三个包(其中有两个是Css资源中需要,不再解释)

如果没有下载stylus包,则需要下载stylus包

  • stylus-loader:将styl文件编译成css文件
module: {
	rules: [
		// less资源的loader配置
		{
			test: /.styl$/i, // 只检测.styl文件 --这是一个正则表达式
			// loader: 'xxxx', 只能使用一个loader,use可以使用多个loader
			// use的执行顺序,从右到左(从下到上)
			use: [
				'style-loader',
				'css-loader',
				'stylus-loader', // 将styl编译成css文件
			],
		},
	],
},

提取Css资源为单独文件——插件实现

在上面的配置中,css资源会被打包到js资源中,通过style-loader创建标签来生成样式。这样对于网站来说会出现闪屏现象,对于用户体验效果不好。我们可以通过标签来外链css资源解决这一问题。

  • 下载
yarn add mini-css-extract-plugin -D
  • 引用
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  • 配置

需要将所有用到style-loader替换成MiniCssExtractPlugin.loader,然后在plugins中调用MiniCssExtractPlugin

plugins: [
  // 提取css成单独文件
  new MiniCssExtractPlugin({
    // 定义输出文件名和目录
    filename: "static/css/main.css",
  }),
],

Css兼容性处理

  • 下载
yarn add postcss-loader postcss postcss-preset-env -D
  • 配置
// postcss-loader配置对象要放在css-loader后面,less-loader/sass-loader/stylus-loader前面
module: {
  rules: [
    {
      test: /.css$/i,
      use: [
        MiniCssExtractPlugin.loader, 
        'css-loader', 
        {
          loader: "postcss-loader",
          options: {
            postcssOptions: {
              plugins: [
                "postcss-preset-env", // 能解决大多数样式兼容性问题
              ],
            },
          },
        },
      ],
    },
  ],
}

我们还可以在 package.json 文件中添加 browserslist 来控制样式的兼容性做到什么程度。

// 浏览器的兼容程度配置
{ 
  // "browserslist": ["ie >= 8"] // 兼容ie以上浏览器
  // "browserslist": ["last 2 version", "> 1%", "not dead"] // 实际开发做到这个程度即可
  // 所有浏览器最近2个版本,覆盖99%的浏览器,且没有“死”的
}

Css压缩 - 插件实现

  • 下载
yarn add css-minimizer-webpack-plugin -D
  • 配置
// 引用
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin');

// 调用
plugins: {
  // css压缩
  new CssMinimizerWebpackPlugin(),
}

处理图片资源

webpack4处理图片资源要用到file-loader和url-loader进行处理。但是在webpack5中,已经将这两个功能内置,我们只需要做简单配置即可。

在 webpack 5 之前,通常使用:

  • raw-loader 将文件导入为字符串
  • url-loader 将文件作为 data URI 内联到 bundle 中,将小于某个大小的图片,会转换成base64格式,对图片资源做了些优化。
  • file-loader 将文件原封不动发送到输出目录

资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:

  • asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
  • asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
  • asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
  • asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。

基础配置

module: {
	rules: [
		// 图片资源的loader配置
		{
			test: /.(png|jpe?g|gif|webp)$/i,
			type: 'asset',
		},
	],
},

对图片资源进行优化 - 将图片资源转换成base64格式

优点:减少图片的请求数量

缺点:体积会更大

module: {
	rules: [
		// 图片资源的loader配置
		{
			test: /.(png|jpe?g|gif|webp)$/i,
			type: 'asset',
			parser: {
				dataUrlCondition: {
					maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
				}
			}
		},
	],
},

处理字体图标资源

  • 下载字体图标文件

打开阿里巴巴矢量图标库,选择所需要的图标添加到购物车,统一下载到本地

  • 添加字体图片资源

将下载到本地的字体文件与css文件移入到所需项目,并进行引入,注意css中字体文件的引入路径需要做对应修改。再将字体文件css进行引入即可。

  • 配置

类似图片资源处理

module: {
	rules: [
		// 字体图标资源的loader配置
		{
			test: /.(ttf|woff2?)$/i,
			// asset/resource:直接打包输出文件资源
			type: 'asset/resource',
			generator: {
				filename: 'static/iconfont/[hash][ext][query]',
			},
		},
	],
},

其他资源

如音视频资源

一律按照字体图标资源处理,即修改图标资源正则即可。

test: /.(ttf|woff2?|mp3|mp4|avi)$/i

修改输出资源的目录及名称

修改JS资源目录

修改图片资源目录

module: {
	rules: [
		// 图片资源的loader配置
		{
			test: /.(png|jpe?g|gif|webp)$/i,
			type: 'asset',
			parser: {
				dataUrlCondition: {
					maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
				}
			},
			// hash: 图片hash值, ext:扩展名, query:携带参数
			// [hash:10]:hash名只取前10位
			generator: {
				filename: 'static/images/[hash][ext][query]'
			}
		},
	],
},

自动清空上次打包内容

处理js资源

针对JS的兼容性我们要用到babel来处理(webpack只编译Js中Es模块化语法),针对代码格式则需要用到Eslint来处理。

Eslint

可组装的JavaScript和JSX检查工具

  • 安装
yarn add eslint-webpack-plugin eslint -D
  • 配置

需要一个.eslintrc.js的配置文件才能干活

会对打包后的文件也进行eslint校验,可以通过.eslintignore配置不校验的文件

module.exports = {
	// 解析选项
	parserOptions: {
		ecmaVersion: 6, // ES 语法版本
		sourceType: 'module', // ES 模块化
		ecmaFeatures: { // ES 其他特性
			jsx: false // 如果是 React 项目,就需要开启 jsx 语法
		}
	},
	// 具体检查规则 键值对形势
	// 0|'off' 关闭规则
	// 1|'warn' 开启规则,仅警告
	// 2|'error' 开启规则, 抛出错误
	rules: {
		'no-var': 2, // 不能使用 var 定义变量
	},
	// 继承其他规则
	// Eslint官方规则:eslint:recommended
	// Vue官方规则:plugin:vue/essential
	// React官方规则:react-app
	// rules中的规则会比extends的优先级更高
	extends: ['eslint:recommended'],
	env: {
		node: true, // 启用node中全局变量
		browser: true, // 启用浏览器中全局变量
	},
	// ...
	// 其他规则详见:https://eslint.bootcss.com/docs/user-guide/configuring
};
const ESLintWebpackPlugin = require('eslint-webpack-plugin');

module.exports ={
	plugins: [
		// 插件一般是个构造函数 需要用new调用
		new ESLintWebpackPlugin({
			// 指定检查文件的根目录
			context: path.resolve(__dirname, "src"),
		}),
	],
}

Babel

主要用于将 ES6 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中

  • 安装
yarn add babel-loader @babel/core @babel/preset-env webpack -D
  • 配置
module.exports = {
  presets: ['@babel/preset-env'],
};
module.exports={
	module: {
		rules:[
			{
				test: /.js$/,
				// 排除node_modules代码不编译
				exclude: /node_modules/,
				loader: 'babel-loader',
				// @babel/preset-env 允许您使用最新的 JavaScript
				// @babel/preset-react 一个用来编译 React jsx 语法的预设
				// @babel/preset-typescript 一个用来编译 TypeScript 语法的预设
				// 可以通过外部文件babel.config.js文件编写
				// options: {
				//   presets: ['@babel/preset-env'],
				// },
			},
		]
	}
}

处理Html资源

  • 安装
yarn add html-webpack-plugin -D
  • 配置

切记要删除public/index.html中对js资源的引用,html-webpack-plugin会自动引入打包输出资源

const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports ={
	plugins: [
		new HtmlWebpackPlugin({
			// 模板:以public/index.html文件创建新的html文件
			// 特点:1.新的html文件结构与原来一致, 2.自动引入打包输出的资源
			template: path.resolve(__dirname, "public/index.html"),
		}),
	],
}

开发服务器自动运行

  • 安装
yarn add webpack-dev-server -D
  • 配置
module.exports={
	// 开发服务器 不会输出资源,在内存中编译打包
	devServer: {
		host: 'localhost', // 启动服务器
		port: '3000', // 端口号
		open: true, // 是否自动打开浏览器
	}
}

生产模式

  • 优化代码运行性能
  • 优化代码打包速度

配置开发/生产环境

开发环境配置

  • 开发模式没有输出,不需要指定输出目录
  • 开发模式没有输出,不需要清空输出结果
  • webpack配置文件目录变了,因此所有绝对路径需要回退目录才能找到对应的文件(webpack配置文件不在项目根目录文件下的情况)
  • 运行指令:npx webpack serve --config ./config/webpack.dev.js(可以在package.json运行命令中进行配置)

生产环境配置

  • 打包之前可以将上一次目录内容清空
  • 无需开发服务器配置
  • mode模式为production
  • 绝对路径需要回退目录(webpack配置文件不在项目根目录文件下的情况)
  • 运行命令:npx webpack --config ./config/webpack.prod.js(可以在package.json运行命令中进行配置)

package.json运行配置

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