有时候,我们希望根据用户当前的使用状态决定加载哪些模块。比如一个网页 IDE,用户在写 JS,我们就加载 JS 模块;用户在写 PHP 我们就加载 PHP 模块。这个功能有点类似路由懒加载,但又不完全相同。
以前在 wepback 里,我们可以通过动态 import
加注释的方式来做:
webpack.config.jsconst _ = 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`)
声明哪些文件可能要用到;接下来,我们就可以根据实际需求加载具体文件。大概方式如下:
/src/components/share.vue<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
,将相关装入特定分包:
vite.config.jsexport 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'; } }, }, }, }, }; });
欢迎吐槽,共同进步