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,
})
}
我有以下情况:
我的 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,
})
}