Vite+VueJS构建后JSON文件动态导入失效问题求助
问题背景
我使用Vue I18n实现应用国际化,希望在特定条件下加载部分翻译文件。当前依赖版本如下:
├── typescript@5.2.2 ├── vite@4.4.9 ├── vue-i18n@9.4.1 ├── vue-tsc@1.8.13 └── vue@3.3.4
我尝试通过动态导入实现需求:
// main.ts let extraLocales; if (import.meta.env.VITE_MY_VAR) { extraLocales = await import(`./locales/${import.meta.env.VITE_MY_VAR}/de.json`); } import deDefault from "./locales/de.json"; const i18n = createI18n({ locale: "de", legacy: false, messages: { de: merge({}, deDefault, extraLocales ? extraLocales : {}) } });
开发模式(npm run dev)下一切正常,能看到请求http://localhost:5173/src/locales/my_var_value/de.json?import=。但构建应用后用Docker+Nginx部署时,出现以下错误:
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.
Uncaught TypeError: Failed to fetch dynamically imported module: http://localhost:8082/assets/locales/my_var_value/de.json
我已在vite.config.ts添加配置:
// vite.config.ts esbuild: { supported: { 'top-level-await': true //browsers can handle top-level-await features }, },
请问哪里操作有误?有什么解决方案?
问题原因及解决方案
1. Vite构建时动态资源识别问题
Vite生产构建时会将静态资源打包到assets目录,但直接使用模板字符串动态导入JSON时,Vite无法提前识别这些文件,导致构建后文件路径不匹配,请求返回404,Nginx默认返回HTML页面,进而触发MIME类型错误。
解决方法:用import.meta.glob预扫描资源
通过import.meta.glob告诉Vite提前扫描所有可能的额外翻译文件,确保它们被正确打包:
// main.ts import deDefault from "./locales/de.json"; // 预定义所有可能的额外locale文件路径,Vite会在构建时打包匹配文件 const extraLocaleModules = import.meta.glob('./locales/*/de.json'); let extraLocales = {}; if (import.meta.env.VITE_MY_VAR) { const targetPath = `./locales/${import.meta.env.VITE_MY_VAR}/de.json`; // 检查目标文件是否在预扫描列表中 if (extraLocaleModules[targetPath]) { const module = await extraLocaleModules[targetPath](); extraLocales = module.default || {}; } } const i18n = createI18n({ locale: "de", legacy: false, messages: { de: merge({}, deDefault, extraLocales) } });
2. Nginx配置问题
如果额外翻译文件已正确打包,但Nginx未配置JSON的MIME类型,或静态资源路径映射错误,也会导致问题。
解决方法:调整Nginx配置
- 添加JSON的MIME类型映射:
http { include mime.types; # 确保JSON类型被正确识别 types { application/json json; } # 其他全局配置... }
- 正确配置静态资源路由:
server { listen 8082; root /usr/share/nginx/html; index index.html; # 处理assets目录下的静态资源 location /assets/ { try_files $uri $uri/ =404; } # 单页应用路由 fallback location / { try_files $uri $uri/ /index.html; } }
3. 动态导入的JSON模块处理问题
动态导入JSON文件时,返回的模块对象包含default属性,直接合并整个模块对象会导致数据结构错误。
解决方法:提取模块的default属性
如果仍要使用原始动态导入方式,需修改代码提取default:
// main.ts let extraLocales = {}; if (import.meta.env.VITE_MY_VAR) { // 提取JSON模块的default属性 const module = await import(`./locales/${import.meta.env.VITE_MY_VAR}/de.json`); extraLocales = module.default || {}; }
内容的提问来源于stack exchange,提问作者rgrosjean

