<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://todayred.castamerego.com/blog</id>
    <title>Today Red's Site Blog</title>
    <updated>2026-05-27T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://todayred.castamerego.com/blog"/>
    <subtitle>Today Red's Site Blog</subtitle>
    <icon>https://todayred.castamerego.com/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[Docusaurus 图片缩放]]></title>
        <id>https://todayred.castamerego.com/blog/docusaurus-image-zoom</id>
        <link href="https://todayred.castamerego.com/blog/docusaurus-image-zoom"/>
        <updated>2026-05-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[本篇记录为个人 Docusaurus 站点添加图片点击缩放功能的完整过程，包括插件安装、基础配置，以及顺手开启导航栏自动隐藏，最后解决了一个缩放图片被导航栏遮挡的 z-index 问题。]]></summary>
        <content type="html"><![CDATA[<p>本篇记录为个人 Docusaurus 站点添加图片点击缩放功能的完整过程，包括插件安装、基础配置，以及顺手开启导航栏自动隐藏，最后解决了一个缩放图片被导航栏遮挡的 z-index 问题。</p>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="缘起">缘起<a href="https://todayred.castamerego.com/blog/docusaurus-image-zoom#%E7%BC%98%E8%B5%B7" class="hash-link" aria-label="缘起的直接链接" title="缘起的直接链接" translate="no">​</a></h2>
<p>文档中经常需要插入截图或流程图，这类图片在页面上为了不影响排版往往显示得比较小，读者想看清细节时只能另开标签页或右键保存查看，体验很糟糕。于是决定为站点添加点击放大功能，找到了社区广泛使用的 <a href="https://github.com/gabrielcsapo/docusaurus-plugin-image-zoom" target="_blank" rel="noopener noreferrer" class="">docusaurus-plugin-image-zoom</a>，它基于 <a href="https://github.com/francoischalifour/medium-zoom" target="_blank" rel="noopener noreferrer" class="">medium-zoom</a> 实现，效果简洁自然。</p>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="安装与配置">安装与配置<a href="https://todayred.castamerego.com/blog/docusaurus-image-zoom#%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE" class="hash-link" aria-label="安装与配置的直接链接" title="安装与配置的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="安装插件">安装插件<a href="https://todayred.castamerego.com/blog/docusaurus-image-zoom#%E5%AE%89%E8%A3%85%E6%8F%92%E4%BB%B6" class="hash-link" aria-label="安装插件的直接链接" title="安装插件的直接链接" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> docusaurus-plugin-image-zoom</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="注册插件并添加主题配置">注册插件并添加主题配置<a href="https://todayred.castamerego.com/blog/docusaurus-image-zoom#%E6%B3%A8%E5%86%8C%E6%8F%92%E4%BB%B6%E5%B9%B6%E6%B7%BB%E5%8A%A0%E4%B8%BB%E9%A2%98%E9%85%8D%E7%BD%AE" class="hash-link" aria-label="注册插件并添加主题配置的直接链接" title="注册插件并添加主题配置的直接链接" translate="no">​</a></h3>
<p>在 <code>docusaurus.config.ts</code> 中注册插件，并在 <code>themeConfig</code> 里添加 <code>zoom</code> 配置项：</p>
<div class="language-ts codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-ts codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> config</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Config </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  plugins</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'docusaurus-plugin-image-zoom'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  themeConfig</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    zoom</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      selector</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'.markdown :not(em) &gt; img'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      background</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        light</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'rgb(255, 255, 255)'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        dark</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'rgb(50, 50, 50)'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p><code>selector</code> 限定只对 markdown 正文中非斜体包裹的图片生效，这样可以避免 logo 等装饰性图片被误触发缩放。<code>background</code> 分别为亮色/暗色模式配置遮罩背景色。</p>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="开启导航栏自动隐藏">开启导航栏自动隐藏<a href="https://todayred.castamerego.com/blog/docusaurus-image-zoom#%E5%BC%80%E5%90%AF%E5%AF%BC%E8%88%AA%E6%A0%8F%E8%87%AA%E5%8A%A8%E9%9A%90%E8%97%8F" class="hash-link" aria-label="开启导航栏自动隐藏的直接链接" title="开启导航栏自动隐藏的直接链接" translate="no">​</a></h2>
<p>在配置缩放的同时，顺手处理了另一个体验问题：阅读长文档时，顶部固定导航栏会一直占据屏幕空间，尤其影响图片的可视区域。Docusaurus 提供了内置的 <code>hideOnScroll</code> 选项，在 <code>navbar</code> 配置中加上一行即可：</p>
<div class="language-ts codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-ts codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token plain">navbar</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  hideOnScroll</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>开启后，向下滚动时导航栏自动隐藏，向上滚动时重新出现，阅读体验明显提升。</p>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="踩坑缩放图片被导航栏遮挡">踩坑：缩放图片被导航栏遮挡<a href="https://todayred.castamerego.com/blog/docusaurus-image-zoom#%E8%B8%A9%E5%9D%91%E7%BC%A9%E6%94%BE%E5%9B%BE%E7%89%87%E8%A2%AB%E5%AF%BC%E8%88%AA%E6%A0%8F%E9%81%AE%E6%8C%A1" class="hash-link" aria-label="踩坑：缩放图片被导航栏遮挡的直接链接" title="踩坑：缩放图片被导航栏遮挡的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="问题现象">问题现象<a href="https://todayred.castamerego.com/blog/docusaurus-image-zoom#%E9%97%AE%E9%A2%98%E7%8E%B0%E8%B1%A1" class="hash-link" aria-label="问题现象的直接链接" title="问题现象的直接链接" translate="no">​</a></h3>
<p>在包含大图的文档页面中，先向下滚动找到大图并放大，此时显示正常：</p>
<p><img decoding="async" loading="lazy" alt="alt text" src="https://todayred.castamerego.com/assets/images/scroll-down-8a3aeb871e5e813f2dadce71dc24bd40.gif" width="1280" height="650" class="img_wQsy"></p>
<p>如果先向下滚动使大图滑出视口（此时导航栏因 <code>hideOnScroll</code> 自动隐藏），然后向上滚动回到大图位置（导航栏重新出现），此时点击图片触发缩放，图片的顶部区域会被导航栏遮住。</p>
<p><img decoding="async" loading="lazy" alt="alt text" src="https://todayred.castamerego.com/assets/images/scroll-up-3ece653a0c20cc6d5be9c9ad066036f5.gif" width="1280" height="650" class="img_wQsy"></p>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="原因分析">原因分析<a href="https://todayred.castamerego.com/blog/docusaurus-image-zoom#%E5%8E%9F%E5%9B%A0%E5%88%86%E6%9E%90" class="hash-link" aria-label="原因分析的直接链接" title="原因分析的直接链接" translate="no">​</a></h3>
<p>Docusaurus 导航栏的 <code>z-index</code> 默认为 <code>200</code>，而 <code>medium-zoom</code> 插件的遮罩层（<code>.medium-zoom-overlay</code>）和缩放图片（<code>.medium-zoom-image--opened</code>）的层级低于此值，导致导航栏始终叠在缩放图片的上方。</p>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="解决方案">解决方案<a href="https://todayred.castamerego.com/blog/docusaurus-image-zoom#%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88" class="hash-link" aria-label="解决方案的直接链接" title="解决方案的直接链接" translate="no">​</a></h3>
<p>在 <code>src/css/custom.css</code> 中覆盖这两个类的层级：</p>
<div class="language-css codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-css codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/* Image zoom: ensure overlay and zoomed image appear above the navbar */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector class" style="color:#00009f">.medium-zoom-overlay</span><span class="token selector punctuation" style="color:#393A34">,</span><span class="token selector" style="color:#00009f"></span><br></div><div class="token-line" style="color:#393A34"><span class="token selector" style="color:#00009f"></span><span class="token selector class" style="color:#00009f">.medium-zoom-image--opened</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">z-index</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">9999</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>将层级提升至 <code>9999</code>，高于导航栏的 <code>200</code>，问题解决。</p>
<p><img decoding="async" loading="lazy" alt="alt text" src="https://todayred.castamerego.com/assets/images/no-block-4bbbf87486f9d5d2a2d26845e0d2870d.gif" width="1280" height="650" class="img_wQsy"></p>
<p>这个改动非常安全——这两个类只在点击触发缩放时才激活，平时完全不影响页面上的任何交互，也不会与 Docusaurus 内置组件产生冲突。</p>]]></content>
        <author>
            <name>Achinoise</name>
        </author>
        <category label="Docusaurus" term="Docusaurus"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[网站一键部署指南]]></title>
        <id>https://todayred.castamerego.com/blog/website-deploy</id>
        <link href="https://todayred.castamerego.com/blog/website-deploy"/>
        <updated>2026-05-25T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[本篇指南将介绍如何在开发服务器上连接到部署服务器，一键完成部署 Docusaurus 网站，涵盖从安装依赖到配置服务的完整流程。]]></summary>
        <content type="html"><![CDATA[<p>本篇指南将介绍如何在开发服务器上连接到部署服务器，一键完成部署 Docusaurus 网站，涵盖从安装依赖到配置服务的完整流程。</p>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="缘起">缘起<a href="https://todayred.castamerego.com/blog/website-deploy#%E7%BC%98%E8%B5%B7" class="hash-link" aria-label="缘起的直接链接" title="缘起的直接链接" translate="no">​</a></h2>
<p>起因是个人在 macOS 开发编写个人网站，在 Ubuntu 部署个人网站时，发现每次部署都需要重复执行一系列命令。而且时间一长，很容易忘记具体命令该怎么用。为了提高效率并减少人为错误，我决定编写一个一键部署脚本，自动化整个流程，解放双手。</p>
<p>想要实现自动化，首先需要捋清楚手动如何操作，然后将这些操作步骤转化为脚本命令。如果想直接获取可用脚本，可以直接跳转到 <a href="https://todayred.castamerego.com/blog/website-deploy#%E5%AE%8C%E6%95%B4%E9%83%A8%E7%BD%B2%E8%84%9A%E6%9C%AC%E5%8F%82%E8%80%83" class="">完整部署脚本</a> 部分。</p>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="旧想法npm-run-serve--nginx-反向代理">旧想法：npm run serve + Nginx 反向代理<a href="https://todayred.castamerego.com/blog/website-deploy#%E6%97%A7%E6%83%B3%E6%B3%95npm-run-serve--nginx-%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86" class="hash-link" aria-label="旧想法：npm run serve + Nginx 反向代理的直接链接" title="旧想法：npm run serve + Nginx 反向代理的直接链接" translate="no">​</a></h2>
<p>最开始没有了解到 Nginx 可以全权代理，因此最先的想法是直接使用 <code>npm run serve</code>（即 <code>docusaurus serve</code>）命令进行部署。</p>
<p>以下是我在部署过程中总结的关键步骤：</p>
<div class="language-text codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-text codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token plain">本地 build → tar 打包 → scp 传输 → 远程解压</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                                    ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                          systemd 守护 npm run serve</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                                    ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                          Nginx 反向代理 :80 → :3000</span><br></div></code></pre></div></div>
<p>接下来，我们把上述流程拆解成一步步的具体操作。需要说明的是，个人更习惯使用 zsh 作为默认 shell，所以下面的示例都会以 zsh 来演示。文章末尾会附上对应的 bash 版本部署脚本，提供给使用 bash 的读者。</p>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="首次部署">首次部署<a href="https://todayred.castamerego.com/blog/website-deploy#%E9%A6%96%E6%AC%A1%E9%83%A8%E7%BD%B2" class="hash-link" aria-label="首次部署的直接链接" title="首次部署的直接链接" translate="no">​</a></h3>
<p>按照部署流程，首次部署需要完成以下步骤：</p>
<ol>
<li class="">本地执行 <code>npm run build</code></li>
<li class="">传输构建产物到部署服务器并解压</li>
<li class="">配置 systemd 服务</li>
<li class="">配置 Nginx 反向代理</li>
<li class="">在目标服务器上 serve 服务</li>
</ol>
<p><strong>本地执行 <code>npm run build</code></strong></p>
<p>首先，在本地 Docusaurus 环境中执行构建，生成静态文件。Docusaurus 官方提供了 <code>docusaurus build</code> 命令，而在实际项目中我们通常通过 npm scripts 来调用它。建议在构建之前先清理上一次的产物：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> run </span><span class="token function" style="color:#d73a49">clear</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> run build</span><br></div></code></pre></div></div>
<p>执行 <code>npm run build</code> 后，会在当前项目根目录下生成一个 build 文件夹，所有构建产物都会输出到这个目录中。结构大致如下：</p>
<div class="language-text codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-text codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token plain">your-website-project/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── build/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── assets/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── blog/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── docs/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── en/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── img/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── markdown-page/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── index.html</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── 404.html</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   └── ...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── src/          (等其他源码目录)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">└── package.json</span><br></div></code></pre></div></div>
<p><strong>传输构建产物到部署服务器并解压</strong></p>
<p>接下来我们需要将其传输到目标服务器上。最直接的方式是使用 <code>scp</code> 命令：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">scp</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> build/ user@server:/path/to/deploy/</span><br></div></code></pre></div></div>
<p>不过直接传输整个目录往往比较慢，尤其是文件数量较多时。更高效的做法是：先打包，再传输，最后在服务器上解压。具体步骤如下：</p>
<ol>
<li class="">在本地将 build 文件夹打包为 tar 文件</li>
</ol>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">tar</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-czf</span><span class="token plain"> build.tar.gz build/</span><br></div></code></pre></div></div>
<ol start="2">
<li class="">使用 scp 将打包后的 tar 文件传输到目标服务器</li>
</ol>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">scp</span><span class="token plain"> build.tar.gz user@server:/path/to/deploy/</span><br></div></code></pre></div></div>
<ol start="3">
<li class="">删除本地的压缩包，节省空间</li>
</ol>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">rm</span><span class="token plain"> build.tar.gz</span><br></div></code></pre></div></div>
<ol start="4">
<li class="">在部署服务器上解包 tar 文件到指定目录，完成后删除 tar 文件。</li>
</ol>
<p>这里使用非交互式远程执行，不需要 ssh 登录到服务器后再执行命令：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"tar -xzf /path/to/deploy/build.tar.gz -C /path/to/deploy/"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"rm /path/to/deploy/build.tar.gz"</span><br></div></code></pre></div></div>
<p>现在 build 产物已经完成传输和解压，接下来我们通过配置 systemd 系统服务，让 <code>npm run serve</code> 在守护进程中运行。</p>
<p><strong>配置 systemd 服务</strong></p>
<p>在 <code>/etc/systemd/system/</code> 目录下创建一个 <code>.service</code> 文件，例如 <code>your-service-name.service</code>，内容如下：</p>
<div class="language-text codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-text codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token plain">[Unit]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Description=Frontend Development Server</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">After=network.target</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">[Service]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">User=root</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">WorkingDirectory=/path/to/deploy/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Environment=your_environment_variables</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">ExecStart=/path/to/npm run serve</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Restart=always</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">[Install]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">WantedBy=multi-user.target</span><br></div></code></pre></div></div>
<p>几个关键配置项说明：</p>
<ul>
<li class=""><code>User</code>：运行该服务的用户</li>
<li class=""><code>WorkingDirectory</code>：服务的工作目录，即部署路径</li>
<li class=""><code>Environment</code>：服务所需的环境变量</li>
<li class=""><code>ExecStart</code>：服务启动时执行的命令，这里是 <code>npm run serve</code></li>
<li class=""><code>Restart</code>：服务在异常退出时的重启策略，设为 <code>always</code> 表示退出后自动重启</li>
</ul>
<p>编写完成后，保存并退出编辑器。执行以下命令完成两项操作：一是重新加载 systemd 的配置文件，二是将服务设为开机自启动：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"sudo systemctl daemon-reload"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"sudo systemctl enable your-service-name.service"</span><br></div></code></pre></div></div>
<p>日常管理中，可以用下面这些命令来启动、停止或重启服务：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"sudo systemctl start your-service-name.service"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"sudo systemctl stop your-service-name.service"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"sudo systemctl restart your-service-name.service"</span><br></div></code></pre></div></div>
<p>需要提醒的是：现在先不要启动服务，等 Nginx 配置完成后再启动。否则直接访问网站时会出现 502 Bad Gateway 错误，因为 Nginx 还没有配置好反向代理。</p>
<p><strong>配置 Nginx 反向代理</strong></p>
<p>下面来配置 Nginx。在 <code>/etc/nginx/conf.d/</code> 下新建一个配置文件，比如 <code>your-site.conf</code>：</p>
<div class="language-text codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-text codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token plain">server {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    listen 80;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    server_name your-domain.com;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    location / {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        proxy_pass http://localhost:3000;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>保存退出后，运行这条命令让 Nginx 重新加载配置：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"sudo nginx -s reload"</span><br></div></code></pre></div></div>
<p><strong>在目标服务器上 serve 服务</strong></p>
<p>启动服务：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"sudo systemctl start your-service-name.service"</span><br></div></code></pre></div></div>
<p>此时打开浏览器并访问 <code>http://your-domain.com</code>，如果一切顺利，你应该能看到网站正常运行。</p>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="更新部署">更新部署<a href="https://todayred.castamerego.com/blog/website-deploy#%E6%9B%B4%E6%96%B0%E9%83%A8%E7%BD%B2" class="hash-link" aria-label="更新部署的直接链接" title="更新部署的直接链接" translate="no">​</a></h3>
<p>后续更新就简单多了。由于 systemd 服务和 Nginx 配置已经在首次部署时完成，后续更新只需要三步：</p>
<ol>
<li class="">本地执行 <code>npm run build</code></li>
</ol>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> run </span><span class="token function" style="color:#d73a49">clear</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> run build</span><br></div></code></pre></div></div>
<ol start="2">
<li class="">传输构建产物到部署服务器并解压</li>
</ol>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">tar</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-czf</span><span class="token plain"> build.tar.gz build/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">scp</span><span class="token plain"> build.tar.gz user@server:/path/to/deploy/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"tar -xzf /path/to/deploy/build.tar.gz -C /path/to/deploy/"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"rm /path/to/deploy/build.tar.gz"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">rm</span><span class="token plain"> build.tar.gz</span><br></div></code></pre></div></div>
<ol start="3">
<li class="">重启 systemd 服务</li>
</ol>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"sudo systemctl restart your-service-name.service"</span><br></div></code></pre></div></div>
<p>Tips：事实上，可以通过编辑 <code>~/.zshrc</code> 文件，添加一个别名来简化后续更新部署的操作。例如：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token builtin class-name">alias</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">rstmyweb</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'systemctl restart your-service-name.service'</span><br></div></code></pre></div></div>
<p>然后通过以下命令调用（注意需要 -i -c 参数来加载 zsh 配置）：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"zsh -i -c 'rstmyweb'"</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="小结">小结<a href="https://todayred.castamerego.com/blog/website-deploy#%E5%B0%8F%E7%BB%93" class="hash-link" aria-label="小结的直接链接" title="小结的直接链接" translate="no">​</a></h3>
<p>以上是使用 <code>npm run serve</code> + Nginx 反向代理的部署方式。非常简单直接，也有两个明显的缺点：</p>
<ol>
<li class="">依赖 Node.js 环境：服务器必须安装 Node.js 和 npm，并且要维护相关版本</li>
<li class="">资源占用偏高：npm run serve 会常驻一个 Node 进程，这个进程只托管静态文件，有些“杀鸡用牛刀”</li>
</ol>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="新想法nginx-全权代理">新想法：Nginx 全权代理<a href="https://todayred.castamerego.com/blog/website-deploy#%E6%96%B0%E6%83%B3%E6%B3%95nginx-%E5%85%A8%E6%9D%83%E4%BB%A3%E7%90%86" class="hash-link" aria-label="新想法：Nginx 全权代理的直接链接" title="新想法：Nginx 全权代理的直接链接" translate="no">​</a></h2>
<p>在了解到可以使用 Nginx 全权代理后，我决定将部署方式改为直接使用 Nginx 托管。此时：</p>
<ul>
<li class="">仅依赖 Nginx</li>
<li class="">不需要启动一个常驻进程</li>
<li class="">资源占用较低</li>
</ul>
<p>对应大致的部署流程如下：</p>
<div class="language-text codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-text codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token plain">本地 build → tar 打包 → scp 传输 → 远程解压 → Nginx 直接托管静态文件目录</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="首次部署-1">首次部署<a href="https://todayred.castamerego.com/blog/website-deploy#%E9%A6%96%E6%AC%A1%E9%83%A8%E7%BD%B2-1" class="hash-link" aria-label="首次部署的直接链接" title="首次部署的直接链接" translate="no">​</a></h3>
<p>由于不需要使用 <code>npm run serve</code>，因此首次部署只需要完成以下步骤：</p>
<ol>
<li class="">使用 build 进行构建</li>
<li class="">将构建产物传输到目标服务器上并解压</li>
<li class="">配置 Nginx 静态文件服务</li>
</ol>
<p><strong>使用 build 进行构建</strong></p>
<p>执行如下命令，清理上一次构建产物并重新构建：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> run </span><span class="token function" style="color:#d73a49">clear</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> run build</span><br></div></code></pre></div></div>
<p><strong>将构建产物传输到目标服务器上并解压</strong></p>
<p>执行如下命令，将构建产物打包并传输目标服务器上：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">tar</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-czf</span><span class="token plain"> build.tar.gz build/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">scp</span><span class="token plain"> build.tar.gz user@server:/path/to/deploy/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">rm</span><span class="token plain"> build.tar.gz</span><br></div></code></pre></div></div>
<p>执行如下命令，在目标服务器上解压构建产物：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"tar -xzf /path/to/deploy/build.tar.gz -C /path/to/deploy/"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"rm /path/to/deploy/build.tar.gz"</span><br></div></code></pre></div></div>
<p>需要注意的是，这里要给 Nginx 服务配置的目录权限，确保 Nginx 可以访问到构建产物：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"chown -R www-data:www-data /path/to/deploy/build"</span><br></div></code></pre></div></div>
<p>其中，<code>www-data</code> 代表 Nginx 运行的用户和组。</p>
<p><strong>配置 Nginx 静态文件服务</strong></p>
<p>在 <code>/etc/nginx/conf.d/</code> 目录下创建一个新的配置文件，例如 <code>your-site.conf</code>，内容如下：</p>
<div class="language-text codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-text codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token plain">server {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    listen 80;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    server_name your-domain.com;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    root /path/to/deploy/build;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    index index.html;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    location / {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        try_files $uri $uri/ =404;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    error_page 404 /404.html;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    location = /404.html {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        internal;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    location /assets/ {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        expires 1y;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        add_header Cache-Control "public, immutable";</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>需要注意的是：</p>
<ul>
<li class=""><code>root</code>：指定网站的根目录，这里是构建产物所在的目录</li>
<li class=""><code>error_page 404 /404.html</code>：指定 404 错误页面的路径，这里是构建产物中的 404.html 文件</li>
<li class=""><code>location /assets/</code>：指定静态资源的缓存策略，这里设置为一年，并添加 Cache-Control 头部，表示资源是公共的且不可变的</li>
</ul>
<p>编写完成后，保存并退出编辑器，然后执行以下命令使 Nginx 重新加载配置文件：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> user@server </span><span class="token string" style="color:#e3116c">"sudo nginx -s reload"</span><br></div></code></pre></div></div>
<p>此时打开浏览器并访问 <code>http://your-domain.com</code>，如果一切顺利，你应该能看到网站正常运行。</p>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="更新部署-1">更新部署<a href="https://todayred.castamerego.com/blog/website-deploy#%E6%9B%B4%E6%96%B0%E9%83%A8%E7%BD%B2-1" class="hash-link" aria-label="更新部署的直接链接" title="更新部署的直接链接" translate="no">​</a></h3>
<p>使用 nginx 全权代理的更新更是简洁：</p>
<ol>
<li class="">使用 build 进行构建</li>
<li class="">将构建产物传输到目标服务器上并解压</li>
</ol>
<p>详细操作参见上一节 <a href="https://todayred.castamerego.com/blog/website-deploy#%E9%A6%96%E6%AC%A1%E9%83%A8%E7%BD%B2-1" class="">首次部署</a>。</p>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="提示输出">提示输出<a href="https://todayred.castamerego.com/blog/website-deploy#%E6%8F%90%E7%A4%BA%E8%BE%93%E5%87%BA" class="hash-link" aria-label="提示输出的直接链接" title="提示输出的直接链接" translate="no">​</a></h2>
<p>如果仅有执行命令操作是不够的，自动化操作应当有提示输出，方便用户了解当前部署进度。可以在脚本中添加一些提示信息，例如：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"正在清理上一次构建产物..."</span><br></div></code></pre></div></div>
<p>在此基础上，可以使用颜色和符号来区分不同类型的提示信息，例如：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token assign-left variable" style="color:#36acaa">GREEN</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput setaf </span><span class="token variable number" style="color:#36acaa">2</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">YELLOW</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput setaf </span><span class="token variable number" style="color:#36acaa">3</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">RESET</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput sgr0</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${GREEN}</span><span class="token string" style="color:#e3116c">[✓]</span><span class="token string variable" style="color:#36acaa">${RESET}</span><span class="token string" style="color:#e3116c"> </span><span class="token string variable" style="color:#36acaa">$*</span><span class="token string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">step</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${YELLOW}</span><span class="token string" style="color:#e3116c">[→]</span><span class="token string variable" style="color:#36acaa">${RESET}</span><span class="token string" style="color:#e3116c"> </span><span class="token string variable" style="color:#36acaa">$*</span><span class="token string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">step </span><span class="token string" style="color:#e3116c">"构建项目中..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> run build</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">info </span><span class="token string" style="color:#e3116c">"构建完成，正在传输构建产物..."</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="tput">tput<a href="https://todayred.castamerego.com/blog/website-deploy#tput" class="hash-link" aria-label="tput的直接链接" title="tput的直接链接" translate="no">​</a></h3>
<p>tput 是一个用于控制终端行为的命令。可以设置文字颜色/加粗文本等样式，例如 <code>tput setaf 2</code> 代表：</p>
<ul>
<li class=""><code>setaf</code>：设置前景色（set foreground color）</li>
<li class=""><code>2</code>：颜色代码，代表绿色</li>
</ul>
<p>执行后，终端后续输出都会变成绿色，直到执行 <code>tput sgr0</code> 恢复默认样式。但请注意，一般 Linux 服务器自带 tput，但不是所有的服务器都一定支持 tput，因此在使用时需要考虑兼容性问题：</p>
<div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token assign-left variable" style="color:#36acaa">GREEN</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput setaf </span><span class="token variable number" style="color:#36acaa">2</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable operator file-descriptor important" style="color:#393A34">2</span><span class="token variable operator" style="color:#393A34">&gt;</span><span class="token variable" style="color:#36acaa">/dev/null </span><span class="token variable operator" style="color:#393A34">||</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable builtin class-name" style="color:#36acaa">echo</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">""</span><span class="token variable" style="color:#36acaa">)</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>2&gt;/dev/null</code>：将错误输出重定向到 /dev/null，避免在不支持 tput 的终端中输出错误信息</li>
<li class=""><code>|| echo ""</code>：如果 tput 执行失败，则输出空字符串，表示使用默认样式。保证脚本不会因为 tput 不支持而中断执行。</li>
</ul>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="完整部署脚本参考">完整部署脚本参考<a href="https://todayred.castamerego.com/blog/website-deploy#%E5%AE%8C%E6%95%B4%E9%83%A8%E7%BD%B2%E8%84%9A%E6%9C%AC%E5%8F%82%E8%80%83" class="hash-link" aria-label="完整部署脚本参考的直接链接" title="完整部署脚本参考的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="nginx-全权代理部署脚本">Nginx 全权代理部署脚本<a href="https://todayred.castamerego.com/blog/website-deploy#nginx-%E5%85%A8%E6%9D%83%E4%BB%A3%E7%90%86%E9%83%A8%E7%BD%B2%E8%84%9A%E6%9C%AC" class="hash-link" aria-label="Nginx 全权代理部署脚本的直接链接" title="Nginx 全权代理部署脚本的直接链接" translate="no">​</a></h3>
<details class="details_lb9f alert alert--info details_jW4y" data-collapsed="true"><summary>完整部署 bash 脚本</summary><div><div class="collapsibleContent_i85q"><div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/bash</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">set</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Colors (tput with graceful fallback) ──────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">GREEN</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput setaf </span><span class="token variable number" style="color:#36acaa">2</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable operator file-descriptor important" style="color:#393A34">2</span><span class="token variable operator" style="color:#393A34">&gt;</span><span class="token variable" style="color:#36acaa">/dev/null </span><span class="token variable operator" style="color:#393A34">||</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable builtin class-name" style="color:#36acaa">echo</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">""</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">YELLOW</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput setaf </span><span class="token variable number" style="color:#36acaa">3</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable operator file-descriptor important" style="color:#393A34">2</span><span class="token variable operator" style="color:#393A34">&gt;</span><span class="token variable" style="color:#36acaa">/dev/null </span><span class="token variable operator" style="color:#393A34">||</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable builtin class-name" style="color:#36acaa">echo</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">""</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">RED</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput setaf </span><span class="token variable number" style="color:#36acaa">1</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable operator file-descriptor important" style="color:#393A34">2</span><span class="token variable operator" style="color:#393A34">&gt;</span><span class="token variable" style="color:#36acaa">/dev/null </span><span class="token variable operator" style="color:#393A34">||</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable builtin class-name" style="color:#36acaa">echo</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">""</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">BOLD</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput bold </span><span class="token variable operator file-descriptor important" style="color:#393A34">2</span><span class="token variable operator" style="color:#393A34">&gt;</span><span class="token variable" style="color:#36acaa">/dev/null </span><span class="token variable operator" style="color:#393A34">||</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable builtin class-name" style="color:#36acaa">echo</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">""</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">RESET</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput sgr0 </span><span class="token variable operator file-descriptor important" style="color:#393A34">2</span><span class="token variable operator" style="color:#393A34">&gt;</span><span class="token variable" style="color:#36acaa">/dev/null </span><span class="token variable operator" style="color:#393A34">||</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable builtin class-name" style="color:#36acaa">echo</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">""</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Logging helpers ───────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${BOLD}</span><span class="token string variable" style="color:#36acaa">${GREEN}</span><span class="token string" style="color:#e3116c">[✓]</span><span class="token string variable" style="color:#36acaa">${RESET}</span><span class="token string" style="color:#e3116c"> </span><span class="token string variable" style="color:#36acaa">$*</span><span class="token string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">step</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${BOLD}</span><span class="token string variable" style="color:#36acaa">${YELLOW}</span><span class="token string" style="color:#e3116c">[→]</span><span class="token string variable" style="color:#36acaa">${RESET}</span><span class="token string" style="color:#e3116c"> </span><span class="token string variable" style="color:#36acaa">$*</span><span class="token string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${BOLD}</span><span class="token string variable" style="color:#36acaa">${RED}</span><span class="token string" style="color:#e3116c">[✗]</span><span class="token string variable" style="color:#36acaa">${RESET}</span><span class="token string" style="color:#e3116c"> </span><span class="token string variable" style="color:#36acaa">$*</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token file-descriptor important">&amp;2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Cleanup on error ──────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">cleanup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  error </span><span class="token string" style="color:#e3116c">"Deployment failed. Cleaning up temporary files..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> build.tar.gz </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> build.tar.gz</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rm -f /tmp/build.tar.gz"</span><span class="token plain"> </span><span class="token operator file-descriptor important" style="color:#393A34">2</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain">/dev/null </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">trap</span><span class="token plain"> cleanup ERR</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Config ────────────────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">REMOTE</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">user@server</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">REMOTE_DIR</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">/path/to/deploy</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Build ─────────────────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">step </span><span class="token string" style="color:#e3116c">"Clearing previous build..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> run </span><span class="token function" style="color:#d73a49">clear</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">step </span><span class="token string" style="color:#e3116c">"Building project..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> run build</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">info </span><span class="token string" style="color:#e3116c">"Build complete."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Package &amp; Transfer ────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">step </span><span class="token string" style="color:#e3116c">"Packaging build files..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">tar</span><span class="token plain"> czf build.tar.gz build/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">step </span><span class="token string" style="color:#e3116c">"Transferring build to remote server..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">scp</span><span class="token plain"> build.tar.gz </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain">:/tmp/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">rm</span><span class="token plain"> build.tar.gz</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">info </span><span class="token string" style="color:#e3116c">"Build files transferred."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Deploy ────────────────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"--init"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  step </span><span class="token string" style="color:#e3116c">"Creating remote directory..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"mkdir -p </span><span class="token string variable" style="color:#36acaa">$REMOTE_DIR</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  step </span><span class="token string" style="color:#e3116c">"Deploying build files..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"tar xzf /tmp/build.tar.gz -C </span><span class="token string variable" style="color:#36acaa">$REMOTE_DIR</span><span class="token string" style="color:#e3116c"> &amp;&amp; rm /tmp/build.tar.gz"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"chown -R www-data:www-data </span><span class="token string variable" style="color:#36acaa">$REMOTE_DIR</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  step </span><span class="token string" style="color:#e3116c">"Setting up nginx configuration..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">scp</span><span class="token plain"> your-site.conf </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain">:/etc/nginx/conf.d/your-site.conf</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"chmod 644 /etc/nginx/conf.d/your-site.conf &amp;&amp; nginx -t &amp;&amp; systemctl reload nginx"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  info </span><span class="token string" style="color:#e3116c">"Nginx configured."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  step </span><span class="token string" style="color:#e3116c">"Deploying build files..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"tar xzf /tmp/build.tar.gz -C </span><span class="token string variable" style="color:#36acaa">$REMOTE_DIR</span><span class="token string" style="color:#e3116c"> &amp;&amp; rm /tmp/build.tar.gz"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"chown -R www-data:www-data </span><span class="token string variable" style="color:#36acaa">$REMOTE_DIR</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"systemctl reload nginx"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fi</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">info </span><span class="token string" style="color:#e3116c">"Deployment complete. Your website should now be live."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div></code></pre></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_jW4y" data-collapsed="true"><summary>完整部署 zsh 脚本</summary><div><div class="collapsibleContent_i85q"><div class="language-bash codeBlockContainer_aalF theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_N_DF"><pre tabindex="0" class="prism-code language-bash codeBlock_zHgq thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_RjmQ"><div class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/zsh</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">set</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Colors (tput with graceful fallback) ──────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">GREEN</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput setaf </span><span class="token variable number" style="color:#36acaa">2</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable operator file-descriptor important" style="color:#393A34">2</span><span class="token variable operator" style="color:#393A34">&gt;</span><span class="token variable" style="color:#36acaa">/dev/null </span><span class="token variable operator" style="color:#393A34">||</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable builtin class-name" style="color:#36acaa">echo</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">""</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">YELLOW</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput setaf </span><span class="token variable number" style="color:#36acaa">3</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable operator file-descriptor important" style="color:#393A34">2</span><span class="token variable operator" style="color:#393A34">&gt;</span><span class="token variable" style="color:#36acaa">/dev/null </span><span class="token variable operator" style="color:#393A34">||</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable builtin class-name" style="color:#36acaa">echo</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">""</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">RED</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput setaf </span><span class="token variable number" style="color:#36acaa">1</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable operator file-descriptor important" style="color:#393A34">2</span><span class="token variable operator" style="color:#393A34">&gt;</span><span class="token variable" style="color:#36acaa">/dev/null </span><span class="token variable operator" style="color:#393A34">||</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable builtin class-name" style="color:#36acaa">echo</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">""</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">BOLD</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput bold </span><span class="token variable operator file-descriptor important" style="color:#393A34">2</span><span class="token variable operator" style="color:#393A34">&gt;</span><span class="token variable" style="color:#36acaa">/dev/null </span><span class="token variable operator" style="color:#393A34">||</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable builtin class-name" style="color:#36acaa">echo</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">""</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">RESET</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable" style="color:#36acaa">tput sgr0 </span><span class="token variable operator file-descriptor important" style="color:#393A34">2</span><span class="token variable operator" style="color:#393A34">&gt;</span><span class="token variable" style="color:#36acaa">/dev/null </span><span class="token variable operator" style="color:#393A34">||</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable builtin class-name" style="color:#36acaa">echo</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">""</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Logging helpers ───────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${BOLD}</span><span class="token string variable" style="color:#36acaa">${GREEN}</span><span class="token string" style="color:#e3116c">[✓]</span><span class="token string variable" style="color:#36acaa">${RESET}</span><span class="token string" style="color:#e3116c"> </span><span class="token string variable" style="color:#36acaa">$*</span><span class="token string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">step</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${BOLD}</span><span class="token string variable" style="color:#36acaa">${YELLOW}</span><span class="token string" style="color:#e3116c">[→]</span><span class="token string variable" style="color:#36acaa">${RESET}</span><span class="token string" style="color:#e3116c"> </span><span class="token string variable" style="color:#36acaa">$*</span><span class="token string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${BOLD}</span><span class="token string variable" style="color:#36acaa">${RED}</span><span class="token string" style="color:#e3116c">[✗]</span><span class="token string variable" style="color:#36acaa">${RESET}</span><span class="token string" style="color:#e3116c"> </span><span class="token string variable" style="color:#36acaa">$*</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token file-descriptor important">&amp;2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Cleanup on error ──────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">cleanup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  error </span><span class="token string" style="color:#e3116c">"Deployment failed. Cleaning up temporary files..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> build.tar.gz </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> build.tar.gz</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rm -f /tmp/build.tar.gz"</span><span class="token plain"> </span><span class="token operator file-descriptor important" style="color:#393A34">2</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain">/dev/null </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">trap</span><span class="token plain"> cleanup ERR</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Config ────────────────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">REMOTE</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">user@server</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">REMOTE_DIR</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">/path/to/deploy</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Build ─────────────────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">step </span><span class="token string" style="color:#e3116c">"Clearing previous build..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> run </span><span class="token function" style="color:#d73a49">clear</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">step </span><span class="token string" style="color:#e3116c">"Building project..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> run build</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">info </span><span class="token string" style="color:#e3116c">"Build complete."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Package &amp; Transfer ────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">step </span><span class="token string" style="color:#e3116c">"Packaging build files..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">tar</span><span class="token plain"> czf build.tar.gz build/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">step </span><span class="token string" style="color:#e3116c">"Transferring build to remote server..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">scp</span><span class="token plain"> build.tar.gz </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain">:/tmp/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">rm</span><span class="token plain"> build.tar.gz</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">info </span><span class="token string" style="color:#e3116c">"Build files transferred."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ── Deploy ────────────────────────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"--init"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  step </span><span class="token string" style="color:#e3116c">"Creating remote directory..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"mkdir -p </span><span class="token string variable" style="color:#36acaa">$REMOTE_DIR</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  step </span><span class="token string" style="color:#e3116c">"Deploying build files..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"tar xzf /tmp/build.tar.gz -C </span><span class="token string variable" style="color:#36acaa">$REMOTE_DIR</span><span class="token string" style="color:#e3116c"> &amp;&amp; rm /tmp/build.tar.gz"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"chown -R www-data:www-data </span><span class="token string variable" style="color:#36acaa">$REMOTE_DIR</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  step </span><span class="token string" style="color:#e3116c">"Setting up nginx configuration..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">scp</span><span class="token plain"> your-site.conf </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain">:/etc/nginx/conf.d/your-site.conf</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"zsh -i -c 'chmod 644 /etc/nginx/conf.d/your-site.conf &amp;&amp; nginx -t &amp;&amp; systemctl reload nginx'"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  info </span><span class="token string" style="color:#e3116c">"Nginx configured."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  step </span><span class="token string" style="color:#e3116c">"Deploying build files..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"tar xzf /tmp/build.tar.gz -C </span><span class="token string variable" style="color:#36acaa">$REMOTE_DIR</span><span class="token string" style="color:#e3116c"> &amp;&amp; rm /tmp/build.tar.gz"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$REMOTE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"chown -R www-data:www-data </span><span class="token string variable" style="color:#36acaa">$REMOTE_DIR</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fi</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">info </span><span class="token string" style="color:#e3116c">"Deployment complete. Your website should now be live."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div></code></pre></div></div></div></div></details>]]></content>
        <author>
            <name>Achinoise</name>
        </author>
        <category label="Linux" term="Linux"/>
        <category label="Deploy" term="Deploy"/>
        <category label="Docusaurus" term="Docusaurus"/>
    </entry>
</feed>