目录
一、Webpack概念
- 当我们习惯了在node中编写代码的方式后,再回到前端编写html、css、js这些东西会感觉到各种的不便。比如:不能放心的使用模块化规范(浏览器兼容性问题)、即使可以使用模块化规范也会面临模块过多时的加载问题。
- 我们就迫切的希望有一款工具可以对代码进行打包,将多个模块打包成一个文件。这样一来即解决了兼容性问题,又解决了模块过多的问题。
- 构建工具就起到这样一个作用,通过构建工具可以将使用ESM规范编写的代码转换为旧的JS语法,这样可以使得所有的浏览器都可以支持代码。
Webpack是一个前端模块打包工具。它可以将多个模块按照依赖关系进行静态分析,并生成一个或多个打包后的文件。
作用:把静态模块内容,压缩,这个和,转译等(前端工程化)。
-
把 less/sass 转成 css 代码
-
把 ES6+ 降级成 ES5 等
-
支持多种模块文件类型,多种模块标准语法
二、Webpack使用步骤
1.新建一个主文件夹(名为webpack),然后初始化包环境,得到 package.json 文件
npm init -y
2.安装 webpack 以及 webpack-cli 依赖包
npm i webpack webpack-cli --save-dev
3.把 webpack 命令配置到 package.json 的 scripts 自定义命令,作为局部命令使用
"scripts": {
"build": "webpack"
},
4.创建文件夹src,在src里创建index.js编写代码
5.开始运行,采用自定义命令的方式:npm run 自定义命令名字
npm run build
- 注意:实际上在终端运行的是 build 右侧的具体命名
6.此时会自动产生 dist 文件夹(压缩和优化后,用于最终运行的代码),默认里面会有一个main.js文件
三、Webpack.config.js配置文件
在项目根目录创建 Webpack.config.js 配置文件,它提供一个配置对象,Webpack将根据这个对象来打包应用程序。
核心概念:
- Entry(入口):Webpack将从指定的入口文件开始分析和构建依赖关系树。入口可以是单个文件或多个文件,Webpack会根据入口配置找出所有的依赖模块。
- Output(出口):指定Webpack打包后的文件输出的路径和文件名。可以通过配置output选项来指定输出文件的路径、名称和格式等。
- Loader(加载器):Webpack本身只能处理JavaScript模块,但通过Loader的使用,可以处理其他类型的文件(如CSS、LESS、图片等)。Loader的作用是在模块加载时对其进行转换和处理。
- Plugin(插件):插件用于扩展Webpack的功能。它可以在打包的不同阶段执行特定的任务。例如,可以使用插件来压缩代码、拆分代码、生成HTML文件等。插件通过在Webpack配置中引入并实例化,然后将其添加到plugins数组中。
示例:
const path = require('path')
const HTMLPlugin = require('html-webpack-plugin')
module.exports = {
mode: "production", //设置打包模式,production表示生产模式,development表示开发模式
//entry用来指定打包时的主文件,默认 ./src/index.js
// entry: ['./src/a.js', './src/b.js'], //合并打包
// entry: { //分别打包
// a: './src/a.js',
// b: './src/b.js'
// },
//output用来配置打包后的地址,默认 ./dist/main.js
// output: {
// path: path.join(__dirname, 'hello'), //指定打包的目录,必须是绝对路径
// filename: '[name]-[id]-[hash].js', //打包后的文件名
// clean: true //自动清理打包目录 (dist目录)
// }
//加载器,处理非js文件
module: {
rules: [
{
test: /\.css$/i, //处理css
use: ['style-loader', 'css-loader'] //从右向左执行
},
{
test: /\.(jpg|png|gif)$/i, //处理图片
type: 'asset/resource'
},
{
test: /\.m?js$/i, //处理js(ES6+ 转译)
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
//插件,增强功能
plugins: [
new HTMLPlugin({
template: './src/index.html'
})
],
devtool: 'inline-source-map' //用于调试代码
}
四、entry 和 output
1. entry
定义打包的起点文件,Webpack 从入口开始分析依赖。
单入口(SPA):
entry: './src/index.js',
多入口(MPA):
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
2. output
定义打包后文件的输出位置和命名规则。
output: {
path: path.resolve(__dirname, 'dist'), // 输出目录(绝对路径)
filename: '[name].[contenthash].js', // 输出文件名模板
clean: true, // 每次构建前清空输出目录
publicPath: '/assets/', // 资源公共路径(CDN 场景使用)
chunkFilename: '[id].[chunkhash].js', // 非入口 chunk 文件名(如异步加载模块)
},
占位符:
-
[name]
:入口名称(多入口时使用)。 -
[contenthash]
:文件内容哈希(用于缓存优化)。 -
[id]
:模块标识符。
五、module
Webpack 默认只识别 JS 和 JSON 文件内容,所以想要让 Webpack 识别更多不同内容,需要使用加载器。
1. CSS
在 src 目录下新建一个 style 文件夹,存放 style.css 文件,然后在index.js中引入:
import './style/index.css'
此时还不能生效,还需要下载依赖包并进行配置。
下载:
npm i css-loader style-loader --save-dev
在 module 下的 rules 数组中配置:
{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
}
- css-loader 只负责打包,style-loader 负责渲染生效
- loader 执行顺序为从后向前执行,因此 use 的数组顺序不能调换
2. 图片
图片使用方法类似,先在index.js中引入:
import pic from './assets/pixmap.png'
然后配置:
{
test: /\.(jpg|png|gif)$/i,
type: 'asset/resource'
}
ps:webpack 内置了资源模块的打包,无需下载额外 loader。
3. babel
-
在编写js代码时,经常需要使用一些js中的新特性,而新特性在旧的浏览器中兼容性并不好。此时就导致我们无法使用一些新的特性。
-
但是我们现在希望能够使用新的特性,我们可以采用折中的方案。依然使用新特性编写代码,但是代码编写完成时我们可以通过一些工具将新代码转换为旧代码。
-
babel就是这样一个工具,可以将新的js语法转换为旧的js,以提高代码的兼容性。
安装:
npm install -D babel-loader @babel/core @babel/preset-env
- @babel/core:babel的转换核心
- @babel/preset-env:预设环境
配置:
{
test: /\.m?js$/i,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
还可以在package.json中设置兼容列表:
"browserslist": [
"defaults"
]
4. 总结
常用的Webpack loader:
- babel-loader:将ES6+代码转换为ES5语法,以便在旧版本的浏览器中运行。
- style-loader 和 css-loader:用于处理CSS文件。css-loader主要负责处理样式文件中的import和url语句,而style-loader将转换后的CSS模块直接注入到HTML页面中。
- file-loader 和 url-loader:用于处理图片和其他资源文件。file-loader会为每一个文件生成一个对应的文件,而url-loader将小于设定大小的文件转换为base64编码的URL,减少HTTP请求。
- sass-loader 和 less-loader:用于处理Sass和Less预处理器。它们将Sass和Less代码转换为普通的CSS代码。
- postcss-loader:用于为CSS代码添加浏览器兼容性前缀,以确保在不同浏览器上的一致性。
- html-loader:用于处理HTML文件,将其中的图片等资源转换为Webpack可以识别的模块。
六、plugins
1.自动生成 html 文件
html-webpack-plugin 这个插件可以在代码打包后,自动在打包目录生成html页面。
下载:
npm i html-webpack-plugin --save-dev
引入依赖:
const HTMLPlugin = require("html-webpack-plugin")
配置:
plugins: [
new HTMLPlugin({
// title: "Hello Webpack", //设置title
template: "./src/index.html" //模板,自动引入script脚本
})
]
七、其它
1.webpack-dev-server 开发服务器
每次改动代码,都要重新打包,很麻烦,所以这里给项目集成 webpack-dev-server 开发服务器。
作用:启动 Web 服务,并自动检测代码变化热更新到网页。
下载:
npm i webpack-dev-server --save-dev
可以在 package.json 中配置自定义命令:
"scripts": {
"dev": "webpack serve --mode=development"
}
使用:
npm run dev
- 此时在 js / css 文件中修改代码保存后,会实时反馈到浏览器。
2. mode 打包模式
指定构建模式,Webpack 会根据模式启用内置优化。
可选值:
-
'development'
:启用开发工具(如 source map)。 -
'production'
:启用代码压缩、Tree Shaking 等优化。 -
'none'
:不启用任何默认优化。
模式名称 | 模式名字 | 特点 | 场景 |
---|---|---|---|
开发模式 | development | 调试代码,实时加载,模块热替换等 | 本地开发 |
生产模式 | production | 压缩代码,资源优化,更轻量等 | 打包上线 |
如何设置影响 Webpack呢?
-
方式1:在 webpack.config.js 配置文件设置 mode 选项
// ... module.exports = { // ... mode: 'production' }
-
方式2:在 package.json 命令行设置 mode 参数
"scripts": { "build": "webpack --mode=production", "dev": "webpack serve --mode=development" },
注意:命令行设置的优先级高于配置文件中的,推荐用命令行设置
3. devtool
可以配置源码的映射,方便调试打包后的代码。
// ...
module.exports = {
// ...
devtool:"inline-source-map"
}
Vite 与 Webpack对比
维度 | Vite | Webpack |
---|---|---|
设计目标 | 为现代浏览器优化开发体验 | 通用打包工具,兼容历史项目 |
开发模式原理 | 基于浏览器原生 ESM,按需编译 | 全量打包为 Bundle |
生产打包工具 | Rollup(默认) | Webpack 自身 |
启动速度 | 极快(毫秒级) | 慢(依赖项目规模) |
热更新(HMR) | 毫秒级响应 | 较慢(需重新构建依赖链) |
配置复杂度 | 简单(约定优于配置) | 复杂(需手动配置 Loader/Plugin) |
生态成熟度 | 较新但快速增长 | 极其成熟(插件生态丰富) |
旧浏览器兼容 | 需额外处理(通过 @vitejs/plugin-legacy ) | 原生支持(通过 Babel + Polyfill) |
一、不同环境对比
1. 开发环境
Vite:
-
基于浏览器原生 ESM:浏览器直接请求源码,Vite 服务器按需编译(如
import React from '/node_modules/react'
)。 -
冷启动快:无需等待全量打包,启动即用。
-
HMR(热更新):仅更新修改的模块,毫秒级响应。
Webpack:
-
全量打包:启动时构建完整 Bundle(如
main.js
),耗时长。 -
HMR:需重新构建依赖链,速度较慢(尤其大型项目)。
2. 生产环境
-
Vite
使用 Rollup 进行打包,生成优化的静态资源(Tree-shaking、代码分割等),配置简单。 -
Webpack
自身完成打包,通过复杂配置实现优化(需手动调优 Loader、Plugin)。
二、功能特性对比
功能 | Vite | Webpack |
---|---|---|
模块化支持 | 原生 ESM,兼容 CommonJS 自动转换 | 支持 CommonJS/AMD/ESM(需配置) |
TypeScript 支持 | 开箱即用(esbuild 编译) | 需 ts-loader 或 babel-loader |
CSS 处理 | 原生支持 CSS Modules、PostCSS、Sass/Less | 需 css-loader 、style-loader 等 |
代码分割 | Rollup 自动优化 | 需手动配置 SplitChunksPlugin |
插件生态 | 兼容 Rollup 插件,生态在成长 | 生态极其丰富(Loader、Plugin 成熟) |
SSR 支持 | 内置轻量级 SSR | 需复杂配置(如 webpack-node-externals ) |
配置复杂度:
-
Vite
-
配置简单:默认优化配置,仅需少量修改(如
vite.config.js
)。 -
约定优于配置:如
public
目录静态资源、src
为源码目录。
-
-
Webpack
-
配置复杂:需手动配置 Loader、Plugin、优化项(如
webpack.config.js
)。 -
学习成本高:需理解 Bundle、Chunk、Loader 机制。
-
三、为什么 Vite 更快?
1. 开发模式革命:原生 ESM 按需编译
-
Webpack 的瓶颈:启动时必须全量打包所有代码为 Bundle(如
main.js
),构建依赖图耗时(项目越大越慢)。# Webpack 工作流程 代码 → 分析依赖 → 打包 Bundle → 浏览器加载
-
Vite 的突破:利用现代浏览器原生支持 ES 模块 (ESM),直接让浏览器通过
import
请求源码,按需编译(无需提前打包)。# Vite 工作流程 浏览器请求模块 → Vite 拦截请求 → 实时编译返回 → 浏览器执行
-
示例:当浏览器请求
App.vue
时,Vite 才会编译它,而不是提前处理所有文件。
2. 预构建优化:缓存第三方依赖
-
问题:第三方包(如
lodash
)可能包含大量 CommonJS 模块,无法直接被浏览器 ESM 加载。 -
Vite 的解决:
-
首次启动时:用
esbuild
将 CommonJS 转换为 ESM,并合并为一个文件(如lodash.js
)。 -
后续启动:直接读取缓存,避免重复构建。
// 预构建后的依赖路径 import lodash from '/node_modules/.vite/lodash.js'
-
3. 极速热更新(HMR)
-
Webpack 的 HMR:修改文件后需重新构建整个模块链(依赖该文件的所有模块)。
-
Vite 的 HMR:基于 ESM,直接替换单个模块(无需重建依赖链),浏览器快速生效。
4. 生产构建优化:Rollup 的高效打包
-
Vite 生产模式:使用 Rollup(专注于 ESM 的高效打包工具),默认启用 Tree-shaking、代码分割。
-
Webpack 生产模式:自身打包,需复杂配置才能达到同等优化效果。
总结:Vite 快的关键
-
开发阶段:
-
利用浏览器原生 ESM,跳过全量打包。
-
按需编译 + 预构建缓存,减少 CPU/内存消耗。
-
-
生产阶段:
-
基于 Rollup 的高效打包。
-
-
架构差异:
-
Webpack 是 打包优先,Vite 是 按需编译优先。
-
何时选择 Vite/Webpack?
场景 | 推荐工具 | 原因 |
---|---|---|
现代浏览器项目 | Vite | 极致开发速度,轻量配置 |
旧浏览器兼容需求 | Webpack | 通过 Babel + Polyfill 完善支持 |
大型复杂工程 | Webpack | 成熟生态,深度优化能力 |
库/工具开发 | Vite | 快速迭代,默认 Tree-shaking |
Vite 重新定义了前端开发体验,而 Webpack 仍是功能完备的“老将”。选择取决于项目需求,两者未来将长期共存。
参考:
Webpack--入门只看这一篇就够了(图文+代码)-CSDN博客
webpack超详细教程,学webpack看这一篇就够了!(上)_webpack教程-CSDN博客
webpack超详细教程,学webpack看这一篇就够了!(下)_new webpack.defineplugin-CSDN博客