news 2026/10/18 10:57:04

React脚手架代理配置详解:从跨域到生产环境一次说清

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
React脚手架代理配置详解:从跨域到生产环境一次说清

开发项目时,本地前端服务跑在 3000 端口,后端接口跑在 8080,浏览器一请求就报跨域。很多人第一反应是让后端加 CORS 头,或者用浏览器插件临时绕过,但这些都治标不治本。React 脚手架自带的代理配置,就是针对这个场景设计的标准解法,也是我每次新起前端项目时最先落地的基础设施之一。

这篇总结不是抄官方文档,而是把我从“只会配 proxy 字段”到“能处理多个后端、路径重写、Cookie 丢失、生产环境失效”这一路踩过的坑和验证过的方案完整梳理一遍。无论你是刚接触脚手架的新手,还是已经被代理问题折磨过的老手,这篇文章都值得花十分钟读完。

1. 本地开发为什么要一张“中转的车票”:跨域问题的本质

浏览器安全策略里的同源限制,是前端开发中绕不开的一道墙。所谓同源,指的是协议、域名、端口三者完全一致。开发时前端跑在http://localhost:3000,后端跑在http://localhost:8080,端口不同,已经不是同源了,浏览器自然拦截跨域响应。

1.1 为什么不能直接让后端放开 CORS 一劳永逸

后端加 CORS 头确实能解决一部分问题,但在开发阶段往往不现实。比如后端是某个老项目,代码里没有统一的请求入口,Header 配置分散在各处;或者后端环境由别人维护,你提出加跨域配置,对方要排期、要测试、要走发布流程,一折腾就是半天。

就算后端真的加了Access-Control-Allow-Origin: *,麻烦也还在。某些时候浏览器会先发预检请求(OPTIONS),后端如果没有处理 OPTIONS 请求的逻辑,预检直接失败,正式请求根本发不出去。还有携带 Cookie 的场景,Access-Control-Allow-Credentials和前端的withCredentials必须同时配置,任何一边漏掉,Cookie 就带不上。

1.2 代理方案的实际原理:同源请求“借道中转”

代理的本质,是把原本跨域的请求“伪装”成同源请求。前端页面请求http://localhost:3000/api/user,脚手架启动的开发服务器拦截到/api开头的请求,转发给http://localhost:8080/api/user,服务端没有跨域概念,正常返回数据;开发服务器拿到响应后,再原样返回给浏览器。此时浏览器看到的是来自localhost:3000的响应,同源,不拦截。

这个过程中,请求头和响应头在转发时通常都会被保留,适合绝大多数 API 场景。我一直把代理理解成“中转车票”:前端买的票是去 3000 站的,代理帮你把行李(请求)转送到 8080 站,取回行李(响应)再交给你,全程没有让浏览器直接接触 8080,所以“跨域”这张墙纸根本不会被触发。

提示:代理只存在于开发服务器层面,上线部署后脚手架开发服务器就不再参与,代理规则也就不生效了。生产环境的跨域问题要靠 Nginx 反向代理或后端 CORS 解决,这是完全不同的另一套逻辑,后面专门说。

2. 一条字段走天下的阶段:package.json 里加 proxy

用 React 脚手架创建项目之后,最省事的代理配置方式就是直接在package.json里配一个proxy字段。这个字段是开发服务器(底层是 webpack-dev-server)预留的快捷入口,专门给没有复杂代理需求的场景用。

2.1 配置的最小写法和它能匹配的路径

在package.json中加上:

{ "name": "my-app", "proxy": "http://localhost:8080" }

保存后重启开发服务器(一般需要重启才能生效),然后前端代码里把请求地址写成相对路径:

fetch('/api/user/list') .then(res => res.json()) .then(data => console.log(data));

请求发到http://localhost:3000/api/user/list,开发服务器发现proxy配置了目标地址http://localhost:8080,就会把请求完整转发过去。后端收到的仍然是/api/user/list,前端拿到的响应体来自后端,一切正常。

2.2 用 proxy 字段时最容易踩到的三个隐藏规则

第一,proxy字段的值只能是一个字符串,也就是说只能指定一个后端地址。如果你同时要对接 A 服务的登录接口、B 服务的列表接口、C 服务的文件上传接口,这个方案就撑不住了。

第二,前端请求必须是以相对路径形式发出。如果代码里写的是fetch('http://localhost:8080/api/user/list'),直接指向了后端地址,那么请求根本不会经过开发服务器的代理转发,跨域问题依然存在。

第三,代理转发是“无脑透传”的,不会帮你做路径改写。什么意思?fetch('/api/user')转发后,后端看到的是/api/user,不是/user。如果后端接口设计没有/api前缀,而前端为了区分代理请求统一加了/api,后端就会找不到路由,返回 404。这种场景要用路径重写,在第二种方案里展开说。

2.3 为什么很多人点开 Network 面板后一脸懵:请求并没有变成后端地址

这是一个非常容易误解的地方。配置代理后,你在浏览器开发者工具里看到的请求地址,依然是http://localhost:3000/api/user/list,而不是http://localhost:8080/api/user/list。因为浏览器只跟 3000 端口交互,代理转发是在“网络层之下”完成的,浏览器感知不到真实后端地址。

所以判断代理是否生效,不要只看 Network 面板的 URL,要看 Response Headers 里的内容是不是来自后端,或者直接观察后端日志是否有请求打进来。

# 后端控制台如果打印了请求日志,说明代理转发成功 [INFO] 2024-05-20 14:32:11 - GET /api/user/list 200

如果后端没有任何日志,说明请求根本没有到达后端,要么代理配置没生效,要么请求路径没匹配上。

3. 多后端并存时的升级打法:http-proxy-middleware 配合 setupProxy.js

项目一旦需要对接多个后端地址,或者需要对不同前缀做不同转发规则,package.json里的proxy字段就必须要让位给更灵活的http-proxy-middleware。这个中间件是 React 脚手架官方文档推荐的替代方案,配置写在src/setupProxy.js里。

3.1 安装和基本配置结构

首先安装依赖:

npm install http-proxy-middleware --save-dev # 或者用 yarn yarn add http-proxy-middleware --dev

然后在src目录下新建setupProxy.js:

const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = function(app) { app.use( '/api', createProxyMiddleware({ target: 'http://localhost:8080', changeOrigin: true, }) ); };

这个文件的加载是脚手架自动完成的,开发服务器启动时会读取src/setupProxy.js并应用里面的 Express 中间件逻辑,不需要手动引入到组件里,也不需要修改webpack配置。

3.2 多路由规则的最常用排列

当后端不止一个时,可以写多个中间件规则:

const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = function(app) { // 用户相关接口,转发到 A 服务 app.use( '/api/user', createProxyMiddleware({ target: 'http://localhost:8081', changeOrigin: true, }) ); // 商品相关接口,转发到 B 服务 app.use( '/api/product', createProxyMiddleware({ target: 'http://localhost:8082', changeOrigin: true, }) ); // 文件上传,单独走 C 服务 app.use( '/upload', createProxyMiddleware({ target: 'http://localhost:8083', changeOrigin: true, }) ); };

配置changeOrigin: true的目的,是把请求头里的Host字段改成目标域名。有些后端会根据Host做不同处理,不设置的话,后端看到 Host 是localhost:3000,可能会报错或返回异常内容。

3.3 pathRewrite 的用处:去掉前缀、改写路径

刚才说过,proxy字段没法改写路径。而http-proxy-middleware提供了pathRewrite,让你可以随心所欲调整转发到后端的路径。

比如前端统一用/api开头,后端路由没有这个前缀:

app.use( '/api', createProxyMiddleware({ target: 'http://localhost:8080', changeOrigin: true, pathRewrite: { '^/api': '', // 把 /api 前缀剥掉 }, }) );

这样前端请求/api/user/list,后端实际收到的是/user/list。正则写法稍微有点绕,但核心就是一个:'^/api': ''表示把所有以/api开头的路径中的/api替换为空字符串。

还可以做更复杂的改写,比如把版本号从路径里剥离:

pathRewrite: { '^/api/v1': '/v1', '^/api/v2': '/v2', }

如果你的后端同一个环境里既有 v1 又有 v2 接口,这种写法可以一个代理入口统一转发,后端根据路径区分版本。

3.4 带 Cookie 和 WebSocket 的代理细节

开发时涉及登录态,需要把 Cookie 带到后端,代理配置里要增加:

createProxyMiddleware({ target: 'http://localhost:8080', changeOrigin: true, cookieDomainRewrite: 'localhost', // 把 Set-Cookie 里的域改写成 localhost onProxyReq: function(proxyReq, req, res) { // 必要时手动设置 Cookie const cookie = req.headers.cookie; if (cookie) { proxyReq.setHeader('cookie', cookie); } }, });

cookieDomainRewrite解决的是后端种 Cookie 时指定了域,导致浏览器无法保存的问题。如果不做改写,后端返回Set-Cookie: Domain=.example.com; ...,浏览器发现当前域名是localhost,不匹配,Cookie 就被拒绝了,登录态自然丢失。

WebSocket 代理需要额外传ws: true:

createProxyMiddleware({ target: 'http://localhost:8080', changeOrigin: true, ws: true, });

如果你的项目用到 WebSocket(比如推送消息),不开启这个选项,连接会被开发服务器默默丢弃,前端一直收不到消息,且网络面板里看不出明显报错,非常隐蔽。

4. 两种方案到底怎么选:场景判断与决策清单

proxy字段和setupProxy.js不是二选一的严格排他关系,但在实际项目中,我的习惯是:单一后端、路径不需要改写、临时联调用,用proxy字段;只要涉及多个后端、需要改写路径、开启 WebSocket 或 Cookie 改写,直接上setupProxy.js。下面这个表格是我在项目评审时常拿出来的对比:

对比维度package.json 的 proxysetupProxy.js + http-proxy-middleware
配置位置单一字符串独立 JS 文件,可编程
多个后端支持不支持支持
路径改写不支持支持(pathRewrite)
Cookie 域改写不支持支持(cookieDomainRewrite)
WebSocket 支持默认支持(简单场景)可显式控制(ws: true)
按环境动态配置很难可根据环境变量灵活配置
底层原理脚手架封装Express 中间件直管

4.1 一个反直觉的事实:url 前缀不匹配时,proxy 字段也能转发

proxy字段有个冷门行为:请求路径不管有没有特殊前缀,只要当前域名端口是开发服务器自己,它都会尝试转发到目标地址。也就是说,fetch('/random/path')也会被转发到后端,只是后端可能返回 404 而已。

而http-proxy-middleware的规则则必须指定匹配路径前缀(比如/api),不在前缀范围内的请求会正常走开发服务器返回前端资源,不会转发。

这个差异会带来一个开发时的“看似正常实则奇怪”的现象:用proxy字段时,前端写一个/api/xxx的错误路径,可能后端返回 404 页面,而前端却拿到了 200 的 HTML 内容;用http-proxy-middleware时同样的请求可能直接被开发服务器当成静态资源请求处理,返回index.html,数据却是 0 字节。

排查这类问题时,我的经验是先看后端有没有请求日志。有日志说明代理规则生效了,再看返回内容。没有日志,则优先检查规则前缀是否匹配。

4.2 实际项目中的三个典型选型场景

场景一:你在做一个内部管理后台,后端只有一个 Java 服务,接口都带/api前缀,前后端联调文件不多。这种直接配proxy字段,十分钟搞定,少即是多。

场景二:公司整体微服务化,不同模块对应不同后端服务,前端需要同时访问用户服务、订单服务、支付服务。这种就只能用setupProxy.js,每个服务一条规则,清晰可维护。

场景三:项目同时接后端 API 和第三方地图服务,地图服务需要特殊 Header,API 服务需要 Cookie。这种更复杂的场景,setupProxy.js里可以在onProxyReq拦截器里按目标地址动态添加请求头。

app.use( '/map', createProxyMiddleware({ target: 'https://map.example.com', changeOrigin: true, onProxyReq(proxyReq, req, res) { proxyReq.setHeader('X-Custom-Key', process.env.MAP_KEY); }, }) );

前端写fetch('/map/place/search?kw=xxx'),代理会自动加上密钥 Header,第三方服务无需暴露密钥给浏览器。

5. 那些让排查成本飙升的报错:现象、根因和药方

代理配置本身并不难,难的是报错时一脸茫然。我把自己在项目中遇到的高频问题整理成了一份排查手册,按现象分类,可以直接照着操作。

5.1 现象一:Network 面板显示 404,但浏览器页面正常

最常见的情况,大概占了代理问题的 40%。请求发到了http://localhost:3000/api/user,开发服务器找不到静态资源,返回了index.html,内容类型是text/html,所以接口虽然不是 200,但页面没坏。

排查步骤:

  1. 确认后端是否启动,端口是否正确;
  2. 确认代理规则的路径前缀是否匹配;
  3. 确认target是否写错了协议(http还是https);
  4. 确认后端路由是否真的存在/api/user。

5.2 现象二:报错Error occurred while trying to proxy: localhost:8080/api/user

这个错误是代理转发到目标地址时失败,常见于:

  • 后端服务没启动;
  • 后端服务启动在其他端口,比如改成了 8081;
  • 后端需要 HTTPS,但代理配置写的是 HTTP;
  • 后端有 IP 白名单,changeOrigin: true后 Host 头变成了 localhost,白名单校验失败。

处理方法:

# 先确认后端端口是否真的在监听 curl http://localhost:8080/health

如果curl有响应,说明代理配置或路径有问题;如果curl都连不上,先去启动后端。

5.3 现象三:请求发出去了,但响应一直 pending 不回来

这种情况多数是因为:

  • 代理配置成了 WebSocket,但后端没有对 WebSocket 请求做响应;
  • 后端接口本身死循环或请求阻塞;
  • 代理网络层因为keepAlive保持了一个不健康的连接。

我的处理方式是先断开所有代理规则,直接用curl调后端接口,看后端自身是否健康。后端没问题,再逐步加代理规则测试。

5.4 现象四:代码里请求地址带了完整域名,代理完全不生效

fetch('http://localhost:8080/api/user/list')

这是很多从其他框架转来的人最容易犯的错误。代理只拦截“相对路径”请求,浏览器发出的绝对 URL 如果指向了非开发服务器地址,就不会经过代理转发,跨域问题再次出现。

规范做法是,项目内维护一个统一的请求基础路径:

// src/utils/request.js const BASE_URL = '/api'; export function get(url) { return fetch(`${BASE_URL}${url}`); }

这样请求全部走相对路径,代理规则才能兜住。

5.5 现象五:代理在 Windows 上启动时报 EADDRINUSE

EADDRINUSE表示端口被占用。开发服务器的默认端口 3000 被其他进程占用了,需要换端口启动:

# 脚手架支持直接指定端口 npm start -- --port 3001

然后用http://localhost:3001访问,代理目标不变。

6. 接口请求封装与代理联动的细节:axios 里的 baseURL 和 withCredentials

很多人配好了代理,却发现 axios 发起的请求仍然有问题。核心原因是 axios 的默认配置和代理规则没有对齐。

6.1 baseURL 到底该写什么

在开发环境,baseURL 不应该写成后端地址,应该写成相对路径/api:

import axios from 'axios'; const service = axios.create({ baseURL: '/api', timeout: 10000, });

请求示例:

service.get('/user/list');

最终发出的 URL 是/api/user/list,代理规则匹配/api前缀,转发到后端。

有些人在 axios 里写了baseURL: 'http://localhost:8080/api',代理基本等于白配,跨域问题原样出现。axios 的 baseURL 和浏览器fetch一样,走的是浏览器网络层,请求会直接发给 8080,跳过开发服务器的转发。

6.2 withCredentials 和代理的联手

如果项目里使用 Cookie 保持登录态,axios 需要开启:

const service = axios.create({ baseURL: '/api', timeout: 10000, withCredentials: true, });

此时代理配置里也要确保cookieDomainRewrite已配置,否则后端Set-Cookie可能会因为域名不匹配被浏览器丢弃。两端都正常,登录态才能完整穿透开发服务器。

6.3 响应拦截器里的常见误判

我在项目里常写一个响应拦截器,当 HTTP 状态码为 401 时自动跳转登录页。但代理配好后,如果后端接口有鉴权校验,返回 401 是很正常的。拦截器逻辑要确保只在真实业务场景触发,不要因为代理在 Network 里显示 401 就以为是代理故障。

service.interceptors.response.use( response => response, error => { if (error.response && error.response.status === 401) { window.location.href = '/login'; } return Promise.reject(error); } );

如果后端接口本来就不需要鉴权,却出现 401,则要检查代理是否把请求头丢掉了,常见的是AuthorizationHeader 在转发过程中被剥离。

6.4 代理对请求方法敏感吗

http-proxy-middleware默认对所有方法都生效,包括 POST、PUT、DELETE 和 OPTIONS。但如果你在中间件里写了自己的逻辑,或者后端对 OPTIONS 预检有要求,可以增加方法过滤:

app.use( '/api', createProxyMiddleware({ target: 'http://localhost:8080', changeOrigin: true, methods: ['GET', 'POST', 'PUT', 'DELETE'], }) );

不写methods时默认全部方法都代理,一般不用刻意设置,除非你有特殊需求。

7. 配置完代理后还要做的事:验证清单和常见遗漏

代理配置完成后,很多人只在前端页面点两下,看到数据出来了就以为结束了,其实很多隐患没暴露。我个人的习惯是跑一套简单的验证清单。

7.1 验证清单详情

  • 检查 Network 面板,请求 URL 依然以localhost:3000开头;
  • 检查 Response Headers,字段来自后端(比如Server头、自定义的X-Request-Id等);
  • 打开后端控制台,确认请求日志有输出;
  • 测试 GET、POST、PUT 各至少一次;
  • 测试带 Cookie 的请求,确认 Set-Cookie 被浏览器接受;
  • 如果有 WebSocket,测试连接能建立、能收发消息;
  • 切换接口路径,比如从/api/user切到/api/product,确认规则匹配正确。

7.2 容易被忽略的一个文件:.env.development

代理规则里如果写死了后端地址,不同开发人员本地后端端口不一致时会互相踩坑。我建议把目标地址抽到环境变量里:

const { createProxyMiddleware } = require('http-proxy-middleware'); const target = process.env.REACT_APP_PROXY_TARGET || 'http://localhost:8080'; module.exports = function(app) { app.use( '/api', createProxyMiddleware({ target, changeOrigin: true, }) ); };

然后在项目根目录建.env.development:

REACT_APP_PROXY_TARGET=http://localhost:8080

其他人拉代码后,修改.env.development里对应后端地址即可,不需要改动任何 JS 文件。

7.3 关于 https 目标地址的一个提示

如果后端地址是https://api.example.com,而本地开发服务器的证书是自签名的,代理可能会因为证书验证失败而报错。这种情况通过在配置里加入secure: false解决:

createProxyMiddleware({ target: 'https://api.example.com', changeOrigin: true, secure: false, // 忽略自签名证书错误 })

secure: false只影响代理到后端的连接,不会强制浏览器信任证书,所以生产环境不受影响。

8. 生产环境还配不配:部署阶段的跨域策略

开发环境的代理解决的是本地联调问题,一旦打包部署,setupProxy.js和proxy字段都不再生效。生产环境的跨域处理是另一套逻辑,需要提前规划。

8.1 Nginx 反向代理的写法参考

最常见的方式是 Nginx 将/api前缀的请求转发到后端服务:

server { listen 80; server_name example.com; location /api/ { proxy_pass http://backend-server:8080/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { root /usr/share/nginx/html; index index.html; } }

注意proxy_pass结尾的/api/和没有/api/的区别,这决定了是透传完整路径还是剥离前缀,和开发环境pathRewrite的思维完全一致。

8.2 后端 CORS 的兜底方案

如果你无法控制 Nginx 配置,或者后端部署在云函数等平台,后端 CORS 是兜底手段。前端请求必须指向完整的后端地址,然后后端在响应里加:

Access-Control-Allow-Origin: https://example.com Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: Content-Type, Authorization

这种方式只适合后端接口不多、域名固定的情况,不然通配符失控,安全性和可维护性都不够。

8.3 上线前必须检查的跨域配置项

上线前的自测清单,我通常包含:

  1. 浏览器直接请求后端接口,查看响应头是否包含允许跨域的字段;
  2. 模拟 POST 带 JSON 请求,确认预检请求能被后端正确响应;
  3. 登录后刷新页面,确认 Cookie 或 Token 存储方式在跨域情况下依然有效;
  4. 检查是否有任何前端代码残留了localhost:8080等开发地址。

这条很关键:开发时为了快速调试,经常有人把baseURL临时改成后端地址,上线前忘记改回来,导致线上请求直接打到 localhost,所有用户调用失败。建议在项目里加一个环境判断工具函数:

const isProduction = process.env.NODE_ENV === 'production'; const BASE_URL = isProduction ? 'https://api.example.com' : '/api';

只要所有请求都通过这一个入口发出去,就不会出现开发地址泄漏到生产环境的问题。

9. 从代理配置延伸出去的思考:前端工程化里的边界意识

代理配置看起来只是一个不起眼的开发辅助功能,但把它放到整个前端工程体系里看,背后反映的是边界意识。前端的代码运行在浏览器里,天然受同源策略约束,所有跨域方案本质都是在“绕”这个约束,只是绕的位置不同:开发环境在 Node 层绕,生产环境在网关层绕。

我见过不少项目,代理配好了,但团队里每个人都在自己的代码里写死http://localhost:8080,或者把后端地址塞进请求工具函数里,导致代理规则形同虚设。这不是配置的问题,而是工程规范的问题——代理不是写给某一个人用的,它应该成为项目基础设施的一部分,统一封装、统一维护,每个人开箱即用。

如果你的团队项目里还没有统一的请求封装,我建议在配代理的同时,把请求工具函数也一起规范化:baseURL 统一用环境变量驱动,超时时间、拦截器、错误提示全部集中管理。代理解决的是“请求怎么出去”,请求封装解决的是“代码怎么写清晰”,两者配合才是完整的解决方案。

另外一个容易忽略的点是,代理规则也会影响前端静态资源的访问。比如你配了/static前缀的代理,但前端本身有静态资源目录,就会和真实资源路径冲突。所以代理前缀的选择要避开脚手架默认的静态资源路径(比如public/目录下的资源通常不走代理中间件)。

我在新项目里通常用/api作为所有后端请求的统一前缀,因为public目录和大多数业务的路径都不冲突,且一眼就能识别哪些请求是需要代理的后端接口。

10. 一些值得保留的实操习惯和最终建议

最后分享几条我在这类配置问题上沉淀的个人习惯,不保证绝对正确,但长期用下来省了很多排查时间。

第一,开发服务器重启频率要高。修改package.json的proxy字段后必须重启开发服务器,修改setupProxy.js后部分情况下脚手架会自动重启,但如果不放心,手动重启一次最稳妥。我在团队里遇到过有人改了配置但没重启,白白排查了半小时。

第二,代理的报错不一定显示在浏览器控制台。很多代理错误是静默的,浏览器只看到 404 或 pending,真实原因在后端日志里。排查时一定要两端同时打开日志,前端控制台和后端控制台对照着看。

第三,不要把代理配置写在组件里或者工具函数里。它应该独立存在,路径清晰、注释完善,属于项目根级别的基础设置,任何开发人员拉下代码后不需要额外沟通就能理解。

第四,提交代码时注意不要把个人的后端地址带上。我见过团队成员本地用localhost:9090,提交代码时把setupProxy.js里的 target 也一起提交了,其他人拉下来代理全部指向错误端口。解决方式是用环境变量隔离,每人本地.env.development文件不同,而setupProxy.js提交的是统一模板。

如果你现在正被本地跨域问题困扰,先不要急着给后端提工单,按照这篇文章的顺序,先确认后端端口健康,再确认请求是相对路径,最后用setupProxy.js完成规则匹配。大概率二十分钟内就能跑通。代理配置本身不难,难的是理解它到底在哪一层解决问题,以及遇到问题时的排查路径是否能覆盖所有可能性。把这些搞清楚了,React 脚手架的代理对你就不再是一个黑盒。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/18 10:49:21

vchart双轴组合图实战:BI看板多指标同图展示的完整方案

做BI看板的人,应该都遇到过这个需求:一个图表里既要看总量规模,又要看比率变化。最典型的组合就是“柱状图展示销售额,折线图展示同比增长率”。指标一多,单Y轴根本塞不下——量纲不同,硬塞在同一个轴上&am…

作者头像 李华
网站建设 2026/10/18 10:49:12

提示工程实战指南:从结构化提示词到稳定可控的大模型输出

开门见山说一句:把大模型用好,真正的分水岭不在模型选得有多新,而在提示工程做得有多扎实。这些年我接手过不少大模型实战项目,也带过团队,发现一个非常普遍的现象:同一位开发者,用同一个模型&a…

作者头像 李华
网站建设 2026/10/18 10:47:14

context-mode 深度解析:如何让 AI 编程助手不乱发挥

第一次看到“context-mode”这个词条的时候,我下意识以为它是某个编辑器插件里的一个开关参数,后来才发现自己狭隘了。它不是字面上的“开启某个模式”,而是一整套关于“如何让模型在有限视野里始终看到最有价值信息”的设计思路。这套思路&a…

作者头像 李华
网站建设 2026/10/18 10:45:05

vLLM高并发推理实战:PagedAttention与连续批处理深度解析

1. 项目概述:为什么本地高并发推理服务正在成为刚需最近三个月,我陆续帮三类不同背景的团队落地了本地大模型推理服务:某高校实验室需要在4张A100上稳定支撑20学生同时调用7B级别模型做论文实验;某制造业企业的产线质检系统要接入…

作者头像 李华