webpakck官网是英文版的,中文版的官网有错误,所以按照你的需求来看文档。
概述
webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。
安装webpack, 为方便起见,以一种熟悉的打包方式呈现,先建立一个你熟悉的文件目录
package-lock.json 和 package.json 的作用
package.json:里面定义的npm安装文件的版本,而node_modules中是npm实际安装的文件,指用来描述项目的依赖,需要注意的点:项目的名字会自动使用文件夹的名字,所以此时文件夹的名字不能是中文,特殊大写字母(执行了npm init -y初始化包描述文件)
package-lock.json:锁定安装时的包的版本号及包的依赖的版本号,保证其他人在使用npm install时下载的依赖包是一致的(执行npm i 或者 npm i xxx命令自动生成package-lock.json文件)
npx的用法
npx是npm包执行器(作用:调用项目内部安装的模块),比如调用xxx模块,只能在项目脚本和 package.json 的scripts字段里面,如果想在命令行下调用,必须像下面这样。
npx webpack ./src/main.js --mode=development
// 或者执行: node_modules/.bin/webpack ./src/main.js --mode=development
webpack官网上说:想要运行本地安装的 webpack,可以通过node_modules/.bin/webpack来访问它的二进制版本。另外,如果你使用的是 npm v5.2.0 或更高版本,则可以运行 npx webpack 来执行。同样的,阮一峰的网络日志-npx 使用教程 中也提到过。
<script src="../main.js"></script>
// 因为我的main用了Es Module的导入导出语法,而浏览器是不识别ES Module,所以报错
<script src="../dist/main.js"></script>
// webpack打包后就可以使用ES Module语法了,这也是webpack的基本功能
简单总结下:
Npm script是一个任务执行者。Npm script是Npm内置的一个功能,允许在package.json文件中使用scripts字段定义任务。
"scripts": {
"start": "npm run dev",
"dev": "webpack serve --config ./config/webpack.dev.js",
"build": "webpack --config ./config/webpack.prod.js",
"toBuild": "webpack",
"serve":"serve dist",
...
},
底层原理是通过Shell去运行脚本命令,例如执行npm run dev命令等同于执行了webpack serve --config ./config/webpack.dev.js
"dev": "webpack serve --config ./config/webpack.dev.js",
**以下三种命令等效执行这个脚本**
// ./node_modules/.bin/webpack serve --config ./config/webpack.dev.js
// npx webpack serve --config ./config/webpack.dev.js
// npm run dev
"serve":"serve dist" //./node_modules/.bin/serve dist,
**以下三种命令等效执行这个脚本**
// ./node_modules/.bin/serve dist
// npx serve dist
// npm run serve
"build": "webpack --config ./config/webpack.prod.js",
**以下三种命令等效执行这个脚本**
// ./node_modules/.bin/webpack --config ./config/webpack.prod.js
// npx webpack --config ./config/webpack.prod.js
// npm run build
聊到Npm Script,不得不提一个常见的面试题。
对比development和production环境
打包到本地开发环境:node_modules/.bin/webpack ./src/main.js --mode=development
打包到线上生产环境:npx webpack ./src/main.js --mode=production
五个核心概念
entry入口: 指示webpack文件以哪个文件为入口起点开始打包,分析构建内部依赖图
output输出:指示webpack打包后的资源bundles输出到哪里,以及如何命名
loader加载器:让webpack能够去处理那些非javascript资源css、img等,将它们处理成webpack能够识别的资源,可以理解为一个编译过程(webpack自身只能js和json文件)。值得关注的是:rules中的配置项:test、include、exclude是数组类型时,里面的项是"或"的关系,满足一个条件即可。
plugins插件:可用于执行范围更广的任务,插件的范围包括,从打包优化到压缩,一直到重新定义环境中的变量等
mode模式:mode指示webpack的使用相应模式的配置 \
开发模式:(development):配置比较简单,能让代码调用本地的环境
生产模式:(production):代码需要不断优化达到性能最好,能让代码优化上线运行时的环境
chunk是什么?Chunk是Webpack打包过程中,一堆module的集合。
我们知道Webpack的打包是从一个入口文件开始,也可以说是入口模块,入口模块引用这其他模块,模块再引用模块。Webpack通过引用关系逐个打包模块,这些module就形成了一个Chunk。*
知道上面这些概念后,我们回头看看打包的操作,除了前面提到那两种,我们用这些概念去实现打包的功能,具体应用如下:
// webpack.config.js文件
const path = require("path"); //nodejs中的
// __dirname
// 配置文件是在node.js环境下运行的,所以采用的是common.js模块化
module.exports = {
// 入口 相对路径
entry: "./src/main.js",
// 出口
output: {
// __dirname 当前文件的文件夹目录,即WEBPACKDEMO下的dist文件
// filename的路径是相对于output.path
path: path.resolve(__dirname, "dist"), // 绝对路径
filename: "main.js",
},
module: {
rules: [],
},
plugins: [],
mode: "production",//development
};
说明:执行npx webpack,命令会找webpackDemo文件下的webpack.config.js文件,并执行其中的打包逻辑代码
// package.json文件
...
"scripts": {
"toBuild": "webpack"
},
...
说明:执行npm run toBuild,执行效果和npx webpack一样,即我们简单的就实现了一个自定义的打包命令了!
样式文件css-loader 和less-loader等
// webpack.config.js文件
...
module: {
rules: [
{
test: /\.css$/i,// 正则中的test
use: [
"style-loader", // 将js中的css通过创建style标签添加到html文件中
"css-loader", // 将css资源编译成commonjs的模块到js中
], // 从右到左执行
},
],
},
...
style-loader的作用效果:
sass-loader、stylus-loader同理,这里不做赘述。
图片资源
// webpack.config.js文件
...
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
parser: {
dataUrlCondition: {
maxSize: 4 * 1024 //小于4kb的会转成base64,而不满足条件的会打包成一个.png文件
}
}
},
...
不需要下载loader,可以使用内置的 Asset Modules加载 images 图像 。文章看到这,当你打包文件时可以看到打包生成的文件时杂乱无章的,怎么解决呢?
配置js文件的打包路径和images的打包路径就ok了,如下:
// webpack.config.js文件
...
output: {
// __dirname 当前文件的文件夹目录,即WEBPACKDEMO下的dist文件
// filename的路径是相对于output.path
path: path.resolve(__dirname, "dist"), // 绝对路径
filename: "static/js/main.js",
clean:true, // 打包前自动清空之前的打包文件,在生成文件之前清空 output 目录
},
...
...
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
parser: {
dataUrlCondition: {
maxSize: 4 * 1024 //小于4kb的会转成base64
}
},
generator: {
filename: 'static/images/[hash][ext][query]'
}
},
...
配置好的打包资源路径如下:
字体图标资源、音视频资源等
跟图片资源类似,不需要下载loader,下面以字体为例:
// webpack.config.js文件
...
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: 'static/media/[hash:10][ext][query]' // hash取前10位
}
}
...
配置好的打包资源路径如下:
Eslint
配置文件写法: 只需要存在以下一种写法即可!
.eslintrc.*:新建文件,位于项目根目录.eslintrc.eslintrc.js.eslintrc.json
packge.json中eslintConfig:不需要创建配置文件,在原有文件基础上写
具体写法,以.eslintrc.json为例:
// eslintrc.json文件
{
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"semi": "error"
}
}
rules规则具体文档,规则太多,实际上规则是可以继承已有的模块。
简单模拟下eslint检查代码的具体操作:项目根目录新建一个.eslintrc.js文件
// .eslintrc.js文件
...
module.exports = {
extends: ["eslint:recommended"],
env: {
node: true,
browser: true,
},
parserOptions: {
ecmaVersion: 6,
sourceType: "module",
},
rules: {
"no-var": 2,
},
};
...
这个配置会根据你vscode中下载的eslint插件同步,也就是这个规则会应用到编译器的插件中。
Babel
主要用于将ES6语法编写的代码,转化为向后兼容的javascript语法,以便正常运行在低版本的浏览器环境 中
配置文件写法: 只需要存在以下一种写法即可!
babel.config.*:新建文件,位于项目根目录babel.config.jsbabel.config.json
babelrc.*:新建文件,位于项目根目录babelrcbabelrc.jsbabelrc.json
packge.json中babel:不需要创建配置文件,在原有文件基础上写
具体写法,以.eslintrc.json为例:
module.exports = {
// 预设
presets:[]
}
// 写法1
// webpack.config.js文件
...
module: {
rules: [
{
test: /.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader', // 通过Loader接入Babel
//options: {
//presets: ['@babel/preset-env']
//}
}
}
]
}
...
// babel.config.js文件
exports.module = {
presets: ['@babel/preset-env'] // presets预设属性,其实是一组Plugins的集合
}
// 写法2
// webpack.config.js文件
...
module: {
rules: [
{
test: /.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
...
babel环节需要单独配置一个文件:babel.config.js文件。
处理html资源
首先,需要安装 eslint-webpack-plugin:
// webpack.config.js文件
// 1.安装
npm install --save-dev html-webpack-plugin
// 2.引入
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 3.使用
module.exports = {
plugins: [new HtmlWebpackPlugin()],
};
优化代码:
// webpack.config.js文件
// 使用
module.exports = {
// 打包输出的文件是原文件,它会自动引入这个文件
new HtmlWebpackPlugin({template: path.resolve(__dirname, "public/index.html")}),
};
打包前后的文件就多了一个自动引入的那行<script/>代码,跟plugin插件有关的,三步走:下载=> 引入=> 使用。
DevServer服务
webpack-dev-server 可用于快速开发应用程序。
完成打包操作,但是我每次跑最新代码前都要打包一遍,显得特变繁琐,下面的操作会自动打包并运行最新的代码到一个服务器,如:http://localhost:3000/
// webpack.config.js文件
// 开发服务器
...
devServer:{
host:'localhost',
port:'3000',
open:true
},
mode: "development", //production
...
一定要注意的是,这里运行的是:npx webpack serve命令。
真实开发项目中的应用
把之前的webpack.config.js写在config文件中,放置开发环境和生产环境的config,如下:
配置文件相关的代码,如下;
// webpack.prod.js文件
const path = require("path"); //nodejs
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ESLintPlugin = require('eslint-webpack-plugin');
// __dirname
// 配置文件是在node.js环境下运行的,所以采用的是common.js模块化
module.exports = {
// 入口 相对路径
entry: "./src/main.js",
// 出口
output: {
// __dirname 当前文件的文件夹目录,即WEBPACKDEMO下的dist文件
// filename的路径是相对于output.path
path: path.resolve(__dirname, "../dist"), // 绝对路径
filename: "static/js/main.js",
clean: true, // 打包前自动清空之前的打包文件
},
module: {
rules: [
{
test: /\.css$/i, // 正则中的test
use: [
"style-loader", // 将js中的css通过创建style标签添加到html文件中
"css-loader", // 将css资源编译成commonjs的模块到js中
], // 从右到左执行
},
{
test: /\.less$/i,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource",
parser: {
dataUrlCondition: {
maxSize: 4 * 1024, //小于4kb的会转成base64
},
},
generator: {
filename: "static/images/[hash][ext][query]",
},
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource",
parser: {
dataUrlCondition: {
maxSize: 4 * 1024, //小于4kb的会转成base64
},
},
generator: {
filename: "static/images/[hash][ext][query]",
},
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader",
// use: {
// loader: 'babel-loader',
// options: {
// presets: ['@babel/preset-env']
// }
// }
},
],
},
plugins: [
// 打包输出的文件是原文件,它会自动引入这个文件
new HtmlWebpackPlugin({template: path.resolve(__dirname, "../public/index.html")}),
new ESLintPlugin({ context: path.resolve(__dirname, "../src") }),
],
// 开发服务器,能运行出,但是不会打包到dist目录,直接用了打包后的资源
// devServer:{
// host:'localhost',
// port:'3000',
// open:true
// },
// 生产模式不需要devServer,只需要打包输出
mode: "production",//development
};
// webpack.dev.js文件
const path = require("path"); //nodejs
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ESLintPlugin = require('eslint-webpack-plugin');
// __dirname
// 配置文件是在node.js环境下运行的,所以采用的是common.js模块化
module.exports = {
// 入口 相对路径
entry: "./src/main.js",
// 出口
output: {
// __dirname 当前文件的文件夹目录,即WEBPACKDEMO下的dist文件
// filename的路径是相对于output.path
// path: path.resolve(__dirname, "../dist"), // 绝对路径
path:undefined,
filename: "static/js/main.js",
clean: true, // 打包前自动清空之前的打包文件
},
module: {
rules: [
{
test: /\.css$/i, // 正则中的test
use: [
"style-loader", // 将js中的css通过创建style标签添加到html文件中
"css-loader", // 将css资源编译成commonjs的模块到js中
], // 从右到左执行
},
{
test: /\.less$/i,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource",
parser: {
dataUrlCondition: {
maxSize: 4 * 1024, //小于4kb的会转成base64
},
},
generator: {
filename: "static/images/[hash][ext][query]",
},
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource",
parser: {
dataUrlCondition: {
maxSize: 4 * 1024, //小于4kb的会转成base64
},
},
generator: {
filename: "static/images/[hash][ext][query]",
},
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader",
// use: {
// loader: 'babel-loader',
// options: {
// presets: ['@babel/preset-env']
// }
// }
},
],
},
plugins: [
// 打包输出的文件是原文件,它会自动引入这个文件
new HtmlWebpackPlugin({template: path.resolve(__dirname, "../public/index.html")}),
new ESLintPlugin({ context: path.resolve(__dirname, "../src") }),
],
// 开发服务器,能运行出,但是不会打包到dist目录,直接用了打包后的资源
devServer:{
host:'localhost',
port:'3000',
open:true
},
mode: "development", //production
};
上面两个配置文件中,都是我直接复制之前webpack.config.js的文件,只是它们和webpack.config.js文件的区别是:dev文件是本地环境,需要把path.resolve()相关的绝对路径在我目前的环境中要返回到上一层也就是加上../。prod文件是线上环境,也需要把path.resolve()相关的绝对路径在我目前的环境中要返回到上一层也就是加上../,还要把devServer自动打开这个关掉,没必要再打开这个服务器了。
// package.json文件
...
"scripts": {
"start": "npm run dev",
"dev": "webpack serve --config ./config/webpack.dev.js",
"build":"webpack --config ./config/webpack.prod.js",
},
...
在package.json文件配置命令脚本,代替npx webpack serve --config ./config/webpack.dev.js 和 npx webpack --config ./config/webpack.prod.js这两串这么长的命令!
特别说明下,当我们把网络调至低速3G运行时,你会发现我强制刷新浏览器,会出现这样的一个现象:
- 普通刷新:F5、地址栏左侧刷新、ctr + R
- 强制刷新: ctrl + F5、ctrl + 地址栏左侧刷新、ctr + shift + R
出现延迟或闪屏的原因是:css文件被打包到js文件中,js会创建一个style标签生成样式
解决的方案:单独打包生成一个css文件,通过link标签加载(通过下面的方式,打包后的html文件中有link标签)
npm install --save-dev mini-css-extract-plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
rules: [
{
test: /.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"], // 把style-loader字符串换成 MiniCssExtractPlugin.loader插件
},
],
plugins: [
new MiniCssExtractPlugin({ filename: "static/css/main.css" }), // 打包到
],
在一些特定的时间段,刷新时不会闪屏的,如下:
css兼容性处理
可参考一个简单易理解的文章
npm install --save-dev postcss-loader postcss postcss-preset-env -D
postcss-loader要放在css-loader 和 style-loader 之后, less-loader 之前 ,不然会报错
// webpack.prod.js文件
use: [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"postcss-preset-env",
{
// Options
},
],
],
},
},
},
],
// package.json文件
"scripts": {
"start": "npm run dev",
},
"browserslist":["ie > 8"] // 或者 "browserslist":["last 2 version",">1%","not dead"] "browserslist":["last 2 version",">1%","not dead"]
mian.css文件中:
// mian.css文件中
...
display:ms-flex; // 可以看到把felx打包成了兼容写法ms-flex
...
css压缩、html压缩和js压缩
npm install css-minimizer-webpack-plugin --save-dev
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
// For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
// `...`,
new CssMinimizerPlugin(),
],
},
plugins: [new MiniCssExtractPlugin()],
};
可见css代码压缩成了一行:
最后像html和js文件在开发环境就自动进行了压缩,而css可以要下载plugin才能压缩。
soursemap
soursemap:一种源代码和构建后代码的映射。 如果代码出错会在控制台显示出错的具体位置,但这个位置是打包后文件的位置,不能定位到源代码出错的位置,怎么解决?用以下方法在某些情况下会映射到源代码的具体位置:
// 开发模式
devtool:"cheap-module-source-map" // 默认值是false,即默认不生成Source map
// 生产模式
devtool:"source-map"
HotModuleReplacement
可以提升提升打包构建速度,开发修改其中一个模块的代码,webpack默认会将所有模块都重新打包,当文件越来越大速度会特别慢所以,需要做到只更新更改模块的代码,其他模块不变怎么实现呢? 启用热模块更换,也称为 HMR。vue或者react项目中有它们自动实现热模块的替换功能。
// webpack.dev.js文件
...
devServer: {
host: "localhost",
port: "3000",
open: true,
hot:false, // 默认hot:true,默认开启HMR方案,效率更高
},
...
// main.js文件
if(moudle.hot){
module.hot.accept('.xxx.js',fn)
}
oneOf
// webpack配置文件中
...
// 常规写法,找到匹配的loader还会进行继续向后查找
rules: [
{
test: /\.less$/i,
use: ["style-loader", "css-loader", "less-loader"],
},
...
]
...
// oneof写法,匹配到其中的一个loader文件进行处理就不在向后查找
rules: [
{
oneOf:[
{
test: /\.less$/i,
use: ["style-loader", "css-loader", "less-loader"],
}
]
},
...
]
cache缓存
使用缓存,提升性能
...
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader",
options: {
cacheDirectory: true, //开启babel缓存
cacheCompression: false, //关闭缓存文件压缩
},
},
...
缓存除了node_modules的文件
...
new ESLintPlugin({
context: path.resolve(__dirname, "../src"),
exclude: "node_modules", // 除去这个文件的默认值
cache: true,
cacheLocation:path.resolve(__dirname,"../node_modules/.cache/eslintCache")
}),
...
eslint也可以进行缓存
多进程配置
模拟多进程打包提升打包速度
npm i thread-loader -D
const os = require("os");
const threads = os.cpus().length; // cpu的核数
const TerserWebpackPlugin = require("terser-webpack-plugin"); // 这个插件已经内置了,不需要 install
...
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: [
{
loader: "thread-loader", //开启多线程
options: {
workers: threads, //进程数量
},
},
{
loader: "babel-loader",
options: {
cacheDirectory: true, //开启babel缓存
cacheCompression: false, //关闭缓存文件压缩
},
},
],
},
new TerserWebpackPlugin({
parallel: threads, //开启
}),
...
Tree-shaking
Tree-shaking的本质是消除无用的js代码,依赖Es Module环境,webpack默认已经开启了这个功能,简单的模拟下这个过程:
main.js文件中只是打包你引入了的文件,未引入的js文件不会被打包
压缩babel、压缩图片
下载对应插件在webpack文件中进行设置就能达到效果,可以自行百度了解,这里不做赘述
代码分割
一种应用场景中:渲染哪个页面加载对应的js文件,而不是整个main.js文件,这样加载资源少,所以加载的速度更快(spa单页面中只有一个入口文件,所以不适用单页面应用),简单模拟下:
// webapck配置文件
// 多入口
entry:{
app:"src/app/js",
main:"src/main/js",
}
output:{
path:path.resolve(__dirname, "dist"),
filename: [name].js, // [name]以文件名自己命名
}
执行结果,如下:
如果app.js和main.js中引入了公共的代码,正常打包后的这两个文件都会有这个公共的代码部分,这个是可以被webpack优化的。执行打包,这个52.js文件就是公共部分,在app.js和main.js中引入的是这个文件,所以达到了复用公共代码的目的,如下:
按需加载
什么场景需要哪个文件才引入哪个文件,而不是一开始就全部引入
点击这个按钮,会在点击时引入这个单独的js,而不必依赖app.js或者main.js这整个js文件
如果是spa单页面应用,单入口文件也能实现按需加载,加上如下配置:
你可能现在有疑问了,这个587.main.js文件可以自定义名字吗?webpack也可以实现,如下:
点击事件中加上:
配置文件加上,即可实现名字自定义模块命名:
Preload和Prefetch
Preload: 告诉浏览器立即加载资源
Prefetch: 告诉浏览器空闲时加载资源
简单区别:Preload优先级比Prefetch高;Preload只加载当前页面使用的资源,而Prefetch可以加载任何页面的资源
缺点:兼容性目前很差
npmjs.com网站中查看用法
npm install --save-dev @vue/preload-webpack-plugin
...
plugins: [
new HtmlWebpackPlugin(),
new PreloadWebpackPlugin({
rel: 'preload',
as: 'script'
// rel :'prefetch'
})
]
...
如果设置成:rel :'prefetch',这里的lowest表示权重很低,在浏览器空闲时就会下载这个文件
core.js 和 babel
1.'core.js' 和 'babel' 是两种概念
1.1.Babel 官方的介绍'Babel is a JavaScript compiler'也就是说'Babel 其实就是一个 JavaScript 的编译器'
1.2.'core.js' 它是JavaScript标准库的 polyfill(垫片/补丁)
2.core-js 又和 Babel 深度绑定,二者其实是两个东西,但又相互彼此的支持可以应用在一起
引入core.js,正确使用打包后会生成另外的js文件,里面就是兼容性的自定义实现代码
npm i core-js -D
// import "core-js" // 完整引入,文件大小200多kb
import "core-js/es/promise" // 按需加载,这个文件时路径是: node_modules/core-js/es/promise,文件大小30多kb
但是上面有个问题,虽然时按需引入但是不是智能的,要手动按需引入,这个时候可以结合bebel来实现智能按需引入
// babel.config.js文件
module.exports = {
presets: [
"@babel/preset-env", // babel智能预设
{
useBuiltIns: "usage", // 按需加载自动引入
corejs: 3,
},
],
};
PWA
Progress web apps:渐进式网络开发应用程序。作用:渐进式网络开发应用程序(离线可访问)
// webpack.config.js文件
// 下载
npm install workbox-webpack-plugin --save-dev
// 引入
const WorkboxPlugin = require('workbox-webpack-plugin');
...
// 注册 Service Worker
new WorkboxPlugin.GenerateSW({
// 这些选项帮助快速启用 ServiceWorkers
// 不允许遗留任何“旧的” ServiceWorkers
clientsClaim: true,
skipWaiting: true,
}),
...
// main.js文件
// 注册 Service Worker 兼容性判断
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register("/service-worker.js")
.then((registration) => {
console.log("SW registered: ", registration);
})
.catch((registrationError) => {
console.log("SW registration failed: ", registrationError);
});
});
}
离线缓存是通过Service Workers技术来实现的。Service Workers是在浏览器后台运行的脚本,它的生命周期完全独立于网页。无法直接访问dom,但是可以通过postMessage接口发送消息和ui进程通信。 这里补充下:
npm i serve
serve dist
http://localhost:3000 // 启动一个开发服务器,部署当前文件夹下的dist资源。同理,因为live Serve访问的地址有后缀:http://127.0.0.1:5500/dist/index.html所以不予采纳。
可以查看Application-Cache-Cache Stroage一栏,查看当前页面缓存的资源
即可实现一个离线加载资源的网站,如下图:
总结
文章参考了开发文档、视频讲解和吴浩麟版本-深入浅出webpack这本书
,通过 Webpack 的基本使用,掌握了以下功能:
- 两种开发模式
- 开发模式:代码能编译自动化运行
- 生产模式:代码编译优化输出
- Webpack 基本功能
- 开发模式:可以编译
ES Module语法 - 生产模式:可以编译
ES Module语法,压缩 js 代码
- Webpack 配置文件
-
5 个核心概念
entryoutputloaderpluginsmode
-
devServer 配置
- Webpack 脚本指令用法
webpack直接打包输出webpack serve启动开发服务器,内存编译打包没有输出