当前位置: 首页 > 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.lqws.cn/news/476047.html

相关文章:

  • 生成器函数概念与用法详解
  • 【Clickhouse系列】增删改查:对比mysql
  • Clickhouse官方文档学习笔记
  • FastAPI 入门教程 #06:FastAPI 请求体和数据模型
  • 从零理解鱼眼相机的标定与矫正(含 OpenCV 代码与原理讲解)
  • PostgreSQL全栈部署指南:从零构建企业级高可用数据库集群
  • React Next快速搭建前后端全栈项目并部署至Vercel
  • 《DeepSeek原生应用与智能体开发实践》案例重现
  • 关于数学函数和数据类型扩展的详细讲解(从属GESP二级)
  • 30天pytorch从入门到熟练(day1)
  • Mybatis-Plus支持多种数据库
  • 【机器学习四大核心任务类型详解】分类、回归、聚类、降维智能决策指南
  • 多项目预算如何集中管控与动态调整
  • 将Linux装进口袋: Ubuntu to Go 制作
  • 【Linux】进程间多种通信方式对比
  • Typescript基础
  • 【后端】负载均衡
  • MiniMax-M1 开源,Kimi 深度研究内测,GPT-5 今夏发布,Gemini 2.5 稳定上线!| AI Weekly 6.16-22
  • 大模型MetaGPT面试题汇总及参考答案
  • Python-break、continue与else语句
  • OJ搭建:Judge0服务器、DeepSeek服务接入简介
  • 70、爬楼梯
  • 相机camera开发之差异对比核查四:测试机和对比机的Camera动态参数差异对比及关键字
  • 笨方法学python-习题1
  • 设计模式精讲 Day 10:外观模式(Facade Pattern)
  • 无锡哲讯科技:助力纺织业搭乘 SAP 数字化快车
  • [xiaozhi-esp32] 应用层(9种state) | 音频编解码层 | 双循环架构
  • OpenGL ES 中的材质
  • 《高等数学》(同济大学·第7版)第五章 定积分 第二节微积分基本公式
  • ASP.NET Core API文档与测试实战指南