You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Vite与Module Federation的微前端部署MIME类型问题

Module Federation动态导入远程组件出现MIME类型错误

错误信息

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. _federation_expose_Page.0d00fb5f.js:1

环境配置

主机应用vite.config.js

import { defineConfig } from "vite";
import { resolve } from "path";
import react from "@vitejs/plugin-react";
import federation from "@originjs/vite-plugin-federation";

export default defineConfig({
  base: "/",
  plugins: [
    react(),
    federation({
      name: "app",
      remotes: {
        billing:
          "https://billing-microfrontend.delever.uz/assets/remoteEntry.js?v=1.2.2",
        singleOrder:
          "https://order-microfrontend.delever.uz/assets/remoteEntry.js?v=1.3.5",
      },
      shared: ["react", "react-dom", "@tanstack/react-query"],
    }),
  ],
  publicDir: "public",
  build: {
    outDir: "build",
    modulePreload: false,
    target: "esnext",
    minify: false,
    cssCodeSplit: false,
    rollupOptions: {
      onwarn(warning, warn) {
        if (warning.code === "MODULE_LEVEL_DIRECTIVE") {
          return;
        }
        warn(warning);
      },
    },
  },
  // Additional server configurations
  server: {
    port: 7777,
    cors: {
      origin: "*",
      methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
      allowedHeaders: ["X-Requested-With", "content-type", "Authorization"],
    },
  },
  // sass configuration
  css: {
    preprocessorOptions: {
      scss: {
        api: "modern",
      },
    },
  },
  resolve: {
    alias: [
      {
        find: "@",
        replacement: resolve(__dirname, "src"),
      },
    ],
  },
});

主机应用Nginx配置

user nginx;
worker_processes 1;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
  worker_connections 1024;
}

http {
  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';
  access_log /var/log/nginx/access.log main;

  sendfile on;
  keepalive_timeout 65;

  gzip on;
  gzip_types text/plain application/xml application/json application/javascript text/css image/svg+xml font/woff2;
  gzip_proxied no-cache no-store private expired auth;
  gzip_min_length 1000;
  gzip_vary on;

  server {
    listen 80;
    server_name localhost;

    root /build;  # Ensure this is the correct path to your build folder

    location / {
      try_files $uri $uri/ /index.html;  # Catch-all for client-side routing
    }

    location /assets/remoteEntry.js {
      add_header Content-Type application/javascript;  # Correct MIME type
      try_files $uri =404;  # Serve 404 if the file doesn't exist
    }
    
    # Serve static files with caching
    location ~* \.(?:js|css|woff2?|ttf|svg|png|jpg|jpeg|gif|ico|html)$ {
      try_files $uri =404;
      expires 6M;  # Cache static files for 6 months
      access_log off;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
      root /usr/share/nginx/html;
    }
  }
}

远程组件(singleOrder)Nginx配置

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
  worker_connections  1024;
}
http {
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;
  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
  access_log  /var/log/nginx/access.log  main;
  sendfile        on;
  keepalive_timeout  65;
  server {
    gzip on;
    gzip_types      text/plain application/xml;
    gzip_proxied    no-cache no-store private expired auth;
    gzip_min_length 1000;
    listen       3000;
    server_name  localhost;
    location / {
      root   /build;
      index  index.html;
      try_files $uri $uri/ /index.html;
    }
    location /assets/remoteEntry.js {
      root /build;
      
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
      root   /usr/share/nginx/html;
    }
  }
}

已知背景

此前通过禁用service workers和更新主机应用Nginx配置解决过同类问题;当前billing远程组件运行正常,但singleOrder组件出现上述MIME错误,二者路径与MIME配置逻辑一致。


问题排查与解决方案

1. 缓存问题(优先级最高)

  • 浏览器缓存:强制刷新页面(Ctrl+Shift+R),或在开发者工具中禁用缓存后重新加载,检查是否仍报错。
  • CDN/反向代理缓存:如果singleOrder组件部署在CDN后,需清除对应CDN节点的缓存,尤其是_federation_expose_Page.0d00fb5f.js这类动态生成的文件。
  • Nginx缓存:检查远程服务器是否开启了Nginx缓存,若有则临时关闭或清除缓存目录。

2. 远程组件Nginx配置缺陷

对比主机应用的Nginx配置,singleOrder的Nginx存在以下问题:

  • 缺少JS文件的MIME类型处理:主机应用中针对/assets/remoteEntry.js单独设置了Content-Type: application/javascript,且有覆盖所有静态文件的location ~* \.(?:js|...)规则;但singleOrder的Nginx仅对/assets/remoteEntry.js设置了root,未指定MIME类型,且全局的gzip_types未包含application/javascript,可能导致JS文件被错误识别为text/html。
  • 修复建议:
    1. 在singleOrder的Nginx配置中,给/assets/remoteEntry.js添加MIME类型头:
      location /assets/remoteEntry.js {
        root /build;
        add_header Content-Type application/javascript;
        try_files $uri =404;
      }
      
    2. 更新全局gzip_types,包含JS类型:
      gzip_types text/plain application/xml application/json application/javascript text/css image/svg+xml font/woff2;
      
    3. 确保静态文件规则覆盖所有JS文件,添加类似主机应用的静态文件location规则:
      location ~* \.(?:js|css|woff2?|ttf|svg|png|jpg|jpeg|gif|ico|html)$ {
        try_files $uri =404;
        expires 6M;
        access_log off;
      }
      

3. Vite构建配置差异

检查singleOrder远程组件的Vite构建配置:

  • 确认build.target设置为esnext,避免生成非模块格式的JS文件。
  • 检查federation配置中的exposes是否正确,确保导出的组件路径无误,避免构建后生成的文件路径错误导致404(进而被Nginx重定向到index.html,返回text/html)。
  • 确认build.outDir为build,且部署到Nginx的root /build路径下的文件完整,没有缺失_federation_expose_Page.0d00fb5f.js这类文件。

4. 网络请求验证

在浏览器开发者工具的Network面板中,查看_federation_expose_Page.0d00fb5f.js的请求:

  • 检查响应状态码:若为200,查看Response Headers中的Content-Type是否为application/javascript;若为404,说明文件不存在,Nginx返回了index.html(text/html)。
  • 检查请求URL是否正确:确认远程组件的资源路径是否与部署路径匹配,比如是否存在路径前缀错误。

内容的提问来源于stack exchange,提问作者Fazliddin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 02:44:53