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

使用Vue.js+Express开发SPA时Chrome跨域请求两次的解决方法咨询

优雅解决Vue+Express SPA跨域时的OPTIONS预检请求问题

Hey there! Let's clear up what's happening first: those two requests aren't a bug—they're the browser's preflight OPTIONS requests, a security measure enforced by the Same Origin Policy. For any "non-simple" cross-domain requests (like those with custom headers, PUT/DELETE methods, or Content-Type: application/json), the browser first sends an OPTIONS request to check if your backend allows the actual request to proceed. Once it gets the green light, it sends the real request.

Here are the most elegant solutions to handle this:

The easiest and most robust way is to leverage the official cors package to handle all cross-domain logic automatically, including OPTIONS preflights.

  • First, install the package:
    npm install cors
    
  • Then configure it in your Express entry file (e.g., app.js):
    const express = require('express');
    const cors = require('cors');
    const app = express();
    
    // Configure strict CORS rules (adjust for your setup)
    const corsOptions = {
      origin: 'https://your-frontend-domain.com', // Replace with your actual frontend URL
      credentials: true, // Enable if you need to send cookies/auth tokens
      allowedMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
      allowedHeaders: ['Content-Type', 'Authorization'] // List any custom headers your frontend uses
    };
    
    app.use(cors(corsOptions));
    
    // Rest of your Express routes/middleware...
    

This setup will automatically respond to OPTIONS requests with the correct headers, and the browser will stop treating your requests as suspicious.

2. Convert Requests to "Simple Requests" (For Minimal Use Cases)

If your use case allows, tweak your requests to fit the browser's definition of a "simple request"—this skips the preflight entirely. A simple request must meet all these criteria:

  • Uses only GET, POST, or HEAD methods
  • Only includes these headers: Accept, Accept-Language, Content-Language, Content-Type (with values limited to application/x-www-form-urlencoded, multipart/form-data, or text/plain)

For example, if you're currently sending JSON payloads, switch to application/x-www-form-urlencoded and use qs.stringify() in Vue to format your data. Just note that this isn't ideal for complex APIs.

3. Cache Preflight Responses (Reduce OPTIONS Frequency)

Browsers cache preflight results by default, but you can extend this cache duration with the Access-Control-Max-Age header. This means the browser won't send an OPTIONS request every time for the same endpoint within the cache window.

Add this to your Express middleware (can be combined with the CORS setup above):

app.use((req, res, next) => {
  res.header('Access-Control-Max-Age', 86400); // Cache preflight for 1 day (in seconds)
  next();
});

This cuts down on redundant OPTIONS requests significantly.

4. Frontend Proxy (For Development Only)

During development, you can avoid cross-domain issues entirely by using Vue CLI's built-in proxy to forward API requests to your backend. This makes the browser think it's making same-origin requests, so no preflights are sent.

Add this to your vue.config.js:

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'https://your-backend-domain.com', // Replace with your backend URL
        changeOrigin: true,
        pathRewrite: { '^/api': '' } // Remove the /api prefix if your backend doesn't use it
      }
    }
  }
};

Now when your Vue app calls /api/users, it gets forwarded to your backend's root /users endpoint seamlessly.

Final Recommendation

For production, stick with the CORS middleware + preflight cache combo—it's secure and low-maintenance. Use the frontend proxy only during development to speed up your workflow.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:32:54