如何使用 electron-forge 搭建 React + Ts 的項目
前言
如果你有桌面應(yīng)用開發(fā)的需求,且比較熟悉 Web 相關(guān)的技術(shù),那么 Electron 會是一個非常不錯的選擇,作為一個使用 Web 技術(shù)構(gòu)建跨平臺桌面應(yīng)用的框架,其允許開發(fā)者使用JavaScript、HTML 和 CSS 等 Web 技術(shù)來構(gòu)建桌面應(yīng)用;同時,Electron 擁有一個活躍的社區(qū)和豐富的生態(tài)系統(tǒng),這不僅意味著開發(fā)者可以輕松找到解決問題的資源和工具,還意味著框架的更新和改進是持續(xù)不斷的,能夠緊跟技術(shù)發(fā)展的步伐
本文將介紹如何用其構(gòu)建一個應(yīng)用 Demo 項目
介紹
創(chuàng)建 Electron 應(yīng)用程序項目的方式有很多,如手動集成、electron-vite
快速構(gòu)建等,本文將介紹通過 electron-forge 構(gòu)建的方式
主要環(huán)境
electron-forge v7.6
webpack
react
typescript
Electron Forge 介紹
Electron Forge 是一個用于打包和分發(fā) Electron 應(yīng)用程序的一體化工具,可以認(rèn)為是 Electron Builder 的替代品,它提供了一個全面的解決方案,包括初始化項目、本地開發(fā)、打包和發(fā)布,同時,其簡化了 Electron 應(yīng)用的開發(fā)和打包流程,使得開發(fā)者可以更專注于應(yīng)用本身的開發(fā)
具體步驟
項目構(gòu)建步驟主要如下,如果你需要源碼,可從文末獲?。?/p>
創(chuàng)建 electron 項目
在開始前,需先備有對應(yīng)的工具,如:npm
或yarn
本例使用的是npm
,使用yarn
的命令也差不多
通過模板創(chuàng)建項目
模板集成了一些項目構(gòu)建工具,可以更為方便的為項目加入插件,主要提供了如下模板:
webpack
webpack-typescript
vite
vite-typescript
創(chuàng)建命令
選擇合適的模板后,按照下列命令創(chuàng)建項目
npm init electron-app@latest [project-name] -- --template=[template-name]
[project-name]
:表示項目名[template-name]
:表示模板名,在上側(cè)提供的里面選擇
開始創(chuàng)建
本例使用命令如下:
npm init electron-app@latest demo -- --template=webpack-typescript
該模板集成了webpack
和typescript
的能力
如果你選用vite
相關(guān)模板,需注意:
創(chuàng)建好項目后的package.json
依賴內(nèi)容如下:
"devDependencies": { "@electron-forge/cli": "^7.6.0", "@electron-forge/maker-deb": "^7.6.0", "@electron-forge/maker-rpm": "^7.6.0", "@electron-forge/maker-squirrel": "^7.6.0", "@electron-forge/maker-zip": "^7.6.0", "@electron-forge/plugin-auto-unpack-natives": "^7.6.0", "@electron-forge/plugin-fuses": "^7.6.0", "@electron-forge/plugin-webpack": "^7.6.0", "@electron/fuses": "^1.8.0", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", "@vercel/webpack-asset-relocator-loader": "1.7.3", "css-loader": "^6.0.0", "electron": "33.2.1", "eslint": "^8.0.1", "eslint-plugin-import": "^2.25.0", "fork-ts-checker-webpack-plugin": "^7.2.13", "node-loader": "^2.0.0", "style-loader": "^3.0.0", "ts-loader": "^9.2.2", "ts-node": "^10.0.0", "typescript": "~4.5.4" }, "dependencies": { "electron-squirrel-startup": "^1.0.1" }
如果命令一直創(chuàng)建失敗,可能是網(wǎng)絡(luò)問題,可考慮使用一些鏡像站
試運行
創(chuàng)建好項目后,可以進入項目根目錄,用執(zhí)行如下命令,嘗試是否可以正常運行:
# 運行npm start
除此運行可能會報一些類型錯誤,大致如下:
Failed to load: ...\...\ele-react-demo\forge.config.ts An unhandled rejection has occurred inside Forge: TSError: 1. ? Unable to compile TypeScript: forge.config.ts:1:34 - error TS2307: Cannot find module '@electron-forge/shared-types' or its corresponding type declarations.
按照錯誤提示添加上相關(guān)依賴即可,可能需要添加的依賴如下
"devDependencies": { "@electron-forge/shared-types": "^7.6.0", "@electron-forge/maker-base": "^7.6.0", "@electron-forge/plugin-base": "^7.6.0", "webpack": "^5.97.0", "@types/node": "^22.10.1" }
添加完缺少的依賴后,再次運行npm start
啟動項目,如運行成功,可看到如下界面
可以看到,默認(rèn)會啟動開發(fā)者工具,這是由于src/index.ts
內(nèi)的代碼設(shè)置的,如下:
如不需要,可將其注釋或刪除,需要打開開發(fā)者工具時通過快捷鍵 Ctrl + Shift + I (windows 系統(tǒng))打開即可
試打包
當(dāng)編寫好項目后,需進行打包,可運行如下命令:
# 打包 npm run make
打包好后,項目根目錄會出現(xiàn)一個out
目錄,內(nèi)部即是打包好的文件;打包會檢測本機系統(tǒng),然后生成對應(yīng)的打包文件
正常打包好后,內(nèi)部會有兩個目錄,一個為make
目錄,里面有對應(yīng)系統(tǒng)的二進制安裝程序,如exe
;另一個目錄(如**-win32-x64
),里面為對應(yīng)系統(tǒng)的便攜式免安裝程序,點擊產(chǎn)品名.exe即可打開應(yīng)用,此目錄內(nèi)有個resource
文件夾,裝著項目編譯的一些內(nèi)容,如app.asar
asar 解包方法
asar
文件類似一種壓縮包,通過對應(yīng)的工具可以對其進行解包,得到實際的文件
- 安裝解包工具:
npm install -g asar
- 運行命令解包:
asar extract app.asar ./app
(該命令會將 app.asar 解包到當(dāng)前目錄的 app 目錄下)
解包后,目錄內(nèi)會有如下結(jié)構(gòu):
.webpack # 項目編譯部分 ├- main # electron 部分 └- renderer # web 部分 node_modules # 項目依賴 package.json
如果你是用
vite
模板構(gòu)建項目,文件名稱可能稍有差別,但結(jié)構(gòu)大致類似
集成 React
集成 React 可以讓 UI 開發(fā)變得更為方便
安裝依賴
首先安裝對應(yīng)依賴,如下:
# 安裝 React 包 npm install --save react react-dom # 安裝 React 類型支持相關(guān)包 npm install --save-dev @types/react @types/react-dom
修改 tsconfig
修改項目根目錄下的tsconfig.json
,在 compilerOptions 下添加如下內(nèi)容:
"compilerOptions": { "jsx": "react-jsx" }
修改項目文件
在項目內(nèi)使用React
組件的能力,首先在src
目錄下新建文件app.tsx
,內(nèi)容如下:
/** src/app.tsx */ import { createRoot } from 'react-dom/client'; import { useState } from 'react'; // 主應(yīng)用 function App() { const [count, setCount] = useState(0); return ( <> <h1>Hello React</h1> <p>count: {count}</p> <button onClick={() => setCount(count + 1)}>count + 1</button> </> ); } const root = createRoot(document.body); root.render(<App />);
接著,在src/renderer.ts
內(nèi)導(dǎo)入它
然后,運行npm start
啟動項目,正常啟動后如下
正常情況下,無需額外配置,項目即可實現(xiàn)熱重載,比如修改了
app.tsx
內(nèi)容后保存,無需重啟項目,修改內(nèi)容即可渲染出來
集成 SCSS
如果你需要使用一些 CSS預(yù)編譯器,可參考一下步驟,這里以scss
舉例:
安裝依賴
需安裝sass
相關(guān)依賴,如下:
npm install --save-dev sass sass-loader
配置 loader
修改項目根目錄下的 webpack.renderer.config.ts 文件,如下:
// webpack.renderer.config.ts // ··· ··· // 加入對對應(yīng)樣式文件的解析規(guī)則 rules.push({ test: /\.(sass|scss|css)$/, use: [{ loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'sass-loader' }] }); // ··· ···
使用 SCSS
重命名src
目錄下的樣式文件,將index.css
改為index.scss
,然后即可在文件內(nèi)添加scss
樣式規(guī)則,例如:
/* index.scss */ body { h1 { color: #68945c; } }
導(dǎo)入 SCSS
將index.scss
導(dǎo)入src/renderer.ts
內(nèi)部使用
接著,npm start
啟動項目,查看效果
可以看到,scss
的樣式已可正常渲染
配置靜態(tài)資源
如果你在項目內(nèi)使用了一些靜態(tài)資源(如圖片),如下:
我在src
目錄下新建了一個assets
目錄,專門用于放置靜態(tài)資源,現(xiàn)在里面放了一張圖片;然后我在app.tsx
內(nèi)引用了它;接著啟動項目,如果沒有意外,可以看到圖片并不會顯示,控制臺會報錯找不到對應(yīng)資源,查看編譯后的.webpack
目錄,發(fā)現(xiàn)缺少沒有對應(yīng)的圖片資源
這是由于靜態(tài)資源沒有被正確加載或復(fù)制,以下介紹兩種簡單可行的方式,僅供參考:
方法一
此方法僅配置打包后的靜態(tài)資源,具體步驟如下:
配置 forge.config.ts
const config: ForgeConfig = { packagerConfig: { asar: true, // 通過如下配置項,配置需打包的靜態(tài)資源 // 該配置會將對應(yīng)資源復(fù)制到打包后的 resource 目錄下 // 這里表示復(fù)制 src/assets 整個目錄 // 打包后在 out/**-win32-x64/resource 目錄下,會有一個 assets 目錄 extraResource: ['./src/assets'] } }
使用時可以用相對路徑,也可以借助path
工具
// src/app.tsx function App() { const [count, setCount] = useState(0); return ( <> <h1>Hello React</h1> // 通過相對路徑 // 打包后的結(jié)構(gòu)可看上方解答 // web 部分在 resource/app.asar/.webpack/renderer/main_window // 資源部分在 resource/assets <img src="../../../../assets/images/cat.jpg" /> // 也可以使用 path 拼接路徑,如:path.join(process.resourcesPath, 'assets/images/cat.jpg') // process.resourcesPath 表示 resource 目錄 <p>count: {count}</p> <button onClick={() => setCount(count + 1)}>count + 1</button> </> ); }
此時npm run make
打包后,運行打包的文件,即可看到靜態(tài)資源已經(jīng)可以正常顯示了
這種方法只適用于處理打包的靜態(tài)資源,開發(fā)
npm start
運行時依舊無法正常顯示并且,復(fù)制的靜態(tài)資源存在于 renderer 目錄下,并為打包進 app.asar
方法二
通過一些插件實現(xiàn),如rollup-plugin-copy
、copy-webpack-plugin
等,這里介紹copy-webpack-plugin
的用法
首先安裝copy-webpack-plugin
插件
npm install --save-dev copy-webpack-plugin
接著配置使用插件,打開根目錄下的webpack.plugins.ts
文件
以上配置會將./src/assets
文件夾內(nèi)的內(nèi)容復(fù)制到./.webpack/renderer/static
文件夾內(nèi),在項目中使用時,只需通過./static
目錄進行訪問即可,如下
// src/app.tsx function App() { const [count, setCount] = useState(0); return ( <> <h1>Hello React</h1> // 使用靜態(tài)資源 <img src="./static/images/cat.jpg" /> <p>count: {count}</p> <button onClick={() => setCount(count + 1)}>count + 1</button> </> ); }
此時無論是開發(fā)運行npm start
,還是打包npm run make
運行,都能正確渲染靜態(tài)資源
這種方法不僅可以正常顯示與開發(fā)和打包中,同時在打包時,靜態(tài)資源也會一并打包進 app.asar 內(nèi)
配置 Loading 頁面
以下內(nèi)容是一些體驗優(yōu)化,參考即可
使用 electron
開發(fā),在啟動時,會有一段白屏?xí)r間,這主要是由于窗口加載后,頁面資源還未加載渲染好造成的,在項目集成了Rreact
、Vue
后,這個問題會愈發(fā)明顯,白屏?xí)r間會更長
想要解決這個問題,由很多方式可以參考,如:優(yōu)化資源、做一些預(yù)加載工作等
這里主要介紹一種比較簡單的解決方式:加入 Loading 頁面,主要思路就是在主窗口創(chuàng)建前,先創(chuàng)建一個 Loading 窗口,只用顯示簡單的 Loading 頁面,然后再創(chuàng)建主窗口;窗口創(chuàng)建時默認(rèn)都隱藏,當(dāng)創(chuàng)建好后才顯示,首先顯示 Loading 窗口,待主窗口創(chuàng)建完成并準(zhǔn)備好時,隱藏 Loading 窗口,展示主窗口
首先在assets
目錄下新建一個loading.html
,里面存放著一個loading
動畫樣式,效果如下(可自行創(chuàng)意實現(xiàn)):
接著,創(chuàng)建窗口渲染使用它,修改src/index.ts
文件
// Loading 窗口 let loadingWin: BrowserWindow; // Loading 窗口的渲染文檔,即上側(cè)的 loading 效果 const loadingUrl = path.join(__dirname, '../renderer/static/loading.html'); /** Loading 窗口 */ const createLoading = () => { return new Promise((resolve, reject) => { loadingWin = new BrowserWindow({ // 一開始是否顯示 show: false, width: 512, height: 512, frame: false, // 無邊框(窗口、工具欄等),只包含網(wǎng)頁內(nèi)容 transparent: true // 窗口是否支持透明,在做高級效果時最好為 true }); // 當(dāng)窗口顯示時 loadingWin.once('show', () => { resolve(true); }); // 配置窗口渲染文檔 loadingWin.loadFile(loadingUrl); // 顯示 Loading 窗口 loadingWin.show(); }); }; /** 主窗口 */ const createWindow = () => { // 創(chuàng)建渲染窗口 const mainWindow = new BrowserWindow({ // 窗口圖標(biāo) // icon: './assets/logo/logo.ico', height: 600, width: 800, // 一開始隱藏 show: false, webPreferences: { // 預(yù)加載腳本 preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY } }); // 主窗口準(zhǔn)備還顯示 mainWindow.once('ready-to-show', () => { // 隱藏 Loading 窗口 loadingWin.hide(); // 關(guān)閉 Loading 窗口 loadingWin.close(); // 展示 主窗口 mainWindow.show(); }); // 為窗口加載 index.html mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY); // 打開開發(fā)者工具 // mainWindow.webContents.openDevTools(); }; // 當(dāng) Electron 初始化完成并準(zhǔn)備創(chuàng)建渲染窗口(mainWindow)時調(diào)用 // 某些 API 只能在此事件發(fā)生后使用 // app.on('ready', createWindow); app.on('ready', async () => { // 先創(chuàng)建 Loading 窗口 await createLoading(); // 再創(chuàng)建 主窗口 createWindow(); });
加入loading
窗口后,白屏?xí)r間可以顯著改善,程序啟動后,會先顯示loading
窗口,待主窗口完全準(zhǔn)備好后再顯示主窗口,效果大致如下:
【一張動圖,但這放不了】
如果需要,還可以給主窗口頁面加入一個淡入的動畫效果,交互體驗也許會更好
總結(jié)
本文介紹了用electron-forge
、webpack
、typescript
、react
、scss
搭建的一個模板項目,同時還包含靜態(tài)資源配置及loading
效果
如果你由于網(wǎng)絡(luò)原因npm init
創(chuàng)建electron
項目一直失敗,也可以到github
克隆本項目直接修改使用
克隆完成后到項目根目錄通過如下命令即可使用
# 安裝依賴 pnpm install # 運行 npm start # 打包 npm run make
參考資料
Electron Forge: https://www.electronforge.io/
模板地址: https://github.com/skmcj/demo
到此這篇關(guān)于如何使用 electron-forge 搭建 React + Ts 的項目的文章就介紹到這了,更多相關(guān)electron-forge 搭建 React + Ts 項目內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react組件中的constructor和super知識點整理
這篇文章主要介紹了react組件中的constructor和super知識點整理,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08react 權(quán)限樹形結(jié)構(gòu)實現(xiàn)代碼
這篇文章主要介紹了react 權(quán)限樹形結(jié)構(gòu)實現(xiàn)代碼,項目背景react + ant design,本文結(jié)合實例代碼給大家介紹的非常詳細,感興趣的朋友一起看看吧2024-05-05詳解基于React.js和Node.js的SSR實現(xiàn)方案
這篇文章主要介紹了詳解基于React.js和Node.js的SSR實現(xiàn)方案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03深入學(xué)習(xí)TypeScript 、React、 Redux和Ant-Design的最佳實踐
這篇文章主要介紹了深入學(xué)習(xí)TypeScript 、React、 Redux和Ant-Design的最佳實踐,TypeScript 增加了代碼的可讀性和可維護性,擁有活躍的社區(qū),,需要的朋友可以參考下2019-06-06