有时候,我们希望根据用户当前的使用状态决定加载哪些模块。比如一个网页 IDE,用户在写 JS,我们就加载 JS 模块;用户在写 PHP 我们就加载 PHP 模块。这个功能有点类似路由懒加载,但又不完全相同。
以前在 wepback 里,我们可以通过动态 import
加注释的方式来做:
const _ = await import(/* webpackChunkName: "lodash" */ 'lodash');
// 通过组合不同注释,还可以实现不同的分包和加载策略
// Single target
import(
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */
/* webpackExports: ["default", "named"] */
'module'
);
// Multiple possible targets
import(
/* webpackInclude: /\.json$/ */
/* webpackExclude: /\.noimport\.json$/ */
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */
/* webpackPrefetch: true */
/* webpackPreload: true */
`./locale/${language}`
);
上面的内容可以在 Webpack 官方文档 找到。
Vite 里提供了类似的功能,不过使用方式不太一样。现在的 Vite 2 已经抛弃了以前的插件式实现,即 vite-plugin-dynamic-import 和 @rollup/plugin-dynamic-import-vars 都不会用到。
首先,我们要使用 import.meta.glob('./*.js`)
声明哪些文件可能要用到;接下来,我们就可以根据实际需求加载具体文件。大概方式如下:
<script lang="ts" setup>
// <script setup> 的代码,相当于 `created`,所以可以使用动态加载
// 未来要使用的变量
let shareTexts:ShareTexts;
// 声明符合 `/src/data/share*.ts` 的文件都可能要用到
const modules = import.meta.glob('../data/share*.ts');
// 如果 store 里有 `langName`,就加载 i18n 版,否则加载普通版
modules[`../data/${store.state.langName ? 'share-i18n' : 'share'}.ts`]()
.then(data => {
// 因为用到 esm,所以要加 `default`
shareTexts = data.default;
});
</script>
接下来,还可以配合 vite.config.js
,将相关装入特定分包:
export default defineConfig(({command, mode}) => {
return {
plugins: [
vue(),
],
build: {
rollupOptions: {
output: {
manualChunks(id) {
let result;
if (result = /(shares\/)?share\d\.txt\?raw$/.exec(id)) {
return result[1] ? 'share-i18n' : 'share';
} else if (id.includes('node_modules')) {
return 'vendor';
}
},
},
},
},
};
});
欢迎吐槽,共同进步