基本介绍
webpack: 静态资源打包工具
将浏览器不能识别的语法编译成浏览器能够识别的语法。
webpack开发模式:仅能编译 JS 中的 ES Module
语法
webpack生产模式:能编译 JS 中的 ES Module
语法,还能压缩 JS 代码
基本使用
- 创建资源目录
webpack_code # 项目根目录(所有指令必须在这个目录运行)
└── src # 项目源码目录
├── js # js文件目录
│ ├── count.js
│ └── sum.js
└── main.js # 项目主文件
- 下载依赖
打开终端,来到项目根目录。运行以下指令。
npm init -y
初始化一个包描述文件package.json
npm i webpack webpack-cli -D
下载webpack webpack-cli两个开发依赖
- 启用webpack
npx会将node_modules中的.bin临时添加为环境变量
npx webpack ./src/main.js --mode=development
指定从./src/main.js这个文件开始打包,指定模式为development开发模式
开发模式下,webpack可以编译ES6模块化语法,然后浏览器可以运行。
npx webpack ./src/main.js --mode=production
指定从./src/main.js这个文件开始打包,指定模式为production生产模式
生产模式下,webpack会对代码进行压缩。
基本配置
在项目根目录下新建文件:webpack.config.js
- 配置文件
const path = require("path");//nodejs核心模块,专门用来处理路径问题
module.exports = {
// 入口
entry: './src/main.js',//相对路径
// 输出
output: {
// 文件的输出路径
// __dirname nodejs变量,代表当前的文件夹目录
path: path.resolve(__dirname, "dist"),//绝对路径
// 文件名
filename: 'main.js'
},
// 加载器
module: {
rules: [
// loader的配置
],
},
// 插件
plugins: [
//plugin的配置
],
// 模式
mode: 'development',
};
- 运行指令
npx webpack
会在WEBPACK目录下找webpack.config.js配置文件,读取里面的配置,按照配置执行相应的打包操作。(如果没写配置文件,就用npx webpack ./src/main.js --mode=development或npx webpack ./src/main.js --mode=production的方法)
处理样式资源
处理css资源
Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源
npm install --save-dev css-loader 安装loader(新版已经自动安装了style loader)
在webpack.config.js中配置loader
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
},
],
},
],
},
use执行顺序:从右到左,从下到上。css-loader,将css资源编译成commonjs的模块到js中
ctyle-loader,将js中css通过style标签添加html文件中生效。
处理less资源
less-loader
:负责将 Less 文件编译成 Css 文件
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
处理sass和scss资源
sass-loader
:负责将 Sass 文件编译成 css 文件
sass
:sass-loader
依赖 sass
进行编译
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
处理stylus资源
stylus-loader
:负责将 Styl 文件编译成 Css 文件
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
处理图像资源
webpack5将file-loader和url-loader两个loader功能内置到webpack里面
{
test: /\.(png|jpe?g|gif|webp|svg)/,
type: 'asset',
parser: {
dataUrlCondition: {
//小于100kb的图片转base64
//优点:减少请求数量 缺点:体积会更大
maxSize: 100 * 1024
}
}
}
此时输出的图片文件就只有两张,有一张图片以 data URI 形式内置到 js 中了 (注意:需要将上次打包生成的文件清空,再重新打包才有效果)
改变输出文件目录情况
改变main.js输出
output: {
//所有文件的输出路径
//__dirname nodejs的变量,代表当前文件的文件夹目录
path: path.resolve(__dirname, "dist"),//绝对路径
filename: "static/js/main.js",
//自动清空上次打包结果
//原理:在打包前,将path整个目录内容清空,再进行打包
clean: true,
}
改变图片输出
{
test: /\.(png|jpe?g|gif|webp|svg)/,
type: 'asset',
parser: {
dataUrlCondition: {
//小于100kb的图片转base64
//优点:减少请求数量 缺点:体积会更大
maxSize: 100 * 1024
},
},
generator: {
//输出图片名称
//[hash:10] hash值只取前10位
filename: 'static/images/[hash:10][ext][query]'
}
}
处理字体图标资源
在阿里矢量图形库中下载
引入图标资源
//需要webpack打包资源需要引入资源
import "./css/iconfont.css";//这个
import "./css/index.css";
import "./less/index.less";
import "./sass/index.sass";
import "./sass/index.scss";
import "./stylus/index.styl";
在webpack.config.js中配置资源
{
test: /\.(ttf|woff?2)$/,
type: 'asset/resource',//这种形式不会转变为base64
generator: {
//输出图片名称
filename: 'static/media/[hash:10][ext][query]'
},
}
使用字体图标
<span class="iconfont icon-dianpu"></span>
<span class="iconfont icon-tijiaoyanzi"></span>
<span class="iconfont icon-zaixianyanzi"></span>
<span class="iconfont icon-dingwei"></span>
<script src="../dist/static/js/main.js"></script>
Eslint
Eslint说明
可组装的 JavaScript 和 JSX 检查工具
使用 Eslint,关键是写 Eslint 配置文件,里面写上各种 rules 规则,将来运行 Eslint 时就会以写的规则对代码进行检查。
配置文件有多种写法:
.eslintrc.*
:新建文件,位于项目根目录.eslintrc
.eslintrc.js
.eslintrc.json
- 区别在于配置格式不一样
package.json
中eslintConfig
:不需要创建文件,在原有文件基础上写
ESLint 会查找和自动读取它们,所以以上配置文件只需要存在一个即可
以.eslintrc.js为例:
module.exports = {
// 解析选项
parserOptions: {},//指定语法环境
// 具体检查规则
rules: {},//比extends高级一点
// 继承其他规则
extends: [],
// ...
// 其他规则详见:https://eslint.bootcss.com/docs/user-guide/configuring
};
Eslint使用
安装 eslint-webpack-plugin:npm install eslint-webpack-plugin --save-dev
npm install eslint --save-dev
在根目录下新建.eslintrc.js,定义 Eslint 配置文件
module.exports = {
// 继承 Eslint 规则
extends: ["eslint:recommended"],
env: {
node: true, // 启用node中全局变量
browser: true, // 启用浏览器中全局变量
},
parserOptions: {
ecmaVersion: 6,//es6
sourceType: "module",//es module
},
rules: {
"no-var": 2, // 不能使用 var 定义变量
},
};
配置webpack.config.js
const ESLintWebpackPlugin = require("eslint-webpack-plugin");//插件需要引入才能使用
......
plugins: [new ESWebpackLintPlugin({
//检测哪些文件
context: path.resolve(__dirname, "src"),
}),
如果是直接在扩展处下载eslint,则会默认检查所有文件,可以通过在根目录下新建一个.eslintignore文件来忽略不需要检查的文件。
dist
webpack.config.js
babel
babel说明
JS编译器,主要用于将 ES6 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。
配置文件有很多种写法
babel.config.*
:新建文件,位于项目根目录babel.config.js
babel.config.json
.babelrc.*
:新建文件,位于项目根目录.babelrc
.babelrc.js
.babelrc.json
package.json
中babel
:不需要创建文件,在原有文件基础上写
Babel 会查找和自动读取它们,所以以上配置文件只需要存在一个即可
@babel/preset-env
: 一个智能预设,允许您使用最新的 JavaScript。@babel/preset-react
:一个用来编译 React jsx 语法的预设@babel/preset-typescript
:一个用来编译 TypeScript 语法的预设
babel使用
npm install -D babel-loader @babel/core @babel/prese-env webpack
具体配置
根目录下新建babel.config.js
module.exports ={
//智能预设:能够编译ES6语法
presets: ["@babel/preset-env"],
}
presets预设
简单理解:就是一组 Babel 插件, 扩展 Babel 功能
@babel/preset-env
: 一个智能预设,允许您使用最新的 JavaScript。@babel/preset-react
:一个用来编译 React jsx 语法的预设@babel/preset-typescript
:一个用来编译 TypeScript 语法的预设
配置webpack.config.js
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
处理HTML资源
下载 npm install --save-dev html-webpack-plugin
配置webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
......
plugins: [new ESLintWebpackPlugin({
//检测哪些文件
context: path.resolve(__dirname, "src"),
}),
new HtmlWebpackPlugin(),
],
搭建开发服务器
下载包:npm i webpack-dev-server -D
配置 webpack.config.js
// 开发服务器: 不会输出资源,在内存中编译打包
devServer: {
host: "localhost", // 启动服务器域名
port: "3000", // 启动服务器端口号
open: true, // 是否自动打开浏览器
},
运行指令:npx webpack serve
生产模式介绍
生产模式是开发完成代码后,我们需要得到代码将来部署上线。这个模式下我们主要对代码进行优化,让其运行性能更好。
文件目录
├── webpack-test (项目根目录)
├── config (Webpack配置文件目录)
│ ├── webpack.dev.js(开发模式配置文件)
│ └── webpack.prod.js(生产模式配置文件)
├── node_modules (下载包存放目录)
├── src (项目源码目录,除了html其他都在src里面)
│ └── 略
├── public (项目html文件)
│ └── index.html
├── .eslintrc.js(Eslint配置文件)
├── babel.config.js(Babel配置文件)
└── package.json (包的依赖管理配置文件)
修改webpack.dev.js
因为文件目录变了,所以所有绝对路径需要回退一层目录才能找到对应的文件
output: {
//所有文件的输出路径
//开发模式没有输出
path: undefined,
filename: "static/js/main.js",
//自动清空上次打包结果
//原理:在打包前,将path整个目录内容清空,再进行打包
clean: true,
},
.......
plugins: [new ESLintWebpackPlugin({
//检测哪些文件
context: path.resolve(__dirname, "../src"),
}),
......
new HtmlWebpackPlugin({
//模板:以public/index.html文件创建新的html文件
//新的文件特点:1.结构和原来一致,可以自动引入打包的资源
template: path.resolve(__dirname, "../public/index.html"),
}),
运行开发模式
npx webpack serve --config ./config/webpack.dev.js
修改webpack.prod.js
生产模式不需要devServer,只需要打包输出文件即可。
output: {
//所有文件的输出路径
//__dirname nodejs的变量,代表当前文件的文件夹目录
path: path.resolve(__dirname, "../dist"),//绝对路径
filename: "static/js/main.js",
//自动清空上次打包结果
//原理:在打包前,将path整个目录内容清空,再进行打包
clean: true,
},
......
plugins: [new ESLintWebpackPlugin({
//检测哪些文件
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
//模板:以public/index.html文件创建新的html文件
//新的文件特点:1.结构和原来一致,可以自动引入打包的资源
template: path.resolve(__dirname, "../public/index.html"),
}),
],
mode: "production",
};
运行生产模式
npx webpack --config ./config/webpack.prod.js
这个地方出现了两个警告:图片太大,超出限制。
解决方法:webpack.config.prod.js文件里添加如下配置
performance: {
hints:false
}
生产模式准备
修改根目录下package.json
{
"name": "src",
"version": "1.0.0",
"description": "",
"main": "./src/main.js",
"scripts": {
"start": "npm run dev",
"dev": "webpack server --config ./config/webpack.dev.js",
"build": "webpack --config ./config/webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.23.2",
"@babel/preset-env": "^7.23.2",
"babel-loader": "^9.1.3",
"css-loader": "^6.8.1",
"eslint": "^8.51.0",
"eslint-webpack-plugin": "^4.0.1",
"html-webpack-plugin": "^5.5.3",
"less-loader": "^11.1.3",
"postcss": "^8.4.31",
"postcss-loader": "^7.3.3",
"postcss-preset-env": "^9.2.0",
"sass": "^1.69.3",
"sass-loader": "^13.3.2",
"style-loader": "^3.3.3",
"stylus-loader": "^7.1.3",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
}
}
如果要启动开发模式,直接npm start
如果要启动生产模式,直接npm run start
提取Css成单独文件
安装 npm install --save-dev mini-css-extract-plugin
配置webpack.prod.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");//引入插件
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "../dist"),//绝对路径
filename: "static/js/main.js",
//自动清空上次打包结果
//原理:在打包前,将path整个目录内容清空,再进行打包
clean: true,
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: [MiniCssExtractPlugin.loader, //提取css成单独文件
"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"],
},
.......
//在插件中加入以下配置
new MiniCssExtractPlugin({
filename:'static/css/main.css',//将提取好的文件输出到这个位置
}),
运行指令:npm run build
兼容性处理
下载包:npm i postcss-loader postcss postcss-preset-env -D
配置 webpack.prod.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
......
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: [MiniCssExtractPlugin.loader, //提取css成单独文件
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
],
},
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
"less-loader"],
},
{
test: /\.s[ac]ss$/,
use: [MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
"sass-loader"],
},
{
test: /\.styl$/,
use: [MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
"stylus-loader"],
},
控制兼容性:在package.json中加入以下语句
"browserslist":[
"last 2 version",
"> 1%",
"not dead"
]
合并配置
//获取用来处理样式的loader
const getStyleLoaders = (preProcessor) => {
return [MiniCssExtractPlugin.loader, //提取css成单独文件
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
preProcessor,
].filter(Boolean);
}
module.exports = {
entry: "./src/main.js",
output: {
//所有文件的输出路径
//__dirname nodejs的变量,代表当前文件的文件夹目录
path: path.resolve(__dirname, "../dist"),//绝对路径
filename: "static/js/main.js",
//自动清空上次打包结果
//原理:在打包前,将path整个目录内容清空,再进行打包
clean: true,
},
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'),
}
压缩css
下载插件 npm i css-minimizer-webpack-plugin -D
配置webpack.prod.js
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");//引入插件
......
plugins: [new ESLintWebpackPlugin({
//检测哪些文件
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
//模板:以public/index.html文件创建新的html文件
//新的文件特点:1.结构和原来一致,可以自动引入打包的资源
template: path.resolve(__dirname, "../public/index.html"),
}),
new MiniCssExtractPlugin({
filename:'static/css/main.css',
}),
new CssMinimizerPlugin(),//css压缩
]
运行指令 npm run build