1. webpack 介绍&基本使用
1. 创建目录
先创建以下目录
python
sgg-webpack # 项目根目录(所有指令必须在这个目录运行)
└── src # 项目源码目录
├── js # js文件目录
│ ├── count.js
│ └── sum.js
└── main.js # 项目主文件
2. 创建文件
count.js
js
export default function count(x, y) {
return x - y;
}
sum.js
js
export default function sum(...args) {
return args.reduce((p, c) => p + c, 0);
}
main.js
js
import count from "./js/count";
import sum from "./js/sum";
console.log(count(2, 1));
console.log(sum(1, 2, 3, 4));
3. 安装依赖
bash
yarn i webpack webpack-cli -D
4. 启动 webpack
- 开发模式启动
bash
npx webpack ./src/main.js --mode=development
就可以看到当前目录下面生成了dist
文件夹。
- 生产模式启动
bash
npx webpack ./src/main.js --mode=production
可以看见 productin 模式下打包后的文件里面少了很多东西。
4. 小结
当前我们只用 webpack 来打包 js 文件,那么其他资源怎么打包呢?例如 css js vue .jsx, 这个在后面会写到。
2. 基本配置
1. 5大核心概念
- entry(入口) 指示 webpack 从那个文件开始打包。
- output(输出) 指示 webpack 打包完的文件输出到哪里去,怎么文件怎样命名
- loader(加载器) webpack 本身只能处理 JS JSON 等资源,其他类型的资源需要 loader 的帮助,webpack 才能够解析。
- plugins(插件) 扩展 webpack 的功能
- mode(模式) 指定打包的模式,主要有两种
- 开发模式: development
- 生产模式: production
2. 准备webpack配置文件
在项目的根目录下面创建 webpack.config.js 文件
js
const path = require("path");
module.exports = {
// 入口
entry: "./src/main.js",
// 出口
output: {
// __dirname 是当前文件的文件夹绝对路径
// path.resolve 方法返回的是一个绝对路径
// path 是文件输出的目录
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
// 加载器
module: {
rules: [],
},
// 插件
plugins: [],
// 模式
mode: "development", // 开发模式
};
运行命令
npx webpack
效果和第一次用 命令行打包是一样的
3. 小结
之后我们都会通过 webpack.config.js 文件来进行配置,并增强 webpack 的功能。
在平时的开发中我们基本上都会进行区分,开发模式,和生产模式,来编写 webpack 的配置文件。
3. 处理样式资源
webpack 本身不识别样式资源,所以要借助 Loader 来帮助 Webpack 来解析样式资源,包括 css less 等, webpack 官方 Loader 文档
处理Css
1. 安装依赖包
bash
yarn add css-loader style-loader -D
css-loader
会对@import
和url()
进行处理,就像 js 解析import/require()
一样。style-loader
把 CSS 插入到 DOM 中。
2. 配置文件
js
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 里面的 loader 执行顺序是 从右往左执行的
use: ["style-loader", "css-loader"],
},
],
},
3. 添加css代码
- src/css/index.css
css
.box {
width: 100px;
height: 100px;
background-color: pink;
}
index.html 文件
html
<!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>
<body>
<h1>Hello Webpack5</h1>
<div class="box"></div>
<script src="./dist/main.js"></script>
</body>
</html>
效果如下
处理Less资源
1. 安装包
bash
npm i less less-loader -D
- webpack 将 Less 编译为 CSS 的 loader。
2. 配置文件
js
module: {
rules: [
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
],
},
3. 添加 less 文件
src/less/index.less
less
.box2 {
width: 100px;
height: 100px;
background: orange;
}
main.js 在入口文件引入
js
import "./less/index.less";
index.html
html
<body>
<h1>Hello Webpack5</h1>
<div class="box"></div>
<div class="box2"></div>
<script src="./dist/main.js"></script>
</body>
处理Sass资源
1. 安装包
bash
yarn add sass sass-loader -D
- sass-loader: 加载 Sass/SCSS 文件并将他们编译为 CSS。
- sass: sass-loader 依赖 sass 进行编译
2. 配置文件
js
{
test: /\.s[ac]ss/,
use: ["style-loader", "css-loader", "sass-loader"],
},
3. 添加 sass & scss 文件
src/sass/index.sass
sass
.box3
width: 100px
height: 100px
background: blue
src/sass/index.scss
scss
.box4 {
width: 100px;
height: 100px;
background-color: green;
}
index.html
html
<body>
<h1>Hello Webpack5</h1>
<div class="box"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
<script src="./dist/main.js"></script>
</body>
处理styl资源
1. 安装包
bash
yarn add stylus stylus-loader -D
2. 配置文件
js
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
3. 添加styl文件
src/styl/index.styl
css
.box5{
width 100px
height 100px
background: red
}
index.html
html
<body>
<h1>Hello Webpack5</h1>
<div class="box"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
<div class="box5"></div>
<script src="./dist/main.js"></script>
</body>
4. 处理图片资源
webpack5 内置了 file-loader
和 url-loader
, 不用我们自己去安装loader
。
1. 配置
js
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
},
2. 使用图片
分别在样式文件中引入
src/less/index.less
less
.box2 {
width: 100px;
height: 100px;
background-image: url("../images/1.jpeg");
background-size: cover;
}
src/sass/index.sass
sass
.box3
width: 100px
height: 100px
background-image: url("../images/2.png")
background-size: cover
src/styl/index.styl
arduino
.box5{
width 100px
height 100px
background-image: url("../images/3.gif")
background-size: cover
}
打包文件结果。
在 index.html 中查看效果
3. 优化输出图片资源
js
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于 10kb的图片会被base64处理
},
},
},
- 优点:减少
http
请求 - 缺点:体积会变得更大
5. 修改输出资源的名词和路径
1. 配置文件
js
{
test: /\.(png|jpe?g|gif|webp)$/,
...
generator: {
// [ext] 使用之前的文件扩展名
// [query] 添加之前的 query 查询参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
打包后的文件目录
6.自动清空dist目录
1. 配置
js
output: {
...
clean: true, // 自动清空上次打包生成的文件
}
7. 处理字体图标
添加字体图标资源文件,在iconfont
网站上面下载到本地。
1. 添加字体图标
src/main.js
js
import "./fonts/iconfont.css";
index.html
html
<!--使用字体图标-->
<i class="iconfont icon-saomiaoxianxuanze"></i>
<i class="iconfont icon-tuxiangxuanze"></i>
<i class="iconfont icon-BheMsudu"></i>
2. 配置
js
module: {
rules: [
{
// 如果有其他资源的话也可以一并在这块处理了。
test: /\.(ttf|woof2?|mp4|mp3|avi)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
],
},
效果如下
在这里区分一下type:"asset/resource"
和type:"asset"
的区别:
type:"asset/resource"
相当于file-loader
,将文件转化成Webpack能识别的资源,不做其他处理。type:"asset"
相当于url-loader
,将文件转化成Webpack能识别的资源,同时小于某个大小的资源会处理成 data URL 的形式。
8. 处理 js 资源
因为webpack
对js
处理是有限的,只能编译js
中的ES
模块化语法,不能编译其他语法,导致js
不能在IE
等浏览器上面运行,所以我们需要做兼容性处理。
主要有下面两种情况:
js
兼容性处理,使用babel
来处理- 代码格式化,使用
eslint
来处理
1. eslint
用来检测js
和jsx
语法的工具,可以进行各项功能配置。
我们使用eslint
,关键是写eslint
里面的配置文件,里面写各种rules
规则,运行eslint
的时候就会按照写的规则来对代码格式进行检查。
1. 配置文件
在项目下面新建文件.eslintrc.js
js
module.exports = {
// 继承 eslint 规则
extends: ["eslint:recommended"],
env: {
node: true, // 启用 node 中的全局变量
browser: true, // 启用 浏览器中全局变量
},
// 解析选项
parserOptions: {
ecmaVersion: 6,
sourceType: "module",
},
// 具体规则
rules: {
"no-var": 2, // 不能使用 var 定义变量
},
};
extends 继承
开发中一点点写 rules 规则太费劲了,所以有更好的办法,继承现有的规则。
现有以下较为有名的规则:
- Eslint 官方的规则open in new window:
eslint:recommended
- Vue Cli 官方的规则open in new window:
plugin:vue/essential
- React Cli 官方的规则open in new window:
react-app
2. 在 Webpack 中使用
下载包
shell
yarn add eslint-webpack-plugin eslint -D
添加 webpack
配置文件
js
const ESlintWebpackPlugin = require("eslint-webpack-plugin");
plugins: [
new ESlintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "src"),
}),
],
然后运行
npx webpack
就可以看见有以下报错了,
同时安装 eslint 插件,这样在编辑器中就有对应的错误提示了。
还有如果我们有不需要通过eslint
校验的文件夹,我们可以写在下面的配置文件中。
.eslintignore
bash
# 忽略 dist 目录下所有文件
dist
2. babel
babel 是 javascript 编译器。能将es6
语法编写的代码转换成为向后兼容的javascript
语法,能够兼容当前版本的浏览器或在其他环境中运行。
1. 配置文件
babel 会查找和自动读取当前的配置文件。
babel.config.js
js
module.exports = {
// 预设
presets: [],
};
- presets 预设
简单理解:就是一组 Babel
的插件,用来扩展 Babel
的功能。
@babel/preset-env
:一个智能预设,允许你使用最新的 javascript 语法@babel/preset-react
:一个用来编译 React jsx 语法的预设@babel/preset-typescript
:用来编译 TypeScript 语法的预设
安装依赖
bash
yarn add babel-loader @babel/core @babel/preset-env -D
添加babel配置
js
module.exports = {
// 预设
presets: ["@babel/preset-env"],
};
webpack.config.js配置
js
module: {
rules: [
//.....
{
test: /\.js$/,
exclude: /node_modules/, // 排除 node_modules 下面的代码不进行编译
loader: "babel-loader",
},
],
},
运行指令:
bash
npx webpack
可以看到箭头函数已经被转换成了普通函数。
9. 处理 Html 资源
安装包
bash
yarn add html-webpack-plugin -D
1. 配置文件
js
plugins: [
...
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "index.html"),
}),
],
2. 打包
我们观察dist
下面输出的index.html
文件,中会自动引入项目配置的入口文件。
注:defer 属性和async有点像,async是js文件刚下载完毕就开始执行,而defer是等待 HTML的解析所有都完毕之后,才会进行js文件的执行,并且这个js文件的执行是按照script标签定义的顺序来执行的,所以这就和在body中的最末尾定义普通没有任何属性的多个script标签一样,从上到下按顺序开始执行,并且没有阻塞HTML文件的解析,所以defer这个属性的添加,完美的解决了async的问题,还有没有属性却还定义在header中script标签,阻塞html文件解析的情况。
10. 开发环境搭建
安装包
bash
yarn add webpack-dev-server -D
1. 配置文件
js
// 开发服务器配置
devServer: {
host: "localhost",
port: "3000",
open: true,
},
运行命令
bash
npx webpack serve
就会自动为我们启动一个服务
11. 生产模式
生产模式,就是我们要部署到线上的代码。
这个模式下面主要是对代码进行优化,让其运行性能更好。
优化主要从两个角度出发:
- 优化代码运行性能
- 优化代码打包速度
1. 开发配置
新建config目录,来区分开发配置和打包配置。
配置如下
webpack.dev.config
js
const path = require("path");
const ESlintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// 入口
entry: path.resolve(__dirname, "../src/main.js"),
// 出口
output: {
// __dirname 是当前文件的文件夹绝对路径
// path.resolve 方法返回的是一个绝对路径
// path 是文件输出的目录
path: undefined,
filename: "static/js/main.js", // 把文件打包到 static/js 下面的目录中
},
// 加载器
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 里面的 loader 执行顺序是 从右往左执行的
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: 10 * 1024, // 小于 10kb的图片会被base64处理
},
},
generator: {
// [ext] 使用之前的文件扩展名
// [query] 添加之前的 query 查询参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woof2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除 node_modules 下面的代码不进行编译
loader: "babel-loader",
},
],
},
// 模式
mode: "development", // 开发模式
// 插件
plugins: [
new ESlintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "../index.html"),
}),
],
// 开发服务器配置
devServer: {
host: "localhost",
port: "3000",
open: true,
},
};
添加 script 脚本
bash
"dev": "webpack server --config ./config/webpack.dev.js"
2. 打包配置
js
const path = require("path");
const ESlintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// 入口
entry: path.resolve(__dirname, "../src/main.js"),
// 出口
output: {
// __dirname 是当前文件的文件夹绝对路径
// path.resolve 方法返回的是一个绝对路径
// path 是文件输出的目录
path: path.resolve(__dirname, "../dist"),
filename: "static/js/main.js", // 把文件打包到 static/js 下面的目录中
clean: true, // 自动清空上次打包生成的文件
},
// 加载器
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 里面的 loader 执行顺序是 从右往左执行的
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: 10 * 1024, // 小于 10kb的图片会被base64处理
},
},
generator: {
// [ext] 使用之前的文件扩展名
// [query] 添加之前的 query 查询参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woof2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除 node_modules 下面的代码不进行编译
loader: "babel-loader",
},
],
},
// 模式
mode: "production", // 开发模式
// 插件
plugins: [
new ESlintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "../index.html"),
}),
],
};
12. Css 处理
现在打包是 将 css 打包到 js 中,在加载 js 文件的时候,会动态创建一个 style 标签来生成样式,有可能出现闪屏的现象,用户体验不好,我们要将 css 文件单独提取出来,通过 link 标签来加载。
1. 单独提取css
安装包
bash
yarn add mini-css-extract-plugin -D
webpack.prod.js
js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 里面的 loader 执行顺序是 从右往左执行的
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"],
}
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "static/css/mini.css",
}),
],
3. css 兼容性处理
安装包
bash
yarn add postcss-loader postcss postcss-preset-env -D
webpack.prod.js
js
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 里面的 loader 执行顺序是 从右往左执行的
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "poss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 兼容大多数样式兼容性
],
},
},
},
],
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "poss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 兼容大多数样式兼容性
],
},
},
},
"less-loader",
],
},
{
test: /\.s[ac]ss/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "poss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 兼容大多数样式兼容性
],
},
},
},
"sass-loader",
],
},
{
test: /\.styl$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "poss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 兼容大多数样式兼容性
],
},
},
},
"stylus-loader",
],
}
],
},
添加.browserslistrc配置文件
perl
last 2 version
> 1%
not dead # no browsers without security updates
合并 css等 loader 的配置文件
js
const getStyleLoaders = (preProcessor) => {
return [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 兼容大多数样式兼容性
],
},
},
},
preProcessor,
].filter(Boolean);
};
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 里面的 loader 执行顺序是 从右往左执行的
use: getStyleLoaders(),
},
{
test: /\.less$/,
use: getStyleLoaders("less-loader"),
},
{
test: /\.s[ac]ss/,
use: getStyleLoaders("sass-loader"),
},
{
test: /\.styl$/,
use: getStyleLoaders("stylus-loader"),
},
],
},
3. 压缩 css
下载包
bash
yarn add css-minimizer-webpack-plugin -D
webpack.prod.js
js
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
plugins: [
new CssMinimizerPlugin(),
],
求职广告^_^
本人目前西安,如有大佬收前端的可私信或者微信:xiuxiuyifanf,求一个前端开发坑位。