Nginx部署的vue动态组件加载问题

Vue dynamic component loading problem with Nginx deployment

我有以下情况:

我的 vue 应用程序中有一个组件,它根据 API 查询动态加载组件。这是我的模板:

<template>
  <main class="flex-1">
    <div class="py-6">
      <div class="px-4 sm:px-6 md:px-0 space-y-6">
        <LoadingComponent v-if="chosenSideBarItem === null" />
        <component v-else :is="getComponent(chosenSideBarItem.component)" />
      </div>
    </div>
  </main>
</template>

这是我的脚本部分

const componentMap = {
  Comp1: "./components/Comp1.vue",
  Comp2: "./components/Comp2.vue",
  Comp3: "./components/Comp3.vue",
};

Object.entries(componentMap).forEach(([key, value]) => {
  asyncComponents[key] = defineAsyncComponent({
    loader: () => import(value),
    loadingComponent: LoadingComponent,
    delay: 200,
    errorComponent: ErrorComponent,
    timeout: 3000,
  })
});


function getComponent(name : string) {
  return asyncComponents[name];
}

所以基本上应用程序根据一些字符串动态加载给定的组件。这在我的开发环境中工作得很好,但是如果我尝试使用 nginx 在我的 docker 容器中部署它,我会收到 MIME 错误

Loading module from “http://localhost/assets/components/Comp1.vue” was blocked because of a disallowed MIME type (“text/html”).

可能是因为该目录不存在。这是我的 nginx.conf

worker_processes 4;

events { worker_connections 1024; }

http {
   server {
          listen       80;
          server_name  localhost;

          location / {
              root   /usr/share/nginx/html;
              index  index.html index.htm;
              include  /etc/nginx/mime.types;
              try_files $uri $uri/ /index.html;
          }
    }
}

提前致谢!

为什么不这样做呢?

components: {
    firstcomponent: defineAsyncComponent({
      loader: () => import('./firstcomponent.vue'),
    }),
    secondcomponent: defineAsyncComponent({
      loader: () => import('./secondcomponent.vue'),
    }),
  },

这样代码就不那么复杂了,在模板中使用时可以按需加载

在模板中的用法类似于

<component :is="componentName" />

其中 componentName 将是“firstcomponent”或“secondcomponent”

如果您在多个加载器中重复相同的代码有问题,您可以这样做

const defaultParams = {
  delay: 20,
  timeout: 3000,
}

components: {
        firstcomponent: defineAsyncComponent({
          loader: () => import('./firstcomponent.vue'),
          ...defaultParams,
        }),
        secondcomponent: defineAsyncComponent({
          loader: () => import('./secondcomponent.vue'),
          ...defaultParams,
        }),
      },

不清楚您使用的是 Vite 还是 Webpack (Vue CLI),但在使用动态导入时两者都有非常相似的限制 (import(...))

这是 Vite

使用的 @rollup/plugin-dynamic-import-vars 的文档

最重要的限制是基于 import() 必须在编译时由捆绑器处理的事实。因此,打包器必须能够在编译时静态地能够分析参数并推断出可能的导入。使用变量当然是不行的...

所以修复它的一种方法是:

const componentLoaders = {
  Comp1: () => import("./components/Comp1.vue"),
  Comp2: () => import("./components/Comp2.vue"),
  Comp3: () => import("./components/Comp3.vue"),
};

Object.entries(componentLoaders).forEach(([key, loader]) => {
  asyncComponents[key] = defineAsyncComponent({
    loader,
    loadingComponent: LoadingComponent,
    delay: 200,
    errorComponent: ErrorComponent,
    timeout: 3000,
  })
});


function getComponent(name : string) {
  return asyncComponents[name];
}

...或不使用地图:

function getAsyncComponent(name : string) {
  return defineAsyncComponent({
    loader: () => import(`./components/${name}.vue`) ,
    loadingComponent: LoadingComponent,
    delay: 200,
    errorComponent: ErrorComponent,
    timeout: 3000,
  })
}