Nhảy tới nội dung

Xây dựng ứng dụng desktop đa nền tảng với electron và react typescript, tailwind css

· 6 phút để đọc
Phạm Quyết Thắng
Fullstack developer

Chào các bạn, tôi mới vừa release phiên bản đầu tiên của Offline Dev Tools - Một ứng dụng desktop nhỏ được tôi xây dựng bằng electron, react typescript, tailwindcss, shadcn/ui và một số công cụ khác.

Nó cung cấp một vài công cụ offline hữu ích như là generation data, transform data, encode/decode base64, so sánh các múi giờ, ...

Phần mềm được tôi lấy cảm hứng từ DevToys và một số thư viện khác như https://transform.tools/ , faker-js, tôi đã tự thiết kế và xây dựng nó trong vài tuần. Còn nhiều tính năng tôi muốn cải thiện và thêm vào phần mềm trong tương lai.

Về ứng dụng tôi đã xây dựng, các bạn có xem nó hoặc tải và sử dụng nó trên Linux, Windows hay Macos

https://github.com/phamquyetthang/offline-dev-tools

Windows Linux macOS GitHub Release

Electron-forge vs electron-vite

Khi bắt đầu xây dựng và tự tìm hiểu về electron, tôi đã khởi tạo project với electron-vite vì tôi đã quen với vite và react dạo gần đây, Và thực sự nó đã làm khá tốt khi tôi không mất nhiều thời gian để start project, tích hợp tailwindcss và shadcn/ui vào project. Mọi thứ bạn cần đều ở đây: https://electron-vite.org/guide/

Tôi đã hoàn thành sơ lược 30% các chức năng trên phần mềm của tôi trong khung của electron-vite, cho đến khi tôi gặp một vài vấn đề khi đóng gói ( Build production ) hay cài thêm 1 vài package. Cộng đồng và document electron-vite không đủ lớn để tôi có tìm sự trợ giúp về các vấn đề tôi gặp phải.

Sau khi đánh giá nhiều lần tôi đã quyết định chuyển sang electron-forge và làm việc khá thuận tiện với nó đến hiện tại.

Việc cài đặt react typescript và tailwindcss vào project electron-forge không khó nhưng sẽ khá mất thời gian nếu bạn chưa có kinh nghiệm ( không dễ dàng như electron-vite), bài viết này tôi sẽ giúp bạn tiết kiệm một chút thời gian và có thể khởi tạo một project electron-forge hoạt động trơn tru với react typescript và tailwindcss.

Create new app with Electron Forge

npm init electron-app@latest my-new-app -- --template=webpack-typescript

my-new-app: hãy đổi thành tên project của bạn

--template=webpack-typescript: cho biết bạn sẽ sử dụng webpack, và typescript thay vì javascript

electron-forge hỗ trợ các bạn khởi tạo với vite nhưng có vẻ nó chưa sẵn sàng với kết hợp với react cho nên các bạn hãy cứ làm việc với webpack lúc này

Sau khi chạy câu lệnh trên, một project sẽ được khởi tạo và các bạn có thể chạy nó bằng lệnh npm start Xem qua các file các bạn sẽ thấy được nội dung trong file src/index.html đang được hiển thị lên giao diện

Và file src/renderer.ts sẽ là nơi chúng ta viết code typescipt của mình.

Cài đặt react vào project:

npm install --save react react-dom
npm install --save-dev @types/react @types/react-dom

# or with yarn
yarn add react react-dom
yarn add -D @types/react @types/react-dom

Lúc này các bạn có thể tạo một file app.tsx trong src để là file root cho phần react của mình

// # src/app.tsx

import './index.css'; // import css

import * as React from "react";
import { createRoot } from "react-dom/client";

const root = createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<h1>Hello react</h1>
</React.StrictMode>
);

Import vào src/renderer.ts:

// # src/renderer.ts
import './index.css'
import './app' // <== add this line

Sửa đổi file src/index.html, bạn thấy đoạn document.getElementById('root') trong file app.tsx chứ:

<!-- # src/index.html -->
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>My app name</title>
</head>

<body>
<div id="root"></div>
<!-- <== add this, root element -->
</body>
</html>

Có thể bạn sẽ gặp lỗi Cannot use JSX unless the '--jsx' flag is provided.ts, hãy thêm dòng này vào file tsconfig.json

{
"compilerOptions": {
"jsx": "react-jsx" // <== add this line
// other existed configs
}
}

Chạy lại project bạn sẽ thấy được phần code mình vừa thay đổi được hiển thị

Đến đây bạn có thể tự tổ chức project structure của một ứng dụng react và import vào src/app.tsx

Cài đặt tailwinds css

Đầu tiên hãy cài tailwind css dependentces

npm install tailwindcss autoprefixer --save-dev

# or with yarn
yarn add -D tailwindcss autoprefixer

Khởi tạo file config

npx tailwindcss init

Một file tailwind.config.js sẽ được khởi tạo trong thư mục gốc của project

Mở file đó ra và sửa đổi phần này để tailwind hiểu được là những classname của nó sẽ được sử dụng ở đâu:

/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./src/**/*.{ts,tsx,html}' // <== Update this
],
theme: {
extend: {}
},
plugins: []
}

Để webpack và electron làm việc được với tailwind, chúng ta cũng cần cài thêm postcss, postcss-loader

npm install postcss postcss-loader

# or with yarn
yarn add postcss postcss-loader

Sau đó hãy tạo file postcss.config.js với nội dung sau

//postcss.config.js

import tailwindcss from 'tailwindcss'
import autoprefixer from 'autoprefixer'
export default {
plugins: [tailwindcss('./tailwind.config.js'), autoprefixer]
}

Thêm postcss-loader vào webpack.renderer.config.ts

// webpack.renderer.config.ts

rules.push({
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'postcss-loader' } // <== add this
]
})

Add the Tailwind directives to your CSS, ở đây là file src/index.css

@tailwind base;
@tailwind components;
@tailwind utilities;

Bây giờ hãy thử kiểm tra nó với việc thêm vài classname vào thẻ h1


const root = createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<h1 className="font-bold text-2xl underline text-red-700">Hello react</h1>
</React.StrictMode>
);

Các bạn sẽ thấy UI đã được apply trên giao diện.

Hoàn thành tích hợp tailwind css, Các bạn có thể tải vào các component của shadcn/ui nếu muốn.

Xem project của tôi để thấy cách tôi làm việc với shadcn/ui , tailwindcss trong project electron.

Trên đây tôi đã hướng dẫn các bạn khởi tạo 1 project electton typescript, tích hợp react, và tailwind css.

Hãy đặt các câu hỏi nếu có phần nào khó hiểu !

Sau cùng cảm ơn các bạn đã dành thời gian đọc bài viết, hãy ủng hộ bài viết gốc tại: