2025/10/27

Varnish

varnish 是一種反向代理伺服器軟體,以記憶體方式存取 cache。透過 VCL (Varnish Configuration Language) 讓使用者設定 varnish。

安裝

在 Rocky Linux 8 安裝

dnf -y install varnish

設定

修改原本的設定檔

mv /etc/varnish/default.vcl /etc/varnish/default.vcl.bak
vi /etc/varnish/default.vcl

此設定檔只會 cache png 圖片檔案 7 天

backend default {
    .host = "127.0.0.1";  # Your app server
    .port = "8081";       # Your app server port
}

sub vcl_recv {
    # 僅對 GET 和 HEAD 快取
    if (req.method != "GET" && req.method != "HEAD") {
        return (pass);
    }

    # 僅快取 .png 圖檔,其餘請求不快取
    # 比對 URL 結尾為 .png
    if (req.url ~ "\.png$") {
        # cache
        return (hash);
    } else {
        # pass
        return (pass);
    }
}

sub vcl_backend_response {
    if (beresp.status == 200) {
        # Cache for 7 day
        set beresp.ttl = 7d;
    } else {
        set beresp.ttl = 0s;
    }
}

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "HIT";
    } else {
        set resp.http.X-Cache = "MISS";
    }
}

啟動

systemctl start varnish
systemctl enable varnish

修改 disk cache

Varnish 無法永久將 cache 儲存到 disk (decprecated),但可透過 memory mapping,將記憶體的資料存放到 file

sudo systemctl edit varnish

修改 service

[Service]
ExecStart=
ExecStart=/usr/sbin/varnishd \
  -a :6081 \
  -f /etc/varnish/default.vcl \
  -s file,/var/lib/varnish/varnish_storage.bin,2G

確認 file folder 存在

sudo mkdir -p /var/lib/varnish
sudo chown varnish: /var/lib/varnish

restart Varnish

# restart varnish
sudo systemctl daemon-reexec
sudo systemctl restart varnish

2025/10/13

如何使用 vue3-draggable-next esm module

vue3-draggable-next 是 draggable 套件的 vue3 版本,預設在 dist 裡面,只提供 umd 及 commonjs module,如果要在 browser 裡面,透過 esm 的方式 import module,必須要先自己製作一個簡單的 esm js

vuedraggable.umd.js 檔案,就跟 vuedraggable.umd.min.js 放在同一個目錄

// 確保 UMD 先載入(它會掛在 window.vuedraggable)
import "./vuedraggable.umd.min.js";
// 把全域變數 export 出去,提供 ESM 的 default
export default window.vuedraggable;

然後在 html 裡面,先以 importmap 方式列出 import list

因為 draggable 有使用到 sortablejs,故這邊要先放到 import list

另外在下面的 module 裡面,要先將 Vue 及 Sortable 掛載到全域變數裡面,因為 draggable 是這樣直接呼叫 Vue 跟 Sortable,所以必須這樣掛載

    <script type="importmap">
    {
        "imports": {
            "vue": "../js/lib/vue-3.5.13/vue.esm-browser.prod.min.js",
            "vuedraggable": "../js/lib/vue3-draggable-next-4.1.4/vuedraggable.esm.js",
            "sortablejs": "../js/lib/sortable-1.15.6/sortable.esm.js"
        }
    }
    </script>

    <script type="module">
        import * as Vue from 'vue';
        window.Vue = Vue; // 讓 draggable UMD 找得到 Vue.defineComponent

        import Sortable from 'sortablejs';
        window.Sortable = Sortable;
    </script>

最後可製作 App

  <script type="module">
    import { createApp, reactive } from "vue";
    import Draggable from "vuedraggable";

    const state = reactive({
      rows: [
        { id: 1, name: "Item A" },
        { id: 2, name: "Item B" },
        { id: 3, name: "Item C" }
      ]
    });

    createApp({
      components: { Draggable },
      setup() {
        return { state };
      }
    }).mount("#app");
  </script>

html 的部分,可放在 tbody 裡面。

這邊注意 #item="{ element, index } #item 裡面,只能用 element, index,不能改成其他變數名稱。否則會一直遇到 undefined 物件的問題。

<div id="app">
    <table border="1">
      <thead>
        <tr>
          <th>Drag</th>
          <th>Name</th>
        </tr>
      </thead>
      <!-- draggable tbody -->
      <draggable
        tag="tbody"
        v-model="state.rows"
        handle=".drag-handle"
      >
        <template #item="{ element, index }">
          <tr :key="element.id">
            <td class="drag-handle" style="cursor: grab;">☰</td>
            <td>{{ element.name }}</td>
          </tr>
        </template>
      </draggable>
    </table>
    <pre>{{ state.rows }}</pre>
  </div>

vuedraggable 是 SortableJS 的包裝,所以大部分事件都對應到 SortableJS events,最常用的是:

  • @start 拖曳開始

  • @end 拖曳結束

  • @add 新元素被加入(跨清單)

  • @remove 元素被移除

  • @update 同一清單內順序改變

  • @change 綜合事件(新增、刪除、移動都會觸發)

實際上操作時

  • 拖曳開始到結束:會觸發 @start 與 @end

  • 順序有變動:會觸發 @update 和 @change

  • 跨清單拖曳:會觸發 @add 與 @remove