[{"data":1,"prerenderedAt":250},["ShallowReactive",2],{"\u002Fblog\u002F20260610":3},{"id":4,"title":5,"body":6,"date":242,"description":73,"extension":243,"meta":244,"navigation":245,"path":246,"seo":247,"stem":248,"__hash__":249},"blog\u002Fblog\u002F20260610.md","Nuxt を SPA フロントエンドとして利用し、バックエンドは API サーバーとして分離する構成でローカル環境においてCORSが発生する場合",{"type":7,"value":8,"toc":238},"minimark",[9,13,21,39,42,58,64,67,149,152,216,224,227,234],[10,11,5],"h2",{"id":12},"nuxt-を-spa-フロントエンドとして利用しバックエンドは-api-サーバーとして分離する構成でローカル環境においてcorsが発生する場合",[14,15,16,17,20],"p",{},"Nuxt を SPA フロントエンドとして利用し、バックエンド API を別サーバーで起動している場合、ローカル環境では CORS ポリシーでエラー が発生することがある。",[18,19],"br",{},"\n必要があれば API 側に CORS を許容する実装を入れるべきだが、本番環境では同じオリジンで運用している場合は、開発環境でのみ有効な設定を入れたい。",[14,22,23,24,28,29,32,33],{},"この場合、Nuxt 側で Nitro の ",[25,26,27],"code",{},"devProxy"," を利用し、Nuxt dev server への ",[25,30,31],{},"\u002Fapi"," リクエストをバックエンド API サーバーへプロキシすることで回避できる。\n",[34,35,36],"a",{"href":36,"rel":37},"https:\u002F\u002Fnitro.build\u002Fconfig#devproxy",[38],"nofollow",[14,40,41],{},"例えば、以下のような構成の場合。",[43,44,45,52],"ul",{},[46,47,48,49],"li",{},"Nuxt dev server: ",[25,50,51],{},"http:\u002F\u002Flocalhost:3000",[46,53,54,55],{},"Backend API server: ",[25,56,57],{},"http:\u002F\u002Flocalhost:8080",[14,59,60,61,63],{},"ブラウザから ",[25,62,57],{}," に直接リクエストすると、オリジンが異なるため CORS の対象になる。",[14,65,66],{},"この場合、 nuxt.config.ts に Nitro の devProxy を入れることで回避できる。",[68,69,74],"pre",{"className":70,"code":71,"language":72,"meta":73,"style":73},"language-ts shiki shiki-themes github-dark","\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  nitro: {\n    devProxy: {\n      \"\u002Fapi\": \"http:\u002F\u002Flocalhost:8080\u002Fapi\",\n    },\n  },\n});\n","ts","",[25,75,76,85,103,109,115,131,137,143],{"__ignoreMap":73},[77,78,81],"span",{"class":79,"line":80},"line",1,[77,82,84],{"class":83},"sAwPA","\u002F\u002F nuxt.config.ts\n",[77,86,88,92,95,99],{"class":79,"line":87},2,[77,89,91],{"class":90},"snl16","export",[77,93,94],{"class":90}," default",[77,96,98],{"class":97},"svObZ"," defineNuxtConfig",[77,100,102],{"class":101},"s95oV","({\n",[77,104,106],{"class":79,"line":105},3,[77,107,108],{"class":101},"  nitro: {\n",[77,110,112],{"class":79,"line":111},4,[77,113,114],{"class":101},"    devProxy: {\n",[77,116,118,122,125,128],{"class":79,"line":117},5,[77,119,121],{"class":120},"sU2Wk","      \"\u002Fapi\"",[77,123,124],{"class":101},": ",[77,126,127],{"class":120},"\"http:\u002F\u002Flocalhost:8080\u002Fapi\"",[77,129,130],{"class":101},",\n",[77,132,134],{"class":79,"line":133},6,[77,135,136],{"class":101},"    },\n",[77,138,140],{"class":79,"line":139},7,[77,141,142],{"class":101},"  },\n",[77,144,146],{"class":79,"line":145},8,[77,147,148],{"class":101},"});\n",[14,150,151],{},"useFetchで以下のようにAPI呼び出しを実装すると、devProxyで設定したURLにリクエストが転送される。",[68,153,157],{"className":154,"code":155,"language":156,"meta":73,"style":73},"language-vue shiki shiki-themes github-dark","\u003Cscript setup>\nconst { data } = await useFetch(\"\u002Fapi\u002Fhealth\");\n\u003C\u002Fscript>\n","vue",[25,158,159,174,207],{"__ignoreMap":73},[77,160,161,164,168,171],{"class":79,"line":80},[77,162,163],{"class":101},"\u003C",[77,165,167],{"class":166},"s4JwU","script",[77,169,170],{"class":97}," setup",[77,172,173],{"class":101},">\n",[77,175,176,179,182,186,189,192,195,198,201,204],{"class":79,"line":87},[77,177,178],{"class":90},"const",[77,180,181],{"class":101}," { ",[77,183,185],{"class":184},"sDLfK","data",[77,187,188],{"class":101}," } ",[77,190,191],{"class":90},"=",[77,193,194],{"class":90}," await",[77,196,197],{"class":97}," useFetch",[77,199,200],{"class":101},"(",[77,202,203],{"class":120},"\"\u002Fapi\u002Fhealth\"",[77,205,206],{"class":101},");\n",[77,208,209,212,214],{"class":79,"line":105},[77,210,211],{"class":101},"\u003C\u002F",[77,213,167],{"class":166},[77,215,173],{"class":101},[14,217,218,219,223],{},"ただし、あくまでリクエスト自体は Nuxt の dev server に向けて行われるため、ブラウザのデベロッパーツール上は ",[34,220,221],{"href":221,"rel":222},"http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fhealth",[38]," へのリクエストになるため注意が必要。",[10,225,226],{"id":226},"参考",[43,228,229],{},[46,230,231],{},[34,232,36],{"href":36,"rel":233},[38],[235,236,237],"style",{},"html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}",{"title":73,"searchDepth":87,"depth":87,"links":239},[240,241],{"id":12,"depth":87,"text":5},{"id":226,"depth":87,"text":226},"2026-06-10","md",{},true,"\u002Fblog\u002F20260610",{"title":5,"description":73},"blog\u002F20260610","Rhfi97D8G-xwWjQfIZSwDeSZgLZVHp1gV5sNLwE4Hbg",1781067249124]