当前位置: 首页 > news >正文

webpack+vite前端构建工具 - 8 代码分割

8 代码分割

  • 代码分割:按需求将代码分割为不同的文件,使项目更快打开。
  • 经常使用代码打包工具(如webpack)处理代码分割

8.1 为什么进行代码分割

8.1.1 为何进行单入口处理

  • 例如vue单页面项目等单入口(一个入口文件打包后对应一个出口js文件)情况,意味所有代码在一个文件里(一个app.js里包含所有的引入的其他js文件),这样会导致代码过大

一个有200多个页面的项目,全都在一个js文件里,意味着要展示首页,要将所有的js文件下载下来。
文件过多,首页加载速度变慢

  • 需要把不是马上用到的代码拆分出来,用于加快首屏速度

例如d.js不是首页要用到的js,可能是进行某个操作要用到的js,那么就将d.js从app.js拆分出来,单独打包。这样就会打出2个js文件,一个app.js,一个d.js. —— 异步引入

8.1.2 为何进行多入口处理

  • 单入口和多入口要处理的问题是不同的

    • 单入口处理的问题是所有的文件都在一个文件里,为避免体积过大,因此要拆为异步引入。
    • 但多入口本身已经拆分为了不同的入口不同的页面,每个入口对应一个结果,不会存在体积过大的问题。
  • 多入口的问题

    • 问题描述:重复加载同一段逻辑代码
    • 问题举例
      • app.js和app2.js同时依赖b.js,打包后的两个js分别打包了b.js文件。
      • b.js分别在app.js和app2.js都存在。
      • 浏览器运行app.js时 ,将b.js代码下载一遍,运行app2.js时,又将b.js下载一遍。
    • 解决思路:相同的模块独立打包。
      • 浏览器存在缓存,对于加载过的文件会缓存下来。
      • 因此加载app.js时加载b.js,并缓存,再加载app2.js时直接使用缓存的b.js而无需再次加载

8.2 何时代码分割

8.2.1 何时处理单入口情况

  • 异步引入的前提分析

    • 不是说所有首页不会马上用到的js都可以拆为异步引入
    • 拆成异步引入 → 减少打包的app.js的体积 → 加快首屏速度
    • 拆成异步引入 → 但增加http请求的数量 → 增加服务器压力
    • 与base64本质相似
      • base64可以减少http请求,但是不能滥用
      • 大的图片转为base64 → 图片体积加到app.js → 增加打包的app.js → 减慢首屏加载速度
        • 原因:app.js下载完成后才能加载页面 → app.js体积过大 → 下载速度会变慢
  • 异步引入的结论

    • 除非文件非常大&首页不会马上使用 → 推荐异步引入

8.3 如何进行代码分割

8.3.1 如何处理单入口情况

  • 异步引入的方法
    • import
      • 较多使用
    • require.ensure
1 情景构建&异步引入

例如app.js需要在3s后使用a.js。

// app.js
setTimeout(() => {import('./a.js').then(res => {// res是a.js export的内容console.log("🚀 ~ import ~ res:", res);console.log("🚀 ~ import ~ res.default:", res.default);});
}, 3000);
// a.js
let b = 3;
console.log(b);
export default b + 1;
2 打包

打包结果:除了app1.xxxx.xxxx.js,还有一个js文件。
在这里插入图片描述

3 实际效果

浏览器打开index.html,打开控制台。
可以看到,初始只有3个文件。

在这里插入图片描述
3s后请求第4个文件。
在这里插入图片描述
控制台打印结果
在这里插入图片描述

4 指定文件命名

添加魔法注释magic comment——/*webpackChunkName:"a"*/

// app.js
simport "./test.css";setTimeout(() => {import(/*webpackChunkName:"a"*/'./a.js').then(res => {// res是a.js export的内容console.log("🚀 ~ import ~ res:", res);console.log("🚀 ~ import ~ res.default:", res.default);});
}, 3000);

打包结果
在这里插入图片描述

5 require.ensure的写法

以上是import的写法,本节介绍require.ensure的写法。

  • 第1个参数是第2个参数回调要用到的依赖
  • 文件命名在于第3个参数
// app.js
import "./test.css";setTimeout(() => {// import(/*webpackChunkName:"a"*/'./a.js').then(res => {//     // res是a.js export的内容//     console.log("🚀 ~ import ~ res:", res);//     console.log("🚀 ~ import ~ res.default:", res.default);// });// 第1个参数是第2个参数回调要用到的依赖require.ensure(["jquery"], ($) => {let b = require("./a.js");// 此处的b与import写法的res是一样的console.log("🚀 ~ require.ensure ~ b:", b);console.log("🚀 ~ require.ensure ~ b.default:", b.default);}, "a");// 文件命名在于第3个参数
}, 3000);

8.3.2 如何处理多入口情况

1 情景构建

app.js和app2.js都引入了a.js

// app.js
import "./test.css";
import './a.js'
// app2.js
import './a.js'
console.log("app2.js")

a.js不赘述了,跟之前一样。

直接打包,看无处理的情况是怎样的。

  • app.js和app2.js打包的文件均有a.js的代码。
  • 即a.js的代码要加载两次
    在这里插入图片描述

在这里插入图片描述

2 配置

在optimization配置splitChunks属性。

const htmlwebpack = require('html-webpack-plugin');
module.exports = {// entry: "./app.js",//单入口写法,入口指定为app.jsentry: {  // 多入口写法:入口名称+入口文件app1: ["./app.js"],app2: "./app2.js"},// entry: ["./app.js", './app2.js'] // 两个文件同时作为一个入口output: {path: __dirname + '/dist', // 绝对路径,__dirname是node的全局变量,表示当前目录的绝对路径filename: "[name].[hash:4].bundle.js", //将name加到filename里,打包结果文件是app.bundle.js和app2.bundle.js,hash是对文件是否有改变的标志,:4表示截取前4位},mode: "development", //webpack4以后要指定mode// loadermodule: {rules: []},plugins: [new htmlwebpack({template: './index.html',// 写法1,指定html模板// templateContent: function () {  // 写法2,自定义模板,使用频率较低//     return '<div>123</div>'// }filename: "index.html",chunks: ["app1"],minify: {collapseInlineTagWhitespace: false, // 是否一行展示removeComments: false, // 是否移除注释removeAttributeQuotes: false, // 是否移除属性之间的多余空格},inject: "body" // 指定js加载位置: body|true(加载到body中), head, false(不加载)}),new htmlwebpack({template: './index2.html',filename: "index2.html",chunks: ["app2"]})],optimization: {splitChunks: {chunks: "all", // 分割规则:all, async(只拆分异步),initial(只拆分同步)minChunks: 2, // 一个chunk重复出现几次才拆分为独立的文件minSize: 0 // 最小拆分量(拆分量多了会增加http请求数量,造成资源浪费),单位bit}}
}
3 打包

只有1个a.js被打包。
在这里插入图片描述
app.js和app2.js都不再有a.js的内容。
在这里插入图片描述
在这里插入图片描述

4 其他配置
多入口文件命名

optimization的splitChunks的属性name值为要指定的文件名。

// webpack.config.js 局部optimization: {splitChunks: {chunks: "all", // 分割规则:all, async(只拆分异步),initial(只拆分同步)minChunks: 2, // 一个chunk重复出现几次才拆分为独立的文件minSize: 0, // 最小拆分量(拆分量多了会增加http请求数量,造成资源浪费),单位bitname: "a"}}

8.4 指定要分割的文件

需要将某个文件单独分割出来,或将第三方库单独打包,runtime代码等单独打包。

这是单入口和多入口通用的功能。

p7 22:00
不看了,多入口的情况用不到,现在碰到的项目还是vue居多,用到再看。

http://www.lryc.cn/news/573633.html

相关文章:

  • 【数据结构试题】
  • C#Halcon从零开发_Day13_几种阈值分割方法
  • 《高等数学》(同济大学·第7版)第五章 定积分 第四节反常积分
  • 目标检测neck算法之MPCA和FSA的源码实现
  • python实战项目77:足球运动员数据分析
  • React 18.2.0 源码打包
  • C++智能指针的知识!
  • 无人机表演越来越火,C端市场大爆发
  • Java基础八股文 - 面试者心理历程与标准答案
  • 微处理器原理与应用篇---常见基础知识(7)
  • 反无人机系统:技术利刃如何守护低空安全?
  • 啥是 SaaS
  • C# .NET多线程异步记录日声,队列LOG
  • docker镜像封装与发布微服务学习
  • NotePad++ 怎么没有找到插件管理?
  • Python打卡DAY34
  • 【科研绘图系列】R语言绘制论文组合图形(multiple plots)
  • Redis快的原因
  • 【单调栈】-----【小A的柱状图】
  • 大零售生态下开源链动2+1模式、AI智能名片与S2B2C商城小程序的协同创新研究
  • 如何用AI开发完整的小程序<7>—让AI微调UI排版
  • Spring AI 项目实战(十):Spring Boot + AI + DeepSeek 构建智能合同分析技术实践(附完整源码)
  • opencv 之双目立体标定算法核心实现
  • C#控制Button单击事件指定时间间隔触发
  • 计算鱼眼相机的内参矩阵和畸变系数方法
  • 风险矩阵与灰色综合评价
  • AMAT P5000 CVDFDT CVDMAINT Precision 5000 Mark 操作 电气原理 PCB图 电路图等
  • git 如何忽略某个文件夹文件
  • NW896NW859美光固态闪存NW893NX764
  • 激活函数为何能增强神经网络的非线性表达能力?