Giới thiệu
Electron là một framework tuyệt vời để xây dựng ứng dụng desktop. Với Vite Electron, một framework mới cho Electron, bạn có thể xây dựng ứng dụng nhanh hơn và tận dụng tất cả lợi ích mà Vite mang lại. Tuy nhiên, việc làm quen với Vite Electron có thể gây bối rối cho nhiều người. Hãy cùng nhau phân tích để dễ hiểu hơn.
Cấu trúc dự án
Đầu tiên, hãy thiết lập một dự án đơn giản. Cấu trúc thư mục sẽ như sau:
my-electron-app/
├── electron/
│ ├── main.js # Điểm vào chính của tiến trình chính
│ └── preload.js # Tập tin preload (cầu nối)
├── src/
│ ├── App.jsx # Một component React đơn giản
│ └── main.jsx # Điểm vào của tiến trình renderer
├── index.html
├── package.json
└── vite.config.js
Tập tin package.json
Tập tin này định nghĩa dự án của chúng ta, các phụ thuộc và các script để chạy và xây dựng dự án.
json
{
"name": "my-electron-app",
"version": "0.1.0",
"main": "electron/main.js", // <-- Quan trọng: Điểm đến của tập tin chính Electron
"scripts": {
"dev": "vite",
"build": "vite build && electron-builder"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.2.1",
"electron": "^28.2.1",
"electron-builder": "^24.9.1",
"vite": "^5.0.12",
"vite-plugin-electron-renderer": "^0.14.5"
},
"build": { // <-- Cấu hình cho electron-builder
"appId": "com.my-app.id",
"productName": "My Awesome App",
"files": [
"dist/**/*",
"electron/**/*"
],
"directories": {
"buildResources": "assets",
"output": "release"
}
}
}
Tập tin vite.config.js
Tập tin này cấu hình Vite để làm việc với Electron một cách hiệu quả.
javascript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import electron from 'vite-plugin-electron-renderer';
export default defineConfig({
plugins: [
react(),
electron(), // <-- Plugin chính cho Electron
],
});
electron/main.js (Tiến trình Chính)
Tập tin này là trái tim của ứng dụng Electron của bạn. Nó chạy trong môi trường Node.js và chịu trách nhiệm tạo ra các cửa sổ và xử lý sự kiện hệ thống.
javascript
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
// Xử lý việc tạo/xóa shortcut trên Windows khi cài đặt/gỡ cài đặt.
if (require('electron-squirrel-startup')) {
app.quit();
}
const createWindow = () => {
// Tạo cửa sổ trình duyệt.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'), // <-- Liên kết đến tập tin preload
contextIsolation: true, // <-- Tính năng bảo mật
nodeIntegration: false, // <-- Tính năng bảo mật
},
});
// Tải ứng dụng.
if (process.env.VITE_DEV_SERVER_URL) {
mainWindow.loadURL(process.env.VITE_DEV_SERVER_URL);
mainWindow.webContents.openDevTools();
} else {
mainWindow.loadFile(path.join(__dirname, '../dist/index.html'));
}
};
app.whenReady().then(() => {
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
electron/preload.js (Cầu nối)
Tập tin này hoạt động như một cầu nối an toàn giữa frontend dựa trên web (Renderer) và backend Node.js (Main).
javascript
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('api', {
send: (channel, data) => {
let validChannels = ['toMain'];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
receive: (channel, func) => {
let validChannels = ['fromMain'];
if (validChannels.includes(channel)) {
ipcRenderer.on(channel, (event, ...args) => func(...args));
}
}
});
src/main.jsx và src/App.jsx (Tiến trình Renderer)
Đây là mã nguồn frontend tiêu chuẩn Vite/React. Nó chạy trong một môi trường giống như trình duyệt.
src/main.jsx
javascript
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.jsx';
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>,
);
src/App.jsx
javascript
import React from 'react';
function App() {
const handleClick = () => {
window.api.send('toMain', 'Hello from the Renderer Process!');
};
React.useEffect(() => {
window.api.receive('fromMain', (data) => {
console.log(`Received from main: ${data}`);
});
}, []);
return (
<div>
<h1>Hello from Vite + React + Electron!</h1>
<button onClick={handleClick}>Gửi tin nhắn tới Main</button>
</div>
);
}
export default App;
Thực hành tốt nhất
- Cấu hình bảo mật: Đảm bảo rằng bạn luôn sử dụng
contextIsolationvànodeIntegrationan toàn để bảo vệ ứng dụng của bạn. - Quản lý phụ thuộc: Sử dụng
npm auditđể kiểm tra các lỗ hổng bảo mật trong các phụ thuộc của bạn.
Các cạm bẫy thường gặp
- Lỗi khi tải tập tin: Đảm bảo rằng đường dẫn đến
index.htmllà chính xác trongmain.js. - Kết nối IPC: Kiểm tra kênh truyền thông IPC để đảm bảo rằng bạn chỉ sử dụng những kênh đã được xác thực.
Mẹo hiệu suất
- Sử dụng React.memo: Giúp cải thiện hiệu suất của các component React.
- Tối ưu hóa ảnh: Sử dụng ảnh chất lượng cao nhưng kích thước nhỏ để giảm thời gian tải.
Giải quyết sự cố
- Ứng dụng không khởi động: Kiểm tra console logs để tìm hiểu nguyên nhân.
- Lỗi không kết nối IPC: Xác minh rằng bạn đang sử dụng đúng tên kênh IPC.
Câu hỏi thường gặp
Vite Electron khác gì so với Electron thông thường?
Vite Electron sử dụng Vite để tăng tốc độ biên dịch và phát triển, giúp giảm thời gian chờ và cải thiện quy trình làm việc.
Tại sao nên sử dụng preload script?
Preload script cung cấp một cầu nối an toàn giữa frontend và backend, cho phép bạn kiểm soát các quyền truy cập mà frontend có thể thực hiện.
Kết luận
Việc thiết lập Vite với Electron có thể ban đầu gây khó khăn, nhưng với hướng dẫn này, bạn sẽ có thể tạo ra một ứng dụng desktop mạnh mẽ và nhanh chóng. Hãy thử nghiệm và sáng tạo với ứng dụng của bạn. Nếu bạn có câu hỏi, đừng ngần ngại đặt câu hỏi trong cộng đồng phát triển của chúng ta!