什么是webpack
- 前端打包构建工具,并将打包的代码能够让浏览器识别
webpack 的安装
- npm install webpack webpack-cli -g 全局安装
- 打包命令:webpack
- npm install webpack webpack-cli -D 局部安装
- 打包命令:npx webpack
webpack 核心概念
Entry Webpack以哪个文件为入口起点开始打包
Output 打包后的资源放到哪,以及如何命名
Loader 将资源翻译成webpack能识别的资源
Plugins 代码压缩和优化
Mode
development 特点:能让代码本地调试运行的环境
production 特点: 能让代码优化上线运行的环境(代码会压缩)
devServer
- 先安装 npm i webpack webpack-cli webpack-dev-server -D , 运行命令 npx webpack-dev-server
- 它不会打包文件
const { resolve } = require("path");
let htmlwebpackplugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
filename: "build.js",
path: resolve(__dirname, "build"),
},
module: {},
plugins: [
new htmlwebpackplugin({
template: "./src/index.html", // 这个文件作为模板
filename: "index.html", // 模板名字
minify: {
// 进行压缩
removeAttributeQuotes: true, // 去掉 ""
collapseWhitespace: true, // 一行显示
},
}),
],
devServer: {
// 打包后的目录
contentBase: "./build",
// 启动 gzip压缩
compress: true,
// 端口
port: 3000,
// 打开浏览器
open: true,
},
mode: "development",
};
HMR
- 热模块替换
- 作用: 一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块)
const { resolve } = require("path")
module.exports = {
entry: "./src/index.js",
output: {
filename: "build.js",
path: resolve(__dirname, "build"),
},
module: {
rules: [
{
test: /\.css$/,
use: [
"style-loader",
"css-loader",
],
},
],
},
// 插件配置
Plugins: [],
// 模式
mode: "development",
devServer:{
// 开启 HMR
hot: true
}
};
// JS不支持热更新,所以在当前需要热更新的文件下加上这个
if(module.hot){
module.hot.accept("./math.js",() => {
// 当这个模块热更新了会执行这个回调函数
})
}
source-map
- 一种提供源代码到构建后代码映射技术(如果构建后代码出错了,通过映射可以追踪源代码错误)
开发环境:速度快,调试更友好
速度快(eval>inline>cheap)
- eval-cheap-source-map
- eval-source-map (不会生成单独文件 , 但可以显示列和行)
- 推荐 :eval-source-map
调试更友好
- source-map (会生成一个单独的sourcemap文件, 当前报错的列和行)
- cheap-module-source-map
- cheap-source-map
生产环境:源代码要不要隐藏?调试要不要更友好
- nosources-source-map (全部隐藏)
- hidden-source-map (隐藏源代码)
- 推荐 :source-map
const { resolve } = require("path")
module.exports = {
entry: "./src/index.js",
output: {
filename: "build.js",
path: resolve(__dirname, "build"),
},
module: {
rules: [
{
test: /\.css$/,
use: [
"style-loader",
"css-loader",
],
},
],
},
// Plugins: [],
mode: "development",
// source-map
devtool: 'eval-source-map'
};
watch
const { resolve } = require("path")
module.exports = {
entry: "./src/index.js",
output: {
filename: "build.js",
path: resolve(__dirname, "build"),
},
module: {
},
watch:true,
watchOptions:{ // 监控的选项
poll:1000, // 每1秒监听一次
aggregateTimeout: 500, // 防抖
ignored:/ node_modules / // 不需要监听的文件
}
// 插件配置
// Plugins: [],
mode: "development",
缓存 (哈希)
-
babel缓存
cacheDirectory: true -
文件资源缓存
-
hash:
每次 wepack 构建时会生成一个唯一的 hash 值
缺点:修改一个文件会重新打包所有文件 -
chunkhash:
根据 chunk 生成的 hash 值,如果打包来源于同一个 chunk,那么 hash 值就一样
缺点:一个文件既有 css 又有 js,当你修改 js 时 css 也会重新打包 -
contenthash:
根据文件的内容生成 hash 值,不同文件 hash 值不一样
对当前修改的文件进行重新打包
-
output: {
filename: "build.[contenthash:6].js",
path: resolve(__dirname, "build"),
},
tree shaking
- tree shaking:去除没有使用的代码,production环境下自动开启
- tree shaking 可能会无意间去掉css文件等,如果出现这种情况
- 在 package.json 中配置 sideEffects":"[*.css] ,这样就不会进行处理,或者在css的use后面设置sideEffects:true
split
- 代码分割,不让代码都在一个文件中,代码都打包在一个文件中加载速度慢
// 只要使用这种方式的都会打包出一个独立的文件
// webpackChunkName: 'test', 重新命名文件名
import(/* webpackChunkName: 'test' */ "./test").then(
(res) => {
console.log(res);
},
(err) => {
console.log("文件加载失败");
}
// webpack
optimization: {
splitChunks: {
// async 异步导入
// initial 同步导入
// all 异步/同步导入
chunks: "all",
// 最小尺寸: 如果拆分出来一个, 那么拆分出来的这个包的大小最小为 minSize
minSize: 20000,
// 将大于 maxSize 的包, 拆分成不小于 minSize 的包
maxSize: 20000,
// minChunks 用了2次就抽离
minChunks: 2,
cacheGroups: {
vendor: {
priority: 1,
test: /node_modules/, // 抽离第三方库
chunks: "initial",
},
},
},
},
CDN
- CDN称之为
内容分发网络
- 它是指通过相互连接的网络系统,利用最靠近每个用户的服务器,将资源更快的发送给用户
// webpack
const { resolve } = require("path");
let htmlwebpackplugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
filename: "[name].js",
path: resolve(__dirname, "build"),
},
plugins: [
new htmlwebpackplugin({
template: "./index.html",
}),
],
resolve: {
alias: {
"@": resolve(__dirname, "./src"),
},
},
externals: {
// key 包名
// value 这个库暴露出来的全局变量
lodash: "_",
dayjs: "dayjs",
},
};
// index
import _ from "lodash";
import dayjs from "dayjs";
console.log("Hello Main");
console.log(_.join(["Hello", "Main"]));
console.log(dayjs(), "Main");
/*
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CDN</title>
</head>
<body>
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
</body>
</html>
*/
懒加载,预加载
// 1. 懒加载
import(/* webpackChunkName: 'test' */ "./test").then(
(res) => {
console.log(res);
},
(err) => {
console.log("文件加载失败");
}
// 2.预加载,等待其他资源加载完,在进行加载
import(/* webpackChunkName: 'test' webpackPrefetch: true */ "./test").then(
(res) => {
console.log(res);
},
(err) => {
console.log("文件加载失败");
}