Vite 里使用动态加载

有时候,我们希望根据用户当前的使用状态决定加载哪些模块。比如一个网页 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';
            }
          },
        },
      },
    },
  };
});

如果您觉得文章内容对您有用,不妨支持我创作更多有价值的分享:


已发布

分类

来自

标签:

评论

欢迎吐槽,共同进步

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据