2024年3月18日 星期一

在前端寫後端?如何寫出不會被快取清掉的資料

前言

前陣子接到一個需求,要前端產出一個uuid,傳給後端當身份驗正。

冷靜點各位,先別噴!雖然身份驗證坐在前端前所未聞,但任務確實就是這樣。

開發過前端的都知道,前端存資料選項沒幾個,就算我把資料存local storage,一但遇到清除快取也會消失。一開始PM那邊當然是說沒關係,我們盡量,但背後還是不斷給壓力說看有沒有辦法解決......這擺明就是後端的工作,我實在想不明白為什麼必須得前端做想,他們困難點到底在哪,相當然爾我兩手一攤說沒有辦法,結果主管有天突然就跳出來了說他想到更好的方法了!!

我們先來解釋一下他的想法,簡單說把產生uuid的做成單獨的一個站,然後除了存入local storage之外,還要用postMessage的方式將產生的uuid回傳,看到這裡聰明的小夥伴應該猜到,在原專案用iframe將上面這個站嵌入就可以了,變且addEventListener("message", (e) => { e.data })去監聽回傳內容就好。

這樣除非對方真的很專業開啟了產生uuid的站並清除快取,不然在原本的站怎麼清uuid都會保持不變,我附上code

// uuid page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SSO Page</title>
</head>
<body>
<script>
function generateUUID() {
var d = new Date().getTime();
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
d += performance.now(); // 使用性能計時器來增加隨機性
}
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
}
var uuid = localStorage.getItem('uuid');
if(!uuid){
uuid = generateUUID();
localStorage.setItem('uuid', uuid);
}
// 發送 local storage 中的數據給父頁面
window.parent.postMessage(uuid, document.referrer);
</script>
</body>
</html>


// parent page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Parent Page</title>
</head>
<body>
<iframe src="https://uuid.com" width="1" height="1" style="display:none"></iframe>
<script>
// 接收來自子 iframe 的消息
window.addEventListener('message', function(event) {
  console.log(event.data) // uuid
}, false);
</script>
</body>
</html>

後記

我雖然滿佩服主管可以想到這種奧步的,且這招不光是只能用來存資料,也可以拿來做些偷雞摸狗的事情,例如我第一分工作就看到老闆使用iframe更新主頁面的畫面.......某種意義上來說也是ajax拉,把部分後端的工作移到前端來做。不考量安全性的話......天啊,我好不想想起當時那個畫面==大家還是考量一下安全性,珍惜生命,少用iframe吧

2024年3月15日 星期五

要改變component的樣式為什麼不是用v-deep

前言

在與前同事隨意尬聊的狀況下,前團是提出要我幫他看code的需求,他說他一直無法改變component的樣式,我想說不過就是v-deep的麽簡單的事情,所以想也不想就答應了,殊不知最終我搞了兩個小時的故事....

問題起源於他使用了套件vue-advanced-chat來製作聊天視窗,正確來說是前同事使用,所以他也只是背鍋而已。然後公司需求很多,然後這套件很多功能其實都無法達成需求。這故事告訴我們,選元件要慎選,如果客製化需求太多,自己造輪子不一定是不好,至少彈性足夠。

接下來要說說這次遇到什麼問題,就是audio的樣式在某種解析度會跑版,需要用css去修正,但無論用v-deep或是global寫css,死活都是吃不到,正一籌莫展之際,我看到了幾個關鍵字。

首先第一個為什麼這個套件的tag還可以保持原樣<vue-advanced-chat>,然後在tag下面出現#shadow-root(open)的字樣,下面可以展開,上次我看到類似的景樣是在iframe裡面,如果這狀況跟iframe真的是類似,那確實css selector無法吃到裡面也很正常。我上網查了關鍵字發現確實是類似的情況shadow dom,簡單說被web component包裝成一個原生tag了。

我原本想說有了關鍵字剩下就簡單了,所以去查要怎麼樣才能讓shadow dom吃到css,查了半天都說有:host之類的選擇器可以用,但每個都是過了一樣沒有效果,但看到這網站說明後才大致明瞭這東西必須在寫web component當時,也就是內部撰寫,所以也還是沒辦法達成我要的效果,且裡面也明確表示css是無法從外層直接影響內層的樣式。

正當我想放棄時我想到,既然css無法做到,能否使用javascript去強制修改呢?結果還真讓我找到解法,要分成兩個步驟來說,首先你要可以選擇到shadow dom,做法也不難,就是你要在選擇到web component之後,直接.shadowRoot就可以選到dom,之後再創造一個style並把內容寫好寫滿,之後appendChild進去就好,我們直接來看code

// 寫一個可以選擇到shadow dome的selector
const querySelectorAll = (node,selector) => {
const nodes = [...node.querySelectorAll(selector)],
nodeIterator = document.createNodeIterator(node, Node.ELEMENT_NODE);
let currentNode;
while (currentNode = nodeIterator.nextNode()) {
if(currentNode.shadowRoot) {
nodes.push(...querySelectorAll(currentNode.shadowRoot,selector));
}
}
return nodes;
}

// inject css
const style = createElement("style")
style.innerHTML = `
.class { ...... }
......
`

document.querySelector("custom-web-component").shadowRoot.appendChild(style)

這樣就大功告成拉。

後記

我就說好好的vue component為什麼要包成web component,應該是考量到要讓各種框架使用,然後你包沒有關係,為什麼要包成shadow dom,然後你包成shadow dom沒有關係,為什麼還要有bug!!好在大爺我幾十歲了,不怕你!雖然已經一點多了,下班

2024年3月11日 星期一

vscode常常壞掉該怎麼處理

前言

如果有寫typescript的人應該再複製貼上或使用snippets來輔助輸入的人應該很常發現貼上後莫名畫面中出現很多紅線,然後vscode的輔助開發就壞掉了,需要關掉重啟才可以

今天我心血來潮,嘗試使用指令reload window去重啟vscode,這樣確實可以達到不用關閉就可以修復編輯器的效果,但每次都要按command+shift+p 然後再輸入reload...實在有點繁瑣,心想應該可以設定個command+r的快捷鍵讓他自動重啟吧

所以我打開快捷設定,我這邊用英文版,所以我不知道中文版叫什麼名字,可以參考圖片


打開之後找到reload window發現原來已經有快捷了,而且還正好是command+r,但為什麼怎麼按都沒反應呢?後來上網查在知道原來when的這個欄位也要設定,要設定觸發情境

所以在reload window上面點右鍵選擇修改上面點右鍵選擇修改when,然後輸入editorTextFocus

因為壞掉一般都在程式編輯過程吧。設定完之後就大功告成了,再遇到壞掉直接敲快捷就搞定了。

祝大家之後都可以準時下班~啾咪~

2024年3月10日 星期日

bilibili內嵌設定

在祖國你別想說要用youtube絕對封得你不要不要,如果直接把影片放s3也不見得會比bilibili穩定,所以難免會使用到影片嵌入。

但直接使用官方給你的內遷網址範例如下

<iframe src="//player.bilibili.com/player.html?aid=10335022&bvid=BV1nx411m7bV&cid=17072810&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>

然後如果你要加上自動播放等其他的功能,autoplay=1,之類的功能,你會發現根本不屌你,你上網查基本上也查不太到有用的資料。如果只是參數沒用那也就算了,safari網頁開啟竟然沒有聲音....我你個去你們家測試工程師會不會太混了一點!

終於找到這篇說明,原來bilibili有寫一個播放器,所以只要把網址稍微改一下

<iframe src="//www.bilibili.com/blackboard/html5mobileplayer.html?aid=10335022&bvid=BV1nx411m7bV&cid=17072810&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>

就是//player.bilibili.com/player.html換成了//www.bilibili.com/blackboard/html5mobileplayer.html

之後其他網站叫的參數基本上就可以生效了,safari功能也正常了,交差去吧~


2024年2月27日 星期二

檢查是否有出現在畫面中可以使用IntersectionObserver

 直接附上程式碼,本程式以vue3寫法為範例


<template>
    <div>
        <div> ... </div>
        <div v-if="!checkFinished" :style="{ height: footerRef?.clientHeight + 'px' }"></div>
    <div ref="heightCheckerRef" :style="{ height: marginBottom + 'px' }" />
        <div ref="footerRef" class="px-3 py-4 fixed">
        <button class="bg-gray-500 w-full text-white rounded py-2">返回网站</button>
    </div>
    </div>
</template>

<script setup>
const footerRef = ref(null)
const heightCheckerRef = ref(null)
const checkFinished = ref(false)
const marginBottom = ref(0)

onMounted(async () => {
  // 在資料齊全後
const observer = new IntersectionObserver(([checker]) => {
if (!checker.isIntersecting) { // 是否有在畫面上
marginBottom.value = footerRef.value.offsetHeight
}
    observer.unobserve(heightCheckerRef.value) // 取消觀察
checkFinished.value = true
})
observer.observe(heightCheckerRef.value) // 放入要觀察的DOM
})
</scirpt>


畫面中情境為footer是fixed,如果有內容被footer擋住,那勢必要設個margin-bottom,可以用類似的方法去做檢查

同理,如果有scroll的情境,拉致最底需要加載資料,可以不用在那邊算高度了,也可以使用IntersectionObserver去檢查最底下區塊是否有出現在畫面中,一旦出現就加載,直到最後一頁

HD鬼故事第N集

 HD鬼故事第N集:

在公元2xxx年,一日雲端設備有些故障,某位年薪據說超過千萬的高級工程師,一頓操作猛如虎,下了重開機指令,頓時風雲變色,機器再啟之際已無過往跡象,不僅程式碼刪光,連資料庫也不見蹤跡,詢問原A場員工才得知,當初啟用機器使用的是暫存碟,也就是重啟資料就會刪得精光,且是破壞式格式化,一旦重啟神仙難救。


公司上下馬上盤點各種可能補救措施,力求把多年客戶資料給救回來,有人提出備份的資料庫(在原來硬碟一起被格式化了,至於為什麼備份的資料庫要跟資料庫放同一個硬碟,這又是另一則鬼故事了),也有人想從request的log試圖把資料補救一點回來,可惜最終依然無力回天。昨日種種譬如昨日死。


沒人知道這年薪千萬的工程師最終下場如何,只知道,做人最好不要太自負,不熟要懂得請教專業人員。


最終,今年才剛開始,希望人人都能領到下個月薪水過個好龍龍year~


免責聲明:以上都是我在翻閱九陽神功時,不小心撇見旁邊的註解文,也不知道什麼意思就轉錄出來了,如有雷同絕對是巧合

2024年2月14日 星期三

Tauri 濃縮版的Electron.js

前言

老實說我還沒開始學這塊,因為也沒什麼場景可以使用,但網路上看起來這玩意兒挺有趣的,相比起來也更輕量,未來或許有機會用到,先做一下紀錄

附上參考連結