您的位置:首页 > 文旅 > 美景 > 北京知名企业100强_三维动画设计_百度手机助手app_google谷歌搜索

北京知名企业100强_三维动画设计_百度手机助手app_google谷歌搜索

2025/7/5 18:15:18 来源:https://blog.csdn.net/YUYUYU972/article/details/147605442  浏览:    关键词:北京知名企业100强_三维动画设计_百度手机助手app_google谷歌搜索
北京知名企业100强_三维动画设计_百度手机助手app_google谷歌搜索

目录

1️⃣ 树摇
2️⃣ 分包
3️⃣ 多入口打包
4️⃣ 其他优化手段


树摇

“树摇”这玩意并非某个构建工具的专利,应该说基于ESM模块化开发的项目都有能力进行树摇。详细的分析可见煮啵的另一篇文章中的最后一小节,最核心的原因是CJS的require本质上是一个运行时的函数。此处只介绍树摇带来的具体效果:

// utils/index.js
export function util1() {console.log('util1')
}
export function util2() {console.log('util2')
}// main.js 入口文件
import { util1 } from './utils/index.js
console.log(util1)

这样的代码在打包后会摒弃未被使用的util2,只保留被使用的util1。但如果用CJS模块化进行改写:

// utils/index.js
exports.util1 = () => console.log('util1')
exports.util2 = () => console.log('util2')// main.js 入口文件
const { util1 } = require('./utils/index.js')

这种写法在打包后,即使util2未被使用,但也会带打包产物中被保留。


分包

在PDD的三面中被狠狠拷打🤯
“分包”即所谓的“代码分割”。常用的实现分包的方法有两种:通过修改Vite配置文件进行分包,或者通过动态导入语法import()进行代码分割。

通过修改Vite配置文件

设想一下:在我们的项目中引入了lodash,在进行分包前,lodash相关的代码会和业务代码一起被打包到同一个chunk中,且chunk的命名是通过哈希的方法来生成的,只要业务代码发生改动,那么chunk的命名几乎就会改变。
问题是,每一次更新我们修改的只是业务代码,lodash这些第三方包的代码我们肯定是不会改动的,但是每一次更新(甚至是每一次刷新)浏览器都得重新请求一次lodash的代码。因为lodash所在的chunk的名称会随版本的更新而变化,对这个chunk的请求浏览器走不了缓存。
所以我们的需求很简单:有没有办法让lodash被打包到一个单独的chunk中,后续浏览器只在第一次加载的时候请求这个chunk即可,后续都读缓存,以提高响应速度?有的兄弟,有的🤓🤓,以下介绍最基本的分包方法(详细的配置可见rollup的文档):

// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({build: {minify: false,  // 取消默认的压缩行为,方便观察打包产物rollupOptions: {output: {manualChunks: (id, { getModuleInfo }) => {// getModuleInfo可以查看当前模块的信息if (id.includes('node_modules/lodash')) return "vendor/lodash"}}}},
})

通过import()动态导入

import()动态导入也是实现代码分割的方法,这种优化本质上是借助Promise实现的,详细的分析见煮啵的另一篇博文的最后一章。import动态导入常用于实现路由懒加载(组件按需引入)。以React为例,见以下Demo:

// LazyComponent.tsx
export default function LazyComponent() {return <div>LazyComponent</div>;
}// App.tsx
import { lazy } from "react";
// 动态(按需)引用懒加载组件
const LazyComponent = lazy(() => import("./LazyComponent/index"));
const App = () => {return (<div><div>App</div><LazyComponent /></div>);
};
export default App;

之后不管是Chrome控制台还是本地打包产物,都可以看见LazyComponent组件相关的代码被抽离为一个单独的chunk。


多入口打包

多入口打包允许你将一个项目拆分为多个独立的入口文件(如前台index.html后台admin.html),每个入口生成单独的依赖图和资源包。这种优化方法更适合多页面应用MPA,不适合常见的SPA应用。~~煮啵用的是在是不多。~~假设现在前端股工程的目录如下:
App/
|—src
|——scriptA.js # 脚本A
|——scriptB.js # 脚本B
|——utils.js # 工具函数
|—indexA.html # 入口A
|—indexB.html # 入口B
|—vite.config.js
代码如下:

// utils.js
export function sayHello() {console.log('Hello')
}
export function sayGoodbye() {console.log('Goodbye')
}// scriptA.js
import { sayHello } from "./utils";
function scriptA() {console.log("scriptA is running");sayHello();
}
scriptA();// scriptB.js
import { sayHello, sayGoodbye } from "./utils";
function scriptB() {console.log("scriptB is running");sayHello();sayGoodbye();
}
scriptB();// vite.config.js
export default defineConfig({build: {minify: false,  // 取消默认的压缩行为,方便观察打包后的产物rollupOptions: {input: {scriptA: path.resolve(__dirname, 'src/indexA.html'),scriptB: path.resolve(__dirname, 'src/indexB.html'),},}},
})

此时Vite会以scriptA.js和scriptB.js这两个文件为入口,打包的产物有三个脚本文件,分别为:

// scriptA-HashCode.js
import { s as sayHello } from "./index-BVlMXCZJ.js";
function scriptA() {console.log("scriptA is running");sayHello();
}
scriptA();// scriptB-HashCode.js
import { s as sayHello, a as sayGoodbye } from "./index-BVlMXCZJ.js";
function scriptB() {console.log("scriptB is running");sayHello();sayGoodbye();
}
scriptB();// index-HashCode.js
(function polyfill() {// ...额外的与Vite相关的代码。
})()
function sayHello() {console.log("Hello");
}
function sayGoodbye() {console.log("Goodbye");
}
export {sayGoodbye as a,sayHello as s
};

此处Vite已进行了默认的优化。默认情况下被引用了至少两次的文件,会被打成一个独立的包。因为sayHello被多次复用,在构建中次函数所属的文件会被单独抽离出来。如果sayHello只在一处被调用,那么打包后它会在调用处的chunk中被声明。


其他优化手段

图片转Base64

关于Base64的分析见煮啵另一篇博文的最后一章。Vite默认将小于4KB的图片转为Base64格式,也可以自己手动调整:

// vite.config.js
export default {build: {assetsInlineLimit: 4096, // 调整阈值},
};

开启资源压缩

Vite默认 (没有手动配过,一直用的是默认) 使用 Terser 压缩 JS,ESBuild 压缩 CSS:

// vite.config.js
export default {build: {minify: 'terser', // 或 'esbuild'(更快但压缩率略低)terserOptions: {  // 自定义 Terser 配置compress: { drop_console: true },},},
};

暂时只想到这么多。后续有新的再来补充🧊

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com