webpack5学习进阶:多页面应用、Tree Shaking、PWA、Shimming

2023-10-22 14:20

本文主要是介绍webpack5学习进阶:多页面应用、Tree Shaking、PWA、Shimming,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

      • 一、多页面应用
        • 1、entry 配置
          • 1.1、将两个本地文件打包在一起
          • 1.2、还可以打包第三方库文件
          • 1.3、多页面打包
        • 2、index.html 模板配置
        • 3、多页面环境搭建
      • 二、Tree Shaking(摇树优化)
        • 1、配置 Tree Shaking
        • 2、设置 sideEffects
        • 3、对全局 css 的影响
      • 三、PWA (开启离线服务)
        • 1、在线服务
        • 2、添加 Workbox 实现 PWA
        • 3、注册 Service-Worker
      • 四、Shimming (预置依赖)
        • 1、预置全局变量
        • 2、改变 this 指向
        • 3、全局导出一个模块(exports)
        • 4、Polyfils
          • 4.1、加载 polyfiles
          • 4.2、优化 polyfiles

一、多页面应用

在实际的项目开发中,一个完整的系统不会将所有的功能都放在一个网页里,这是因为会导致网页的性能不佳;实际的做法是,按照功能模块来划分为多个单页面应用,每一个单页面应用又生成一个 HTML 文件,随着业务的发展,更多的多页应用可以被逐渐的加到这个项目里;

1、entry 配置
1.1、将两个本地文件打包在一起
entry:['./src/app1.js', './src/app2.js']
//或者
entry:{main:{import:['./src/app1.js', './src/app2.js']}
}

打包过后,app1.js 和 app2.js 都会被打包进 dist/main.js 文件中,按照数组里面的前后顺序,webpack 会将前面的文件先打包,并且放在 main.js 的上面;

1.2、还可以打包第三方库文件
entry:['./src/app1.js', './src/app2.js', 'lodash']
1.3、多页面打包
entry:{app1:'./src/app1.js',app2:'./src/app2.js',
}

这种配置 webpack 会打包出两个文件,dist/app1.js 和 dist/app2.js ;

2、index.html 模板配置

新建一个 html 页面,动态获取 html-webpack-plugin 插件配置的 title,将多个 js 文件分别打包到对应的 html 文件中;

<title><%= htmlWebpackPlugin.options.title %></title>

在配置文件中

plugins:[new HtmlWebpackPlugin({title:'nihao xxs', template:'./index.html',inject:'body',chunks:['app1'],filename:'http:www.a.com/'})]

title:html 的 title 名称
template:打包 html 页面的模板
inject:js 在打包后的 html 中引入的位置
chunks:默认情况下,多入口文件打包出来的 js 文件都会放到打包后的 html 页面中,如果想载入指定的 js,可以在 chunks 数组中配置对应的 js 名称;
filename:配置包的前缀,一般比较大的项目会用到;

3、多页面环境搭建

添加多个 HtmlWebpackPlugin 插件配置:

plugins:[new HtmlWebpackPlugin({filename:'index1.html',title:'nihao xxs', template:'./index.html',inject:'body',chunks:['app1']}),new HtmlWebpackPlugin({filename:'index2.html',title:'nihao xxs', template:'./index.html',inject:'body',chunks:['app2']})]

不设置 chunks 的话会默认两个打包后的 html 文件都引入所有的 js,设置 chunks 之后,只会引入设置的 js;

我们还可以设置其他的一些东西:
1、打包后的 html 放到指定文件夹下,只需要修改 filename 路径,在路径上加一个文件夹名称,打包就会自动生成一个文件夹并把 html 放进去;

plugins:[new HtmlWebpackPlugin({filename:'chunk/index1.html',template:'./index.html',})]

2、将 js 页放到对应 html 文件夹下,也是修改入口文件的 filename 路径;

entry:{app1:{import:'./src/app.js',filename:'chunk/[name].js'}},

二、Tree Shaking(摇树优化)

Tree Shaking 是 webpack 内置的一个优化,主要功能就是去除没有用到代码。因为 JavaScript 大多数是要通过加载的,加载的文件越小,性能越好,所以 Tree-shaking 对于优化 JavaScript 很有意义。

Tree-shaking 主要依赖于 ES6 的模块化 import 和 export,在 production 环境默认开启;

注意:
1、Tree Shaking 只支持 ESMAScript 的引入方式,不支持 Common JS 的引入方式
2、在引入模块时就应该避免将全部引入,应该引入局部才可以触发 tree shaking 机制

1、配置 Tree Shaking
//test.js
import {add,mun} from './app1'
console.log(add(1,2))//app.js
export const add = function(a,b){return a+b
}
export const mun = function(a,b){return a
}

webpack中开启 Tree Sharking:

optimization:{usedExports:true
}

开发环境打包结果:
在这里插入图片描述
这里只暴露了 add 方法,并且提示 mun 未被导出;哪怕引入了,但是未被使用,依然会被认为是死代码,webpack5 在打包的时候会自动过滤掉死代码;

2、设置 sideEffects

如果在一个纯粹的 ESMScript 模块项目中,很容易识别出哪些文件有副作用;然而,我们实际开发的项目却无法达到这种纯度,所以,此时就必要提示 webpack compiler 哪些代码是“纯粹部分”。 通过 package.json 文件中的 sideEffects 属性;

1、sideEffects 默认为 true, 告诉 Webpack ,所有文件都有副作用,他们不能被 Tree Shaking。
2、sideEffects 为 false 时,告诉 Webpack ,没有文件是有副作用的,他们都可以 Tree Shaking。
3、sideEffects 为一个数组时,告诉 Webpack ,数组中那些文件不要进行 Tree Shaking,其他的可以 Tree Shaking。

在 package.json 文件中:

{"description": "","sideEffects":true,
}
3、对全局 css 的影响

正常不设置 sideEffects 的话,我们通过 import 引入一个全局的样式文件,webpack 默认是可以正常打包使用的;但是如果设置 sideEffects 为 false 时,这时候所有的文件都会被 Tree Shaking;我们需要单独设置 css 文件文件不要 Tree Shaking;

{"description": "","sideEffects":["*.css"],
}

所以我的理解是:开启 Tree Sharking 后 sideEffects 默认值为 true,这个时候 Tree Sharking 只处理没有关联关系的 js 代码,不处理引入的文件;如果设置 sideEffects 为 false,那么 import 引入的文件也放入到 Tree Sharking 中进行修剪处理;sideEffects 是控制 Tree Sharking 处理文件直接依赖关系的开关;

三、PWA (开启离线服务)

渐进式网络应用程序:简称 PWA,它可以提供类似于 native(原生)应用程序体验的 web app(web 应用程序),换句话就说说我们可以在浏览器端能够实现类似于原生应用程序的体验;

PWA 可以做的事情很多,其中最重要的就是在离线的情况下,应用程序能够继续运行的功能,它是通过 service worker 的 web 技术实现的;

1、在线服务

通常情况下,用户通过网络访问 web app ,浏览器会与一个提供所需资源的 server 通讯;这里我们来看看非离线环境下项目的运行效果;
1、安装 http-server

npm i http-server -D

2、在 package.json 定义自己的 npm 脚本

"scripts":{"start":"http-server dist"
}

用 http-server 来编译运行 dist 下的内容
3、启动服务

npm start

webpack-dev-server 和 http-server 都是在线的服务;在线服务在服务停止后,浏览器是无法正常访问到网页的;同时在线服务会把启动服务时编译的代码放在内存里,也就是说当我们修改代码之后重新启动服务,这个时候并不会把修改同步打包到 dist 文件夹下面;
4、如果启动服务想同步打包更新 dist 文件

devServer:{devMiddleware:{writeToDisk:true}
}

这个配置没什么太大意义,只是介绍一下有这个功能;

2、添加 Workbox 实现 PWA

1、安装 workbox-webpack-plugin 插件

npm i workbox-webpack-plugin -D

2、安装成功之后修改配置文件

const WorkboxPlugin = require("workbox-webpack-plugin")
module.exports={plugins:[new WorkboxPlugin.GenerateSW({clientsClaim:true, //帮助快速启用 service-workerskipWaiting:true //跳出等待,不允许遗留任何旧的 service-worker})]
}

3、打包编译
这个时候会发现多了两个文件:workbox.js 、service-worker.js;添加成功之后还需要进行下一步:注册 service-worker;

3、注册 Service-Worker

注册 service-worker 实现离线浏览页面的功能;

//在入口文件中 业务代码中 app.js
//判断浏览器是否支持service-worker
if("serviceWorker" in navigator) {//页面资源加载完成之后执行下面函数window.addEventListener("load",()=>{navigator.serviceWorker.register("/service-worker.js").then(reg=>{console.log('注册成功')}).catch(err=>{console.log("注册失败”)})})
}

然后执行 npx webpack 打包,执行 npm start 启动服务;这里我们是通过 npm start 来启动服务的,所以必须重新打包;这样我们的离线服务就启动成功了;

为了实验效果,可以在控制台将服务停止,然后继续在浏览器刷新页面访问网页,是能正常访问的;

实现这个效果主要原理是:浏览器把我们的页面做了缓存,我们可以把这个缓存清理掉:新开个页面输入"chrome://serviceworker-internals" 然后点击 Unregister 按钮,这样缓存就被清理了,页面就不能正常访问了;

四、Shimming (预置依赖)

shimming 又称垫片,本身不是一种具体的使用方法,而是一种使用思路。比如 @babel/polyfill,他所解决的就是打包代码运行在低版本浏览器上时有些 api 不兼容的问题,这些行为就是 shimming;

1、预置全局变量

比如我们想将 lodash 暴露成一个全局变量,需要借助 webpack 提供的 providePlugin 来实现,无需安装,因为是 webpack 内部提供的;

const webpack = require('webpack')
module.exports={plugins:[new webpack.providePlugin({_:lodash})]
}

这样,lodash 就是一个全局的变量了;

2、改变 this 指向

如果一些模块依赖的 this 指向的是 window,当它运行在 CommonJS 上下文中的时候,这就会出现问题,因为此时的 this 指向的是 module.exports ;这个时候我们需要通过 imports-loader 来改变 this;
安装

npm i imports-loader -D

配置

module:{rules:[{test:require.resolve('./src/index.js'),use:"imports-loader?wrapper=window"}]
}

这里的 test 需要加载某一个文件,所以借助 require.resolve 方法;然后 imports-loader 后面问号拼接一个 wrapper=window ,这是将包里面的 this 指向 window;

3、全局导出一个模块(exports)

将某些不支持模块化规范的模块所声明的全局变量、局部变量作为模块内容导出;
安装

npm i exports-loader -D

配置

module:{rules:[{test:require.resolve('./src/index.js'),loader:'exports-loader',options:{type:'commonjs',exports:["hello", "multiple help.parse parse"]}}]
}

需要导出的模块

const hello = "hello webpack"
const help = {parse:function(){console.log("i need help")}
}

type:模块导出的类型,我们指定的是 CommonJS
exports:导出的变量,我们导出的是 hello,multiple 表示导出局部变量
参数设置:参考 exports-loader

4、Polyfils

polyfill(polyfiller),指的是一个代码块;这个代码块向开发者提供了一种技术, 这种技术可以让浏览器提供原生支持,抹平不同浏览器对 API 兼容性的差异;你只需要把需要的Polyfill引入到你的程序里,就可以正常使用了;

4.1、加载 polyfiles

安装

npm i @babel/polyfile -D

引入

import "@babel/polyfile"
4.2、优化 polyfiles

如果在全局引入整个 polyfiles 包,转化之后打包的体积会比较大,而且还会污染全局环境;所以我们可以通过 babel-preset-env 包通过 browserslist 来指定那些浏览器、那些浏览器的版本进行转译;
我们要使用 babel 所以要先安装 babel 相关的 loader:

npm i babel-loader @babel/core @babel/preset-env core-js@3 -D

配置

module:{rules:[test:/\.js$/,exclude:/node_modules/,use:{loader:'babel-loader',options:{presets:[["@babel/preset-env",targets:["last 1 version","> 1%"],useBuiltIns:'usage',corejs:3]]}}]
}

配置完成之后,我们就不需要在手动引入 @babel/polyfile 包了;同时如果已经引入了,需要删除掉;

这篇关于webpack5学习进阶:多页面应用、Tree Shaking、PWA、Shimming的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/262015

相关文章

JavaScript中的isTrusted属性及其应用场景详解

《JavaScript中的isTrusted属性及其应用场景详解》在现代Web开发中,JavaScript是构建交互式应用的核心语言,随着前端技术的不断发展,开发者需要处理越来越多的复杂场景,例如事件... 目录引言一、问题背景二、isTrusted 属性的来源与作用1. isTrusted 的定义2. 为

Python调用另一个py文件并传递参数常见的方法及其应用场景

《Python调用另一个py文件并传递参数常见的方法及其应用场景》:本文主要介绍在Python中调用另一个py文件并传递参数的几种常见方法,包括使用import语句、exec函数、subproce... 目录前言1. 使用import语句1.1 基本用法1.2 导入特定函数1.3 处理文件路径2. 使用ex

Python进阶之Excel基本操作介绍

《Python进阶之Excel基本操作介绍》在现实中,很多工作都需要与数据打交道,Excel作为常用的数据处理工具,一直备受人们的青睐,本文主要为大家介绍了一些Python中Excel的基本操作,希望... 目录概述写入使用 xlwt使用 XlsxWriter读取修改概述在现实中,很多工作都需要与数据打交

将Python应用部署到生产环境的小技巧分享

《将Python应用部署到生产环境的小技巧分享》文章主要讲述了在将Python应用程序部署到生产环境之前,需要进行的准备工作和最佳实践,包括心态调整、代码审查、测试覆盖率提升、配置文件优化、日志记录完... 目录部署前夜:从开发到生产的心理准备与检查清单环境搭建:打造稳固的应用运行平台自动化流水线:让部署像

Linux中Curl参数详解实践应用

《Linux中Curl参数详解实践应用》在现代网络开发和运维工作中,curl命令是一个不可或缺的工具,它是一个利用URL语法在命令行下工作的文件传输工具,支持多种协议,如HTTP、HTTPS、FTP等... 目录引言一、基础请求参数1. -X 或 --request2. -d 或 --data3. -H 或

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

使用JavaScript将PDF页面中的标注扁平化的操作指南

《使用JavaScript将PDF页面中的标注扁平化的操作指南》扁平化(flatten)操作可以将标注作为矢量图形包含在PDF页面的内容中,使其不可编辑,DynamsoftDocumentViewer... 目录使用Dynamsoft Document Viewer打开一个PDF文件并启用标注添加功能扁平化

SpringBoot如何访问jsp页面

《SpringBoot如何访问jsp页面》本文介绍了如何在SpringBoot项目中进行Web开发,包括创建项目、配置文件、添加依赖、控制层修改、测试效果以及在IDEA中进行配置的详细步骤... 目录SpringBoot如何访问JSP页python面简介实现步骤1. 首先创建的项目一定要是web项目2. 在