-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
【探讨】关于 vite
和 webpack
的分包优化的探讨
#5025
Labels
Comments
This comment was marked as outdated.
This comment was marked as outdated.
This was referenced Jul 10, 2024
Closed
diff --git a/dist/env.js b/dist/env.js
new file mode 100644
index 0000000000000000000000000000000000000000..364a5c722dd0774027e550899bc6eee9c8a04c4f
--- /dev/null
+++ b/dist/env.js
@@ -0,0 +1,22 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const path_1 = __importDefault(require("path"));
+const fs_1 = require("fs");
+const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
+const platform = process.env.UNI_PLATFORM;
+const inputDir = process.env.UNI_INPUT_DIR;
+
+// #region 分包优化参数获取
+const manifestJson = (0, uni_cli_shared_1.parseManifestJsonOnce)(inputDir);
+const platformOptions = manifestJson[platform] || {};
+const optimization = platformOptions.optimization || {};
+process.env.UNI_OPT_TRACE = !!optimization.subPackages;
+
+const pagesJsonPath = path_1.default.resolve(inputDir, 'pages.json');
+const jsonStr = fs_1.readFileSync(pagesJsonPath, 'utf8');
+const { appJson } = (0, uni_cli_shared_1.parseMiniProgramPagesJson)(jsonStr, platform, { subpackages: true });
+process.UNI_SUBPACKAGES = appJson.subPackages || {};
+// #endregion
\ No newline at end of file
diff --git a/dist/index.js b/dist/index.js
index f343787fe9d9aa1ac97f15a91078814ce747f9ed..6795d4f25cedc4ca7408cbe530b5ac4aa5c0ca2e 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -1,5 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
+// 引入一个初始化环境变量的脚本
+require("./env");
const shared_1 = require("@vue/shared");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const plugin_1 = require("./plugin");
diff --git a/dist/plugin/build.js b/dist/plugin/build.js
index 47598739e43a1f8049b54fcd756411b42a5dc0af..61ac0227f4587def6bb28baae63ddc789341fe3d 100644
--- a/dist/plugin/build.js
+++ b/dist/plugin/build.js
@@ -91,9 +91,87 @@ function isVueJs(id) {
return id.includes('\0plugin-vue:export-helper');
}
const chunkFileNameBlackList = ['main', 'pages.json', 'manifest.json'];
+
+// #region subpackage
+const UNI_SUBPACKAGES = process.UNI_SUBPACKAGES || {};
+const subPkgsInfo = Object.values(UNI_SUBPACKAGES);
+const normalFilter = ({ independent }) => !independent;
+const independentFilter = ({ independent }) => independent;
+const map2Root = ({ root }) => root + '/';
+const subPackageRoots = subPkgsInfo.map(map2Root);
+const normalSubPackageRoots = subPkgsInfo.filter(normalFilter).map(map2Root);
+const independentSubpackageRoots = subPkgsInfo.filter(independentFilter).map(map2Root);
+
+// id处理器:将id中的moduleId转换为相对于inputDir的路径并去除查询参数后缀
+function moduleIdProcessor(id) {
+ let inputDir = (0, uni_cli_shared_1.normalizePath)(process.env.UNI_INPUT_DIR);
+ // 确保inputDir以斜杠结尾
+ if (!inputDir.endsWith('/')) {
+ inputDir += '/';
+ }
+
+ const normalized = (0, uni_cli_shared_1.normalizePath)(id);
+ const name = normalized.split('?')[0];
+ // 从name中剔除inputDir前缀
+ const updatedName = name.replace(inputDir, '');
+
+ return updatedName;
+}
+// 查找模块列表中是否有属于子包的模块
+const findSubPackages = function (importers) {
+ return importers.reduce((pkgs, item) => {
+ const pkgRoot = normalSubPackageRoots.find(root => moduleIdProcessor(item).indexOf(root) === 0);
+ pkgRoot && pkgs.add(pkgRoot);
+ return pkgs;
+ }, new Set())
+}
+// 判断是否有主包(是否被主包引用)
+const hasMainPackage = function (importers) {
+ return importers.some(item => {
+ return !subPackageRoots.some(root => moduleIdProcessor(item).indexOf(root) === 0);
+ })
+}
+// 判断该模块引用的模块是否有跨包引用的组件
+const hasMainPackageComponent = function (moduleInfo, subPackageRoot) {
+ if (moduleInfo.id && moduleInfo.importedIdResolutions) {
+ for (let index = 0; index < moduleInfo.importedIdResolutions.length; index++) {
+ const m = moduleInfo.importedIdResolutions[index];
+
+ if (m && m.id) {
+ const name = moduleIdProcessor(m.id);
+ // 判断是否为组件
+ if (
+ name.indexOf('.vue') !== -1 ||
+ name.indexOf('.nvue') !== -1
+ ) {
+ // 判断存在跨包引用的情况(该组件的引用路径不包含子包路径,就说明跨包引用了)
+ if (name.indexOf(subPackageRoot) === -1) {
+ if (process.env.UNI_OPT_TRACE) {
+ console.log('move module to main chunk:', moduleInfo.id,
+ 'from', subPackageRoot, 'for component in main package:', name)
+ }
+
+ // 独立分包除外
+ const independentRoot = independentSubpackageRoots.find(root => name.indexOf(root) >= 0)
+ if (!independentRoot) {
+ return true
+ }
+ }
+ } else {
+ return hasMainPackageComponent(m, subPackageRoot)
+ }
+ }
+ }
+ }
+ return false;
+}
+// #endregion
+
function createMoveToVendorChunkFn() {
const cache = new Map();
const inputDir = (0, uni_cli_shared_1.normalizePath)(process.env.UNI_INPUT_DIR);
+ const UNI_OPT_TRACE = process.env.UNI_OPT_TRACE === 'true' ? true : false;
+ console.log('分包优化开启状态:', UNI_OPT_TRACE);
return (id, { getModuleInfo }) => {
const normalizedId = (0, uni_cli_shared_1.normalizePath)(id);
const filename = normalizedId.split('?')[0];
@@ -114,6 +192,20 @@ function createMoveToVendorChunkFn() {
}
return;
}
+ if (UNI_OPT_TRACE) {
+ // 如果这个资源只属于一个子包,并且其调用组件的不存在跨包调用的情况,那么这个模块就会被加入到对应的子包中。
+ const moduleInfo = getModuleInfo(id) || {};
+ const importers = moduleInfo.importers || []; // 依赖当前模块的模块id
+ const matchSubPackages = findSubPackages(importers);
+ if (
+ matchSubPackages.size === 1 &&
+ !hasMainPackage(importers) &&
+ !hasMainPackageComponent(moduleInfo, matchSubPackages.values().next().value)
+ ) {
+ debugChunk(`${matchSubPackages.values().next().value}common/vendor`, normalizedId);
+ return `${matchSubPackages.values().next().value}common/vendor`;
+ }
+ }
// 非项目内的 js 资源,均打包到 vendor
debugChunk('common/vendor', normalizedId);
return 'common/vendor'; |
Otto-J
added
question
Further information is requested
mp
mini program
Good!完整的提问
完整的提问 full info
labels
Jul 12, 2024
我原本写了一个简单的,参考博主的做了一些修改,已经用上了,感谢。 |
实现了插件化了哈,见这里的说明 |
m |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
引语
以下是uniapp2, 也就是基于webpack打包的vue2版本的分包优化策略的详细实现
uni-app/packages/vue-cli-plugin-uni/lib/split-chunks.js
Line 114 in fb00949
以下是基于vite打包的vue3版本的rollup的打包配置
uni-app/packages/uni-mp-vite/src/plugin/build.ts
Line 118 in 1c19012
问题
本人的项目(uniapp-vue3版本)在小程序这边的包大小已经到了一个瓶颈阶段,该分包的都分包了,公共组件也是尽可能的少了;
甚至魔改了uniapp的源码实现了小程序那边支持的异步分包功能,实现了主包异步引用分包组件的能力;
但是随着业务功能的增多,以上分包优化策略已不满足,小程序发版受到严重的影响,急需实现与vue2版本的分包优化一致功能。
探讨
本人研究了uniapp2版本的webpack的分包优化的具体实现,正在尝试对vite的分包优化进行实现(此工作正在进行中,突发奇想发个issue想知道官方有没有考虑这一块)。
不知官方对此处rollup的打包配置有没有什么指导性的建议,以实现与vue2版本的一样的分包优化的效果。
问题整理
https://github.com/Vanisper/uniapp-bundle-optimizer 我做的分包优化解决方案的一个整理,请阅读readme指引操作。
The text was updated successfully, but these errors were encountered: