<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>Front End Development｜林鼎淵 Dean Lin</title>
    <link>https://deanlin.net/tags/front-end-development/</link>
    <image><url>https://deanlin.net/images/author_hu_aa256fc934e9a932.jpg</url><title>Front End Development｜林鼎淵 Dean Lin</title><link>https://deanlin.net/tags/front-end-development/</link><width>144</width><height>144</height></image>
    <description>林鼎淵（Dean Lin）的部落格：生成式 AI 企業內訓講師、外商資安公司軟體專家、7 本書作者。400 多篇文章用白話分享生成式 AI 實戰、Claude Code 與 Vibe Coding 教學、團隊合作與職場成長。</description>
    <generator>Hugo</generator>
    <language>zh-tw</language>
    <copyright>© 2020–2026 林鼎淵 Dean Lin</copyright>
    <lastBuildDate>Thu, 19 Jan 2023 10:06:38 +0800</lastBuildDate>
    <atom:link href="https://deanlin.net/tags/front-end-development/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>想幫前端專案導入測試框架？也許我的想法與學習地圖能給你一點方向</title>
      <link>https://deanlin.net/blog/202301/frontend-testing-roadmap/</link>
      <pubDate>Thu, 19 Jan 2023 10:06:38 +0800</pubDate>
      <guid>https://deanlin.net/blog/202301/frontend-testing-roadmap/</guid>
      <dc:creator>林鼎淵</dc:creator>
      <category>技術教學</category>
      <description>筆者自首，過去我只撰寫後端測試，總是忽略前端測試的重要性。 當初會這樣，是因為經手的專案規格變動頻繁，感覺測試寫完沒多久就要棄用；但近期與業界的朋友聊天時，他們跟我強調了 TDD（Test-Driven Development），也就是「測試驅動開發」的概念。</description>
      <media:content url="https://deanlin.net/blog/202301/frontend-testing-roadmap/images/frontend-testing-roadmap-og_hu_e01158bc3b725f5a.jpg" medium="image" type="image/jpeg" width="1200" height="675" />
      <content:encoded><![CDATA[<p><img src="https://deanlin.net/blog/202301/frontend-testing-roadmap/images/frontend-testing-roadmap-01.webp" width="1150" height="602" alt="想幫前端專案導入測試框架？也許我的想法與學習地圖能給你一點方向（圖 1）" fetchpriority="high" decoding="async"></p>
<pre tabindex="0"><code>大綱

一、前端為什麼需要寫測試？
二、寫測試對開發人員有哪些幫助？
三、筆者的學習地圖
</code></pre><h2 id="一前端為什麼需要寫測試">一、前端為什麼需要寫測試？<a class="h-anchor" href="#%e4%b8%80%e5%89%8d%e7%ab%af%e7%82%ba%e4%bb%80%e9%ba%bc%e9%9c%80%e8%a6%81%e5%af%ab%e6%b8%ac%e8%a9%a6" aria-label="這個段落的連結"></a></h2>
<p>筆者自首，過去我只撰寫後端測試，總是忽略前端測試的重要性。</p>
<p>當初會這樣，是因為經手的專案規格變動頻繁，感覺測試寫完沒多久就要棄用；但近期與業界的朋友聊天時，他們跟我強調了 TDD（Test-Driven Development），也就是「測試驅動開發」的概念。</p>
<p>這名詞也不是第一次聽到，但是否對專案有幫助我也是心存懷疑。</p>
<p>針對這個疑問，朋友很認真的回應我，這邊整理概要如下：</p>
<blockquote>
<p>規格之所以會頻繁變更，大多數的原因是前期規劃不良所導致。</p>
<p>有些 PM 甚至沒有技術背景只能當傳聲筒，在這種前提下訂出的規格往往非常模糊。</p>
<p>而工程師面對這種模糊的規格，他有兩條路，一條路是不管那麼多，先開發再說，如果選擇這條路，那日後頻繁的遇到規格變更實屬正常。</p>
<p>而另一條路則是「確定規格後」再開發，我們常常把沒寫測試歸咎於專案時程太緊；但其實在專案完成後做 Review 時，發現很多時候都是在白忙一場。</p>
<p>所以如果能先把模糊的地方定義清楚，並將其納入測試程式，有時反而是在節省時間，要是日後規格有異動時，也方便確認哪一塊需要調整。</p>
</blockquote>
<p>每個人學習新技術的理由不盡相同，但我就是在這次聊天後開始學習的。</p>
<blockquote class="pullquote"><p><em>其實有時候也不是沒時間，只是因為自己不熟悉測試程式，而用其他藉口逃避。</em></p>
</blockquote>
<hr>
<h2 id="二寫測試對開發人員有哪些幫助">二、寫測試對開發人員有哪些幫助？<a class="h-anchor" href="#%e4%ba%8c%e5%af%ab%e6%b8%ac%e8%a9%a6%e5%b0%8d%e9%96%8b%e7%99%bc%e4%ba%ba%e5%93%a1%e6%9c%89%e5%93%aa%e4%ba%9b%e5%b9%ab%e5%8a%a9" aria-label="這個段落的連結"></a></h2>
<p>系統會越來越複雜，公司的同事會來來去去，不管是為了自己還是同事，有測試程式對我們最直接的幫助有：</p>
<ul>
<li><strong>減少人工測試</strong>：如果每次 release 新的版本就要全部手動測試一次，你絕對會崩潰。</li>
<li><strong>減少測試上的遺漏</strong>：如果是人工測試，那就可能有「啊！這功能之前都沒問題，這次就不用測了」的想法，然後上線後就爆了；不過交給機器跑就不會有這個問題。</li>
<li><strong>避免調整程式後，一堆功能壞掉而不自知</strong>：無論是重構程式/新增功能/解決 Bug，你勢必都會動到程式邏輯，很有可能你完成了新功能，但上線後才發現其他相依的功能壞掉了（程式也是有蝴蝶效應的）。</li>
<li><strong>未來的同事（自己）會感謝你</strong>：專案可能上線後一兩年都沒事，但當需要新增/調整功能時，如果維護的人發現前人沒有測試程式，那改程式就跟走鋼索一樣（那個人很可能是自己）。</li>
</ul>
<hr>
<h2 id="三筆者的學習地圖">三、筆者的學習地圖<a class="h-anchor" href="#%e4%b8%89%e7%ad%86%e8%80%85%e7%9a%84%e5%ad%b8%e7%bf%92%e5%9c%b0%e5%9c%96" aria-label="這個段落的連結"></a></h2>
<p>把知識集中在一篇文章會讀得太辛苦，這邊筆者將其規劃成以下主題供大家閱讀。</p>
<h3 id="-認識-jest-測試框架開始動手寫測試程式link">認識 Jest 測試框架，開始動手寫測試程式：<a href="https://deanlin.net/blog/202301/jest-unit-testing-typescript/">link</a><a class="h-anchor" href="#-%e8%aa%8d%e8%ad%98-jest-%e6%b8%ac%e8%a9%a6%e6%a1%86%e6%9e%b6%e9%96%8b%e5%a7%8b%e5%8b%95%e6%89%8b%e5%af%ab%e6%b8%ac%e8%a9%a6%e7%a8%8b%e5%bc%8flink" aria-label="這個段落的連結"></a></h3>
<ul>
<li>初始化專案、設定測試環境</li>
<li>了解單元測試的結構，撰寫程式</li>
<li>了解 Jest 常用的匹配器（Matchers）</li>
</ul>
<h3 id="-jest-框架進階應用describesetup-and-teardownmock-functionlink">Jest 框架進階應用（describe、Setup and Teardown、Mock function）：<a href="https://deanlin.net/blog/202301/jest-advanced-mock-setup-teardown/">link</a><a class="h-anchor" href="#-jest-%e6%a1%86%e6%9e%b6%e9%80%b2%e9%9a%8e%e6%87%89%e7%94%a8describesetup-and-teardownmock-functionlink" aria-label="這個段落的連結"></a></h3>
<ul>
<li>測試分組（describe）</li>
<li>在測試前、後要執行的任務（Setup and Teardown）</li>
<li>用 Mock Function 減少測試時的相依性</li>
<li>VSCode 的 Jest 外掛</li>
</ul>
<h3 id="-在-vuetifyvite--typescript中導入單元測試-unit-testinglink">在 Vuetify（Vite &amp; TypeScript）中導入單元測試 Unit Testing：<a href="https://deanlin.net/blog/202301/vuetify-vite-unit-testing/">link</a><a class="h-anchor" href="#-%e5%9c%a8-vuetifyvite--typescript%e4%b8%ad%e5%b0%8e%e5%85%a5%e5%96%ae%e5%85%83%e6%b8%ac%e8%a9%a6-unit-testinglink" aria-label="這個段落的連結"></a></h3>
<ul>
<li>初始化專案、安裝必要套件</li>
<li>調整專案各項設定檔，讓單元測試可以運行</li>
<li>撰寫第一隻測試程式</li>
<li>運行測試程式確認結果符合預期</li>
</ul>
<h3 id="-透過實際案例了解在-vuetifyvite--typescript中如何運用-vuetest-utilslink">透過實際案例了解在 Vuetify（Vite &amp; TypeScript）中如何運用 @vue/test-utils：<a href="https://deanlin.net/blog/202301/vue-test-utils-examples/">link</a><a class="h-anchor" href="#-%e9%80%8f%e9%81%8e%e5%af%a6%e9%9a%9b%e6%a1%88%e4%be%8b%e4%ba%86%e8%a7%a3%e5%9c%a8-vuetifyvite--typescript%e4%b8%ad%e5%a6%82%e4%bd%95%e9%81%8b%e7%94%a8-vuetest-utilslink" aria-label="這個段落的連結"></a></h3>
<ul>
<li>從測試的角度來設計頁面規格（以登入頁為範例）</li>
<li>撰寫登入頁程式</li>
<li>從測試案例了解 @vue/test-utils 常用的功能（ex：getComponent、setValue、wrapper.vm、trigger button、Vue Router）</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>6 種不可不知的「console.log」進階應用</title>
      <link>https://deanlin.net/blog/202209/advanced-console-log/</link>
      <pubDate>Fri, 09 Sep 2022 14:54:09 +0800</pubDate>
      <guid>https://deanlin.net/blog/202209/advanced-console-log/</guid>
      <dc:creator>林鼎淵</dc:creator>
      <category>技術教學</category>
      <description>相信 console.log 是 Frontend 開發人員的好朋友，我們用它印出各種輔助資訊來解決問題。這邊文章會跟你分享 6 種 console.log 的進階應用，並說明各自的使用情境，讓你在開發路上更加順利。</description>
      <media:content url="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-og_hu_5f2789370e8389b.jpg" medium="image" type="image/jpeg" width="1200" height="675" />
      <content:encoded><![CDATA[<p>相信 console.log 是 Frontend 開發人員的好朋友，我們用它印出各種輔助資訊來解決問題。</p>
<p>這邊文章會跟你分享 6 種 console.log 的進階應用，並說明各自的使用情境，讓你在開發的路上更加順利。</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-01.webp" width="1400" height="731" alt="6 種不可不知的「console.log」進階應用（圖 1）" fetchpriority="high" decoding="async"></p>
<blockquote>
<p>大家可以在瀏覽器按下「F12」，於 Console 的分頁貼上文中的程式碼來驗證喔！</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>大鋼
</span></span><span style="display:flex;"><span>ㄧ<span style="color:#f85149">、</span>在 console.log 加入 {}<span style="color:#f85149">，</span>讓資訊顯示的更友善
</span></span><span style="display:flex;"><span>二<span style="color:#f85149">、</span>原來 console.log 竟然可以使用 CSS Style <span style="color:#ff7b72;font-weight:bold">!</span>
</span></span><span style="display:flex;"><span>三<span style="color:#f85149">、</span>console.log 寫太多找不到重點<span style="color:#f85149">？</span>你該試試看 console.warn()<span style="color:#f85149">！</span>
</span></span><span style="display:flex;"><span>四<span style="color:#f85149">、</span>錯誤訊息請用 console.error()<span style="color:#f85149">，</span>不要用 console.log() 來整自己
</span></span><span style="display:flex;"><span>五<span style="color:#f85149">、</span>用 console.time() 追蹤程式執行時間<span style="color:#f85149">，</span>找出效能瓶頸
</span></span><span style="display:flex;"><span>六<span style="color:#f85149">、</span>用 console.table() 將資訊轉成表格來閱讀
</span></span></code></pre></div><h2 id="ㄧ在-consolelog-加入-讓資訊顯示的更友善">ㄧ、在 console.log 加入 {}，讓資訊顯示的更友善<a class="h-anchor" href="#%e3%84%a7%e5%9c%a8-consolelog-%e5%8a%a0%e5%85%a5-%e8%ae%93%e8%b3%87%e8%a8%8a%e9%a1%af%e7%a4%ba%e7%9a%84%e6%9b%b4%e5%8f%8b%e5%96%84" aria-label="這個段落的連結"></a></h2>
<p>如果想要將變數的內容印出來，我們通常會這麼做：</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">const</span> name <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;Dean&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> book <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;給全端工程師的職涯生存筆記&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(name, book);
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/e917d4286b1ccfb52cb27b14a997050f" rel="noopener">console-basic.js</a>（GitHub Gist）</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-02.webp" width="1176" height="286" alt="ㄧ、在 console.log 加入 {}，讓資訊顯示的更友善（圖 2）" loading="lazy" decoding="async"></p>
<p>但這種作法在變數很多的時候，你就會搞不清楚各自對應的關係了，比如：</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">const</span> name <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;Dean&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> book <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;給全端工程師的職涯生存筆記&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> skill <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;Full-Stack&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> type <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;Career&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(name, book, skill, type);
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/e29960572a643720eb49ec7e04d5f706" rel="noopener">console-complex.js</a>（GitHub Gist）</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-03.webp" width="1176" height="390" alt="ㄧ、在 console.log 加入 {}，讓資訊顯示的更友善（圖 3）" loading="lazy" decoding="async"></p>
<p>有沒有覺得上面的資訊閱讀起來很不友善？其實我們只要在 console.log 中，<strong>把這些變數用 {} 包起來</strong>，它就會以物件的類型來顯示嚕！</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">const</span> name <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;Dean&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> book <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;給全端工程師的職涯生存筆記&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> skill <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;Full-Stack&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> type <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;Career&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log({ name, book, skill, type });
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/365d5c816d7aed5bd299e83a9b33378b" rel="noopener">console-object.js</a>（GitHub Gist）</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-04.webp" width="1216" height="764" alt="ㄧ、在 console.log 加入 {}，讓資訊顯示的更友善（圖 4）" loading="lazy" decoding="async"></p>
<hr>
<h2 id="二原來-consolelog-竟然可以使用-css-style-">二、原來 console.log 竟然可以使用 CSS Style !<a class="h-anchor" href="#%e4%ba%8c%e5%8e%9f%e4%be%86-consolelog-%e7%ab%9f%e7%84%b6%e5%8f%af%e4%bb%a5%e4%bd%bf%e7%94%a8-css-style-" aria-label="這個段落的連結"></a></h2>
<p>如果你在 Facebook 的頁面按下「F12」，於 Console 的分頁中應該會看到如下警告：</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-05.webp" width="1400" height="916" alt="二、原來 console.log 竟然可以使用 CSS Style !（圖 5）" loading="lazy" decoding="async"></p>
<p>當時我就很好奇這種特殊的 Style 是怎麼呈現的，後來發現只要在前面加上「%c」就可以了：</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">const</span> text <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;大寶寶&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> style <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;color: blue;font-size:40px&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(<span style="color:#a5d6ff">`使用 CSS Style %c</span><span style="color:#a5d6ff">${</span>text<span style="color:#a5d6ff">}</span><span style="color:#a5d6ff">`</span>, style);
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/f38fbea3fcb0e1847b6d96f82f15a172" rel="noopener">console-css.js</a>（GitHub Gist）</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-06.webp" width="1190" height="414" alt="二、原來 console.log 竟然可以使用 CSS Style !（圖 6）" loading="lazy" decoding="async"></p>
<hr>
<h2 id="三consolelog-寫太多找不到重點你該試試看-consolewarn">三、console.log 寫太多找不到重點？你該試試看 console.warn()！<a class="h-anchor" href="#%e4%b8%89consolelog-%e5%af%ab%e5%a4%aa%e5%a4%9a%e6%89%be%e4%b8%8d%e5%88%b0%e9%87%8d%e9%bb%9e%e4%bd%a0%e8%a9%b2%e8%a9%a6%e8%a9%a6%e7%9c%8b-consolewarn" aria-label="這個段落的連結"></a></h2>
<p>遇到 Bug 時，我們常常需要沿著線索下 console.log 找問題，但如果 console.log 寫太多，我們會無法找到哪個才是我們需要的資訊，下面就舉一個極端點的例子：</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">for</span> (<span style="color:#ff7b72">let</span> i <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">0</span>; i <span style="color:#ff7b72;font-weight:bold">&lt;</span> <span style="color:#a5d6ff">30</span>; i<span style="color:#ff7b72;font-weight:bold">++</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">if</span> (i <span style="color:#ff7b72;font-weight:bold">===</span> <span style="color:#a5d6ff">13</span>) {
</span></span><span style="display:flex;"><span>    console.log(<span style="color:#a5d6ff">`i ---: </span><span style="color:#a5d6ff">${</span>i<span style="color:#a5d6ff">}</span><span style="color:#a5d6ff">`</span>);
</span></span><span style="display:flex;"><span>  } <span style="color:#ff7b72">else</span> {
</span></span><span style="display:flex;"><span>    console.log(<span style="color:#a5d6ff">`i -+-: </span><span style="color:#a5d6ff">${</span>i<span style="color:#a5d6ff">}</span><span style="color:#a5d6ff">`</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/0cfe7cea92a72819ca67e15950cbd0db" rel="noopener">console-no-warn.js</a>（GitHub Gist）</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-07.webp" width="432" height="708" alt="三、console.log 寫太多找不到重點？你該試試看 console.warn()！（圖 7）" loading="lazy" decoding="async"></p>
<p>我相信大多數人第一眼是不會發現「i === 13」時印出的東西不同，但如果透過 console.warn() 來輔助就會一目瞭然：</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">for</span> (<span style="color:#ff7b72">let</span> i <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">0</span>; i <span style="color:#ff7b72;font-weight:bold">&lt;</span> <span style="color:#a5d6ff">30</span>; i<span style="color:#ff7b72;font-weight:bold">++</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">if</span> (i <span style="color:#ff7b72;font-weight:bold">===</span> <span style="color:#a5d6ff">13</span>) {
</span></span><span style="display:flex;"><span>    console.warn(<span style="color:#a5d6ff">`i ---: </span><span style="color:#a5d6ff">${</span>i<span style="color:#a5d6ff">}</span><span style="color:#a5d6ff">`</span>);
</span></span><span style="display:flex;"><span>  } <span style="color:#ff7b72">else</span> {
</span></span><span style="display:flex;"><span>    console.log(<span style="color:#a5d6ff">`i -+-: </span><span style="color:#a5d6ff">${</span>i<span style="color:#a5d6ff">}</span><span style="color:#a5d6ff">`</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/fb17de3c628059d2897af68f5c86998d" rel="noopener">console-warn.js</a>（GitHub Gist）</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-08.webp" width="432" height="708" alt="三、console.log 寫太多找不到重點？你該試試看 console.warn()！（圖 8）" loading="lazy" decoding="async"></p>
<hr>
<h2 id="四錯誤訊息請用-consoleerror不要用-consolelog-來整自己">四、錯誤訊息請用 console.error()，不要用 console.log() 來整自己<a class="h-anchor" href="#%e5%9b%9b%e9%8c%af%e8%aa%a4%e8%a8%8a%e6%81%af%e8%ab%8b%e7%94%a8-consoleerror%e4%b8%8d%e8%a6%81%e7%94%a8-consolelog-%e4%be%86%e6%95%b4%e8%87%aa%e5%b7%b1" aria-label="這個段落的連結"></a></h2>
<p>筆者發現有些工程師在 try…catch 的撰寫上，是用 console.log() 來印錯誤訊息的 😅</p>
<p>這會導致錯誤訊息被其他 console.log() 的訊息淹沒，運氣不好就是系統出包後才發現，因此建議乖乖使用 console.error() 來印錯誤訊息，這樣自己比較方便 Debug。</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">try</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#8b949e;font-style:italic">// 直接拋錯誤訊息讓 catch 來接
</span></span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">throw</span> <span style="color:#a5d6ff">&#34;Something went wrong.&#34;</span>;
</span></span><span style="display:flex;"><span>} <span style="color:#ff7b72">catch</span> (err) {
</span></span><span style="display:flex;"><span>  console.error(err);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/6571d256c3d3c2a402961407e40e8b17" rel="noopener">console-error.js</a>（GitHub Gist）</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-09.webp" width="950" height="388" alt="四、錯誤訊息請用 console.error()，不要用 console.log() 來整自己（圖 9）" loading="lazy" decoding="async"></p>
<hr>
<h2 id="五用-consoletime-追蹤程式執行時間找出效能瓶頸">五、用 console.time() 追蹤程式執行時間，找出效能瓶頸<a class="h-anchor" href="#%e4%ba%94%e7%94%a8-consoletime-%e8%bf%bd%e8%b9%a4%e7%a8%8b%e5%bc%8f%e5%9f%b7%e8%a1%8c%e6%99%82%e9%96%93%e6%89%be%e5%87%ba%e6%95%88%e8%83%bd%e7%93%b6%e9%a0%b8" aria-label="這個段落的連結"></a></h2>
<p>有時我們發現某些頁面跑的特別慢，為了確定問題到底出哪裡，「console.time() &amp; console.timeEnd()」就是一個很好的方案：</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>console.time();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>setTimeout(<span style="color:#ff7b72">function</span> () {
</span></span><span style="display:flex;"><span>  console.timeEnd();
</span></span><span style="display:flex;"><span>}, <span style="color:#a5d6ff">2000</span>);
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/fa9d05d945efc7b1eb4fbba650523d03" rel="noopener">console-time.js</a>（GitHub Gist）</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-10.webp" width="950" height="398" alt="五、用 console.time() 追蹤程式執行時間，找出效能瓶頸（圖 10）" loading="lazy" decoding="async"></p>
<p>但一個功能裡面可能用到多個 api，當你想釐清到底是哪個 api 效率有問題時，就可以給 console.time() 加上標記(flag)。</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>console.time(<span style="color:#a5d6ff">&#34;api-1&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>setTimeout(<span style="color:#ff7b72">function</span> () {
</span></span><span style="display:flex;"><span>  console.timeEnd(<span style="color:#a5d6ff">&#34;api-1&#34;</span>);
</span></span><span style="display:flex;"><span>}, <span style="color:#a5d6ff">2000</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.time(<span style="color:#a5d6ff">&#34;api-2&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>setTimeout(<span style="color:#ff7b72">function</span> () {
</span></span><span style="display:flex;"><span>  console.timeEnd(<span style="color:#a5d6ff">&#34;api-2&#34;</span>);
</span></span><span style="display:flex;"><span>}, <span style="color:#a5d6ff">1000</span>);
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/07a46eb153dd89f5e02ee5a6f9f2071f" rel="noopener">console-time-multi.js</a>（GitHub Gist）</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-11.webp" width="946" height="758" alt="五、用 console.time() 追蹤程式執行時間，找出效能瓶頸（圖 11）" loading="lazy" decoding="async"></p>
<hr>
<h2 id="六用-consoletable-將資訊轉成表格來閱讀">六、用 console.table() 將資訊轉成表格來閱讀<a class="h-anchor" href="#%e5%85%ad%e7%94%a8-consoletable-%e5%b0%87%e8%b3%87%e8%a8%8a%e8%bd%89%e6%88%90%e8%a1%a8%e6%a0%bc%e4%be%86%e9%96%b1%e8%ae%80" aria-label="這個段落的連結"></a></h2>
<p>Backend 很常回傳 Table 格式的資訊，如果我們使用 console.log() 直接將結果印出來，在需要比對資料的時候會不好閱讀：</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">const</span> users <span style="color:#ff7b72;font-weight:bold">=</span> [
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    name<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Dean&#34;</span>,
</span></span><span style="display:flex;"><span>    email<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;dean_lin@test.com&#34;</span>,
</span></span><span style="display:flex;"><span>    department<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Cloud&#34;</span>,
</span></span><span style="display:flex;"><span>    job_title<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Manager&#34;</span>,
</span></span><span style="display:flex;"><span>    age<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">33</span>,
</span></span><span style="display:flex;"><span>    hire_date<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;2016-06-06&#34;</span>,
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    name<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Ray&#34;</span>,
</span></span><span style="display:flex;"><span>    email<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;ray_chen@test.com&#34;</span>,
</span></span><span style="display:flex;"><span>    department<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Cloud&#34;</span>,
</span></span><span style="display:flex;"><span>    job_title<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Engineer&#34;</span>,
</span></span><span style="display:flex;"><span>    age<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">31</span>,
</span></span><span style="display:flex;"><span>    hire_date<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;2019-06-06&#34;</span>,
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    name<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Davy&#34;</span>,
</span></span><span style="display:flex;"><span>    email<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;davy_chang@test.com&#34;</span>,
</span></span><span style="display:flex;"><span>    department<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Cloud&#34;</span>,
</span></span><span style="display:flex;"><span>    job_title<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Designer&#34;</span>,
</span></span><span style="display:flex;"><span>    age<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">35</span>,
</span></span><span style="display:flex;"><span>    hire_date<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;2017-06-06&#34;</span>,
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.table(users);
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/786093942e0147d8fbb09d13a79b9a98" rel="noopener">console-array.js</a>（GitHub Gist）</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-12.webp" width="1400" height="1019" alt="六、用 console.table() 將資訊轉成表格來閱讀（圖 12）" loading="lazy" decoding="async"></p>
<p>在上圖中，我們可以看到如果想要知道個別 user 的詳細資訊，需要自己手動展開 object，不過如果我們將最後的 <code>console.log(users);</code> 改寫成 <code>console.table(users);</code>，資料就會像下圖一樣變成表格很好閱讀嚕！</p>
<p><img src="https://deanlin.net/blog/202209/advanced-console-log/images/advanced-console-log-13.webp" width="1400" height="216" alt="六、用 console.table() 將資訊轉成表格來閱讀（圖 13）" loading="lazy" decoding="async"></p>
<blockquote class="pullquote"><p>希望這篇文章對 Frontend 開發人員有所幫助，透過 console.log 的靈活使用，資料就會更清晰、準確地呈現！</p>
</blockquote>
<p>參考資源：<a href="https://javascript.plainenglish.io/its-2022-please-don-t-just-use-console-log-anymore-217638337c7d">It’s 2022, Please Don’t Just Use “console.log” Anymore</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>NUXTJS GCP serverless實戰</title>
      <link>https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/</link>
      <pubDate>Wed, 24 Jun 2020 14:01:45 +0800</pubDate>
      <guid>https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/</guid>
      <dc:creator>林鼎淵</dc:creator>
      <category>技術教學</category>
      <description>因為跟著官方文件做，讓我被雷了整整一天，於是我決定紀錄操作流程，希望看到的人可以節省時間</description>
      <media:content url="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-og_hu_eeaef78b542d87fb.jpg" medium="image" type="image/jpeg" width="1200" height="675" />
      <content:encoded><![CDATA[<p><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-01.webp" width="1080" height="600" alt="NUXTJS GCP serverless實戰（圖 1）" fetchpriority="high" decoding="async"></p>
<h3 id="事前準備">事前準備<a class="h-anchor" href="#%e4%ba%8b%e5%89%8d%e6%ba%96%e5%82%99" aria-label="這個段落的連結"></a></h3>
<ol>
<li>你有GCP的帳戶(沒有就直接去開一個)</li>
<li>你有信用卡(因為GCP serverless服務一定要綁信用卡，就算你一塊錢都沒花，你還是得綁定)</li>
<li>你會用git(如果不會你要抄襲前人的成果都很難)</li>
<li>如果有mac電腦會是最棒的，因為作者的操作都是在mac的環境</li>
</ol>
<h3 id="文章目標">文章目標<a class="h-anchor" href="#%e6%96%87%e7%ab%a0%e7%9b%ae%e6%a8%99" aria-label="這個段落的連結"></a></h3>
<ol>
<li>根據官方文件建立Nuxt專案</li>
<li>開啟GCP App Engine</li>
<li>將Nuxt專案deploy到GCP</li>
</ol>
<p>SETP 1/5 : 建立Nuxt專案</p>
<p><a href="https://nuxtjs.org/guide/installation">這裡是官方安裝說明文件</a>，根據我的個人經驗，你每個禮拜都會得到不一樣的錯誤訊息(感覺他們工程師根本沒有qa就直接上正式版本了…)，以下為我操作的及遇到的錯誤及相關解決方案。</p>
<p>創建nuxt專案，project-name請自由發揮</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ yarn create nuxt-app &lt;project-name&gt;
</span></span></code></pre></div><p><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-02.webp" width="1312" height="236" alt="文章目標（圖 2）" loading="lazy" decoding="async"></p>
<p>接下來會問你一堆問題，根據我之後會撰寫的文章類型，你可以跟我做一樣的設定</p>
<p><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-03.webp" width="1274" height="390" alt="文章目標（圖 3）" loading="lazy" decoding="async"></p>
<p>只要你運氣夠差，你就會遇到這個錯誤：</p>
<pre tabindex="0"><code>throw new SAOError(`Failed to install ${packageName} in ${cwd}`)
</code></pre><p><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-04.webp" width="1400" height="633" alt="文章目標（圖 4）" loading="lazy" decoding="async"></p>
<p>別怕，仔細看錯誤訊息，你會發現是因為local端的node版本過低，最新的nuxt需要你的<a href="https://nodejs.org/en/">node版本</a>保持在13.7以上，建議你可以使用<a href="https://github.com/nvm-sh/nvm#install--update-script">nvm這個套件</a>來做local端node的版本控制</p>
<p><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-05.webp" width="810" height="72" alt="文章目標（圖 5）" loading="lazy" decoding="async"></p>
<p>調整完node版本後再下一樣建立nuxt的指令</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ yarn create nuxt-app &lt;project-name&gt;
</span></span></code></pre></div><p><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-06.webp" width="1286" height="968" alt="文章目標（圖 6）" loading="lazy" decoding="async"></p>
<p>這次就會通過嚕～接著下指令確認使否正常跑</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cd nuxt_baobao
</span></span><span style="display:flex;"><span>yarn dev
</span></span></code></pre></div><p>如果成功出現下面的畫面就恭喜你嚕～</p>
<p><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-07.webp" width="740" height="938" alt="文章目標（圖 7）" loading="lazy" decoding="async"></p>
<figure class="figure"><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-08.webp" width="1400" height="726" alt="NUXTJS GCP serverless實戰（圖 1）" loading="lazy" decoding="async">
  <figcaption><a href="http://localhost:3000/">http://localhost:3000/</a></figcaption>
</figure>

<p>SETP 2/5 : 將nuxt專案build起來</p>
<p>因為實際運行你總不可能把整個專案丟到GCP，所以要下指令build這個專案，那他變小一點</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>yarn build
</span></span></code></pre></div><p>如果沒發生意外應該會build失敗(我真的懷疑他們到底有沒有做過上線測試…)</p>
<p><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-09.webp" width="1400" height="755" alt="文章目標（圖 9）" loading="lazy" decoding="async"></p>
<p>因為很多人遇到這個問題，有興趣可以參考<a href="https://github.com/postcss/autoprefixer/issues/1328#issuecomment-647279513">這篇文章</a>，不然就複製下面指令執行</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>nvm use 14.4
</span></span><span style="display:flex;"><span>yarn add autoprefixer@9.8.1
</span></span></code></pre></div><p>安裝完套件再下一次yarn build指令就能順利完成</p>
<p><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-10.webp" width="1400" height="755" alt="文章目標（圖 10）" loading="lazy" decoding="async"></p>
<p>SETP 3/5 : 開啟GCP App Engine</p>
<p>我建議你先建立一個<a href="https://console.cloud.google.com/cloud-resource-manager">GCP新的專案</a>來做這次的操作，建立好專案去App Engine建立應用程式</p>
<p><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-11.webp" width="1275" height="608" alt="文章目標（圖 11）" loading="lazy" decoding="async"></p>
<figure class="figure"><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-12.webp" width="551" height="555" alt="地區請選擇離自己近的，價格會便宜一點" loading="lazy" decoding="async">
  <figcaption>地區請選擇離自己近的，價格會便宜一點</figcaption>
</figure>

<p><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-13.webp" width="776" height="363" alt="文章目標（圖 13）" loading="lazy" decoding="async"></p>
<p>SETP 4/5 : 下載Google Cloud SDK</p>
<p>如果你可以根據<a href="https://cloud.google.com/sdk/docs/quickstarts">官方文件</a>操作，裡面有提供各式各樣的安裝方法，一開始我是直接下載壓縮檔來安裝，但遇到各種悲劇…</p>
<pre tabindex="0"><code>Welcome to the Google Cloud SDK!
ERROR:root:code for hash md5 was not found.
</code></pre><p>然後網路上你查到<a href="https://stackoverflow.com/questions/25372911/python-pip-error-on-osx">大部分的答案</a>都是唬爛你的</p>
<p>所以我個人建議你使用<a href="https://brew.sh/zh-tw/">homebrew</a>安裝吧</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>brew cask install google-cloud-sdk
</span></span></code></pre></div><p>安裝後你可以嘗試看看</p>
<pre tabindex="0"><code>gcloud init
</code></pre><p>如果不發生意外應該又是一大串的錯誤…這個時候的問題通常是python版本的問題，請指定你執行gcp的python版本</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>export <span style="color:#79c0ff">CLOUDSDK_PYTHON</span><span style="color:#ff7b72;font-weight:bold">=</span>python3
</span></span></code></pre></div><p>之後再執行gcloud init應該就是一路通暢了，裡面會有一些讓你登入以及選擇專案的選項就按造個人需求調整即可</p>
<p>SETP 5/5 : deploy Nuxt專案到GCP App Engine</p>
<p>如果你上面的操作都很順利，你接下來就可以嘗試把本地的nuxt專案發布到GCP上面了，首先你要在nuxt專案做以下調整，這裡是<a href="https://nuxtjs.org/faq/appengine-deployment/">官方文件</a>(跟著照做會錯誤)：</p>
<p>新增app.yaml檔案，這個檔案是在deploy的時候使用的</p>
<p>PS.在這裡我要特別提醒一件事情，一但你的環境(env)設定為flex，你醒來的時候帳單就有可能爆掉，所以這個部分請謹慎，這是我端午連假完打開GCP帳單發現的慘痛經驗，使用標準環境才會有免費配額，但還是會扣一點費用(ex: Google Storage、Could Build…)。</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#7ee787">runtime</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">nodejs12</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">instance_class</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">F1</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">automatic_scaling</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">max_instances</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">1</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">handlers</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span>- <span style="color:#7ee787">url</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">/_nuxt</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">static_dir</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">.nuxt/dist/client</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">secure</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">always</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span>- <span style="color:#7ee787">url</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">/(.*\.(gif|png|jpg|ico|txt))$</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">static_files</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">static/\1</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">upload</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">static/.*\.(gif|png|jpg|ico|txt)$</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">secure</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">always</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span>- <span style="color:#7ee787">url</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">/.*</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">script</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">auto</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">secure</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">always</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">env_variables</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">HOST</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#39;0.0.0.0&#39;</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">NODE_ENV</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#39;production&#39;</span><span style="color:#6e7681">
</span></span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/6b739e200a284d085377d96555e2d171" rel="noopener">nuxt_baobao_app.yaml</a>（GitHub Gist）</p>
<p>調整package.json檔案，要在dependencies加上“@nuxtjs/vuetify”，並加上這個專案nodejs的版本(本範例為14.4)</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#7ee787">&#34;name&#34;</span>: <span style="color:#a5d6ff">&#34;nuxt_baobao&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#7ee787">&#34;version&#34;</span>: <span style="color:#a5d6ff">&#34;1.0.0&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#7ee787">&#34;private&#34;</span>: <span style="color:#79c0ff">true</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#7ee787">&#34;scripts&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;dev&#34;</span>: <span style="color:#a5d6ff">&#34;nuxt&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;build&#34;</span>: <span style="color:#a5d6ff">&#34;nuxt build&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;start&#34;</span>: <span style="color:#a5d6ff">&#34;nuxt start&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;export&#34;</span>: <span style="color:#a5d6ff">&#34;nuxt export&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;serve&#34;</span>: <span style="color:#a5d6ff">&#34;nuxt serve&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;lint:js&#34;</span>: <span style="color:#a5d6ff">&#34;eslint --ext .js,.vue --ignore-path .gitignore .&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;lint&#34;</span>: <span style="color:#a5d6ff">&#34;yarn lint:js&#34;</span>
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>  <span style="color:#7ee787">&#34;dependencies&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;@nuxtjs/axios&#34;</span>: <span style="color:#a5d6ff">&#34;^5.11.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;@nuxtjs/vuetify&#34;</span>: <span style="color:#a5d6ff">&#34;^1.11.2&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;autoprefixer&#34;</span>: <span style="color:#a5d6ff">&#34;9.8.1&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;chart.js&#34;</span>: <span style="color:#a5d6ff">&#34;^2.9.3&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;hchs-vue-charts&#34;</span>: <span style="color:#a5d6ff">&#34;^1.2.8&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;nuxt&#34;</span>: <span style="color:#a5d6ff">&#34;^2.13.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;vue-chartjs&#34;</span>: <span style="color:#a5d6ff">&#34;^3.5.0&#34;</span>
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>  <span style="color:#7ee787">&#34;devDependencies&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;@nuxtjs/eslint-config&#34;</span>: <span style="color:#a5d6ff">&#34;^3.0.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;@nuxtjs/eslint-module&#34;</span>: <span style="color:#a5d6ff">&#34;^2.0.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;@nuxtjs/vuetify&#34;</span>: <span style="color:#a5d6ff">&#34;^1.11.2&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;babel-eslint&#34;</span>: <span style="color:#a5d6ff">&#34;^10.1.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;eslint&#34;</span>: <span style="color:#a5d6ff">&#34;^7.2.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;eslint-config-prettier&#34;</span>: <span style="color:#a5d6ff">&#34;^6.11.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;eslint-plugin-nuxt&#34;</span>: <span style="color:#a5d6ff">&#34;^1.0.0&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;eslint-plugin-prettier&#34;</span>: <span style="color:#a5d6ff">&#34;^3.1.4&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;prettier&#34;</span>: <span style="color:#a5d6ff">&#34;^2.0.5&#34;</span>
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>  <span style="color:#7ee787">&#34;engines&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#7ee787">&#34;node&#34;</span>: <span style="color:#a5d6ff">&#34;^12&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/e4436bcdb26e49a6bb1be8afc98d59a9" rel="noopener">nuxt_baobao_package.json</a>（GitHub Gist）</p>
<p>完成以上設定後在專案目錄下指令</p>
<pre tabindex="0"><code>gcloud init
</code></pre><p>這裡會讓你再次確認自己的設定檔(是否初始化、新增)，登入的google帳號，選擇雲端專案(就是你剛剛新增的那個專案)</p>
<p>在完成上述設定後就可以輸入以下指令來deploy啦(這裡會讓你在確認一下deploy發布的專案位置)</p>
<pre tabindex="0"><code>gcloud app deploy
</code></pre><p>如果你看到以下畫面就要恭喜你了</p>
<p><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-14.webp" width="1400" height="341" alt="文章目標（圖 14）" loading="lazy" decoding="async"></p>
<p>輸入下面指令可以檢視你的網頁是否發布成功嚕～</p>
<pre tabindex="0"><code>gcloud app browse
</code></pre><figure class="figure"><img src="https://deanlin.net/blog/202006/nuxtjs-gcp-serverless/images/nuxtjs-gcp-serverless-15.webp" width="1400" height="758" alt="NUXTJS GCP serverless實戰（圖 3）" loading="lazy" decoding="async">
  <figcaption><a href="https://nuxt-demo-281302.dt.r.appspot.com">https://nuxt-demo-281302.dt.r.appspot.com</a></figcaption>
</figure>

<p>如果有問題歡迎在下方回覆，如果這篇文章有讓你少走彎路請用力拍手喔～</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
