{"id":7653,"date":"2025-12-09T12:31:25","date_gmt":"2025-12-09T04:31:25","guid":{"rendered":"https:\/\/www.xinyixx.com\/?p=7653"},"modified":"2025-12-09T12:31:25","modified_gmt":"2025-12-09T04:31:25","slug":"node","status":"publish","type":"post","link":"https:\/\/www.xinyixx.com\/index.php\/2025\/12\/09\/node\/","title":{"rendered":"Vue + Node + Nginx \u4ece 0 \u5230\u4e0a\u7ebf"},"content":{"rendered":"<h1>\ud83d\ude80 <strong>\u603b\u6d41\u7a0b\uff08\u4e00\u6b21\u641e\u6e05\u695a\uff09<\/strong><\/h1>\n<pre><code>1. \u521b\u5efa Vue \u524d\u7aef\u9879\u76ee\n2. \u521b\u5efa Node.js \u540e\u7aef API\n3. \u524d\u540e\u7aef\u672c\u5730\u8054\u8c03\n4. \u6253\u5305\u524d\u7aef\uff08\u751f\u6210 dist\uff09\n5. \u90e8\u7f72\u540e\u7aef\uff08PM2\uff09\n6. \u90e8\u7f72\u524d\u7aef\uff08Nginx\uff09\n7. \u4f7f\u7528 Nginx \u505a\u53cd\u5411\u4ee3\u7406\n8. \u914d\u7f6e HTTPS\uff08\u53ef\u9009\uff09<\/code><\/pre>\n<p>\u4f60\u53ef\u4ee5\u5b8c\u5168\u7167\u7740\u4e0b\u9762\u505a\u3002<\/p>\n<hr \/>\n<h1>\ud83d\udfe6 <strong>\u7b2c\u4e00\u90e8\u5206\uff1a\u521b\u5efa Vue \u524d\u7aef\u9879\u76ee<\/strong><\/h1>\n<h2>\u2714 1. \u521b\u5efa\u9879\u76ee<\/h2>\n<pre><code class=\"language-bash\">npm create vite@latest vue-app\ncd vue-app\nnpm install\nnpm run dev<\/code><\/pre>\n<p>\u6b64\u65f6\u4f60\u7684\u524d\u7aef\u5728\uff1a<\/p>\n<blockquote>\n<p><a href=\"http:\/\/localhost:5173\/\">http:\/\/localhost:5173<\/a><\/p>\n<\/blockquote>\n<h3>\u2714 \u6dfb\u52a0\u4e00\u4e2a\u6d4b\u8bd5 API \u8c03\u7528<\/h3>\n<p><code>src\/App.vue<\/code>\uff1a<\/p>\n<pre><code class=\"language-js\">onMounted(async () =&gt; {\n  const res = await fetch('\/api\/hello')\n  const data = await res.json()\n  console.log(data)\n})<\/code><\/pre>\n<hr \/>\n<h1>\ud83d\udfe9 <strong>\u7b2c\u4e8c\u90e8\u5206\uff1a\u521b\u5efa Node \u540e\u7aef\u9879\u76ee<\/strong><\/h1>\n<h2>\u2714 1. \u521b\u5efa\u76ee\u5f55<\/h2>\n<pre><code class=\"language-bash\">mkdir node-api\ncd node-api\nnpm init -y\nnpm install express cors<\/code><\/pre>\n<h2>\u2714 2. \u521b\u5efa <code>app.js<\/code><\/h2>\n<pre><code class=\"language-js\">const express = require('express')\nconst app = express()\n\napp.get('\/hello', (req, res) =&gt; {\n  res.json({ msg: \"Hello from Node API!\" })\n})\n\napp.listen(3000, () =&gt; {\n  console.log(\"API running on 3000\")\n})<\/code><\/pre>\n<p>\u8fd0\u884c\uff1a<\/p>\n<pre><code>node app.js<\/code><\/pre>\n<p>\u8bbf\u95ee\uff1a<\/p>\n<blockquote>\n<p><a href=\"http:\/\/localhost:3000\/hello\">http:\/\/localhost:3000\/hello<\/a><\/p>\n<\/blockquote>\n<hr \/>\n<h1>\ud83d\udfe7 <strong>\u7b2c\u4e09\u90e8\u5206\uff1a\u524d\u540e\u7aef\u672c\u5730\u8054\u8c03\uff08Vite \u4ee3\u7406\uff09<\/strong><\/h1>\n<p>\u7f16\u8f91 <code>vite.config.js<\/code>\uff1a<\/p>\n<pre><code class=\"language-js\">server: {\n  proxy: {\n    '\/api': {\n      target: 'http:\/\/localhost:3000',\n      changeOrigin: true,\n      rewrite: (path) =&gt; path.replace(\/^\/api\/, '')\n    }\n  }\n}<\/code><\/pre>\n<p>\u73b0\u5728\u8bbf\u95ee Vue \u9875\u9762\u7684\u65f6\u5019\uff0c\u5b83\u80fd\u4ece Node \u83b7\u53d6\u6570\u636e\u3002<\/p>\n<hr \/>\n<h1>\ud83d\udfe5 <strong>\u7b2c\u56db\u90e8\u5206\uff1a\u6253\u5305\u524d\u7aef\uff08\u751f\u4ea7\u73af\u5883\uff09<\/strong><\/h1>\n<p>\u8fd0\u884c\uff1a<\/p>\n<pre><code class=\"language-bash\">npm run build<\/code><\/pre>\n<p>\u4f1a\u751f\u6210\uff1a<\/p>\n<pre><code>dist\/\n  index.html\n  assets\/<\/code><\/pre>\n<p>\u8fd9\u662f\u751f\u4ea7\u73af\u5883\u524d\u7aef\u8d44\u6e90\uff0cNginx \u4f1a\u4f7f\u7528\u5b83\u3002<\/p>\n<hr \/>\n<h1>\ud83d\udfe6 <strong>\u7b2c\u4e94\u90e8\u5206\uff1a\u90e8\u7f72\u540e\u7aef\uff08PM2\uff09<\/strong><\/h1>\n<p>\u5728\u670d\u52a1\u5668\u4e0a\u5b89\u88c5\uff1a<\/p>\n<pre><code>npm install pm2 -g<\/code><\/pre>\n<p>\u542f\u52a8\u4f60\u7684 Node\uff1a<\/p>\n<pre><code>pm2 start app.js --name node-api<\/code><\/pre>\n<p>\u5e38\u7528\u547d\u4ee4\uff1a<\/p>\n<pre><code>pm2 restart node-api\npm2 logs node-api\npm2 stop node-api\npm2 save\npm2 startup<\/code><\/pre>\n<blockquote>\n<p>Node \u540e\u7aef\u73b0\u5728\u7a33\u5b9a\u8fd0\u884c\u5728 <strong>3000 \u7aef\u53e3<\/strong>\u3002<\/p>\n<\/blockquote>\n<hr \/>\n<h1>\ud83d\udfe9 <strong>\u7b2c\u516d\u90e8\u5206\uff1a\u5b89\u88c5 Nginx\uff08Win\/Linux \u90fd\u53ef\u4ee5\uff09<\/strong><\/h1>\n<h3>Windows Server<\/h3>\n<p>\u4e0b\u8f7d Nginx\uff1a<\/p>\n<ul>\n<li>\u5b98\u65b9 ZIP<\/li>\n<li>\u89e3\u538b\u5230 <code>C:nginx<\/code><\/li>\n<li>\u8fd0\u884c\uff1a<code>nginx.exe<\/code><\/li>\n<\/ul>\n<h3>Linux<\/h3>\n<pre><code class=\"language-bash\">sudo apt install nginx<\/code><\/pre>\n<p>\u68c0\u67e5\uff1a<\/p>\n<pre><code>nginx -v<\/code><\/pre>\n<hr \/>\n<h1>\ud83d\udfe7 <strong>\u7b2c\u4e03\u90e8\u5206\uff1aNginx \u914d\u7f6e\u524d\u7aef + \u540e\u7aef\u53cd\u5411\u4ee3\u7406<\/strong><\/h1>\n<h2>\ud83d\udd25 \u8fd9\u662f\u6700\u6838\u5fc3\u7684\u914d\u7f6e\uff08\u76f4\u63a5\u53ef\u7528\uff09<\/h2>\n<p>\u7f16\u8f91\uff1a<\/p>\n<h3>Linux<\/h3>\n<pre><code>\/etc\/nginx\/sites-available\/default<\/code><\/pre>\n<h3>Windows<\/h3>\n<pre><code>nginx\/conf\/nginx.conf<\/code><\/pre>\n<p>\u5199\u5165\uff1a<\/p>\n<pre><code class=\"language-nginx\">server {\n    listen 80;\n    server_name example.com;\n\n    # \u524d\u7aef\n    location \/ {\n        root  D:\/vue-app\/dist;\n        try_files $uri $uri\/ \/index.html;\n    }\n\n    # \u540e\u7aef API \u53cd\u5411\u4ee3\u7406\n    location \/api\/ {\n        proxy_pass http:\/\/127.0.0.1:3000\/;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n    }\n}<\/code><\/pre>\n<p>\u6d4b\u8bd5\u914d\u7f6e\uff1a<\/p>\n<pre><code>nginx -t<\/code><\/pre>\n<p>\u91cd\u542f\uff1a<\/p>\n<pre><code>nginx -s reload<\/code><\/pre>\n<hr \/>\n<h1>\ud83d\udfeb <strong>\u6548\u679c\u9a8c\u8bc1\uff08\u4e0a\u7ebf\u6210\u529f\u6807\u51c6\uff09<\/strong><\/h1>\n<p>\u6253\u5f00\uff1a<\/p>\n<h3><strong>\u524d\u7aef\uff1a<\/strong><\/h3>\n<pre><code>http:\/\/your-domain.com<\/code><\/pre>\n<h3><strong>\u540e\u7aef\uff1a<\/strong><\/h3>\n<pre><code>http:\/\/your-domain.com\/api\/hello<\/code><\/pre>\n<p>\u5982\u679c\u4f60\u80fd\u770b\u5230 Node API \u7684\u8f93\u51fa\uff0c\u8bf4\u660e\u53cd\u5411\u4ee3\u7406\u6210\u529f\u3002<\/p>\n<hr \/>\n<h1>\ud83d\udfea <strong>\u7b2c\u516b\u90e8\u5206\uff1a\u914d\u7f6e HTTPS\uff08\u63a8\u8350\uff09<\/strong><\/h1>\n<p>\u4f7f\u7528\u514d\u8d39\u7684 Let\u2019s Encrypt\u3002<\/p>\n<p>Linux\uff1a<\/p>\n<pre><code>sudo apt install certbot python3-certbot-nginx\nsudo certbot --nginx<\/code><\/pre>\n<p>Windows Server\uff08\u63a8\u8350 Win-ACME\uff09\uff1a<\/p>\n<pre><code>wacs.exe<\/code><\/pre>\n<p>Nginx \u751f\u6210\u7684 HTTPS \u914d\u7f6e\u4f1a\u50cf\uff1a<\/p>\n<pre><code class=\"language-nginx\">listen 443 ssl;\nssl_certificate \/path\/fullchain.pem;\nssl_certificate_key \/path\/privkey.pem;<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\ude80 \u603b\u6d41\u7a0b\uff08\u4e00\u6b21\u641e\u6e05\u695a\uff09 1. \u521b\u5efa Vue \u524d\u7aef\u9879\u76ee 2. \u521b\u5efa Node.js \u540e\u7aef API 3. \u524d\u540e\u7aef [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[6,14,10],"tags":[],"class_list":["post-7653","post","type-post","status-publish","format-standard","hentry","category-build","category-teacher","category-coding","entry"],"_links":{"self":[{"href":"https:\/\/www.xinyixx.com\/index.php\/wp-json\/wp\/v2\/posts\/7653","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xinyixx.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xinyixx.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xinyixx.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xinyixx.com\/index.php\/wp-json\/wp\/v2\/comments?post=7653"}],"version-history":[{"count":1,"href":"https:\/\/www.xinyixx.com\/index.php\/wp-json\/wp\/v2\/posts\/7653\/revisions"}],"predecessor-version":[{"id":7660,"href":"https:\/\/www.xinyixx.com\/index.php\/wp-json\/wp\/v2\/posts\/7653\/revisions\/7660"}],"wp:attachment":[{"href":"https:\/\/www.xinyixx.com\/index.php\/wp-json\/wp\/v2\/media?parent=7653"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xinyixx.com\/index.php\/wp-json\/wp\/v2\/categories?post=7653"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xinyixx.com\/index.php\/wp-json\/wp\/v2\/tags?post=7653"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}