笔记对 webpack 的常用实现进行了整理,适合于了解 webpack,想要快速温习或进行一些常见功能拓展的情况。
相关笔记:
- webpack 不同环境的配置分离
- 用 webpack-chain 的方式配置
- webpack-demo
+ public
- index.html
+ src
- banner.js
- index.js
- tabs.js
public/index.html
<body>
<div>轮播图</div>
<div>tabs标签页</div>
</body>
<script src="../src/index.js"></script>
src/banner.js
console.log('实现轮播图的业务逻辑')
src/tabs.js
console.log('实现tabs标签页的逻辑')
src/index.js
import './banner.js'
import './tabs.js'
此时用 Live Server 启动 index.html 会报错,因为直接使用了 import;
使用 webpack 可以解决这个问题,它内置了对 CommonJS 模块化的处理。
需要项目下存在 package.json 文件,如果不存在,可以通过如下命令生成。
yarn init
或
yarn init -y
🐬 该命令会跳过文件的基本配置,生成默认文件。
# 安装依赖包
yarn add webpack webpack-cli -D
方法一
./node_modules/bin/webpack
方法二
npx webpack
👻 若是在项目下直接运行 webpack
,其会使用全局安装的 webpack。
方法三
package.json
"script": {
"build": "webpack"
}
yarn build
🐢 结果:生成默认dist目录和打包后默认main.js文件,默认会打包src下的index.js
目录/webpack.config.js
告诉webpack从哪开始打包, 打包后的文件生成在哪个位置。
属性 | 默认值 | 版本 |
---|---|---|
entry | ./src/index.js | webpack4 |
output.path | ./dist/main.js | webpack4 |
const path = require("path")
module.exports = {
entry: "./src/main.js",
output: {
path: path.join(__dirname, "dist"),
filename: "bundle.js",
clean: true // 每次打包前,删除原打包内容 v5.20.0+
}
}
键 | 说明 |
---|---|
entry | 需要打包的源文件 |
output.path | 输出地址,需为绝对路径 |
filename | 打包后的文件名 |
path.resolve() | 拼接路径 |
__dirname | 当前文件所在的绝对路径,注意是双下划线 |
修改文件名
- src
- index.js ==> main.js
重新打包后的结果
- dist2
+ bundle.js
const path = require("path")
module.exports = {
entry: "./src/main.js", // 入口
output: {
path: path.join(__dirname, "dist"), // 出口路径
filename: "js/[name].[hash:8].js", // 出口文件名
// filename: "js/[name].[hash:8].[ext]"
}
}
🐙 这里测试,如果使用 [ext] ,将会被当做字符串视作为文件名的一部分,不太理解;
🐬 这里相当于在打包目录下创建一个 js 文件夹,用于存放打包后的文件。
配置 | 说明 |
---|---|
[name] | 原文件名字 |
[hash:8] | 生成 8 位哈希值 |
[ext] | 原文件拓展名 |
[] | 代表变量 |
module.exports = {
mode: 'production', // // 设置 process.env.NODE_ENV 的值
}
模式值 | 翻译 | 说明 |
---|---|---|
development | 开发阶段 | 简易打包,打包速度快 |
production | 发布阶段 | 打包精细,打包速度慢 |
none | 不使用任何默认优化配置 |
production 会对源码做一些丑化和优化;
development 会把 webpack 的 devtool 设置为 evel。
webpack.config.js
module.exports = {
mode: 'development', // 开发阶段
devtool: 'inline-source-map' // 建立js映射文件,方便调试代码和错误
};
-
下载插件
yarn add html-webpack-plugin -D
-
webpack.config.js
// 引入自动生成 html 的插件 const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { // ...省略其他代码 plugins: [ // ...其它插件, new HtmlWebpackPlugin() ] }
👻 默认配置会根据默认的内置模板生成入口文件。
-
打包并观察
- dist + index.html # 自动引入bundle.js + bundle.js
-
自定义打包的html模版,和输出文件名字
plugins: [ new HtmlWebpackPlugin({ template: './public/index.html', filename: 'index.html' }) ]
修改代码需要打包才能看到最新效果,但打包的过程很耗时;
可以开起一个开发服务器, 在电脑内存中打包, 缓存一些已经打包过的内容, 只重新打包修改的文件, 最终运行加载在内存中给浏览器使用;
启动本地服务, 可实时更新修改的代码, 打包变化代码到内存中, 然后直接提供端口和网页访问。
-
下载包
yarn add webpack-dev-server -D
-
配置自定义命令
package.json
scripts: { // ... "serve": "webpack serve" }
-
启动webpack开发服务器
yarn serve
package.json
"scripts": {
// ...
"serve": "webpack serve --port 8083 --open"
},
webpack.config.js
module.exports = {
// ...其他配置
devServer: {
port: 3000, // 本地服务器占用的端口号
open: true // 服务器启动完成自动打开到浏览器
}
}
测试
src/style/index.css
.banner {
width: 100px;
height: 100px;
background-color: hotpink;
}
main.js
// 添加
import './style/index.css'
🐙 webpack 默认只能处理js类型文件,所以此时直接运行项目会报错。
支持配置
-
安装依赖
yarn add style-loader css-loader -D
-
webpack.config.js
module.exports = { // ...其他代码 module: { rules: [ // loader的规则 { test: /\.css$/, // 匹配所有的css文件 // use数组里从右向左运行 // 先用 css-loader 让webpack能够识别 css 文件的内容并打包 // 再用 style-loader 将样式, 把css插入到dom中 use: [ "style-loader", "css-loader"] } ] } }
测试
src/style/index.less
body {
.tabs {
width: 400px;
height: 40px;
background-color: pink;
}
}
main.js
// 添加
import './style/index.less'
🐙 webpack 默认只能处理js类型文件,所以此时直接运行项目会报错。
支持配置
-
安装依赖
yarn add less less-loader -D
-
webpack.config.js
module.exports = { // ...其他代码 module: { rules: [ { // 使用less-loader, 让webpack处理less文件 // 并能够将less转译成css代码 test: /\.less$/, use: ["style-loader", "css-loader", 'less-loader'] } ] } }
测试
-
定义盒子结构
<div class="box"></div> <div class="box2"></div>
-
通过样式设置背景图
.box { width: 100px; height: 100px; background-image: url(../assets/logo_small.png); } .box2 { width: 100px; height: 100px; background-image: url(../assets/1.gif); }
-
打包
会在打包目录下生成对应的一样数量的图片,且页面正常展示
配置
webpack5
module.exports = {
// ...其他代码
module: {
rules: [
{
test: /\.(png|jpg|gif|jpeg)$/i,
type: 'asset'
}
]
}
}
打包后发现图片被转化为了 base64 在js文件中出现,包总体积略增大;推测是体积小的图才转:question:
🐳 博客也有 webpack4 的配置。
-
以8kb进行区分,小于8kb图片转成 base64 字符串
- 好处是可以减少浏览器的请求次数,直接从js中读取
- 缺点是如果图片太大,再转
base64
就会让图片的体积增大 30% 左右
测试
-
准备并引入字体文件
main.js
// 引入字体图标文件 import '../assets/fonts/iconfont.css'
-
使用字体图标样式
public/index.html
<i class="iconfont icon-weixin"></i>
配置
webpack5
module.exports = {
// ...其他代码
module: {
rules: [
{
// webpack5默认内部不认识这些文件, 所以当做静态资源直接输出即可
test: /\.(eot|svg|ttf|woff|woff2)$/,
type: 'asset/resource',
generator: {
filename: 'font-[name].[hash:6][ext]'
}
}
]
}
}
按照上面的测试,这里配置与否没有影响文件数量和包体积大小
据说可配置可不配置,有什么区别吗:question:
🐳 博客也有 webpack4 的配置。
测试
main.js
// 添加
class App {
static a = 123
}
console.log(App.a)
🐳 不是所有的浏览器都支持ES6,使用 Chrome 测试支持很多新语法,但无法保证全部都支持。
说明
babel-loader 可以让 webpack 对高版本js语法做降级处理后打包。
依赖 | 说明 |
---|---|
@babel/core | babel的核心库,所有的核心Api都在这个库里,这些Api供babel-loader调用 |
@babel/preset-env | 一个预设的插件集合,包含了一组相关的插件,Bable中是通过各种插件来指导如何进行代码转换。该插件包含所有es6转化为es5的翻译规则 |
配置
-
安装包
yarn add -D babel-loader @babel/core @babel/preset-env
-
配置规则
module: { rules: [ { test: /\.js$/, exclude: /(node_modules)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] }
配置后,导入对应类型文件时,可以省略后缀。
module.exports = {
// 其他配置
resolve: {
extensions: [".js", ".css", ".vue"],
},
};
配置写法一
const path = require("path");
const resolve = (dir) => path.resolve(__dirname, dir);
module.exports = {
// 其它配置
resolve: {
alias: {
"@": resolve("src"),
style: resolve("src/style"),
},
},
};
🐙 注意不要在配置中使用多个 resolve 属性,会报一些找不到头绪的error。
配置写法二
const path = require("path");
module.exports = {
// 其它配置
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
style: "@/style",
},
},
};
使用示例
import "@/style/index";
import "style/index.less";
const webpack = require('webpack')
module.exports = {
...
plugins: [
new webpack.BannerPlugin('最终版权归大自然所有')
]
}
npm install uglifyjs-webpack-plugin -S -D
webpack.config.js
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')
plugins: [
new UglifyjsWebpackPlugin()
]
🌟 将删除所有的注释,与【配置版权信息的插件】冲突。
❓ webpack5 以上内置,应该只能应用于 webpack4 以下的版本,否则存在依赖版本问题。
npm install friendly-errors-webpack-plugin -D -S
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
module.exports = {
...
plugins: [
new FriendlyErrorsPlugin({
// 成功提示
compilationSuccessInfo: {
messages: [
`open here: http://localhost:8080`,
],
},
onErrors: undefined,
}),
]
}
module.exports = {
// ...其他配置
stats: 'errors-only' // 只在发生错误时输出到控制台
}
👻 在启动项目时可以过滤掉分析信息,开发出错时的信息也更简洁。
module.exports = {
// ...其他配置
devServer: {
port: 3000, // 本地服务器占用的端口号
// 当出现编译错误或警告时,在浏览器中显示全屏覆盖
client: {
overlay: {
errors: true,
warnings: false, // 警告时不进行全屏覆盖
},
},
}
}
webpack5.20+
const path = require("path")
module.exports = {
// ...
output: {
clean: true
}
}
webpack低版本
npm install clean-webpack-plugin -D
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
plugins: [
new CleanWebpackPlugin()
]
}
yarn add html-webpack-plugin -D
index.html
<link rel="icon" href="%= BASE_URL %>favicon.icon">
<title><%= htmlWebpackPlugin.options.title %></title>
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 使用示例,非必须
const { DefinePlugin } = require('webpack'); // 内置模板,无需安装
module.exports = {
plugins: [
new HtmlWebpackPlugin({
title: "网页标题",
template: "./public/index.html"
}),
new DefinePlugin({
BASE_URL: "'./'" // 需要内置引号,否则会在该上下文找对应变量
})
]
}
对于不存在依赖关系的图片等本地资源,可以将它们放在打包后的资源目录下。
npm install copy-webpack-plugin -D
const CopyWebackPlugin = require('copy-webpack-plugin');
plugins: [
new CopyWebackPlugin({
patterns: [
{
from: "public", // 需要复制的源位置
to: "./", // 复制到的位置
globOptions: {
ignore: { // 忽略,不进行复制的资源
"**/index.html"
}
}
}
]
})
]
🐢 可以忽略 CopyWebackPlugin 中的 to 配置项,它会自动读取上下文中的 output.path,即打包的目录下。
- 全局使用
- 项目文件下直接执行
webpack
命令
- 项目文件下直接执行
- 局部使用
- 项目文件下执行配置在
package.json
中的脚本命令,如npm run build
- 项目文件下,执行
node_modules/.bin/webpack
或相关命令
- 项目文件下执行配置在
👻 package.json
中的脚本在执行时,先寻找本地的 node_modules/.bin
路径中的命令,找不到就到全局环境(更上级?)找;
👻 项目一般在局部安装 webpack(-S -D
),因为不同的项目依赖的版本不同。
参考资料:
- 笔记/vue2-coderwhy
- 笔记/vue3-coderwhy
- 笔记/工具与业务/业务实现/其它/st/配置
- webpack看这一篇就够了
在仓库,还提供了许多前端常见需求及实现的归纳整理,欢迎客官看看~
如果这篇笔记能够帮助到你,请帮忙在 github 上点亮 star
,感谢!