personal website.
Table of contents
Note
使用 vite+vue3 构建项目
测试用仓库 进入
app/website文件夹下后进行bun run build即可
import xx from 'xxx'会合并, 异步引用() => import('xxx')会分包a,b,c三个文件。a同步引用b, b同步引用c, 同步引用可以平铺, 这其实相当于直接在a中同步引用了b和c。这时如果在a中对c进行异步引用则会导致冲突, 使得c无法被分包(因为c已经在同一个地方a中被同步引用)a异步引用b, b同步引用c, 这相当于a中没有任何同步引用, 但有另一个异步分支引用b。这时在a中同步引用c的话,c会与a进行合并,而在b中则通过同步引用这个合并后的文件获取ca异步引用b, b异步引用c。这时在a中同步引用c,c还是会与a进行合并,而在b中则通过__vitePreload异步引用这个合并后的文件获取cexport可以被保留named export, 例如export default {}和export const/function xxx = something等变为:const a = {};
const o = something;
export { a as default, o as xxx };
而通过同步引用的包经过其他手段进行分包(如manualChunks)则无法保留named export, 同样引用上面的例子,打包后可能会变为:const a = {};
const o = something;
export { a as u, o as p };
通过manualChunks实现类似组件库分割组件的想法不可行, 最好通过每个组件一个入口文件实现分割, 推荐通过配置build.lib来实现manualChunks中进行分包 则无法保留 named exportvite是否存在chunk大小上限限制或其他的同步引用分包策略,理论上来说所有同步引用都会被打成一个chunk?Note
如果该包作为组件使用而不是网页则推荐使用build.lib模式配置并打包
当然也可以自己写rollup配置文件, 但两种方式都需要自己写点脚本代码
项目src下的结构:
.
├── assets
│ └── vue.svg
├── components
│ └── i18n
│ ├── index.ts
│ └── lang
│ ├── en.ts
│ └── zh.ts
├── index.ts
└── vite-env.d.ts
这里在entry中配置了所有语言文件及其他入口,并且在fileName中通过matchLocaleLang来匹配语言文件的名字并加上路径
function getLocaleMap() {
const cwd = "./src/components/i18n/lang/";
const resList = Array.from(
new Bun.Glob("*.ts").scanSync({
cwd,
}),
).map((v) => path.join(cwd, v));
const resMap: Record<string, string> = {};
const tsPattern = /(.*)\.ts$/i;
resList.forEach((v) => {
console.log(v);
const name = "locale_" + path.basename(v).replace(tsPattern, "$1");
resMap[name] = v;
});
console.log(resMap);
return resMap;
}
function matchLocaleLang(name: string) {
const localePathBase = "i18n/";
const localeLangPath = "lang/";
// local lang
const localPattern = /^locale_(.*)/i;
const res = localPattern.exec(name);
if (res && res[1]) return path.join(localePathBase, localeLangPath, res[1]);
// locale
if (name === "locale") return path.join(localePathBase, name);
// other
return name;
}
export default defineConfig(() => {
return {
build: {
lib: {
entry: {
index: "src/index.ts",
locale: "src/components/i18n/index.ts",
...getLocaleMap(),
},
fileName(format, entryName) {
entryName = matchLocaleLang(entryName);
console.log(entryName);
return `${entryName}.${format}.js`;
},
formats: ["es"],
},
},
};
});
打包后得到:
.
├── components
│ └── i18n
│ ├── index.d.ts
│ └── lang
│ ├── en.d.ts
│ └── zh.d.ts
├── i18n
│ ├── lang
│ │ ├── en.es.js
│ │ └── zh.es.js
│ └── locale.es.js
├── index.d.ts
├── index.es.js
└── vite.svg
tsc输出的d.ts与js路径不同没事,可以通过package.json中的exports配置来实现:
{
"type": "module",
"exports": {
".": {
"import": "./dist/index.es.js",
"types": "./dist/index.d.ts"
},
"./i18n/lang/*": {
"types": "./dist/components/i18n/lang/*.d.ts",
"import": "./dist/i18n/lang/*.es.js"
},
},
}
这里我指明了入口和i18n/lang/*, types和import分别指定d.ts和js的路径, 但需要注意的是*只能匹配一次, 不能实现类似**/*.xxx的匹配
这样就实现了分开导出且保留named export