Để tạo một ứng dụng Node.js Electron chạy dưới nền (background), bạn cần thiết lập ứng dụng để có thể hoạt động mà không cần hiển thị cửa sổ (hoặc với cửa sổ bị ẩn) và vẫn thực hiện các tác vụ như thông báo, xử lý dữ liệu, hoặc giao tiếp với hệ thống.
Dưới đây là hướng dẫn cụ thể:
1. Tạo ứng dụng Electron cơ bản
Đầu tiên, bạn cần đảm bảo rằng ứng dụng Electron của bạn đã được thiết lập. Một tệp main.js
cơ bản sẽ trông như sau:
const { app, BrowserWindow } = require('electron');
let mainWindow;
app.on('ready', () => {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
show: false, // Ẩn cửa sổ khi khởi động
webPreferences: {
nodeIntegration: true,
},
});
mainWindow.loadFile('index.html');
// Đảm bảo không đóng hoàn toàn khi cửa sổ bị tắt
mainWindow.on('close', (e) => {
if (!app.isQuiting) {
e.preventDefault();
mainWindow.hide(); // Ẩn cửa sổ thay vì đóng
}
});
});
2. Chạy ứng dụng dưới nền (Background Process)
a. Ẩn cửa sổ ứng dụng
Sử dụng thuộc tính show: false
khi tạo cửa sổ (BrowserWindow
).
Bạn cũng có thể ẩn cửa sổ sau khi khởi động bằng mainWindow.hide()
.
b. Kích hoạt biểu tượng tray (System Tray)
Thêm biểu tượng vào system tray để người dùng vẫn có thể tương tác với ứng dụng.
Ví dụ:
const { Tray, Menu } = require('electron');
let tray;
app.on('ready', () => {
tray = new Tray('path/to/icon.png'); // Đường dẫn đến icon của ứng dụng
const contextMenu = Menu.buildFromTemplate([
{ label: 'Mở ứng dụng', click: () => mainWindow.show() },
{ label: 'Thoát', click: () => {
app.isQuiting = true;
app.quit();
}},
]);
tray.setToolTip('Ứng dụng chạy nền của tôi');
tray.setContextMenu(contextMenu);
tray.on('click', () => {
mainWindow.show(); // Hiển thị cửa sổ khi nhấp vào tray
});
});
c. Giữ ứng dụng hoạt động khi cửa sổ bị ẩn
Sử dụng mainWindow.hide()
thay vì mainWindow.close()
để ứng dụng không bị đóng hoàn toàn.
3. Chạy tác vụ dưới nền (Background Task)
Sử dụng các module Node.js như child_process
, worker_threads
, hoặc gói như node-schedule
để chạy các tác vụ nền.
Ví dụ: Một task chạy lặp trong nền:
const { setInterval } = require('timers');
function runBackgroundTask() {
setInterval(() => {
console.log('Tác vụ đang chạy dưới nền...');
// Thực hiện logic, như kiểm tra dữ liệu mới hoặc gửi thông báo
}, 5000); // Mỗi 5 giây
}
// Chạy task khi ứng dụng sẵn sàng
app.on('ready', () => {
runBackgroundTask();
});
4. Tự động khởi động khi bật máy (Auto Start)
Sử dụng gói electron-settings
hoặc auto-launch
để tự động khởi động ứng dụng khi người dùng bật máy.
Ví dụ với gói auto-launch
:
const AutoLaunch = require('auto-launch');
const appLauncher = new AutoLaunch({
name: 'MyElectronApp',
path: app.getPath('exe'), // Đường dẫn tới file thực thi
});
appLauncher.isEnabled().then((isEnabled) => {
if (!isEnabled) {
appLauncher.enable();
}
}).catch((err) => {
console.error('Lỗi khi thiết lập tự động khởi động:', err);
});
Cài đặt gói:
npm install auto-launch
5. Gửi thông báo từ background
Electron hỗ trợ gửi thông báo native:
const { Notification } = require('electron');
function showNotification(title, body) {
new Notification({ title, body }).show();
}
app.on('ready', () => {
showNotification('Ứng dụng đang chạy nền', 'Ứng dụng của bạn đã sẵn sàng!');
});
6. Đóng ứng dụng hoàn toàn
Đảm bảo ứng dụng không còn chạy trong system tray khi người dùng chọn thoát:
tray.on('right-click', () => {
const contextMenu = Menu.buildFromTemplate([
{ label: 'Thoát', click: () => {
app.isQuiting = true;
app.quit();
}},
]);
tray.popUpContextMenu(contextMenu);
});
Tóm tắt các bước
- Ẩn cửa sổ khi khởi động (
show: false
). - Thêm tray icon để ứng dụng dễ dàng tương tác dưới nền.
- Tạo tác vụ nền với
setInterval
,worker_threads
, hoặc các gói nhưnode-schedule
. - Tự động khởi động khi bật máy với gói
auto-launch
. - Gửi thông báo hệ thống khi cần thiết để tương tác với người dùng.
😊
Có, các tác vụ đang chạy trong ứng dụng Electron vẫn sẽ tiếp tục hoạt động ngay cả khi cửa sổ ứng dụng bị ẩn, miễn là ứng dụng vẫn đang chạy (tức là không bị đóng). Điều này là do bản chất của Electron: nó hoạt động như một quá trình Node.js và quá trình này không phụ thuộc vào trạng thái hiển thị của cửa sổ.
Cơ chế hoạt động khi cửa sổ bị ẩn
- Quá trình Main Process:
- Đây là quá trình chính quản lý toàn bộ ứng dụng Electron.
- Các tác vụ chạy trong Main Process (như giao tiếp với hệ thống, thực hiện các tác vụ định kỳ, hoặc quản lý cửa sổ) vẫn sẽ hoạt động bình thường khi cửa sổ bị ẩn.
- Quá trình Renderer Process:
- Đây là nơi mã JavaScript/HTML/CSS của bạn được hiển thị trong cửa sổ (giao diện người dùng).
- Khi cửa sổ bị ẩn, Renderer Process vẫn chạy, nhưng người dùng sẽ không thấy giao diện. Bạn có thể tiếp tục thực hiện logic trong trình duyệt (như cập nhật dữ liệu, xử lý sự kiện…).
Khi nào các tác vụ dừng lại?
- Nếu ứng dụng bị đóng hoàn toàn (quit):
- Mọi quá trình, bao gồm cả Main Process và Renderer Process, đều sẽ dừng lại.
- Điều này xảy ra khi bạn gọi
app.quit()
hoặc người dùng tắt ứng dụng qua system tray hoặc Task Manager.
- Nếu chỉ đóng cửa sổ (ẩn xuống nền):
- Các tác vụ trong Main Process và Renderer Process vẫn tiếp tục hoạt động.
- Điều này xảy ra khi bạn sử dụng
mainWindow.hide()
hoặc không gọimainWindow.close()
.
Ví dụ minh họa: Tác vụ vẫn hoạt động khi cửa sổ bị ẩn
Dưới đây là một ví dụ mà tác vụ trong Main Process vẫn chạy khi cửa sổ bị ẩn:
main.js
const { app, BrowserWindow, Tray, Menu } = require('electron');
let mainWindow;
let tray;
app.on('ready', () => {
// Tạo cửa sổ chính
mainWindow = new BrowserWindow({
width: 800,
height: 600,
show: false, // Ẩn cửa sổ khi khởi động
webPreferences: {
nodeIntegration: true,
},
});
mainWindow.loadFile('index.html');
// Tạo icon trong system tray
tray = new Tray('path/to/icon.png');
const contextMenu = Menu.buildFromTemplate([
{ label: 'Hiện ứng dụng', click: () => mainWindow.show() },
{ label: 'Thoát', click: () => {
app.isQuiting = true;
app.quit();
}},
]);
tray.setContextMenu(contextMenu);
// Chạy một tác vụ nền trong Main Process
setInterval(() => {
console.log('Tác vụ vẫn chạy dưới nền...');
}, 5000);
// Ngăn đóng hoàn toàn cửa sổ
mainWindow.on('close', (e) => {
if (!app.isQuiting) {
e.preventDefault();
mainWindow.hide(); // Ẩn cửa sổ thay vì đóng
}
});
});
Khi nào cần tạo tác vụ nền riêng?
Bạn chỉ cần tạo tác vụ nền riêng (ví dụ, dùng worker_threads
hoặc child_process
) khi:
- Tác vụ nặng (như xử lý dữ liệu lớn, phân tích tệp…) làm ảnh hưởng đến hiệu suất Main Process.
- Bạn muốn chia các tác vụ ra nhiều luồng (multi-threading) để tăng hiệu suất.
- Bạn cần thực hiện một công việc độc lập mà không phụ thuộc vào trạng thái của ứng dụng.
Nếu tác vụ của bạn nhẹ và không phức tạp, thì chỉ cần chạy trực tiếp trong Main Process hoặc Renderer Process là đủ.
Kết luận
- Cửa sổ bị ẩn không làm dừng các tác vụ đang chạy.
- Mọi tác vụ trong Main Process hoặc Renderer Process vẫn tiếp tục hoạt động miễn là ứng dụng chưa bị thoát hoàn toàn.
- Bạn chỉ cần tạo tác vụ nền riêng khi cần hiệu suất cao hoặc xử lý công việc phức tạp.
2 thoughts on “Xây dựng ứng dụng Node.js Electron có thể chạy background”