Vue+Vite+Express生产环境路由异常:模块脚本MIME类型错误
问题:Vue+Vite+Express生产环境嵌套路由资源加载失败
问题现象
生产环境测试时,非嵌套URL(如/home、/access)可正常访问,但嵌套URL(如/access/error、/access/login)触发以下错误:
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.
相关代码
index.html.ejs
<!DOCTYPE html> <html> <head> <% if (environment === 'production') { %> <link rel="stylesheet" href="<%= manifest['src/main.css'].file %>" /> <% } %> </head> <body> <div id="app"></div> <% if (environment == "production") { %> <script type="module" src="<%= manifest['src/main.js'].file %>"></script> <% } else { %> <!-- this link may be @vite instead of @vite/client--> <script type="module" src="http://localhost:5173/@vite/client"></script> <script type="module" src="http://localhost:5173/src/main.js"></script> <% } %> </body> </html>
Express服务器代码
import homepageRouter from "./homepage_router.js"; import apiRoutes from "./api_router.js"; const app = express(); app.set('view engine', 'ejs'); const distPath = path.join(path.resolve(), "dist"); app.use("/", express.static(distPath)); app.use('/', apiRoutes); app.use('/', homepageRouter); // set port, listen for requests app.listen(process.env.PORT, () =>{ console.log(`Server is running on port ${process.env.PORT}`); })
homepageRouter代码
router.get("/*", async (_req, res) => { const data = { environment: 'production', manifest: await parseManifest('production'), }; res.render("index.html.ejs", data); }); const parseManifest = async (enviroment) => { if (enviroment != 'production') return {}; const manifestPath = path.join(path.resolve(), "dist", "manifest.json"); const manifestFile = await fs.readFile(manifestPath); return JSON.parse(manifestFile); };
原因分析
问题核心是资源路径使用了相对路径。比如在/access/error页面中,浏览器会把src/main.xxx.js这类相对路径解析为/access/error/src/main.xxx.js——这个路径不存在,Express的通配路由(router.get("/*"))会返回index.html,导致资源请求拿到的是HTML文件而非JS/CSS,从而触发MIME类型不匹配错误。
解决方案
1. 改用绝对路径加载资源
修改index.html.ejs中的资源引用,在路径前加上根路径/,确保浏览器从网站根目录查找资源:
<% if (environment === 'production') { %> <link rel="stylesheet" href="/<%= manifest['src/main.css'].file %>" /> <% } %> <% if (environment == "production") { %> <script type="module" src="/<%= manifest['src/main.js'].file %>"></script> <% } %>
2. 适配子路径部署(可选)
如果应用部署在子路径下(而非根域名),需要在vite.config.js中设置base字段,比如部署在https://example.com/my-app/,则:
// vite.config.js export default { base: '/my-app/' }
Vite会自动将manifest.json中的资源路径加上base前缀,配合上述绝对路径引用,资源就能正确加载。
内容的提问来源于stack exchange,提问作者Max Vuksan
相关产品推荐
相关产品推荐

