<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on Kaisekukun</title><link>https://netguide.jp/zh/posts/</link><description>Recent content in Posts on Kaisekukun</description><generator>Hugo -- gohugo.io</generator><language>zh</language><copyright>Kaisekukun</copyright><lastBuildDate>Wed, 14 Oct 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://netguide.jp/zh/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>现代 CSS 新功能的实际使用（子网格/容器查询）</title><link>https://netguide.jp/zh/posts/%E7%8E%B0%E4%BB%A3-css-%E6%96%B0%E5%8A%9F%E8%83%BD%E7%9A%84%E5%AE%9E%E9%99%85%E4%BD%BF%E7%94%A8%E5%AD%90%E7%BD%91%E6%A0%BC/%E5%AE%B9%E5%99%A8%E6%9F%A5%E8%AF%A2/</link><pubDate>Wed, 14 Oct 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E7%8E%B0%E4%BB%A3-css-%E6%96%B0%E5%8A%9F%E8%83%BD%E7%9A%84%E5%AE%9E%E9%99%85%E4%BD%BF%E7%94%A8%E5%AD%90%E7%BD%91%E6%A0%BC/%E5%AE%B9%E5%99%A8%E6%9F%A5%E8%AF%A2/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/modern-css-subgrid-container-queries-guide-zh.png" alt="Featured image of post 现代 CSS 新功能的实际使用（子网格/容器查询）" /&gt;&lt;h3 id="从视口标准到独立组件的范式转变"&gt;从视口标准到独立组件的范式转变
&lt;/h3&gt;&lt;p&gt;传统的响应式网页设计依赖于屏幕（视口）的整体宽度。然而，在当今面向组件的设计世界中，UI 部件的可用宽度根据它们所在的父元素（侧边栏或主列）而有所不同。&lt;/p&gt;
&lt;p&gt;随着CSS Grid的“子网格”和“容器查询”的出现，布局的灵活性和可维护性得到了极大的提高。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="配方-1subgrid在对齐卡片高度的同时同步按钮位置"&gt;配方 1：“subgrid”在对齐卡片高度的同时同步按钮位置
&lt;/h3&gt;&lt;p&gt;即使在多列卡片UI中标题字符数不均匀，每张卡片中“图像、标题、文本和按钮”的高度也可以在水平线上完美对齐。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#a6e22e"&gt;card-grid&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;display&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;grid&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;grid-template-columns&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;repeat&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;fit, &lt;span style="color:#a6e22e"&gt;minmax&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;280&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;fr));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;gap&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1.5&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;rem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#a6e22e"&gt;card&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;display&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;grid&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;grid-template-rows&lt;/span&gt;: subgrid;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;grid-row&lt;/span&gt;: span &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;; &lt;span style="color:#75715e"&gt;/* 画像・タイトル・本文・フッターの4行を親グリッドに同期 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;不需要任何 JavaScript 来计算每张卡片的高度。&lt;/p&gt;
&lt;h3 id="方法-2container-其布局根据其宽度进行调整"&gt;方法 2：&lt;code&gt;@container&lt;/code&gt; 其布局根据其宽度进行调整
&lt;/h3&gt;&lt;p&gt;卡片组件根据其所在容器的宽度自动在水平和垂直对齐之间切换。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#a6e22e"&gt;card-wrapper&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;container-type&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;inline&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;size&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;container-name&lt;/span&gt;: card-container;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#66d9ef"&gt;container&lt;/span&gt; &lt;span style="color:#f92672"&gt;card-container&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#f92672"&gt;min-width&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#f92672"&gt;450px&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;card-content&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;flex-direction&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;row&lt;/span&gt;; &lt;span style="color:#75715e"&gt;/* 横幅に余裕があれば横並びへ自動変形 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;您可以在主页的宽区域和侧边栏的窄区域中重复使用相同的组件。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="实际实施的概念"&gt;实际实施的概念
&lt;/h3&gt;&lt;p&gt;子网格和容器查询已经在主要的现代浏览器中得到完全支持。摆脱整个屏幕上的断点造成的破坏，并转向每个组件都可以独立存在的 CSS 设计。&lt;/p&gt;</description></item><item><title>使用 Vitest 和测试库进行高效的前端测试</title><link>https://netguide.jp/zh/posts/%E4%BD%BF%E7%94%A8-vitest-%E5%92%8C%E6%B5%8B%E8%AF%95%E5%BA%93%E8%BF%9B%E8%A1%8C%E9%AB%98%E6%95%88%E7%9A%84%E5%89%8D%E7%AB%AF%E6%B5%8B%E8%AF%95/</link><pubDate>Tue, 06 Oct 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E4%BD%BF%E7%94%A8-vitest-%E5%92%8C%E6%B5%8B%E8%AF%95%E5%BA%93%E8%BF%9B%E8%A1%8C%E9%AB%98%E6%95%88%E7%9A%84%E5%89%8D%E7%AB%AF%E6%B5%8B%E8%AF%95/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/efficient-frontend-testing-vitest-testing-library-zh.png" alt="Featured image of post 使用 Vitest 和测试库进行高效的前端测试" /&gt;&lt;h3 id="vite原生测试环境带来的开发速度提升"&gt;Vite原生测试环境带来的开发速度提升
&lt;/h3&gt;&lt;p&gt;Jest 多年来一直是前端测试的主流，但其设置复杂性和开销是问题。通过组合共享 Vite 设置的“Vitest”和“React 测试库”，您可以获得极快的测试环境。&lt;/p&gt;
&lt;p&gt;我们总结了构建高度可维护且难以破坏的测试套件的实用原则。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="原则测试用户行为而不是实现细节"&gt;原则：测试“用户行为”而不是“实现细节”
&lt;/h3&gt;&lt;p&gt;直接测试组件的内部状态会导致脆弱的测试，每次重构都会破坏测试。基本思想是验证屏幕向用户显示的行为。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;screen&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;@testing-library/react&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;userEvent&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;@testing-library/user-event&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;LoginForm&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./LoginForm&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;test&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;入力からログイン完了までのフローを検証&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;user&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;userEvent&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setup&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;(&amp;lt;&lt;span style="color:#f92672"&gt;LoginForm&lt;/span&gt; /&amp;gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;user&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;screen&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getByLabelText&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;メールアドレス&amp;#39;&lt;/span&gt;), &lt;span style="color:#e6db74"&gt;&amp;#39;test@example.com&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;user&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;click&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;screen&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getByRole&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;button&amp;#39;&lt;/span&gt;, { &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;ログイン&amp;#39;&lt;/span&gt; }));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;expect&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;screen&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;findByText&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;ようこそ&amp;#39;&lt;/span&gt;)).&lt;span style="color:#a6e22e"&gt;toBeInTheDocument&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="异步更新的陷阱正确使用查询函数"&gt;异步更新的陷阱：正确使用查询函数
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;getBy**&lt;/code&gt;&lt;/strong&gt;：同步验证元素“现在存在”。如果不存在则立即错误。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;findBy**&lt;/code&gt;&lt;/strong&gt;：等待API获取等“异步延迟显示”的元素（返回Promise）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;queryBy**&lt;/code&gt;&lt;/strong&gt;：用于断言该元素“屏幕上不存在”（返回 null）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="并行化点减少-ci-执行时间"&gt;并行化点减少 CI 执行时间
&lt;/h3&gt;&lt;p&gt;Vitest默认使用线程并行执行。对于涉及 DOM 操作的测试，请在“afterEach”中正确重置模拟，以保持每个测试用例的独立性，最大化并行测试的数量，并降低 CI 成本。&lt;/p&gt;</description></item><item><title>UI 组件设计考虑到 Web 可访问性 (a11y)</title><link>https://netguide.jp/zh/posts/ui-%E7%BB%84%E4%BB%B6%E8%AE%BE%E8%AE%A1%E8%80%83%E8%99%91%E5%88%B0-web-%E5%8F%AF%E8%AE%BF%E9%97%AE%E6%80%A7-a11y/</link><pubDate>Tue, 29 Sep 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/ui-%E7%BB%84%E4%BB%B6%E8%AE%BE%E8%AE%A1%E8%80%83%E8%99%91%E5%88%B0-web-%E5%8F%AF%E8%AE%BF%E9%97%AE%E6%80%A7-a11y/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/accessible-ui-components-design-a11y-zh.png" alt="Featured image of post UI 组件设计考虑到 Web 可访问性 (a11y)" /&gt;&lt;h3 id="平衡设计和可用性的辅助功能基础"&gt;平衡设计和可用性的辅助功能基础
&lt;/h3&gt;&lt;p&gt;网络可访问性 (a11y) 是一项质量标准，旨在改善每个人的体验，不仅针对特定残疾人，还针对键盘用户以及暂时受伤或单手操作的用户。&lt;/p&gt;
&lt;p&gt;我们整理了组件设计的要点，以便任何人都可以直观地操作它。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="模态对话框设计的三个基本要求"&gt;模态对话框设计的三个基本要求
&lt;/h3&gt;&lt;p&gt;模态框是最常发生可访问性违规的部分。您必须确保满足以下三个要求。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;焦点陷阱&lt;/strong&gt;：打开时，Tab 键移动仅限于模态，防止焦点泄漏到其后面的元素。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Escape键操作&lt;/strong&gt;：按ESC键立即关闭，关闭后将焦点返回到“打开模态框的原始按钮”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;适当的 WAI-ARIA 属性&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;授予&lt;code&gt;role =“dialog”&lt;/code&gt;和&lt;code&gt;aria-modal =“true”&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;明确指向标题的“aria-labelledby”&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id="经常被忽视的三大反模式"&gt;经常被忽视的三大反模式
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;反模式 1：将点击事件附加到 &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; 或 &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;问题&lt;/strong&gt;：无法使用键盘（Enter/Space）进行操作，并且不显示为屏幕阅读器的按钮。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;解决方案&lt;/strong&gt;：使用原生 &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; 标签和 CSS 样式。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;反模式 2：使用占位符作为标签&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;问题&lt;/strong&gt;：当您开始打字时它就会消失，从而损害可见性和认知负荷。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;已解决&lt;/strong&gt;：准备一个始终显示的&lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt;，并使用&lt;code&gt;htmlFor&lt;/code&gt;将其与输入的id关联起来。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;反模式3：对比度不足&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;问题&lt;/strong&gt;：对比度小于4.5:1时难以阅读，例如浅灰色文本。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;已解决&lt;/strong&gt;：修复了符合 WCAG 2.1 AA 标准的调色板。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="使用-headless-ui-库减少工时"&gt;使用 Headless UI 库减少工时
&lt;/h3&gt;&lt;p&gt;自己从头开始实现可访问性非常耗时。现代标准是使用“高度可访问的无样式 UI 原语”，例如 Radix UI 和 React Aria，并仅应用 Tailwind CSS 等样式。&lt;/p&gt;</description></item><item><title>使用 Next.js 和 Hono 创建的全栈 WebAPI 简介</title><link>https://netguide.jp/zh/posts/%E4%BD%BF%E7%94%A8-next.js-%E5%92%8C-hono-%E5%88%9B%E5%BB%BA%E7%9A%84%E5%85%A8%E6%A0%88-webapi-%E7%AE%80%E4%BB%8B/</link><pubDate>Tue, 22 Sep 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E4%BD%BF%E7%94%A8-next.js-%E5%92%8C-hono-%E5%88%9B%E5%BB%BA%E7%9A%84%E5%85%A8%E6%A0%88-webapi-%E7%AE%80%E4%BB%8B/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/building-fullstack-web-apis-nextjs-hono-zh.png" alt="Featured image of post 使用 Next.js 和 Hono 创建的全栈 WebAPI 简介" /&gt;&lt;h3 id="nextjs-app-router--hono-带来的开发革命"&gt;Next.js App Router × Hono 带来的开发革命
&lt;/h3&gt;&lt;p&gt;Next.js 的路由处理程序很强大，但随着端点的增加，样板文件和类型共享的复杂性往往成为一个问题。&lt;/p&gt;
&lt;p&gt;通过将符合Web标准的超轻量级框架“Hono”纳入API层，您可以轻松创建复杂的端到端、类型安全的RPC（远程过程调用）环境。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="第-1-步使用-catch-all-route-进行-hono-初始化"&gt;第 1 步：使用 Catch-all Route 进行 Hono 初始化
&lt;/h3&gt;&lt;p&gt;在 App Router 中放置通配符路由，并将所有“/api/*”委托给 Hono。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// app/api/[[...route]]/route.ts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Hono&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;hono&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;handle&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;hono/vercel&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;zValidator&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;@hono/zod-validator&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;z&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;zod&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;runtime&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;edge&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;app&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Hono&lt;/span&gt;().&lt;span style="color:#a6e22e"&gt;basePath&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;/api&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;routes&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;/users/:id&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;zValidator&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;param&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;z&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;object&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;z.string&lt;/span&gt;() })),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;c.req.valid&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;param&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Alice&amp;#39;&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AppType&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;typeof&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;routes&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;GET&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;handle&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="步骤-2使用-hc-获取类型安全的数据"&gt;步骤 2：使用 &lt;code&gt;hc&lt;/code&gt; 获取类型安全的数据
&lt;/h3&gt;&lt;p&gt;Hono 的一个主要优势是服务器端路由定义（“AppType”）可以作为客户端上的类型导入。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// クライアント側コンポーネント
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;hc&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;hono/client&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;AppType&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;@/app/api/[[...route]]/route&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;client&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;hc&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;AppType&lt;/span&gt;&amp;gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;http://localhost:3000&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getUser&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;res&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;client&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;api&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;users&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#39;:id&amp;#39;&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;$get&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;param&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt; } });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;(); &lt;span style="color:#75715e"&gt;// 返り値の型が自動推論される
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;###生产操作三大要点&lt;/p&gt;</description></item><item><title>在 TypeScript 5 系列中练习的类型安全编码技术</title><link>https://netguide.jp/zh/posts/%E5%9C%A8-typescript-5-%E7%B3%BB%E5%88%97%E4%B8%AD%E7%BB%83%E4%B9%A0%E7%9A%84%E7%B1%BB%E5%9E%8B%E5%AE%89%E5%85%A8%E7%BC%96%E7%A0%81%E6%8A%80%E6%9C%AF/</link><pubDate>Tue, 15 Sep 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E5%9C%A8-typescript-5-%E7%B3%BB%E5%88%97%E4%B8%AD%E7%BB%83%E4%B9%A0%E7%9A%84%E7%B1%BB%E5%9E%8B%E5%AE%89%E5%85%A8%E7%BC%96%E7%A0%81%E6%8A%80%E6%9C%AF/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/type-safe-coding-techniques-typescript-5-zh.png" alt="Featured image of post 在 TypeScript 5 系列中练习的类型安全编码技术" /&gt;&lt;h3 id="typescript-5x时代所需的类型设计哲学"&gt;TypeScript 5.x时代所需的类型设计哲学
&lt;/h3&gt;&lt;p&gt;TypeScript 5 系列引入了许多新功能，可以在不影响开发人员体验的情况下最大限度地提高类型推断的准确性。依赖过多类型断言 (as) 的代码是运行时错误的滋生地。有了型系统在您身边，我们将解释实用技术，自然地缩小您的型。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="1-const-类型参数更智能的文字类型推断"&gt;1. &lt;code&gt;const&lt;/code&gt; 类型参数：更智能的文字类型推断
&lt;/h3&gt;&lt;p&gt;以前，如果您想在函数参数中保留文字类型，则必须在调用方添加“as const”。 TypeScript 5.0 的 &lt;code&gt;const&lt;/code&gt; 类型参数允许您在函数定义端强制进行文字推理。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 呼び出し側の as const なしで厳密なリテラル配列として推論
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createRoutes&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;T&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;readonly&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;string&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;[]&lt;/span&gt;&amp;gt;(&lt;span style="color:#a6e22e"&gt;routes&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;T&lt;/span&gt;)&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;T&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;routes&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;routes&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createRoutes&lt;/span&gt;([&lt;span style="color:#e6db74"&gt;&amp;#39;/home&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;/dashboard&amp;#39;&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;作为参数传递的数组和对象不会被扩展，并被安全地推断为精确的元组或文字。&lt;/p&gt;
&lt;h3 id="2-satisfies-运算符类型兼容性验证和推理的兼容性"&gt;2. &lt;code&gt;satisfies&lt;/code&gt; 运算符：类型兼容性验证和推理的兼容性
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;satisfies&lt;/code&gt; 解决了添加类型注释会导致属性的具体类型信息丢失，而删除它会导致验证失败的困境。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Palette&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Record&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;string&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;string&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;number&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;[]&lt;/span&gt;&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;theme&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;primary&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#0066cc&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;rgb&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;102&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;204&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#a6e22e"&gt;satisfies&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Palette&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 型制約を満たしつつ、個別プロパティの型が完全保持される
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;theme&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;primary&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toUpperCase&lt;/span&gt;(); &lt;span style="color:#75715e"&gt;// string型メソッドが安全に呼出可能
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-具有模板文字类型的事件中心"&gt;3. 具有模板文字类型的事件中心
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Event&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;click&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;focus&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;HandlerMap&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { [&lt;span style="color:#a6e22e"&gt;K&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`on&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Capitalize&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;Event&lt;/span&gt;&amp;gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;]&lt;span style="color:#f92672"&gt;?:&lt;/span&gt; () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在类型级别强制执行字符串连接规则，并在构建时防止事件名称 100% 出现拼写错误。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="反模式应在该领域根除的任何"&gt;反模式：应在该领域根除的“任何”
&lt;/h3&gt;&lt;p&gt;使用“as any”作为解决类型错误的快速方法是放弃 TypeScript 优势的糟糕方法。使用类型保护函数（“is”运算符）和模式验证器（例如 Zod）在运行时边界安全地缩小类型范围。&lt;/p&gt;</description></item><item><title>使用 Next.js 15 构建的超快速 Web 应用程序</title><link>https://netguide.jp/zh/posts/%E4%BD%BF%E7%94%A8-next.js-15-%E6%9E%84%E5%BB%BA%E7%9A%84%E8%B6%85%E5%BF%AB%E9%80%9F-web-%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F/</link><pubDate>Tue, 08 Sep 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E4%BD%BF%E7%94%A8-next.js-15-%E6%9E%84%E5%BB%BA%E7%9A%84%E8%B6%85%E5%BF%AB%E9%80%9F-web-%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/building-blazing-fast-web-apps-nextjs-15-zh.png" alt="Featured image of post 使用 Next.js 15 构建的超快速 Web 应用程序" /&gt;&lt;p&gt;“Next.js 15”终于在最近的更新中发布了测试版，并在前端界引起了很大的轰动。
我也立即将我的个人项目从 Next.js 14 升级到 15，并尝试了一些新功能。在这篇文章中，我将回顾一下我实际接触后感受到的“惊人的进化”。&lt;/p&gt;
&lt;h2 id="nextjs-15-的演变让我一接触就感到惊讶"&gt;Next.js 15 的演变让我一接触就感到惊讶
&lt;/h2&gt;&lt;p&gt;如果非要用一个词来形容的话，那就是“开发者体验（DX）和性能的终极提升”。
自 App Router 推出以来，Next.js 一直处于重大范式转变之中，版本 15 感觉已经接近完成。&lt;/p&gt;
&lt;h3 id="1-使用-react-compiler-将自己从手动记忆中解放出来"&gt;1. 使用 React Compiler 将自己从手动记忆中解放出来
&lt;/h3&gt;&lt;p&gt;就我个人而言，给我印象最深的是官方对 React Compiler 的支持。
以前，您必须在各处编写“useMemo”、“useCallback”和“React.memo”，以防止不必要的重新渲染。但是，在 Next.js 15 中，编译器将为您进行优化。&lt;/p&gt;
&lt;p&gt;实际上，我尝试从代码中删除所有这些挂钩，它根本没有减慢速度，反而使我的代码库变得非常干净。仅此一点就值得采取行动。&lt;/p&gt;
&lt;h3 id="2默认缓存策略修改"&gt;2.默认缓存策略修改
&lt;/h3&gt;&lt;p&gt;在以前的版本中，许多开发人员对“默认缓存所有内容”的激进规范感到困惑（我就是其中之一）。
在 Next.js 15 中，获取请求（“fetch”）的默认值已修改为“no-store”，并且我们返回了一种选择加入方法，您可以在该方法中仅显式指定需要缓存的部分。这减少了无意的陈旧数据显示的数量，并使直观的开发再次成为可能。&lt;/p&gt;
&lt;h3 id="3-turbopack-稳定性带来爆炸性的启动速度"&gt;3. Turbopack 稳定性带来爆炸性的启动速度
&lt;/h3&gt;&lt;p&gt;本地开发环境搭建的速度也值得注意。
Turbopack 是一个基于 Rust 的捆绑器，现在更加稳定，允许服务器立即启动，即使对于大型项目也是如此。热重载（Fast Refresh）的响应也是压倒性的，等待时间带来的压力几乎被消除。&lt;/p&gt;
&lt;h2 id="总体回顾您现在应该迁移吗"&gt;总体回顾：您现在应该迁移吗？
&lt;/h2&gt;&lt;p&gt;总之，如果它是一个新项目，我们建议毫不犹豫地在 Next.js 15（或 React 19）上构建它。即使您有一个现有项目，如果您已经迁移到 App Router，升级它的障碍也不会那么高。&lt;/p&gt;
&lt;p&gt;“快”不仅仅指浏览器的绘制速度。这意味着开发人员编写、审查和部署代码的整个周期更快。我认为 Next.js 15 是能够实现这种“极快循环”的框架的顶峰。&lt;/p&gt;</description></item><item><title>后端开发中的性能调优介绍</title><link>https://netguide.jp/zh/posts/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84%E6%80%A7%E8%83%BD%E8%B0%83%E4%BC%98%E4%BB%8B%E7%BB%8D/</link><pubDate>Thu, 03 Sep 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84%E6%80%A7%E8%83%BD%E8%B0%83%E4%BC%98%E4%BB%8B%E7%BB%8D/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/backend-performance-tuning-introduction-zh.png" alt="Featured image of post 后端开发中的性能调优介绍" /&gt;&lt;p&gt;随着Web服务的用户数量增加，他们不可避免地会遇到响应时间慢、服务器崩溃等性能问题。
前端优化固然重要，但负责基础数据处理的后端往往是瓶颈。&lt;/p&gt;
&lt;p&gt;本文为首次致力于提高后端性能的工程师提供了实用检查点列表。&lt;/p&gt;
&lt;h3 id="-5-个检查点需要检查"&gt;🚨 5 个检查点需要检查
&lt;/h3&gt;&lt;p&gt;如果盲目进行性能调优，效果不会很好。首先检查是否是以下原因造成的。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;**不是出现了N+1问题吗？ **
&lt;ul&gt;
&lt;li&gt;使用 O/R 映射器 (ORM) 时，N+1 问题经常会在不知不觉中发生。检索列表数据时，检查查询日志，看看是否发出了一条一条循环遍历相关数据的 SQL。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;**索引是否正确附加？ **
&lt;ul&gt;
&lt;li&gt;索引与数据库搜索速度最直接相关。请为搜索条件或排序条件中经常使用的列设置合适的索引（单一索引或复合索引）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;**您是否有效地使用了缓存？ **
&lt;ul&gt;
&lt;li&gt;通过使用Redis或Memcached将经常访问但很少更新的数据（例如主数据）缓存在内存中，可以显着减少数据库的负载。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;**您是否在调用外部API时等待太久？ **
&lt;ul&gt;
&lt;li&gt;如果与第三方 API 或其他微服务的通信是同步进程，则该进程将被阻塞。如果可能，请考虑使用异步处理或后台工作程序的设计。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;**是否存在内存泄漏？ **
&lt;ul&gt;
&lt;li&gt;如果长时间运行的应用程序性能逐渐下降，则可能怀疑存在内存泄漏。使用探查器调查是否存在任何不必要的对象引用。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="-没有测量就没有改善"&gt;🛠️ 没有测量就没有改善
&lt;/h3&gt;&lt;p&gt;调优时最糟糕的事情就是“通过猜测来修复”。我的“我感觉这里很慢”的直觉常常被证明是错误的。&lt;/p&gt;
&lt;p&gt;首先，引入 APM（应用程序性能监控）工具，例如 &lt;strong&gt;New Relic&lt;/strong&gt; 或 &lt;strong&gt;Datadog&lt;/strong&gt;，以数字方式可视化哪些事务和哪些进程（SQL 执行时间、外部通信等）正在花费时间。&lt;/p&gt;
&lt;h3 id="调整心态"&gt;💡调整心态
&lt;/h3&gt;&lt;p&gt;最后要记住的是，并不是所有事情都需要最快。
从维护成本的角度来看，引入复杂的缓存机制来减少每天只执行一次的批处理过程几秒钟通常是不值得的。&lt;/p&gt;
&lt;p&gt;确定与用户体验直接相关的关键端点，并将资源集中在这些端点上。这是成为优秀后端工程师的第一步。在日常的发展中要注意“衡量”，一点一点地改进。&lt;/p&gt;</description></item><item><title>秋夜学习：最新前端技术趋势</title><link>https://netguide.jp/zh/posts/%E7%A7%8B%E5%A4%9C%E5%AD%A6%E4%B9%A0%E6%9C%80%E6%96%B0%E5%89%8D%E7%AB%AF%E6%8A%80%E6%9C%AF%E8%B6%8B%E5%8A%BF/</link><pubDate>Sun, 30 Aug 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E7%A7%8B%E5%A4%9C%E5%AD%A6%E4%B9%A0%E6%9C%80%E6%96%B0%E5%89%8D%E7%AB%AF%E6%8A%80%E6%9C%AF%E8%B6%8B%E5%8A%BF/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/learning-autumn-nights-latest-frontend-trends-zh.png" alt="Featured image of post 秋夜学习：最新前端技术趋势" /&gt;&lt;p&gt;正是这个季节，窗外隐约能听到虫鸣声。
我喜欢夏天，手捧冷饮，在空调房里写代码，但作为一名工程师，没有什么比在漫长的秋夜里，一边感受凉爽的夜风，一边悠闲地看新技术文档的了。&lt;/p&gt;
&lt;p&gt;这次我想稍微放松一下，以散文的方式回顾一下今年在前端界掀起波澜的技术趋势。&lt;/p&gt;
&lt;h3 id="切换回服务器端"&gt;切换回服务器端
&lt;/h3&gt;&lt;p&gt;如果让我选出一个代表今年的关键词，那肯定是“React Server Components (RSC)”。
在过去的几年里，我们全心全意地研究“如何在浏览器端（客户端）创建丰富的体验”。然而，JavaScript 包的大小不断增加，初始加载速度已达到极限。&lt;/p&gt;
&lt;p&gt;这就是 RSC 的用武之地。从某种意义上说，这种方法让人想起 PHP 和 Ruby 的美好时光：“任何可以在服务器上呈现的东西都应该在服务器上完成。”这是一种将客户端交互性与服务器稳健性高度融合的新范例。 Next.js 的 App Router 处于领先地位，许多开发人员对其潜力感到兴奋，尽管他们很难获得新的思维模型。&lt;/p&gt;
&lt;h3 id="人工智能和编码之间的复杂性"&gt;人工智能和编码之间的复杂性
&lt;/h3&gt;&lt;p&gt;另一件不容忽视的事情是通过生成式人工智能改变开发体验。
Copilot 建议更多代码，ChatGPT 在几秒钟内编写复杂的正则表达式。人工智能已经超越了“有用的工具”的范畴，而成为结对编程的伙伴。
我突然在半夜里想到，未来前端工程师的要求将从从头开始编写代码的能力转变为审查AI输出和设计整体架构的能力。&lt;/p&gt;
&lt;h3 id="持续学习的乐趣"&gt;持续学习的乐趣
&lt;/h3&gt;&lt;p&gt;人们常说前端技术的部署太快了。我能理解那种疲惫不堪并想着“新框架又出来了”的感觉。
然而，如果你从不同的角度来看，没有比这个更无聊的游乐场了。每年我们都会出现一个新玩具，世界各地的天才们都会争论是否有更好的方法。&lt;/p&gt;
&lt;p&gt;以昆虫的声音作为背景音乐，我尝试遵循有关我以前从未使用过的工具的教程。拥有这样一个秋夜，岂不是很美好吗？相信明天的你会变得更好一点。&lt;/p&gt;</description></item><item><title>实现安全身份验证功能：NextAuth.js 简介</title><link>https://netguide.jp/zh/posts/%E5%AE%9E%E7%8E%B0%E5%AE%89%E5%85%A8%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E5%8A%9F%E8%83%BDnextauth.js-%E7%AE%80%E4%BB%8B/</link><pubDate>Fri, 28 Aug 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E5%AE%9E%E7%8E%B0%E5%AE%89%E5%85%A8%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E5%8A%9F%E8%83%BDnextauth.js-%E7%AE%80%E4%BB%8B/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/secure-authentication-nextauth-js-zh.png" alt="Featured image of post 实现安全身份验证功能：NextAuth.js 简介" /&gt;&lt;p&gt;在开发Web应用程序时，不可避免的一件事就是“身份验证功能”的实现。
然而，从头开始自己实现密码哈希、会话管理、CSRF 对策、OAuth 集成等会带来很高的安全风险，并且需要大量的开发成本。&lt;/p&gt;
&lt;p&gt;因此，这次我们将介绍一些使用“NextAuth.js”（目前为 Auth.js）实现安全身份验证的最佳实践，它是 Next.js 环境中身份验证的事实标准。&lt;/p&gt;
&lt;h3 id="最佳实践-1基本上优先考虑-oauth社交登录"&gt;最佳实践 1：基本上优先考虑 OAuth（社交登录）
&lt;/h3&gt;&lt;p&gt;管理自己的密码意味着您面临信息泄露的风险。
使用 NextAuth.js 时，首先考虑引入社交登录（OAuth 提供商），例如 Google 或 GitHub。设置提供程序非常简单，只需在配置文件中写入客户端 ID 和 Secret 并添加几行代码即可创建强大的身份验证系统。也省去了用户记住密码的麻烦，有利于提高注册率。&lt;/p&gt;
&lt;h3 id="最佳实践2jwt和数据库会话的区别使用"&gt;最佳实践2：JWT和数据库会话的区别使用
&lt;/h3&gt;&lt;p&gt;使用 NextAuth.js，您可以选择两种类型的会话保留方法：“JWT（JSON Web 令牌）”和“数据库会话”。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;JWT 的优点：&lt;/strong&gt; 无需数据库查询，从而实现更快的响应时间和更轻松的扩展。默认情况下建议这样做。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据库会话的优点：&lt;/strong&gt; 会话可以轻松地立即失效（例如，管理员强制特定用户注销）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;根据您的要求进行设计，例如需要高安全控制的业务系统的数据库会话，以及面向性能的消费应用程序的 JWT。&lt;/p&gt;
&lt;h3 id="最佳实践-3使用中间件确保路由保护"&gt;最佳实践 3：使用中间件确保路由保护
&lt;/h3&gt;&lt;p&gt;通过将 NextAuth.js 与 Next.js 12 及更高版本中引入的中间件功能相结合，您可以坚决阻止对特定页面（例如“/dashboard/*”）的未经授权的访问。
在组件内使用“useSession”进行重定向的传统方法存在瞬时屏幕闪烁 (FOUC) 的问题，但通过使用在边缘端运行的中间件，可以在用户看到登录屏幕之前无缝重定向到登录屏幕。&lt;/p&gt;
&lt;h3 id="最佳实践-4严格管理密钥"&gt;最佳实践 4：严格管理密钥
&lt;/h3&gt;&lt;p&gt;要在生产环境中运行 NextAuth.js，需要设置环境变量“NEXTAUTH_SECRET”。
这是用于加密令牌的最重要的密钥，如果它被泄露，将直接导致重大漏洞。请确保您的团队在部署环境（例如Vercel）的环境变量设置屏幕上安全地管理环境变量，并且永远不要将它们提交到源代码（Git）。&lt;/p&gt;
&lt;p&gt;避免重新发明轮子，并将身份验证的负担留给受信任的库。这是现代安全网络开发的黄金法则。&lt;/p&gt;</description></item><item><title>React Server 组件的工作原理和使用示例</title><link>https://netguide.jp/zh/posts/react-server-%E7%BB%84%E4%BB%B6%E7%9A%84%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E5%92%8C%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B/</link><pubDate>Sat, 22 Aug 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/react-server-%E7%BB%84%E4%BB%B6%E7%9A%84%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E5%92%8C%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/react-server-components-mechanism-use-cases-zh.png" alt="Featured image of post React Server 组件的工作原理和使用示例" /&gt;&lt;p&gt;React Server Components (RSC) 正在彻底改变前端架构。您可能听说过这个名字，但是您是否确切知道它与SSR（服务器端渲染）有何不同以及幕后进行了什么样的处理？
在本文中，我们将深入探讨其技术机制并考虑其实际使用的示例。&lt;/p&gt;
&lt;h3 id="与-ssr-的决定性区别"&gt;与 SSR 的决定性区别
&lt;/h3&gt;&lt;p&gt;传统的SSR是一种在初始加载期间在服务器端生成HTML并将其返回给浏览器的技术。但随后浏览器必须加载 JavaScript 并重新运行（水合）该组件以使其具有交互性。换句话说，组件代码本身最终被下载到浏览器。&lt;/p&gt;
&lt;p&gt;另一方面，RSC 是一个仅在服务器上运行且从不发送到浏览器的组件。
RSC经过服务器处理后，会被序列化为特殊的类似JSON的格式而不是HTML，然后发送到客户端。浏览器端只是接收这些数据并将其反映在 DOM 中。&lt;/p&gt;
&lt;h3 id="捆绑包大小大幅减小"&gt;捆绑包大小大幅减小
&lt;/h3&gt;&lt;p&gt;这种机制的最大好处是减少了发送到客户端的 JavaScript 包的大小。
例如，假设您想使用一个重型库（例如“marked”）将 markdown 转换为 HTML。如果您使用 RSC 实现此功能，则所有解析都在服务器上完成，因此不会将繁重的库代码下载到用户的浏览器。这是移动环境性能的革命性改进。&lt;/p&gt;
&lt;h3 id="客户端边界设计是关键"&gt;客户端边界设计是关键。
&lt;/h3&gt;&lt;p&gt;使用 RSC 时最麻烦的事情是设计服务器和客户端组件之间的边界。
由于 RSC 在服务器上运行，因此它不能具有事件处理程序，例如“onClick”或状态管理（“useState”）。只有需要它们的最终组件（按钮和输入表单）才应该成为客户端组件。&lt;/p&gt;
&lt;p&gt;需要一种树形结构设计理念，其中“数据采集和繁重处理在树的上层（服务器）进行，只有需要用户操作的叶子部分作为客户端。”&lt;/p&gt;
&lt;h3 id="实际使用示例"&gt;实际使用示例
&lt;/h3&gt;&lt;p&gt;在实践中，RSC 在以下用例中表现最为出色：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;博客和媒体文章展示：&lt;/strong&gt; 与上面提到的Markdown转换一样，RSC在渲染静态内容方面是独一无二的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;直接数据库访问：&lt;/strong&gt; 由于RSC 是服务器环境，因此您可以安全地将查询直接发送到数据库。由于可以省略一层API，因此可以节省开发工作量。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;专注于 SEO 的登陆页面：&lt;/strong&gt; 快速初始加载，无需额外的 JS，这会直接提高您的 Core Web Vitals 分数。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;RSC 并不是要取代现有的 React，而是澄清客户端和服务器之间“角色分工”的新武器。正确理解这一机制并将其适当地融入到设计中将是未来前端开发的关键。&lt;/p&gt;</description></item><item><title>通过 Vercel 进行自动化部署并利用预览环境</title><link>https://netguide.jp/zh/posts/%E9%80%9A%E8%BF%87-vercel-%E8%BF%9B%E8%A1%8C%E8%87%AA%E5%8A%A8%E5%8C%96%E9%83%A8%E7%BD%B2%E5%B9%B6%E5%88%A9%E7%94%A8%E9%A2%84%E8%A7%88%E7%8E%AF%E5%A2%83/</link><pubDate>Sun, 16 Aug 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E9%80%9A%E8%BF%87-vercel-%E8%BF%9B%E8%A1%8C%E8%87%AA%E5%8A%A8%E5%8C%96%E9%83%A8%E7%BD%B2%E5%B9%B6%E5%88%A9%E7%94%A8%E9%A2%84%E8%A7%88%E7%8E%AF%E5%A2%83/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/vercel-automated-deployment-preview-environments-zh.png" alt="Featured image of post 通过 Vercel 进行自动化部署并利用预览环境" /&gt;&lt;p&gt;“〇〇先生，现在已经实现完成了，能否将分支拉到您当地的环境中看看是否有效？”
你是否因为这样的互动而浪费了团队发展的时间？设置环境的麻烦和本地构建的等待时间大大降低了整个团队的生产力。&lt;/p&gt;
&lt;p&gt;Vercel 的自动化部署和预览环境完美地解决了这个问题，并引发了前端开发工作流程的范式转变。&lt;/p&gt;
&lt;p&gt;###预览网址打破审核瓶颈&lt;/p&gt;
&lt;p&gt;当您将 Vercel 与 GitHub 等存储库集成时，将会有一种神奇的体验。
当开发人员实现新功能并创建拉取请求 (PR) 时，Vercel 会自动为该分支构建代码，并发出一个临时“预览 URL”，其配置与生产中的配置完全相同。&lt;/p&gt;
&lt;p&gt;这消除了审阅者在本地删除代码的需要。只需点击 PR 中评论的 URL，您就可以立即在浏览器中检查实际行为、动画、损坏的响应式设计等。&lt;/p&gt;
&lt;h3 id="加速与非工程师的协作"&gt;加速与非工程师的协作
&lt;/h3&gt;&lt;p&gt;工程师并不是唯一从预览环境中受益的人。
即使是没有开发环境的人，例如设计师和产品经理，也可以通过简单地分享消息“请看一下这个 URL”来接收实施反馈。&lt;/p&gt;
&lt;p&gt;这极大地加速了敏捷开发过程，让您能够在开发的早期阶段快速发现并纠正返工，例如“按钮的颜色有点不同”或“动画不是您所期望的”。&lt;/p&gt;
&lt;h3 id="vercel-评论的上下文反馈"&gt;Vercel 评论的上下文反馈
&lt;/h3&gt;&lt;p&gt;更强大的是直接在预览环境中留下评论的能力。
审阅者可以单击预览屏幕上的任何元素（例如，稍微偏离中心的按钮）并直接在那里留下评论，说：“请将此处的边距扩大一点。”这些评论链接到 Slack 和 GitHub，让开发人员可以通过上下文立即了解“评论指向屏幕的哪个部分”。&lt;/p&gt;
&lt;h3 id="创建团队节奏的基础设施"&gt;创建团队“节奏”的基础设施
&lt;/h3&gt;&lt;p&gt;Vercel 的吸引力不仅仅在于托管速度。
真正的价值在于它可以让团队适应一种优美、无摩擦的开发节奏：“编写代码”→“发布 PR”→“通过 URL 获取确认”→“合并到生产（自动部署）”。&lt;/p&gt;
&lt;p&gt;如果您的团队仍然手动将文件上传到服务器或在本地进行繁琐的审核，请考虑立即实施 Vercel。您会注意到沟通质量的变化和团队士气的提高。&lt;/p&gt;</description></item><item><title>GraphQL 基础知识和 REST API 之间的差异</title><link>https://netguide.jp/zh/posts/graphql-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%92%8C-rest-api-%E4%B9%8B%E9%97%B4%E7%9A%84%E5%B7%AE%E5%BC%82/</link><pubDate>Tue, 11 Aug 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/graphql-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%92%8C-rest-api-%E4%B9%8B%E9%97%B4%E7%9A%84%E5%B7%AE%E5%BC%82/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/graphql-basics-differences-rest-api-zh.png" alt="Featured image of post GraphQL 基础知识和 REST API 之间的差异" /&gt;&lt;p&gt;“REST API”作为API设计方法早已成为行业标准。然而，近年来，随着前端变得越来越复杂，越来越多的公司开始采用 GraphQL。
在讨论技术细节之前，我们首先以在餐厅点餐为例来思考一下两者之间的区别。&lt;/p&gt;
&lt;h3 id="rest-api-在餐厅中的局限性"&gt;REST API 在餐厅中的局限性
&lt;/h3&gt;&lt;p&gt;REST API 就像一个“美食广场”，每个菜单都有不同的柜台。
例如，假设您想订购一份汉堡包套餐。您必须首先前往汉堡柜台（&lt;code&gt;/api/burgers/1&lt;/code&gt;），然后前往土豆柜台（&lt;code&gt;/api/sides/potato&lt;/code&gt;），最后前往饮料柜台（&lt;code&gt;/api/drinks/coke&lt;/code&gt;）。&lt;/p&gt;
&lt;p&gt;这就需要多次来回柜台（多次请求）的麻烦。此外，即使你想把汉堡中的泡菜去掉，柜台也会给你带有泡菜的成品。这是一个称为“过度获取”的问题，即检索不必要的数据。&lt;/p&gt;
&lt;h3 id="名为-graphql-的终极定制"&gt;名为 GraphQL 的终极定制
&lt;/h3&gt;&lt;p&gt;另一方面，GraphQL 是“非常能干的私人服务员”。
你递给服务员一份订单（查询），上面写着“汉堡（不含泡菜）、小份薯条和可乐”。然后服务员去厨房，把你指定的东西端到一个托盘上。&lt;/p&gt;
&lt;p&gt;这是GraphQL最大的特点。前端（客户）可以准确指定他们想要什么数据以及以什么形式，后端将相应地返回准确的数据量。&lt;/p&gt;
&lt;h3 id="graphql-的好处和实施障碍"&gt;GraphQL 的好处和实施障碍
&lt;/h3&gt;&lt;p&gt;该机制具有以下优点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;减少通信量：&lt;/strong&gt; 在智能手机等移动环境中，不获取不必要的数据可以显着提高性能。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;灵活的UI更改：&lt;/strong&gt; 即使您想向屏幕添加新的显示项，也不需要像REST中那样让后端创建新的端点，只需重写前端查询即可完成。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;另一方面，它不是一根魔杖。
还有诸如“缓存难以控制”、“容易出现N+1问题”、“后端实现变得更加困难”等问题。对于简单的博客网站，REST API往往更简单、更合适。&lt;/p&gt;
&lt;h3 id="你应该选择哪一个"&gt;你应该选择哪一个？
&lt;/h3&gt;&lt;p&gt;GraphQL 是开发在单个屏幕上显示多种类型资源（用户信息、帖子、评论、点赞等）的复杂 Web 应用程序的最佳选择。
确定您的“餐厅”收到最多的订单类型并选择合适的架构。&lt;/p&gt;</description></item><item><title>Web 性能优化的最佳实践</title><link>https://netguide.jp/zh/posts/web-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/</link><pubDate>Wed, 05 Aug 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/web-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/web-performance-optimization-best-practices-zh.png" alt="Featured image of post Web 性能优化的最佳实践" /&gt;&lt;p&gt;网站显示速度是一个非常重要的因素，直接关系到用户放弃率和SEO。
然而，当谈到性能优化时，过去的常识“就这样做”实际上可能在现代浏览器环境中产生相反的效果。&lt;/p&gt;
&lt;p&gt;在这里，我们将揭穿常见的性能改进神话并探索真正的最佳实践。&lt;/p&gt;
&lt;h3 id="误区-1所有图像都应该延迟加载"&gt;误区 1：“所有图像都应该延迟加载”
&lt;/h3&gt;&lt;p&gt;很容易误解，如果你的图像很重，添加 &lt;code&gt;loading=&amp;quot;lazy&amp;quot; 会让它们变得更快。 虽然它对于离屏图像肯定有效，但将延迟加载应用于第一个视图（打开页面时看到的第一个区域）中的图像是一个很大的错误。 浏览器推迟了这一过程，导致 LCP（最大内容绘制）显着恶化。正确的答案是优先加载第一视图图像（考虑&lt;/code&gt;fetchpriority =“high”`）。&lt;/p&gt;
&lt;h3 id="误解-2只需缩小-css-和-js-就可以了"&gt;误解 2：“只需缩小 CSS 和 JS 就可以了。”
&lt;/h3&gt;&lt;p&gt;压缩代码当然是必要的，但这还不够。
问题是，“您是否正在加载当前未使用的代码？”在现代方法中，“代码拆分”很重要，它会拆分并仅加载每个屏幕所需的 CSS/JS。简单地删除不必要的第三方脚本（例如未使用的聊天工具和跟踪标签）通常可以带来显着的改进。&lt;/p&gt;
&lt;h3 id="误区-3google-lighthouse-得分-100-分就完美了"&gt;误区 3：“Google Lighthouse 得分 100 分就完美了。”
&lt;/h3&gt;&lt;p&gt;Lighthouse 的分数是一个很好的指标，但它只是您的 PC 和网络环境的模拟结果。
真实用户可能通过旧智能手机或不可靠的地铁线路访问它。 Core Web Vitals 的真正目的是“衡量实际用户体验”，称为 RUM（真实用户监控）。重要的是要定期使用 Google Search Console 等工具检查实际的现场数据，而不是仅仅依赖 Lighthouse 分数。&lt;/p&gt;
&lt;h3 id="持续监控的重要性"&gt;持续监控的重要性
&lt;/h3&gt;&lt;p&gt;性能优化不是“设置好后就忘记”的任务。
当您添加更多功能时，您的网站会变得有点重。最终的最佳实践是将性能测试纳入 CI/CD 管道中，并创建一个“防止恶化的系统”，在创建 PR 时检测分数下降。&lt;/p&gt;
&lt;p&gt;让我们更新旧知识，为用户提供真正舒适的网络体验。&lt;/p&gt;</description></item><item><title>使用Supabase构建后端简介</title><link>https://netguide.jp/zh/posts/%E4%BD%BF%E7%94%A8supabase%E6%9E%84%E5%BB%BA%E5%90%8E%E7%AB%AF%E7%AE%80%E4%BB%8B/</link><pubDate>Fri, 31 Jul 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E4%BD%BF%E7%94%A8supabase%E6%9E%84%E5%BB%BA%E5%90%8E%E7%AB%AF%E7%AE%80%E4%BB%8B/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/backend-development-with-supabase-zh.png" alt="Featured image of post 使用Supabase构建后端简介" /&gt;&lt;h2 id="前端工程师的救星"&gt;前端工程师的救星？
&lt;/h2&gt;&lt;p&gt;“构建后端非常耗时，因此很难制作应用程序原型。”
近年来，“Supabase”迅速获得了有此类担忧的开发商的支持。它经常被认为是 Firebase 的替代品，但到底有什么区别呢？&lt;/p&gt;
&lt;p&gt;我们以问答的形式总结了常见问题。&lt;/p&gt;
&lt;h3 id="q1supabase-是什么"&gt;Q1：Supabase 是什么？
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;答：&lt;/strong&gt; 它是一个开源的“BaaS（后端即服务）”。基于PostgreSQL，您可以非常轻松地将后端所需的全套功能（例如数据库、认证功能、存储和实时监听器）合并到您的项目中。&lt;/p&gt;
&lt;h3 id="q2与现有服务firebase等有什么区别"&gt;Q2：与现有服务（Firebase等）有什么区别？
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;A:&lt;/strong&gt; 最大的区别是我们使用关系数据库（RDB）。 NoSQL（例如 Firebase 的 Firestore）很有用，但如果您想使用 SQL 关联复杂数据或执行高级聚合，基于 PostgreSQL 的 Supabase 将是一个非常强大的盟友。&lt;/p&gt;
&lt;h3 id="q3适合什么样的项目"&gt;Q3：适合什么样的项目？
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;答：&lt;/strong&gt; 个人发展和初创 MVP 发展的理想选择。特别兼容React、Next.js等现代前端框架，只需加载SDK，几行代码即可完成数据读写和用户认证。&lt;/p&gt;
&lt;h2 id="实际实施后我注意到了什么"&gt;实际实施后我注意到了什么
&lt;/h2&gt;&lt;p&gt;我自己在多个项目中使用过 Supabase，仪表板的直观性给我留下了深刻的印象。您可以直接从浏览器创建表、指定列数据类型，甚至设置称为行级安全性 (RLS) 的安全规则。&lt;/p&gt;
&lt;p&gt;由于前端可以直接安全地访问数据库，而无需创建 API 端点，因此开发速度提高了一倍以上。&lt;/p&gt;
&lt;h3 id="这里要小心"&gt;这里要小心
&lt;/h3&gt;&lt;p&gt;然而，这并不能完全消除对后端知识的需求。
如果数据库设计（规范化等）出现错误，后期将很难维护数据完整性，而如果RLS设置出现错误，则存在信息泄露的风险。您至少需要学习 SQL 基础知识和关系数据库的设计理念。&lt;/p&gt;
&lt;h2 id="未来展望"&gt;未来展望
&lt;/h2&gt;&lt;p&gt;Supabase 仍在积极开发中，Edge Functions（无服务器功能）等新功能正在陆续添加。毫无疑问，它不仅会演变成“数据库的替代品”，而且会演变成一个全栈应用平台。&lt;/p&gt;
&lt;p&gt;如果您还没有尝试过，请在周末花几个小时尝试一下教程。您一定会爱上它舒适的开发体验。&lt;/p&gt;</description></item><item><title>如何比较和选择无头 CMS</title><link>https://netguide.jp/zh/posts/%E5%A6%82%E4%BD%95%E6%AF%94%E8%BE%83%E5%92%8C%E9%80%89%E6%8B%A9%E6%97%A0%E5%A4%B4-cms/</link><pubDate>Sat, 25 Jul 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E5%A6%82%E4%BD%95%E6%AF%94%E8%BE%83%E5%92%8C%E9%80%89%E6%8B%A9%E6%97%A0%E5%A4%B4-cms/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/headless-cms-comparison-guide-zh.png" alt="Featured image of post 如何比较和选择无头 CMS" /&gt;&lt;p&gt;将前端和后端（管理屏幕）分开的“无头 CMS”架构已在现代 Web 生产中牢固确立。
然而，在介绍时，有“Contentful”、“microCMS”、“Strapi”等多种选项，很多人都困惑该选择哪一个。&lt;/p&gt;
&lt;p&gt;在本文中，我们将建议如何根据您的项目的特点和情况选择最合适的 Headless CMS。&lt;/p&gt;
&lt;p&gt;###情况一：如果你看重国货的安全性和易用性&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;推荐：microCMS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;“如果管理屏幕是英文的，客户的负责人就无法更新。”
MicroCMS 是日本制造的领先无头 CMS，可以立即解决这个在合同生产中常见的问题。
管理界面的UI非常精致，即使IT素养不高的用户也能直观地提交文章。另外，日语官方文档丰富，支持系统完善。如果您有一个企业网站或一个中小型媒体网站，您一定应该毫不犹豫地选择这个。&lt;/p&gt;
&lt;h3 id="情况2在全球企业领域"&gt;情况2：在全球企业领域
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;推荐：内容丰富&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;对于需要多语言部署、广泛的内容版本控制和复杂的审批流程的大型项目，Contentful 是您的行业先锋。
它具有高度可扩展性，并具有广泛的插件，可与各种第三方工具（翻译工具、DAM 等）链接。但需要注意的是，由于其功能丰富，学习成本较高，且定价结构面向大规模用户。&lt;/p&gt;
&lt;h3 id="情况-3如果您想完全控制您的数据"&gt;情况 3：如果您想完全控制您的数据
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;推荐：斯特拉皮&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SaaS类型的CMS无法满足您的安全需求，或者您希望将来添加自己的后端处理。在这种情况下，开源且可以托管在您自己的服务器（或 AWS 等）上的 Strapi 是一个候选者。
它运行在 Node.js 上，并且可以轻松定制 API。尽管管理基础设施需要时间和精力，但您可以在自由和数据所有权方面获得巨大的好处。&lt;/p&gt;
&lt;h3 id="引入的决定因素是谁会使用它"&gt;引入的决定因素是“谁会使用它？”
&lt;/h3&gt;&lt;p&gt;选择无头CMS时最重要的是不仅要有开发人员的视角，还要有实际更新文章的运营者的视角。
无论API响应多快，如果提交界面难以使用，内容就不会更新。首先，我们首先使用免费计划，并让操作员触摸实际的管理屏幕，看看它是否适合。&lt;/p&gt;</description></item><item><title>使用 Tailwind CSS 进行高效 U​​I 开发</title><link>https://netguide.jp/zh/posts/%E4%BD%BF%E7%94%A8-tailwind-css-%E8%BF%9B%E8%A1%8C%E9%AB%98%E6%95%88-ui-%E5%BC%80%E5%8F%91/</link><pubDate>Mon, 20 Jul 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E4%BD%BF%E7%94%A8-tailwind-css-%E8%BF%9B%E8%A1%8C%E9%AB%98%E6%95%88-ui-%E5%BC%80%E5%8F%91/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/efficient-ui-development-tailwind-css-zh.png" alt="Featured image of post 使用 Tailwind CSS 进行高效 U​​I 开发" /&gt;&lt;p&gt;直到几年前，当涉及到前端样式时，通常的做法是根据 BEM 等命名约定提出唯一的类名称，并通过往返 CSS 文件来创建设计。
但现在，“Tailwind CSS”的出现彻底改变了这种情况。为什么实用优先的理念吸引了如此多的开发商？&lt;/p&gt;
&lt;p&gt;这次，对于那些正在考虑实施Tailwind CSS的人，我们将彻底分析它的优点和缺点。&lt;/p&gt;
&lt;h3 id="好处1免去对类名的深切担忧"&gt;好处1：免去对类名的深切担忧
&lt;/h3&gt;&lt;p&gt;“我们应该为这个按钮的包装元素命名什么&amp;hellip;&amp;hellip;‘button-container’？‘action-wrapper’？”
你是否曾经因为这些无用的想法而浪费过时间？ Tailwind 将简短的预定义实用程序类（“flex”、“p-4”、“text-center”等）直接添加到 HTML 中，完全消除了命名类的心理负担。&lt;/p&gt;
&lt;h3 id="好处-2消除上下文切换"&gt;好处 2：消除上下文切换
&lt;/h3&gt;&lt;p&gt;在传统开发中，不可避免地要在编写 HTML（或 JSX）、打开 CSS 文件和返回 HTML 之间来回切换。
Tailwind 直接在标记中编写样式，减少了眼球移动和文件导航，让您可以在不中断思考的情况下组装组件。这比你想象的更快的开发速度。&lt;/p&gt;
&lt;h3 id="缺点-1html-看起来脏"&gt;缺点 1：HTML 看起来“脏”
&lt;/h3&gt;&lt;p&gt;Tailwind 的一个常见批评是 HTML 类属性变得太长，降低了可读性。
确实，一个复杂的组件有几十个类，乍一看很难理解发生了什么。为了避免这种情况，React和Vue等框架需要划分为组件单元，并进行设计以防止单个文件变得太大。&lt;/p&gt;
&lt;h3 id="缺点2很难获得独特的css知识"&gt;缺点2：很难获得独特的CSS知识
&lt;/h3&gt;&lt;p&gt;因为我们过于依赖方便的实用程序类，所以我们往往忽略了对底层原始 CSS（Flexbox 规范、Grid 机制等）的理解。如果您不理解和使用 Tailwind 的类名（它们所映射到的 CSS 属性），您在创建自己的复杂动画和布局时可能会陷入困境。&lt;/p&gt;
&lt;h3 id="项目适宜性诊断"&gt;项目适宜性诊断
&lt;/h3&gt;&lt;p&gt;那么，Tailwind CSS适合什么样的项目呢？
总之，任何使用面向组件的现代框架（例如 React/Next.js/Vue/Nuxt）的项目几乎肯定会受益。另一方面，如果您有一个仅使用旧的 HTML 文件构建的静态站点，或者一个没有重用组件概念的环境，则结果可能只是更长的代码。&lt;/p&gt;
&lt;p&gt;了解优势和劣势，并在正确的地方使用这个强大的武器。&lt;/p&gt;</description></item><item><title>使用 TypeScript 构建强大的 Web 应用程序</title><link>https://netguide.jp/zh/posts/%E4%BD%BF%E7%94%A8-typescript-%E6%9E%84%E5%BB%BA%E5%BC%BA%E5%A4%A7%E7%9A%84-web-%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F/</link><pubDate>Tue, 14 Jul 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/%E4%BD%BF%E7%94%A8-typescript-%E6%9E%84%E5%BB%BA%E5%BC%BA%E5%A4%A7%E7%9A%84-web-%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/building-robust-web-apps-with-typescript-zh.png" alt="Featured image of post 使用 TypeScript 构建强大的 Web 应用程序" /&gt;&lt;p&gt;JavaScript 是一种非常灵活且易于编写的语言，但其灵活性有时会在大规模开发过程中导致意想不到的错误。
“我将一个数字传递给了一个需要字符串的函数”或“我从 API 响应中访问了一个不存在的属性”——每个人都至少经历过一次这些错误。&lt;/p&gt;
&lt;p&gt;在本文中，我们将使用问题与解决方案的方法来理解为什么 TypeScript 对于现代 Web 应用程序开发至关重要。&lt;/p&gt;
&lt;h3 id="挑战担心在执行之前不知道错误"&gt;挑战：担心在执行之前不知道错误
&lt;/h3&gt;&lt;p&gt;用纯 JavaScript 编写的应用程序的最大弱点是代码中的错误只能在运行时发现。
除非您实际单击浏览器中的按钮或转到特定屏幕，否则您不会注意到该错误。这会导致开发过程风险极高，只有通过 QA 团队的测试遗漏或用户的缺陷报告才能发现错误。&lt;/p&gt;
&lt;p&gt;###解决方案：称为“类型”的强大装甲&lt;/p&gt;
&lt;p&gt;通过引入 TypeScript，这个问题将得到显着改善。
TypeScript 将“静态类型”的概念引入了 JavaScript。可以为变量、函数参数和返回值建立规则（类型），例如“这是一个字符串”或“这是一个具有特定结构的对象”。&lt;/p&gt;
&lt;p&gt;这允许编辑器警告您，当您编写代码或构建代码时，您在此处传递的值是不同类型的。这意味着许多错误可以在发生之前预防。&lt;/p&gt;
&lt;p&gt;###挑战：介绍学习成本和描述量&lt;/p&gt;
&lt;p&gt;然而，有很多职场对于引入它犹豫不决，因为类型定义写起来麻烦，学习成本高。
诚然，一开始您可能会对“接口”、“类型”定义和泛型等不熟悉的概念感到困惑。编写的代码量也会暂时增加。&lt;/p&gt;
&lt;h3 id="解决方案压倒性的编辑器互补性和中长期生产力"&gt;解决方案：压倒性的编辑器互补性和中长期生产力
&lt;/h3&gt;&lt;p&gt;然而，最初的投资可以很快收回。
TypeScript 与 VS Code 等现代编辑器具有很好的兼容性。定义类型允许编辑器完美地推断对象具有哪些属性，并提供强大的自动完成功能。&lt;/p&gt;
&lt;p&gt;一旦您体验到只需按一个点即可建议下一个条目，而无需特意查看文档或规范，您将永远不会回头。即使在团队开发中，也可以安全地调用其他人编写的函数，从而降低沟通成本并提高开发速度。&lt;/p&gt;
&lt;h3 id="而不是摘要"&gt;而不是摘要
&lt;/h3&gt;&lt;p&gt;起初，您可能会觉得自己被迫遵守复杂的规则。然而，TypeScript 的类型系统并不约束开发人员；它是保护开发者免受 bug 恐惧的“盾牌”。
如果您想创建健壮且持久的 Web 应用程序，请尝试使用 TypeScript。&lt;/p&gt;</description></item><item><title>Next.js App Router 基础知识和好处介绍</title><link>https://netguide.jp/zh/posts/next.js-app-router-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%92%8C%E5%A5%BD%E5%A4%84%E4%BB%8B%E7%BB%8D/</link><pubDate>Thu, 09 Jul 2026 00:00:00 +0900</pubDate><guid>https://netguide.jp/zh/posts/next.js-app-router-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E5%92%8C%E5%A5%BD%E5%A4%84%E4%BB%8B%E7%BB%8D/</guid><description>&lt;img src="https://netguide.jp/img/thumbnail/nextjs-app-router-basics-benefits-zh.png" alt="Featured image of post Next.js App Router 基础知识和好处介绍" /&gt;&lt;p&gt;“App Router”在 Next.js 13 中引入，现已成为标准。这个概念与之前的 Pages Router 相比发生了很大的变化，因此有些人可能仍然对迁移犹豫不决。
本文提供了了解 App Router 基础知识的分步指南。&lt;/p&gt;
&lt;h3 id="第-1-步了解目录结构的差异"&gt;第 1 步：了解目录结构的差异
&lt;/h3&gt;&lt;p&gt;在之前的 Pages Router 中，“pages”目录中的文件名被用作 URL 路由（例如，“pages/about.tsx”→“/about”）。&lt;/p&gt;
&lt;p&gt;App Router 使用“app”目录。 URL 路由由文件夹名称确定，并且规则已更改为始终将名为“page.tsx”的文件放置在该文件夹中（例如“app/about/page.tsx”→“/about”）。
虽然乍一看这似乎很麻烦，但它有一个很大的优点，可以让与路由无关的组件和测试文件共存于同一个文件夹中。&lt;/p&gt;
&lt;h3 id="第-2-步理解布局概念"&gt;第 2 步：理解布局概念
&lt;/h3&gt;&lt;p&gt;App Router 的一个强大功能是“布局”。
创建 &lt;code&gt;app/layout.tsx&lt;/code&gt; 允许您将通用 UI（页眉、页脚等）应用到该文件夹​​下的所有页面。
值得注意的是，这个Layout部分在页面转换时并没有重新渲染。这样可以在保留状态的同时实现平滑的屏幕转换，从而极大地提高应用程序性能。&lt;/p&gt;
&lt;h3 id="步骤-3在服务器和客户端之间划清界限"&gt;步骤 3：在服务器和客户端之间划清界限
&lt;/h3&gt;&lt;p&gt;这是最重要的变化。 App Router 中的组件默认为 React Server Components（在服务器端运行的组件）。
您不能在服务器组件内使用浏览器 API（例如“window”）或 React hook（例如“useState”和“useEffect”）。&lt;/p&gt;
&lt;p&gt;如果需要按钮单击事件等，则需要通过在文件顶部写入“use client”来显式将其转换为客户端组件。
App Router 成功的关键是要记住“基本上，服务器执行一些轻微渲染，只有交互部分留给客户端。”&lt;/p&gt;
&lt;h3 id="步骤-4简化数据获取"&gt;步骤 4：简化数据获取
&lt;/h3&gt;&lt;p&gt;以前所需的 Next.js 特定函数（例如“getServerSideProps”和“getStaticProps”）已被弃用。
相反，只需在组件中直接通过“await”使用标准“fetch” API。 Next.js 内部扩展了 fetch ，现在您只需使用 fetch 的可选参数即可直观地控制缓存。&lt;/p&gt;
&lt;p&gt;如果你一步步理解它，App Router 并不可怕。请向更先进、更快的 Web 应用程序开发迈出第一步。&lt;/p&gt;</description></item></channel></rss>