<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Leon</title>
    <description>The latest articles on DEV Community by Leon (@leon0824).</description>
    <link>https://dev.to/leon0824</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F92118%2F0ba206fe-abb3-4220-9aad-65732e2d40b5.jpeg</url>
      <title>DEV Community: Leon</title>
      <link>https://dev.to/leon0824</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/leon0824"/>
    <language>en</language>
    <item>
      <title>ngrok 讓本機發佈出可被訪問的網址</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Thu, 04 Jan 2024 04:34:28 +0000</pubDate>
      <link>https://dev.to/leon0824/ngrok-rang-ben-ji-fa-bu-chu-ke-bei-fang-wen-de-wang-zhi-45io</link>
      <guid>https://dev.to/leon0824/ngrok-rang-ben-ji-fa-bu-chu-ke-bei-fang-wen-de-wang-zhi-45io</guid>
      <description>&lt;p&gt;常常會遇到需要把本機開發環境的 web app 給別人或自己預覽，甚至開放給外網連入的需求，這時候就需要 &lt;a href="https://ngrok.com/"&gt;ngrok&lt;/a&gt;（發音：&lt;em&gt;en-grok&lt;/em&gt;）這樣的工具幫我們搞定這一切。&lt;/p&gt;

&lt;h2&gt;
  
  
  ngrok 的特性
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;綁定本機的埠號並接受外部連入。&lt;/li&gt;
&lt;li&gt;可穿透 NAT 或防火牆讓外部連入。&lt;/li&gt;
&lt;li&gt;會拿到一個 ngork 的網址方便貼到信件或訊息內。&lt;/li&gt;
&lt;li&gt;ngrok 產生的網址支援 HTTP / HTTPS。&lt;/li&gt;
&lt;li&gt;有 web 界面讓我們可以監看連入的請求內容。&lt;/li&gt;
&lt;li&gt;可加設 HTTP 帳密認證，避免被不必要的人亂連。&lt;/li&gt;
&lt;li&gt;除了支援 HTTP 外，也支援 WebSocket 和 SSH。&lt;/li&gt;
&lt;li&gt;可同時發布多個服務。&lt;/li&gt;
&lt;li&gt;還支援 API，可以用 API 操控 ngork。&lt;/li&gt;
&lt;li&gt;付費方案可以自定網址。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ngrok 的工作原理
&lt;/h2&gt;

&lt;p&gt;其實 ngrok 並未真正的穿透 NAT，它只是接受 ngork cloud 機台轉發來的請求並做出回應，而那個 ngrok 的網址其實也就是連到 ngrok cloud 的網址。&lt;/p&gt;

&lt;h2&gt;
  
  
  安裝與初始化
&lt;/h2&gt;

&lt;p&gt;根據 &lt;a href="https://ngrok.com/download"&gt;Install ngrok&lt;/a&gt; 頁面的指南，使用適合自己的方式安裝 ngrok。&lt;/p&gt;

&lt;p&gt;開始前必須先註冊帳號，在 ngrok 的網站登入後會看到一組 token：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IDKy3E6B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/noxx65iegrrpcnvbu4k9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IDKy3E6B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/noxx65iegrrpcnvbu4k9.png" alt="ngrok authtoken" width="700" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;拿這串 token 來做登入：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ngrok authtoken &amp;lt;TOKEN&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;正確的話應該會看到一行寫著 authtoken 已被寫入 ngrok.yml 的訊息：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authtoken saved to configuration file: /home/leon/.ngrok2/ngrok.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;登入只要做一次就好，有這組 authtoken 才能去向 ngrok 伺服器要到一些後面操作會用到的的基本權限。&lt;/p&gt;

&lt;h2&gt;
  
  
  使用
&lt;/h2&gt;

&lt;p&gt;假設電腦內已經有某個監聽 1111 埠的服務，例如用 &lt;a href="https://editor.leonh.space/2023/caddy/"&gt;Caddy server&lt;/a&gt; 提供的靜態網頁，而我們想要用 ngrok 讓 1111 埠也可以對外服務：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ngrok http 1111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;此時會出現下面的狀態畫面：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ngrok by @inconshreveable

Session Status      online
Account             Leon (Plan: Free)
Version             2.3.40
Region              United States (us)
Web Interface       http://127.0.0.1:4040
Forwarding          http://1b0f.ngrok.io -&amp;gt; http://localhost:1111
Forwarding          https://1b0f.ngrok.io -&amp;gt; http://localhost:1111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;從上面的狀態畫面可以得知一些訊息，包括有一組 Web Interface，以及對外提供服務的 HTTP / HTTPS 網址。&lt;/p&gt;

&lt;p&gt;是不是很簡單。&lt;/p&gt;

&lt;p&gt;從上面可以看到，預設的節點是在美國，訪客透過 ngrok.io 網址連線會先到美國的節點，節點再把請求傳送到我們位於台灣的電腦，回覆的路徑也是相仿，如果追求更快的連線，可以改用 ngrok 位於東京的節點，指令稍微改一下即可：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ngrok http &lt;span class="nt"&gt;-region&lt;/span&gt; jp 1111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;從狀態就可以看到變成東京節點了：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ngrok by @inconshreveable

Session Status      online
Account             Leon (Plan: Free)
Version             2.3.40
Region              Japan (jp)
Web Interface       http://127.0.0.1:4040
Forwarding          http://e25b.jp.ngrok.io -&amp;gt; http://localhost:1111
Forwarding          https://e25b.jp.ngrok.io -&amp;gt; http://localhost:1111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  監控請求
&lt;/h2&gt;

&lt;p&gt;在 ngrok 執行時的狀態訊息內，除了有網址之外，還有一個 &lt;a href="http://127.0.0.1:4040"&gt;Web Interface&lt;/a&gt;，我們可以透過這個 Web Interface 來監控往來的請求與回覆內容，包括 HTTP 檔頭與 body （payload）都可以檢視，對開發中的除錯是滿實用的工具。&lt;/p&gt;

&lt;h2&gt;
  
  
  結語
&lt;/h2&gt;

&lt;p&gt;其實免費版能調用的設定不多，並且免費版最大的缺點就是那又亂又長的網址了吧，只有付費版支援自訂網址，還可以用自有的網域，不過免費版就滿適合我這種小資宅宅。&lt;/p&gt;

&lt;p&gt;有一些我認為次要的功能就沒寫上來，或許之後有用到再說吧。&lt;/p&gt;

</description>
      <category>ngrok</category>
    </item>
    <item>
      <title>Plesk 升級筆記</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Thu, 30 Nov 2023 00:24:31 +0000</pubDate>
      <link>https://dev.to/leon0824/plesk-sheng-ji-bi-ji-4neo</link>
      <guid>https://dev.to/leon0824/plesk-sheng-ji-bi-ji-4neo</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---NPc1LbJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ys82l8fbz0knxmp0fqcm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---NPc1LbJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ys82l8fbz0knxmp0fqcm.png" alt="Plesk" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.plesk.com/"&gt;Plesk&lt;/a&gt; 是一款伺服器管理系統，透過 Plesk，我們可以比較方便的在主機上配置各種服務與應用，例如最典型的虛擬主機，Plesk 可以幫助我們配置 web server 的 vhost 設定，另外像是資料庫、DNS、郵件、防火牆等的都可以在 Plesk 內做配置，在應用方面，也支援 PHP 服務，還可以指定每一個虛擬主機所要搭配的 PHP 版本，雖然以上這些事都可以透過手工自行配置，但 Plesk 提供了友善的 web 界面以及更為周全的配置設定，包括負載監控、遠端備份、系統更新、TLS 憑證管理、第三方服務整合等，對要建構一個可靠的服務而言，Plesk 是個很省力的選擇。&lt;/p&gt;

&lt;h2&gt;
  
  
  Plesk CLI
&lt;/h2&gt;

&lt;p&gt;一般來說我們都是用 web 界面對 Plesk 做操控，但其實 Plesk 也是有提供 CLI 的工具讓我們可以在 shell 內操作 Plesk，當然，想要用 shell 操作 Plesk 的先決條件是我們必須可以透過 SSH 登進主機內，這點前提是一定要的，如果是自己的主機自己裝的 Plesk，那應該是都有 SSH，但若是外購主機，那很有可能主機商不會提供你 SSH 的權限，那只能殘念了。&lt;/p&gt;

&lt;p&gt;下面記錄本人的 Plesk CLI 筆記，會隨著時間而增加內容。&lt;/p&gt;

&lt;p&gt;Plesk 的命令就是 &lt;code&gt;plesk&lt;/code&gt;，而因為 Plesk 本身是管理許多服務的軟體，所以通常也必須搭配 &lt;code&gt;sudo&lt;/code&gt; 使用，容先敘明。&lt;/p&gt;

&lt;h2&gt;
  
  
  更新 Plesk
&lt;/h2&gt;

&lt;p&gt;Plesk 本身也是由許多的作業系統套件所組成，但它有自己的套件管理體系，與 Plesk 自己本身組件管理有關的命令通常都是被歸納在 &lt;code&gt;installer&lt;/code&gt; 這個子命令內，例如要更新 Plesk 自己，使用以下命令：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;plesk installer update plesk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;要注意，上面這行一旦執行就會立馬更新，不會再次確認，使用前務必確認前置作業是否已完成，例如備份—最重要也最常被忽略的事。&lt;/p&gt;

&lt;p&gt;正常情況下，上面的命令會幫我們把 Plesk 自己更新，但有時會遇到有另外一個 Plesk Installer 安裝程序在執行，導致我們無法重複執行的問題，這時候我們必須先把既有的安裝程序終止：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;plesk installer stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;上面這行會把原有的 Plesk 安裝程序終止，終止之後再跑上面的更新命令應該就可以順利執行了。&lt;/p&gt;

&lt;h2&gt;
  
  
  升級 Plesk
&lt;/h2&gt;

&lt;p&gt;在 Plesk 目前的版次是這樣的：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;18.0.28 Update 3&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;前面的 18.0.28 表示版次，從 18.0.28 到 18.0.29 稱為升級（upgrade），以升級的命令處理，而從 18.0.28 到 18.0.28 Update1 稱為更新（update），以上節的 &lt;code&gt;update&lt;/code&gt; 子命令處理。更新和升級雖然都是對軟體的改版，但更新往往表示規模較小，大多是一些錯誤修正或安全性補丁，而升級的版次跳號象徵著幅度更大的改版，除了錯誤修正與安全性補丁外，可能還會有新特性的加入或舊特性的退役，然而不管是更新還是升級，都建議在施做前，對系統做一次快照備份，施做後有問題才有機會挽回。&lt;/p&gt;

&lt;p&gt;升級的命令與更新類似，但稍有不同的是更新必須明確的指定目標版號：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;plesk installer upgrade plesk 18.0.29
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;上面這行表示「把 Plesk 升級到 18.0.29 版」。&lt;/p&gt;

&lt;p&gt;關於 Plesk 新版的釋出資訊，可以看 &lt;a href="https://docs.plesk.com/release-notes/obsidian/change-log/"&gt;Change Log for Plesk Obsidian&lt;/a&gt;。&lt;/p&gt;

&lt;h2&gt;
  
  
  相關文章
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://editor.leonh.space/2020/cloudflare-lightsail-plesk/"&gt;Plesk / Cloudflare / Lightsail 混合架構的安全規劃&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>plesk</category>
    </item>
    <item>
      <title>WordPress 備份外掛 WPvivid Backup</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Thu, 19 Oct 2023 00:25:45 +0000</pubDate>
      <link>https://dev.to/leon0824/wordpress-bei-fen-wai-gua-wpvivid-backup-53n3</link>
      <guid>https://dev.to/leon0824/wordpress-bei-fen-wai-gua-wpvivid-backup-53n3</guid>
      <description>&lt;p&gt;&lt;a href="https://wpvivid.com/ref/240/"&gt;WPvivd Backup&lt;/a&gt; 是一款佛心的 WordPress 備份外掛，功能完整，許多其它家備份外掛付費的功能在 &lt;a href="https://tw.wordpress.org/plugins/wpvivid-backuprestore/ref/240/"&gt;WPvivid Backup 免費版&lt;/a&gt;都無料提供。&lt;/p&gt;

&lt;p&gt;照例列一下特色：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;排程備份。&lt;/li&gt;
&lt;li&gt;備份完會寄給我們備份的結果。&lt;/li&gt;
&lt;li&gt;備份的打包檔可以放在主機上、下載自己管、上傳到各大空間。&lt;/li&gt;
&lt;li&gt;可備份檔案、資料庫。&lt;/li&gt;
&lt;li&gt;支援 AB 站備份，A 站和 B 站互相認證後，A 站的備份檔可以傳到 B 站幫 B 站還原，省時省力省心。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;付費的 WPvivid Backup Pro 版當然有更多的功能，不過本人沒用過，可以參考 &lt;a href="https://wpvivid.com/backup-plugin-pro/ref/240/"&gt;WPvivid Backup 的比較表&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;下面是一些 WPvivid Backup 的基礎操作。&lt;/p&gt;

&lt;h2&gt;
  
  
  手動備份與還原
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sf9j8yK1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w6ajfo2zq0gh2a98appc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sf9j8yK1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w6ajfo2zq0gh2a98appc.png" alt="WPvivid Backup" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;安裝完進到 WPvivid Backup，以上方的頁籤作為主要功能的導航。&lt;/p&gt;

&lt;p&gt;在 Backup &amp;amp; Restore 可以做最單純的手動備份，就是中間那顆藍色的 Backup Now，而按鈕上方左邊可以選擇要備份的項目；右邊可以選擇要備份到主機或其它空間，雲端空間需要先設定連線才能使用，目前都還是灰色的。&lt;/p&gt;

&lt;p&gt;勇敢地按下 Backup Now 會出現進度條，跑完之後往下看會看到目前這個站有的備份檔：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zF8X-xut--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a94c9o4a4loyq9fijaja.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zF8X-xut--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a94c9o4a4loyq9fijaja.png" alt="WPvivid Backup" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;這邊顯示備份檔的資訊，時間，儲存方式等，還可以對備份檔做簡單的管理，以及下載到自己的電腦、從備份檔還原等功能。&lt;/p&gt;

&lt;p&gt;切換到 Upload 頁籤，可以把自己電腦的備份檔上傳到主機，如下圖：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bZW7gAJ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jwto3mh8dll8z2189nue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bZW7gAJ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jwto3mh8dll8z2189nue.png" alt="WPvivid Backup" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;上傳的備份檔也會出現在 Backups 頁籤內，如果要用備份檔還原的話再按 Restore 即可。&lt;/p&gt;

&lt;h2&gt;
  
  
  排程
&lt;/h2&gt;

&lt;p&gt;回到畫面最上方，切換到 Schedule 頁籤，在這邊可以設定排程：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0v7G327I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yc2nsl6sxgyb0fyxcbe7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0v7G327I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yc2nsl6sxgyb0fyxcbe7.png" alt="WPvivid Backup" width="800" height="868"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;這頁的設定相當直覺，啟用排程，設定週期、備份項目、儲存位置，存檔，WPvivid Backup 就會按計劃幫我們自動做備份。&lt;/p&gt;

&lt;h2&gt;
  
  
  設定遠端空間
&lt;/h2&gt;

&lt;p&gt;來到 Remote Storage 頁籤，這裡可以設定備份檔要儲存的遠端空間：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xL-X1TJp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5vppj51beq0x49lojyl7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xL-X1TJp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5vppj51beq0x49lojyl7.png" alt="WPvivid Backup" width="800" height="732"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;常用的空間都有支援，授權認證的方式也是走常見的認證流程。依我自己的習慣都會把備份檔放到遠端空間，避免主機掛掉的憾事發生。&lt;/p&gt;

&lt;p&gt;在設定完遠端空間後，前面備份那邊原本灰色的圖示應該就會變成可選的彩色了。&lt;/p&gt;

&lt;h2&gt;
  
  
  AB 站互傳備份
&lt;/h2&gt;

&lt;p&gt;雖然用手動的上傳下載也可以做到 AB 站互傳備份的目的，不過就是多了人工的力氣，WPvivid Backup 內建 AB 站互傳的功能，可以幫我們節省喝一杯水的時間。&lt;/p&gt;

&lt;p&gt;AB 站之間要互傳，大前提當然是兩個站的網路要能溝通，再透過 WPvivid Backup 的密鑰認證機制，建立認證後，才可以傳檔。&lt;/p&gt;

&lt;p&gt;假設是 A 站要備份打包傳給 B 站，則 A 站要有 B 站的密鑰。&lt;/p&gt;

&lt;p&gt;在 B 站產生密鑰，B 站也要裝 WPvivid Backup，到 B 站 WPvivd Backup 的 Key 頁籤：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RdqzBFI5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mwaey83kf0c9po9oaiul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RdqzBFI5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mwaey83kf0c9po9oaiul.png" alt="WPvivid Backup" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;先設定密鑰的有效時間，再按一下 Generate 就會產生一大串亂碼密鑰，回到 A 站的 Auto-migration 頁籤：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X2kHge1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vqjtuv5evvvjybvny86i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X2kHge1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vqjtuv5evvvjybvny86i.png" alt="WPvivid Backup" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;把密鑰貼上，設定一下要打包的項目，按 Clone then Transfer 就會開始幫我們做備份、打包、傳輸的動作到 B 站了。&lt;/p&gt;

&lt;p&gt;傳完後回到 B 站的 Backup &amp;amp; Restore 頁籤，下方的 Backup 區段還不會出現剛剛 A 站傳來的打包檔，按一下 Scan uploaded backup or received backup 才會出現。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wbhhbwbY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gd6i621zlty5vvv2wcyx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wbhhbwbY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gd6i621zlty5vvv2wcyx.png" alt="WPvivid Backup" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;收到的備份檔，就如同其它的備份檔一樣還原即可。&lt;/p&gt;

&lt;p&gt;AB 站互傳模式的還原之後，最好還是去每個設定與頁面看一下，是不是有網址或字串要改的，WPvivid Backup 還原後會自動使用 B 站的網址，但有些第三方外掛內的設定可能需要手動修正成 B 站的設定。頁面內容也是，有可能某些連結當初在建立是手動鍵入 A 站網址，這些細微的部分都還是要一一檢查。&lt;/p&gt;

&lt;h2&gt;
  
  
  結語
&lt;/h2&gt;

&lt;p&gt;WPvivid Backup 是本人嘗試過幾個不同的備份外掛後覺得最好用的，推薦給大家，另外本文的連結也都很故意的埋了 &lt;a href="https://wpvivid.com/affiliate/ref/240/"&gt;WPvivid Backup 聯盟行銷&lt;/a&gt;的連結，你各位一不小心點到還順手結了帳就會有部份回扣流入本人口袋，不可不慎。&lt;/p&gt;

&lt;p&gt;最後補充一點關於 AB 站備份還原的注意事項，在 AB 的備份還原情境下，A 站與 B 站有許多不同的地方，這些地方在還原至 B 站後都還是要一一調整以符合 B 站的環境，要調整的地方大多是與第三方服務有關的，包括 GA 追總代碼、Pixel 代碼、GTM 代碼、以及其它類似外掛的代碼或 API 認證等等，都需要在還原後逐一調整，這部份需要特別留意一下。&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>wpvivid</category>
    </item>
    <item>
      <title>WordPress Child Theme</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Thu, 12 Oct 2023 05:53:21 +0000</pubDate>
      <link>https://dev.to/leon0824/wordpress-child-theme-9e6</link>
      <guid>https://dev.to/leon0824/wordpress-child-theme-9e6</guid>
      <description>&lt;h2&gt;
  
  
  Theme
&lt;/h2&gt;

&lt;p&gt;Theme 的檔案由許多 PHP 模板構成，而這些模板之間是有階層關係存在的，階層關係可以參考 &lt;a href="https://wphierarchy.com/"&gt;The WordPress Template Hierarchy&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;WordPress 會根據當前訪客的訪問頁面嘗試以該頁面歸屬之模板檔內容組版出完整的網頁回應給訪客，如果專屬的模板不存在，則會退一步抓取通用模板組版回應。&lt;/p&gt;

&lt;p&gt;舉例來說，訪客訪問一篇網誌，對照階層表，WordPress 會首先找 single-post.php 作為模板回應，但假設 single-post.php 不存在，則會找 single.php，如果還是沒有，繼續找 singular.php，再沒有就用 index.php，當然往往越通用的模板越不可能是恰當的回應內容，上述只是舉例用於解釋 WordPress 的模板階層與回退機制（fall-back）而已。&lt;/p&gt;

&lt;h2&gt;
  
  
  Child theme
&lt;/h2&gt;

&lt;p&gt;一般的 theme 都會常態性的更新，因此如果要客製，不建議直接魔改 theme 的檔案，以免 theme 更新把我們的修改覆蓋掉，在 WordPress 有設計 child theme 的機制，child theme 可以繼承 parent theme 的模板與函式，並且可以自由覆蓋 parent theme 任意的模板或函式。&lt;/p&gt;

&lt;p&gt;上面提到 WordPress 對模板檔的階層與回退機制，如果再把 child theme 的概念加入，依然是同樣的原則，會先去 child theme 找與當前請求頁面較匹配的模板檔，例如網誌會去 child theme 內的 single-post.php，若 child theme 沒有則會到 parent theme 找 single-post.php，再沒有才會去找 child theme 的 single.php，再沒有去找 parent theme 的 single.php，以此類推。&lt;/p&gt;

&lt;h2&gt;
  
  
  建立 child theme 目錄與檔案
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;在 wp-content/theme/ 新建一個 storefront-child 資料夾，資料夾名字可以自取，可以識別就好，這個 storefront-child 就是我們的專案資料夾，也是 Git 專案資料夾。&lt;/li&gt;
&lt;li&gt;在專案資料夾內建立 functions.php 和 style.css。&lt;/li&gt;
&lt;li&gt;截至目前 wp-content/ 目錄結構會長這樣：
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wp-content/
├─ languages/
├─ mu-plugins/
├─ plugins/
├─ themes/
│  ├─ storefront/
│  └─ storefront-child/
│     ├─ style.css
│     └─ functions.php
├─ upgrade/
└─ uploads/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  在樣式表寫入 child theme 基本資料
&lt;/h2&gt;

&lt;p&gt;截至目前檔案都還沒有內容，在 style.css 填入一些基本資料：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/*
Theme Name:   Storefront Child
Theme URI:    http://example.com/wordpress-theme-child/
Description:  WordPress Child Theme
Author:       Leon
Author URI:   http://example.com
Template:     storefront
Version:      1.0
License:      GNU General Public License v2 or later
License URI:  http://www.gnu.org/licenses/gpl-2.0.html
Tags:         WooCommerce
Text Domain:  storefrontchild
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Theme Name：不可與其它既有的佈景主題同名，必填。&lt;/li&gt;
&lt;li&gt;Theme URI：非必填。&lt;/li&gt;
&lt;li&gt;Description：非必填。&lt;/li&gt;
&lt;li&gt;Author：非必填。&lt;/li&gt;
&lt;li&gt;Author URI：非必填。&lt;/li&gt;
&lt;li&gt;Template：parent theme 的目錄名。&lt;/li&gt;
&lt;li&gt;Version：非必填。&lt;/li&gt;
&lt;li&gt;License：非必填。&lt;/li&gt;
&lt;li&gt;License URI：非必填。&lt;/li&gt;
&lt;li&gt;Tags：非必填。&lt;/li&gt;
&lt;li&gt;Text Domain：此主題在程式碼內的代稱，某些地方會用到，非必填。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;這些基本資料對 CSS 來說是註解，但對 WP 來說是作為辨識 child theme 資訊的欄位。&lt;/p&gt;

&lt;h2&gt;
  
  
  在 functions.php 載入 parent theme 的樣式表
&lt;/h2&gt;

&lt;p&gt;目前的 child theme 不管是樣式或頁面都是空白，雖然 WordPress 對 child theme 的模板有回退機制，但對 CSS 檔案而言這樣的機制並不生效，所以要透過 functions.php 內的函數把 parent theme 的樣式表載入。&lt;/p&gt;

&lt;p&gt;在 child theme 的資料夾內編輯 functions.php：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="cm"&gt;/* enqueue script for parent theme stylesheeet */&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;childtheme_parent_styles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// enqueue style&lt;/span&gt;
    &lt;span class="nf"&gt;wp_enqueue_style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'parent'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;get_template_directory_uri&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'/style.css'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'wp_enqueue_scripts'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'childtheme_parent_styles'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;截至目前為止，雖然還是沒有自己的樣式與模板，但因為 WordPress 的模板回退機制，以及我們也載入了 parent theme 的 CSS，所以在 WordPress Admin 勇敢的把佈景主題切換成 child theme 後，一切如常，頁面、樣式都沒跑掉。&lt;/p&gt;

&lt;h2&gt;
  
  
  客製模板
&lt;/h2&gt;

&lt;p&gt;從 parent theme 複製想改的模板檔到 child theme 再做修改，確保與為異動的部分仍然與 parent theme 保持一致以確保相容性。&lt;/p&gt;

&lt;h2&gt;
  
  
  客製樣式
&lt;/h2&gt;

&lt;p&gt;直接在 child theme 的樣式表做編修。&lt;/p&gt;

&lt;h2&gt;
  
  
  客製函式
&lt;/h2&gt;

&lt;p&gt;客製函式前，必須先確定要做的功能是應該在 theme 內實現還是應該在 plugin 內實現，一般會以功能的目的來判斷，如果是與外觀內容無關的部分，會以 plugin 實現；反之若是與 theme 外觀或內容相關的部分，會以 theme 實現。&lt;/p&gt;

&lt;p&gt;WordPress 內預埋了大量的 hook 點，這些 hook 點會在頁面組版產生的時候依序執行。我們客製的函式會透過把函式註冊到 hook 點的方式讓函式在特定的位置生效。&lt;/p&gt;

&lt;p&gt;WordPress hook 又可分為 action hook 與 filter hook，兩者差別可參考別人寫的優文〈&lt;a href="https://audilu.com/2011/10/10/wordpress-hook/"&gt;WordPress的Hook機制與原理&lt;/a&gt;〉。&lt;/p&gt;

&lt;p&gt;客製函式的一般規則：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;如果要添加的函式與 parent theme 無關，可自由添加。&lt;/li&gt;
&lt;li&gt;如果是要變更／追加於 parent theme 內的函式，則可以有三種途徑：

&lt;ul&gt;
&lt;li&gt;對 pluggable function，可直接以同樣的函式名建立於 child theme 的 functions.php 內，可完全取代 parent theme 的同名函式。&lt;/li&gt;
&lt;li&gt;在 child theme 內定義一組函式，把 parent theme 的目標函式解除 hook。&lt;/li&gt;
&lt;li&gt;附加到 parent theme 的既有函式後執行。&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  取代 pluggable function
&lt;/h2&gt;

&lt;p&gt;Pluggable function 是一種被判斷式包住的函式，判斷式用於確認是否已經有同名函式存在，依照 WordPress 的規則，child theme 的 functions.php 會先被載入，因此 parent theme 的 pluggable function 的檢查式會發現已經有同名函式存在，而採用 child theme 的同名函式並忽略 parent theme 的同名函式。&lt;/p&gt;

&lt;p&gt;在 storefront/inc/storefront-template-functions.php 有個 &lt;code&gt;storefront_credit()&lt;/code&gt; 就是 pluggable function，它結構長這樣：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;function_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'storefront_credit'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;storefront_credit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// contents for function here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;可以看到在 &lt;code&gt;storefront_credit()&lt;/code&gt; 外面還包了一層判斷式用於確認是否已經有同名的 &lt;code&gt;storefront_credit&lt;/code&gt; 函式存在，沒有的話才會執行下面的 &lt;code&gt;storefront_credit()&lt;/code&gt;。&lt;/p&gt;

&lt;h2&gt;
  
  
  解除 parent theme 的 hook
&lt;/h2&gt;

&lt;p&gt;假設在 parent theme 有一函式：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;parent_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;//contents of function here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'parent_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;可以在 child theme 定義解除它的函式：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;remove_parent_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nf"&gt;remove_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'parent_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'wp_head'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'remove_parent_function'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;上面是以 action hook 為例，如果是 filter hook 也是以此類推，把 &lt;code&gt;remove_action()&lt;/code&gt; 改成 &lt;code&gt;remove_filter()&lt;/code&gt; 即可。&lt;/p&gt;

&lt;h2&gt;
  
  
  附加到既有的函式後
&lt;/h2&gt;

&lt;p&gt;最後一種模式，不異動 parent theme 既有函式，而是隨後執行。假設在 parent theme 有組函式用於產生 footer 的內容：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;parent_footer_content&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;// content of function here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'parent_footer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'parent_footer_content'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;我們可以在 child theme 定義另一組函式並 hook 到同一個位置，以及確保 child theme 的 priority 大於上面的 parent theme 函式，上面的 parent theme 函式沒有指定 priority，所以會被 WordPress 認定為 10。&lt;/p&gt;

&lt;p&gt;Child theme 函式內容如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;child_footer_extra_content&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;// contents of function here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'parent_footer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'child_footer_extra_content'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  參考文件
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kinsta.com/blog/wordpress-child-theme/"&gt;How to Create a Child Theme in WordPress (Extended Guide)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.templatetoaster.com/how-to-create-child-theme-wordpress/"&gt;How to Create Child Theme in WordPress – Tutorial for Beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.hostinger.com/tutorials/how-to-create-wordpress-child-theme"&gt;How to Create and Customize a WordPress Child Theme&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>wordpress</category>
    </item>
    <item>
      <title>Local 本機 WordPress 開發環境建置工具</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Mon, 02 Oct 2023 05:37:44 +0000</pubDate>
      <link>https://dev.to/leon0824/local-ben-ji-wordpress-kai-fa-huan-jing-jian-zhi-gong-ju-27k6</link>
      <guid>https://dev.to/leon0824/local-ben-ji-wordpress-kai-fa-huan-jing-jian-zhi-gong-ju-27k6</guid>
      <description>&lt;p&gt;最近又碰到那萬惡的 WordPress，重新調查了 WordPress 在本機端建置的方案，發現了一個新東西覺得還不錯用，在這邊分享。&lt;/p&gt;

&lt;h2&gt;
  
  
  本機環境
&lt;/h2&gt;

&lt;p&gt;如同大多數的資訊專案一樣，在為 WordPress 製作新站台也往往是先在本機端建置一套開發環境，在比較穩定後再部署到生產機台中，可是萬惡的 WordPress 並沒有內建原生的開發環境，所以以往都是採用一些第三方包好的懶人包／架站機之類來使用，可是使用體驗並不好，包括必須要配置一些參數等，以及它們有些還在用老舊的 PHP 或 Apache 或 MySQL，這裡介紹的 &lt;a href="https://localwp.com/"&gt;Local&lt;/a&gt; 解決了一部分前面提到的的問題。&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://localwp.com/"&gt;Local&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Local 也算是本機架 WordPress 的懶人包之一，它有一些值得一提的特色：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;跨平台 Linux、macOS、Windows。&lt;/li&gt;
&lt;li&gt;管理工具簡單好上手。&lt;/li&gt;
&lt;li&gt;支援在本機建立多個獨立站台。&lt;/li&gt;
&lt;li&gt;每個站台的底層套件 PHP、MySQL 可自由更換版本。&lt;/li&gt;
&lt;li&gt;整合 &lt;a href="https://github.com/mailhog/MailHog"&gt;MailHog&lt;/a&gt; 用於確認信件寄發狀況。&lt;/li&gt;
&lt;li&gt;預設支援 HTTPS。&lt;/li&gt;
&lt;li&gt;整合 &lt;a href="https://wp-cli.org/"&gt;WP-CLI&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;整合 &lt;a href="https://ngrok.com/"&gt;Ngrok&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;整合 &lt;a href="https://www.adminer.org/"&gt;Adminer&lt;/a&gt; 作為 MySQL 管理界面。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Local 的安裝與建立站台
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://localwp.com/"&gt;Local&lt;/a&gt; 的安裝與使用非常簡單，只要去 &lt;a href="https://localwp.com/"&gt;Local 的網站&lt;/a&gt;下載並安裝即可，並且 Local 同時提供了 Linux、macOS、Windows 的安裝包，以及一致的管理介面。&lt;/p&gt;

&lt;p&gt;安裝後跑起來應該會看到這個畫面：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lkrotjve--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j861p2aekdzyyqk68a34.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lkrotjve--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j861p2aekdzyyqk68a34.png" alt="Local" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;左邊的主選單，除了第二個「Local Sites」外，其它都是些付費相關的加值服務，我輩小資男女們應該用不到。&lt;/p&gt;

&lt;p&gt;Local Sites 這頁，按 CREATE A NEW SITE 應該會看到這幾頁：&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup Site
&lt;/h3&gt;

&lt;p&gt;第一頁填站名。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5MgtLeiM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5tlr7b94uexpitgd3o6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5MgtLeiM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5tlr7b94uexpitgd3o6.png" alt="Setup Site" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;先輸入站名，再把 ADVANCED OPTIONS 展開後會看到更多欄位：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local site domain：本地的網址。&lt;/li&gt;
&lt;li&gt;Local site path：站台專案在電腦內的資料夾。&lt;/li&gt;
&lt;li&gt;Create site from Blueprint?：付費服務可略過。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setup Environment
&lt;/h3&gt;

&lt;p&gt;第二頁決定底層組件，它預帶的 PHP 7.3.5、Nginx、MySQL 8.0.16 都是目前的主流選擇，可以直接使用。&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup WordPress
&lt;/h3&gt;

&lt;p&gt;第三頁設定 WordPress 帳密。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sBC3Xg6U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rfw05bz2vjg07cofrpbz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sBC3Xg6U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rfw05bz2vjg07cofrpbz.png" alt="Setup WordPress" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;那個 email 不用去改它，Local 有整合 &lt;a href="https://github.com/mailhog/MailHog"&gt;MailHog&lt;/a&gt; 來確認信件的寄發狀況。&lt;/li&gt;
&lt;li&gt;那個 multisite 的欄位一般不會使用。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Local 管理工具
&lt;/h2&gt;

&lt;p&gt;依照上面的步驟建立站台後，會回到 Local Sites 的頁面：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2Y83roFP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vra5uzmchjhvufaw3isd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2Y83roFP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vra5uzmchjhvufaw3isd.png" alt="Local Sites" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;頁面內大部分的內容應該都很好懂，重點提示一下幾個可能較陌生的功能：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;最下方的 Live Link 啟動後會透過 ngrok 的服務產生一組 xxxxxxxxx.ngrok.io 的網址，這組網址可以給外部的人訪問，即使這台本機電腦可能是在內網 NAT 後方也無妨，但每次開關 Live Link 的網址都會變動，所以真的只適合拿來給同事或客戶預覽，無法作為正式網址。詳細的 ngrok 介紹可以參考另外一篇〈&lt;a href="//@/2021/2021-12-09-ngrok/index.md"&gt;ngrok 讓本機發佈出可被訪問的網址&lt;/a&gt;〉。&lt;/li&gt;
&lt;li&gt;Local 又自動幫我們建立 HTTPS 所需要的 TLS 憑證，不過是自簽的，需要對憑證做信任許可，在 SSL 頁面的 TRUST 按下去，Local 會把憑證加入系統的信任憑證庫內。&lt;/li&gt;
&lt;li&gt;在 UTILITIES 內有可以進到 MailHog 的連結，MailHog 是 SMTP 發信的攔截器，所有 WordPress 寄出的信件都會被放進 MailHog 內，方便我們做格式或內容的確認。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Local 可以更好的地方
&lt;/h2&gt;

&lt;p&gt;Local 已經是本人遇過最佳的 WordPress 懶人包，但還是有些缺憾：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web server 只能選 Nginx 或 Apache，還無法用更新一代的 &lt;a href="https://caddyserver.com/"&gt;Caddy&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;Local 較適合單人單線開發，因為沒有同步或版控的機制，較不適合多人多線開發，不過這其實是萬惡的 WordPress 的原罪。&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>wordpress</category>
    </item>
    <item>
      <title>裝 WP-CLI</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Sat, 19 Aug 2023 21:53:46 +0000</pubDate>
      <link>https://dev.to/leon0824/zhuang-wp-cli-51hn</link>
      <guid>https://dev.to/leon0824/zhuang-wp-cli-51hn</guid>
      <description>&lt;p&gt;在裝 WordPress 之前，先裝 &lt;a href="https://wp-cli.org/"&gt;WP-CLI&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;參照 WP-CLI 〈&lt;a href="https://make.wordpress.org/cli/handbook/guides/installing/#recommended-installation"&gt;Installing&lt;/a&gt;〉文件。&lt;/p&gt;

&lt;p&gt;抓下來：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;確認一下運作正常：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;php wp-cli.phar &lt;span class="nt"&gt;--info&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;加上可執行屬性：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x wp-cli.phar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;移放到 /usr/local/bin/wp：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo mv &lt;/span&gt;wp-cli.phar /usr/local/bin/wp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;再次確認運作正常：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;wp &lt;span class="nt"&gt;--info&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;很簡單。&lt;/p&gt;

&lt;p&gt;我是用 CentOS，不過以上步驟應該都是通用的。&lt;/p&gt;

</description>
      <category>wordpress</category>
    </item>
    <item>
      <title>談 CSS 命名</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Sun, 13 Aug 2023 12:05:44 +0000</pubDate>
      <link>https://dev.to/leon0824/tan-css-ming-ming-33ni</link>
      <guid>https://dev.to/leon0824/tan-css-ming-ming-33ni</guid>
      <description>&lt;p&gt;一直以來本人較偏好的 CSS 命名都是依照 &lt;a href="https://eddiewen.gitbooks.io/rscss/content/"&gt;rscss&lt;/a&gt; 的原則，可是即便如此，還是常常會遇到難以命名的問題，這篇試著把問題梳理，並提出一些可能的解法。&lt;/p&gt;

&lt;h2&gt;
  
  
  rscss
&lt;/h2&gt;

&lt;p&gt;先簡單介紹一下 rscss 的命名原則，在 rscss 我們把網頁拆各部位解成一塊塊的元件（component），例如 header 元件，而元件可以再容納子元件，例如 header 元件內有 brand、navigation、search 三個子元件，它們也可以有各自的子元件，一直到最後的小單位稱為元素（element），像是導覽區內的單一的連結，或是搜尋區的文字框等等，但 rscss 的元素並非一定相當於 HTML 的 tag，例如前面的導覽區的一個連結，在 rscss 的概念是元素，但在 HTML 結構上它可能是數個 tag 組合起來的：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&amp;gt;&amp;lt;i&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;link text&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;總而言之 rscss 或其它的 CSS 命名原則，大多是以頁面的結構邏輯來解構與命名，而非以 HTML 碼結構來命名。&lt;/p&gt;

&lt;p&gt;當然 rscss 很棒，但它只是原則性的指南，現實上有些狀況需要自行排除，下面談現實上會遇到某些難以命名的情況。&lt;/p&gt;

&lt;h2&gt;
  
  
  這塊怎麼取名？container 還是 wrapper 還是 block 還是其它？
&lt;/h2&gt;

&lt;p&gt;對於組件，rscss 的命名原則是兩個單字，中間以連字號串連，例如 &lt;code&gt;.left-sidebar&lt;/code&gt; 或 &lt;code&gt;.search-block&lt;/code&gt;；而對於元素，則只用一個單字命名，這樣的命名原則很直觀的區分了組件與元素結構上的層級，但若是父子皆為組件的情況，又會再次遇到命名的問題。舉例來說，對於元件，最常用的也就是那三個單字—container、wrapper、block，例如這樣的 HTML 結構：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;main&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"main-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"list-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"list-block"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;xxx&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;以上面的例子來說，如果走到第四層，就立馬會遇到「單字不夠用」的問題，下面提出一些個人的解法。&lt;/p&gt;

&lt;h2&gt;
  
  
  可能的解法
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;加入 section 之類的描述「區塊」的字，讓可巢狀的層級更多，不過這看起來不是個夠通用的解法。&lt;/li&gt;
&lt;li&gt;對於功能型元件，強迫自己禁止使用 container、wrapper、block、section 之類的單字，而改用更具有描述性、語意性的字代替，譬如說 &lt;code&gt;.navigation-list&lt;/code&gt;，而 container、wrapper、block、section 僅限用於排版型元件，或稱為容器型元件，就是只為了切版而存在的元件。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  補充
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;關於描述「區塊」的單字們—container、wrapper、section、block，誰大誰小應該也是要在專案內被定義的，可參考別人家的文章：

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/best-way-implement-wrapper-css/"&gt;The Best Way to Implement a“Wrapper”in CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/q/4059163"&gt;CSS Language Speak: Container vs Wrapper?&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;別的流派的 CSS 命名原則有可能不會遇到前文描述的問題，不過過於畫蛇添足，非我所愛。把事情變複雜沒有比較厲害。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  參考資料
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/rstacruz/rscss"&gt;rscss&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>開源產業</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Thu, 10 Aug 2023 03:45:30 +0000</pubDate>
      <link>https://dev.to/leon0824/kai-yuan-chan-ye-47f0</link>
      <guid>https://dev.to/leon0824/kai-yuan-chan-ye-47f0</guid>
      <description>&lt;p&gt;從《&lt;a href="https://crazyangelo.github.io/Cathedral-and-Bazaar/"&gt;教堂與市集&lt;/a&gt;》說起，這部兩千年的經典文章告訴我們開源軟體與商業軟體的差異，開源軟體的開發模式像市集，看似無章法卻在無章法中有機般的長出自己的一條路；商業軟體的開發模式則像教堂，團隊遵守嚴謹的教條依照教條的指示建構軟體專案。&lt;/p&gt;

&lt;p&gt;然而今日再回頭看這篇二十年前的經典文章，卻令人覺得與當代的開源產業格格不入。&lt;/p&gt;

&lt;p&gt;是的，現在的開源，已經形成一種&lt;strong&gt;產業&lt;/strong&gt;，再拿教堂、市集來比喻可能都無法恰當的套入，而更像是兩者的混搭。凡是稍具規模的開源產品，源是開了，但是是由背後的資本企業所控制的，企業把產品開源，是有助於提昇在社群間的形像，但這一切努力最終還是以獲利為依歸。&lt;/p&gt;

&lt;p&gt;不要誤會，我不是要批判這種現象，我本人也並非佛心來著的人，也是要賺錢吃飯的。&lt;/p&gt;

&lt;p&gt;只是最近的一些新聞令我感受到過往那種純粹以熱請壯志為出發點的市集模式的消亡，並因此有點感慨罷了。&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>語意化網頁</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Tue, 18 Jul 2023 08:01:44 +0000</pubDate>
      <link>https://dev.to/leon0824/yu-yi-hua-wang-ye-jfc</link>
      <guid>https://dev.to/leon0824/yu-yi-hua-wang-ye-jfc</guid>
      <description>&lt;p&gt;&lt;a href="https://zh.wikipedia.org/wiki/%E8%AF%AD%E4%B9%89%E7%BD%91"&gt;語意網&lt;/a&gt;，或者也有人稱為語義網，都是英文 semantic web 的翻譯，指的是在 html 內埋入一些定義好的標籤，這些定義好的標籤裡面有可以讓機器更容易理解網頁的內容，也就是語意，這整件事就稱為語意網。&lt;/p&gt;

&lt;p&gt;語意網的概念一直到今天都還存在，不過換了個名字，現在埋語意標籤這件事一般稱為 &lt;a href="https://zh.wikipedia.org/wiki/%E6%90%9C%E5%B0%8B%E5%BC%95%E6%93%8E%E6%9C%80%E4%BD%B3%E5%8C%96"&gt;SEO&lt;/a&gt;，目的也更明確，就是盡可能的讓搜尋引擎讀懂我的網頁，並更準確的對應到潛在訪客的關鍵字搜尋結果內，最終就是要爭取更多的訪客，不過本人是個老派的人，在本文還是用語意網稱之。&lt;/p&gt;

&lt;p&gt;語意網要埋入的標籤，實做的規範很多，並未統一，甚至 HTML5 也加上了 &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; 等一系列標籤試圖讓 HTML 本身就可以語義化，不過事實證明這些在外觀和行為上和 &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; 一模一樣的標籤根本對幫助機器理解網頁這件事起不了作用，因為&lt;a href="https://whatwg-cn.github.io/html/multipage/"&gt;規範&lt;/a&gt;上對於標籤用法訂的過於寬鬆，導致沒有人知道怎麼用才叫正確，所以可以說人人都正確，也可以說人人都不正確，可是對爬蟲來說，這樣鬆散的標籤使用方式還是無法讓爬蟲正確的理解網頁的架構與內容。&lt;/p&gt;

&lt;p&gt;語意標籤除了給爬蟲讀優化 SEO 外，還有為障礙人士埋入的輔助標籤也是一種，這些標籤讓障礙人士的輔助設備可以更好的把網頁的理解那些是控制元素（導覽、按鈕等等）哪些是內容，這一系列統稱為 &lt;a href="https://www.w3.org/TR/html-aria/"&gt;ARIA&lt;/a&gt; 屬性，透過把 ARIA 屬性附加在 HTML 標籤內，就可以讓障礙人士的輔助設備理解網頁的架構。&lt;/p&gt;

&lt;p&gt;除了上面提到的 HTML5 語意標籤與 ARIA 屬性外，目前真正實際被廣泛採納的語意標籤系統是 Schema.org 與 Open Graph。&lt;/p&gt;

&lt;h2&gt;
  
  
  Schema.org
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://schema.org/"&gt;Schema.org&lt;/a&gt; 是由 Google、Microsoft、Yahoo、Yandex 一起成立的組織，他們定義了&lt;a href="https://schema.org/docs/full.html"&gt;八百多種的結構化欄位格式（schema）&lt;/a&gt;，包括文章、新聞、電影、書籍、音樂、網誌、網站、活動等等，而 schema 的撰寫格式（syntax）可以是 RDFa、Microdata 與 &lt;a href="https://json-ld.org/"&gt;JSON-LD&lt;/a&gt;。&lt;/p&gt;

&lt;h3&gt;
  
  
  Schema / Syntax
&lt;/h3&gt;

&lt;p&gt;中文說的「格式」在資訊領域可能對應到三個不同的英文單詞－format / schema / syntax。&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Format&lt;/dt&gt;
  &lt;dd&gt;
    指的是檔案的格式，以影片為例，檔案格式會有 .mov、.mp4 等。
  &lt;/dd&gt;
  &lt;dt&gt;Schema&lt;/dt&gt;
  &lt;dd&gt;
    指的是資料欄位的定義，以通訊錄來說，會有姓名、電話、地址、年齡等欄位，而各個欄位又有自己的欄位定義，譬如說電話欄位只能是數字或符號，不能是文字；年齡欄位只能是整數。
    更進階的會牽涉到欄位的歸納與分組，也就是關聯式資料庫的領域。
  &lt;/dd&gt;
  &lt;dt&gt;Syntax&lt;/dt&gt;
  &lt;dd&gt;
    指的是語法格式，延續上面的通訊錄例子，這些欄位定義可以用不同的語法規範撰寫，可能是 JSON 或 XML 或 SQL 等。
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;在實務上，JSON-LD 已經是目前的主流，所以可以無視其它的選項。&lt;/p&gt;

&lt;p&gt;雖然 Schema.org 定義了八百多種 schema，但 &lt;a href="https://developers.google.com/search/docs/guides/search-gallery?hl=zh-tw"&gt;Google 只採用幾十種&lt;/a&gt;，Google 不認得的，除非是自有其它用途，否則看起來完全沒有實用價值。&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Graph
&lt;/h2&gt;

&lt;p&gt;Facebook 無視於現成的 Schema.org 而自行成立了 &lt;a href="https://ogp.me/"&gt;Open Graph&lt;/a&gt;。Open Graph 因為臉書的關係，也是目前主流標準之一，語法以 HTML 為基礎，比 JSON-LD 更為簡單易讀也易寫。&lt;/p&gt;

&lt;p&gt;Open Graph 只有四個基礎欄位－title、type、image、url，範本也很簡單：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;prefix=&lt;/span&gt;&lt;span class="s"&gt;"og: http://ogp.me/ns#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;The Rock (1996)&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"The Rock"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"video.movie"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:url"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"http://www.imdb.com/title/tt0117500/"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"http://ia.media-imdb.com/images/rock.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open Graph 標籤內定義的內容具體會影響網頁被貼進 Facebook 後會呈現的樣貌，而 Open Graph 雖然簡單，但相較於 Schema.org 還是有所不足，以目前的業界需求來說，在臉書放產品貼文是非常普遍的需求，但 Open Graph 卻缺少了 product 這類的 type，所以要打產品的，在臉書還是只能用 &lt;a href="https://www.facebook.com/marketplace/"&gt;Facebook Marketplace&lt;/a&gt; 或 &lt;a href="https://www.facebook.com/business/help/2343035149322466?id=1077620002609475"&gt;Facebook Shops&lt;/a&gt;。&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;time&gt;2020-05-27&lt;/time&gt; 更新
&lt;/h3&gt;

&lt;p&gt;Open Graph 有 product type，不過定義在 &lt;a href="https://developers.facebook.com/docs/payments/product/"&gt;Facebook 自己的文件&lt;/a&gt;內。&lt;/p&gt;

&lt;h2&gt;
  
  
  其它
&lt;/h2&gt;

&lt;p&gt;除了 Schema.org 和 Open Graph，越來越多台灣人用的 Twitter 也有自己的標籤系統 &lt;a href="https://developer.twitter.com/en/docs/tweets/optimize-with-cards/guides/getting-started"&gt;Twitter Cards&lt;/a&gt;，&lt;a href="https://developer.twitter.com/en/docs/tweets/optimize-with-cards/guides/getting-started#opengraph"&gt;Twitter Cards 相容於 Open Graph&lt;/a&gt;，意思是 Twitter 爬蟲找不到 Twitter Cards 標籤的情況下會去找 Open Graph 的標籤，所以不用特別為 Twitter Card 埋入標籤。&lt;/p&gt;

&lt;h2&gt;
  
  
  第三方工具
&lt;/h2&gt;

&lt;p&gt;前面講了這麼多格式，其實不用靠自己手工製作埋入網頁，有許多現成的第三方服務可以幫我們把這些格式產生出來，隨便找一下就有：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://webcode.tools/"&gt;Web Code Tools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  結語
&lt;/h2&gt;

&lt;p&gt;Schema.org 和 Open Graph 都是目前在網頁內埋入的語意格式的主流，它們能讓 Google 和 Facebook 更精確的解讀網頁的內容，對有心經營網站的人來說是必須加入的元素。&lt;/p&gt;

</description>
      <category>semantic</category>
      <category>opengraph</category>
    </item>
    <item>
      <title>如何在 elementary OS 安裝 Firefox Beta</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Mon, 03 Jul 2023 00:52:43 +0000</pubDate>
      <link>https://dev.to/leon0824/ru-he-zai-elementary-os-an-zhuang-firefox-beta-374c</link>
      <guid>https://dev.to/leon0824/ru-he-zai-elementary-os-an-zhuang-firefox-beta-374c</guid>
      <description>&lt;h2&gt;
  
  
  Firefox Beta
&lt;/h2&gt;

&lt;p&gt;Firefox 除了一般的版本之外，還另外有 Beta、Developer、Nightly 版，這些額外的預覽版本是用來供應給網頁開發者等等的早期用戶，這些早期用戶可以透過預覽版的 Firefox 來測試新的網頁技術，當然既然是預覽版那麼它們的穩定性一定是不如一般版的，喜歡嚐鮮或工作上對新的網頁技術有需求的朋友可以斟酌安裝。&lt;/p&gt;

&lt;h2&gt;
  
  
  elementary OS
&lt;/h2&gt;

&lt;p&gt;elementary OS 是以 Ubuntu Desktop 為基礎，再改用 elementary OS 自己的桌面環境而來，提供了比原本 Ubuntu Desktop 更美觀也更友善的桌面體驗，並且依然保留了 Ubuntu 的系統架構與沿用 Debian 流派的套件管理系統 APT，所以網路上對 Debian / Ubuntu 的文章大多也可以適用於 elementary OS。&lt;/p&gt;

&lt;h2&gt;
  
  
  PPA
&lt;/h2&gt;

&lt;p&gt;前面提到過 elemantary OS 是基於 Ubuntu 的，並且也是用 APT 作為套件管理系統，因此若要安裝普通版的 Firefox，則只要一行簡單的指令：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;firefox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;因為普通版的 Firefox 有被收錄在 Ubuntu 的套件庫內，而 elementary OS 也是有沿用 Ubuntu 的套件庫，才能安裝的這麼輕鬆寫意。&lt;/p&gt;

&lt;p&gt;然而如果想嘗試 Firefox Beta，你會發現好像有難度，在 Firefox Beta 的下載頁雖然有列出 Linux 版的下載包，但是它只提供 .tar.bz2 的壓縮包，雖然解開免安裝就可以用，但並未整合入 elementary OS 的 app 選單內，有點像以前 Windows 上的綠色軟體，但這不是我想要的，本人還是較偏好與 OS 能夠做到整合的做法，因此我們必須手動把 Firefox Beta 的 PPA 套件庫加入系統內。&lt;/p&gt;

&lt;p&gt;PPA，即 Personal Package Archive，是讓任何大眾可以寄存自己的 DEB 套件的平台，最大的 PPA 平台 Launchpad 也是由 Ubuntu 背後的公司 Canonical 所營運的。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://launchpad.net/~mozillateam/+archive/ubuntu/firefox-next"&gt;Firefox Beta PPA 的專案頁面&lt;/a&gt;。裡面的說明有教導我們如何把這個 PPA 套件庫加入我們的 elementary OS 之內，依照頁面的指示加入 PPA 套件庫：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;add-apt-repository ppa:mozillateam/firefox-next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然後重整套件庫清單：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;最後安裝 Firefox Beta：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;firefox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;注意到，套件的名稱還是 &lt;code&gt;firefox&lt;/code&gt;，也就是說這個 PPA 內的 Firefox Beta 的套件名稱還是 &lt;code&gt;firefox&lt;/code&gt;，並且取代了原本 Ubuntu 套件庫的那個普通版的 &lt;code&gt;firefox&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;安裝完之後我們的系統內的 Firefox 應該就會被取代成 Firefox Beta。&lt;/p&gt;

</description>
      <category>firefox</category>
      <category>linux</category>
    </item>
    <item>
      <title>Google Chrome 好快啊！</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Mon, 19 Jun 2023 13:12:00 +0000</pubDate>
      <link>https://dev.to/leon0824/google-chrome-hao-kuai-a--4c4d</link>
      <guid>https://dev.to/leon0824/google-chrome-hao-kuai-a--4c4d</guid>
      <description>&lt;p&gt;Google Chrome 跑 JS 的速度跟飛的一樣，如果想做更量化的數據測試，那可以上 &lt;a href="https://browserbench.org/"&gt;BrowserBench.org&lt;/a&gt;，裡面有三種測試：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JetStream2&lt;/li&gt;
&lt;li&gt;MotionMark&lt;/li&gt;
&lt;li&gt;Speedometer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其中的 MotionMark 比較偏向圖形效能的測試，而 Spee*&lt;em&gt;dom&lt;/em&gt;*eter 比較偏向 DOM 操作的測試，對現代化的 web app 來說，應該是比較適合用 Speedometer 來跑分。&lt;/p&gt;

&lt;p&gt;同場加映 &lt;a href="https://experiments.withgoogle.com/"&gt;Experiments with Google&lt;/a&gt; 裡面的實驗性作品有的相當有創造力，同時又能操爆你的瀏覽器。&lt;/p&gt;

</description>
      <category>browser</category>
    </item>
    <item>
      <title>Java 語言筆記</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Sat, 17 Jun 2023 14:24:06 +0000</pubDate>
      <link>https://dev.to/leon0824/java-yu-yan-bi-ji-2la2</link>
      <guid>https://dev.to/leon0824/java-yu-yan-bi-ji-2la2</guid>
      <description>&lt;h2&gt;
  
  
  迴圈控制
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Break
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;break&lt;/code&gt; 用來中斷整個迴圈：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// i = 2 就中斷整個迴圈&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;輸出：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0
1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Continue
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;continue&lt;/code&gt; 用來略過某次迴圈：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 跳過 i = 2 的迴圈&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;輸出：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0
1
3
4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Label
&lt;/h3&gt;

&lt;p&gt;如果是巢狀迴圈的話勒？&lt;/p&gt;

&lt;p&gt;Java 的迴圈是可以命名的，稱為 label，可以指定要 &lt;code&gt;break&lt;/code&gt; 或 &lt;code&gt;continue&lt;/code&gt; 的是哪一層的迴圈：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nl"&gt;labelA:&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;labelB:&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="n"&gt;labelA&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 會中斷整個 labelA&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;帥吧！&lt;/p&gt;

&lt;h2&gt;
  
  
  常數
&lt;/h2&gt;

&lt;p&gt;很簡單，在宣告前加個 final 關鍵字就是常數，如同多數程式語言，常數的命名習慣上全大寫。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;MY_ANGEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;689&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;常數建立後是不能修改的，編譯時會檢查。&lt;/p&gt;

</description>
      <category>java</category>
    </item>
  </channel>
</rss>
