如何搭配 NW.js 使用
本指南說明如何在 NW.js (先前稱為 node-webkit) 應用程式中使用 Socket.IO。
使用
預設情況下,NW.js 會建立兩個不同的 JavaScript 環境
- 瀏覽器環境,可存取 Web API (每個視窗/框架一個環境)
- Node 環境,可存取 Node.js API (所有視窗/框架共用)
參考:https://nwjs.dev.org.tw/en/latest/For%20Users/Advanced/JavaScript%20Contexts%20in%20NW.js/
Socket.IO 用戶端可以建立在兩個環境中,視你的使用案例而定。
瀏覽器環境
index.html
<!doctype html>
<html lang="en">
<body>
<p>Status: <span id="status"></span></p>
<p>Transport: <span id="transport"></span></p>
<!-- from the socket.io-client package -->
<script src="./node_modules/socket.io-client/dist/socket.io.min.js"></script>
<!-- or from a CDN -->
<!--<script src="https://cdn.socket.io/4.7.5/socket.io.js"></script>-->
<script>
const socket = io("https://#:3000");
const statusSpan = document.getElementById("status");
const transportSpan = document.getElementById("transport");
statusSpan.innerText = "Disconnected";
transportSpan.innerText = "N/A";
socket.on("connect", () => {
statusSpan.innerText = "Connected";
transportSpan.innerText = socket.io.engine.transport.name;
socket.io.engine.on("upgrade", (transport) => {
transportSpan.innerText = transport.name;
});
console.log(`connect ${socket.id}`);
});
socket.on("connect_error", (err) => {
console.log(`connect_error due to ${err.message}`);
});
socket.on("disconnect", (reason) => {
statusSpan.innerText = "Disconnected";
transportSpan.innerText = "N/A";
console.log(`disconnect due to ${reason}`);
});
socket.emit("hello", "world");
</script>
</body>
</html>
在此情況下,Socket.IO 用戶端會使用瀏覽器提供的 WebSocket 物件。
優點
- Socket.IO 連線可以在 DevTools 中進行除錯
缺點
- 僅使用 WebSocket 時,
extraHeaders
選項會被忽略
const socket = io("https://#:3000", {
transports: ["websocket"],
extraHeaders: {
"my-custom-header": "1234" // ignored
}
});
Node 環境
index.html
<!doctype html>
<html lang="en">
<body>
<p>Status: <span id="status"></span></p>
<p>Transport: <span id="transport"></span></p>
<script>
const statusSpan = document.getElementById("status");
const transportSpan = document.getElementById("transport");
const { registerListeners, emit } = require("./socket");
registerListeners({ statusSpan, transportSpan });
emit("hello", "world");
</script>
</body>
</html>
socket.js
const { io } = require("socket.io-client");
const socket = io("https://#:3000");
exports.registerListeners = function ({ statusSpan, transportSpan }) {
statusSpan.innerText = "Disconnected";
transportSpan.innerText = "N/A";
function onConnect() {
statusSpan.innerText = "Connected";
transportSpan.innerText = socket.io.engine.transport.name;
socket.io.engine.on("upgrade", (transport) => {
transportSpan.innerText = transport.name;
});
console.log(`connect ${socket.id}`);
}
if (socket.connected) {
onConnect();
}
socket.on("connect", onConnect);
socket.on("connect_error", (err) => {
console.log(`connect_error due to ${err.message}`);
});
socket.on("disconnect", (reason) => {
statusSpan.innerText = "Disconnected";
transportSpan.innerText = "N/A";
console.log(`disconnect due to ${reason}`);
});
}
exports.emit = function (...args) {
socket.emit(...args);
}
在這種情況下,Socket.IO 客戶端將使用 ws
套件提供的 WebSocket 物件。
優點
Socket.IO 連線將在應用程式的不同視窗間共用
客戶端支援特定於 Node.js 的額外選項,例如
agent
、ca
或cert
const socket = io("https://#:3000", {
ca: fs.readFileSync("cert.pem")
});
- 僅在使用 WebSocket 時,
extraHeaders
選項才會正確傳送
const socket = io("https://#:3000", {
transports: ["websocket"],
extraHeaders: {
"my-custom-header": "1234"
}
});
缺點
- Socket.IO 連線無法在 DevTools 中進行偵錯(即使選擇「檢查背景頁面」)。
範例專案
https://github.com/socketio/socket.io/tree/main/examples/nwjs-example
這就是全部,感謝您的閱讀!