使用Vue.js+Express开发SPA时Chrome跨域请求两次的解决方法咨询
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:
1. Use Express's CORS Middleware (Most Recommended for Production)
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, orHEADmethods - Only includes these headers:
Accept,Accept-Language,Content-Language,Content-Type(with values limited toapplication/x-www-form-urlencoded,multipart/form-data, ortext/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

