Skip to content
This repository was archived by the owner on Jun 11, 2024. It is now read-only.

Commit 81ccf22

Browse files
authored
Merge pull request #2 from 2skydev/dev
전체적인 패키지 업데이트 및 속도 개선
2 parents ca673fe + 74876d1 commit 81ccf22

File tree

30 files changed

+2139
-2105
lines changed

30 files changed

+2139
-2105
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ yarn-error.log*
77
dist
88
/resources/windows/chromium
99
chrome_data
10-
release
10+
release
11+
dist-electron

.vscode/settings.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,13 @@
33
"editor.formatOnSave": true,
44
"editor.defaultFormatter": "esbenp.prettier-vscode",
55
"typescript.preferences.importModuleSpecifier": "shortest",
6-
"typescript.tsdk": "node_modules/typescript/lib"
6+
"typescript.tsdk": "node_modules/typescript/lib",
7+
"json.schemas": [
8+
{
9+
"fileMatch": [
10+
"/*electron-builder.json"
11+
],
12+
"url": "https://json.schemastore.org/electron-builder"
13+
}
14+
]
715
}

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
![electron-vite-template-github-card](https://user-images.githubusercontent.com/43225384/196135599-585afdc5-9905-4400-bb02-ab0e7720da50.png)
22

3-
43
# Electron + Vite + React + TypeScript Template
54

65
A template for using electron quickly.<br/>
@@ -9,6 +8,7 @@ Please understand that the code and explanation are mainly written in Korean.
98
<br />
109

1110
## 특징들 둘러보기
11+
1212
- electron & vite를 사용해 빠른 개발, 빌드가 가능한 TypeScript 환경
1313
- 앱에 필수적인 요소 자동 업데이트, 저장소, 로그 등 사전구성
1414
- 파일 시스템 라우팅 기능 (Next.js에서 사용하던 방식)
@@ -32,7 +32,6 @@ Please understand that the code and explanation are mainly written in Korean.
3232
- CSS: [`styled-components`](https://styled-components.com/)
3333
- State management library: [`recoil`](https://hookstate.js.org/)
3434
- Date: [`dayjs`](https://day.js.org/)
35-
- Form value handle: [`formik`](https://formik.org/)
3635

3736
<br />
3837

@@ -61,7 +60,7 @@ yarn build:all
6160
<br />
6261

6362
## 스크린샷들
63+
6464
<img width="1718" alt="image" src="https://user-images.githubusercontent.com/43225384/196127143-2fd2fb65-5858-4bda-87a8-97c6e0487d8f.png">
6565
<img width="1718" alt="image" src="https://user-images.githubusercontent.com/43225384/196126603-388acf2c-760b-45f2-8738-5c1d2a4b4892.png">
6666
<img width="1718" alt="image" src="https://user-images.githubusercontent.com/43225384/196126770-08f75a7c-653d-4264-8c38-eb147c55193d.png">
67-

app/app.ts

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@ import { app, BrowserWindow, Menu, nativeImage, Tray } from 'electron';
22

33
import { join } from 'path';
44

5-
import { productName, protocols } from '../electron-builder.json';
5+
import { globImport } from './utils/import';
66

7-
export type MyAppType = InstanceType<typeof MyApp>;
8-
export type ModuleFunction = (app: MyAppType) => void | Promise<void>;
7+
export type AppContextType = InstanceType<typeof AppContext>;
8+
export type ModuleFunction = (context: AppContextType) => void | Promise<void>;
99

10-
class MyApp {
10+
const { productName, protocols } = require(app.isPackaged
11+
? './app.json'
12+
: '../electron-builder.json');
13+
14+
class AppContext {
1115
// deep link protocol
1216
readonly PROTOCOL = protocols.name;
1317

@@ -18,7 +22,7 @@ class MyApp {
1822
readonly DEV_URL = `http://localhost:3000/#`;
1923

2024
// production mode - load file
21-
readonly PROD_LOAD_FILE_PATH = join(__dirname, '../index.html');
25+
readonly PROD_LOAD_FILE_PATH = join(__dirname, '../dist/index.html');
2226
readonly PROD_LOAD_FILE_HASH = '#';
2327

2428
// resources directory
@@ -37,6 +41,7 @@ class MyApp {
3741
async bootstrap() {
3842
await this.initliazeElectron();
3943
await this.autoload();
44+
await this.createWindow();
4045
}
4146

4247
async initliazeElectron() {
@@ -58,7 +63,6 @@ class MyApp {
5863
});
5964

6065
await app.whenReady();
61-
await this.createWindow();
6266
await this.createTray();
6367
}
6468

@@ -88,11 +92,9 @@ class MyApp {
8892
this.window.loadFile(this.PROD_LOAD_FILE_PATH, {
8993
hash: this.PROD_LOAD_FILE_HASH,
9094
});
91-
92-
this.window.webContents.openDevTools(); // FIXME: Remove this line
9395
} else {
94-
this.window.loadURL(this.DEV_URL);
95-
this.window.webContents.openDevTools(); // FIXME: Remove this line
96+
await this.window.loadURL(this.DEV_URL);
97+
this.window.webContents.openDevTools();
9698
}
9799

98100
this.window.on('ready-to-show', () => {
@@ -119,14 +121,10 @@ class MyApp {
119121
}
120122

121123
async autoload() {
122-
const modules = import.meta.glob<{ default: ModuleFunction }>('./modules/**/index.ts', {
123-
eager: true,
124-
});
124+
const modules = await globImport('./modules/**/index.js', { cwd: __dirname });
125125

126-
for (const module of Object.values(modules)) {
127-
await this.register(module.default);
128-
}
126+
await Promise.all(modules.map(({ default: module }) => this.register(module)));
129127
}
130128
}
131129

132-
export default MyApp;
130+
export default AppContext;

app/electron-env.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/// <reference types="vite-electron-plugin/electron-env" />

app/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import MyApp from './app';
1+
import AppContext from './app';
22

33
(async () => {
4-
const myApp = new MyApp();
5-
await myApp.bootstrap();
4+
const context = new AppContext();
5+
await context.bootstrap();
66
})();

app/modules/deepLink/index.ts

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,44 @@ import { app } from 'electron';
22

33
import { match, MatchResult } from 'path-to-regexp';
44

5-
import { ModuleFunction, MyAppType } from '@app/app';
5+
import { ModuleFunction, AppContextType } from '@app/app';
6+
import { globImport } from '@app/utils/import';
67

78
export type DeepLinkResolvers = Record<
89
string,
9-
(matchResult: MatchResult<any>, app: MyAppType) => void
10+
(matchResult: MatchResult<any>, app: AppContextType) => void
1011
>;
1112

12-
const DeepLinkModule: ModuleFunction = myapp => {
13-
let resolvers: DeepLinkResolvers = {};
13+
const DeepLinkModule: ModuleFunction = async context => {
14+
const modules = await globImport('./resolvers/**/*.resolver.js', { cwd: __dirname });
1415

15-
const resolverFiles = import.meta.glob<{ default: DeepLinkResolvers }>(
16-
'./resolvers/**/*.resolver.ts',
17-
{
18-
eager: true,
19-
},
20-
);
21-
22-
for (const resolverFile of Object.values(resolverFiles)) {
23-
resolvers = { ...resolvers, ...resolverFile.default };
24-
}
16+
const resolvers: DeepLinkResolvers = modules.reduce((resolvers, module) => {
17+
return { ...resolvers, ...module.default };
18+
}, {});
2519

2620
const runDeepLinkResolver = (url: string) => {
27-
const pathname = url.replace(`${myapp.PROTOCOL}://`, '/');
21+
const pathname = url.replace(`${context.PROTOCOL}://`, '/');
2822

2923
for (const path in resolvers) {
3024
const data = match(path)(pathname);
3125

3226
if (data) {
33-
resolvers[path](data, myapp);
27+
resolvers[path](data, context);
3428
break;
3529
}
3630
}
3731
};
3832

3933
app.on('second-instance', (_, argv) => {
40-
if (!myapp.IS_MAC) {
41-
const url = argv.find(arg => arg.startsWith(`${myapp.PROTOCOL}://`));
34+
if (!context.IS_MAC) {
35+
const url = argv.find(arg => arg.startsWith(`${context.PROTOCOL}://`));
4236

4337
if (url) {
4438
runDeepLinkResolver(url);
4539
}
4640
}
4741

48-
myapp.createWindow();
42+
context.createWindow();
4943
});
5044

5145
app.on('open-url', (_, url) => {

app/modules/general/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import { configStore } from '@app/stores/config';
55

66
export type AppControlAction = 'devtools' | 'minimize' | 'maximize' | 'close';
77

8-
const GeneralModule: ModuleFunction = ({ window }) => {
8+
const GeneralModule: ModuleFunction = context => {
99
// 창 닫기, 최대화, 최소화 같은 컨트롤 기능
1010
ipcMain.on('appControl', async (_, action: AppControlAction) => {
11+
const { window } = context;
12+
1113
if (!window) return;
1214

1315
switch (action) {

app/modules/update/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export type UpdateEvent =
1919
| 'download-progress'
2020
| 'update-downloaded';
2121

22-
const UpdateModule: ModuleFunction = ({ window }) => {
22+
const UpdateModule: ModuleFunction = context => {
2323
const handleUpdateEvent = (event: UpdateEvent) => {
2424
return (data?: any) => {
2525
if (event !== 'download-progress') {
@@ -30,8 +30,8 @@ const UpdateModule: ModuleFunction = ({ window }) => {
3030
});
3131
}
3232

33-
if (window) {
34-
window.webContents.send('update', event, data);
33+
if (context.window) {
34+
context.window.webContents.send('update', event, data);
3535
}
3636
};
3737
};

app/preload/index.ts

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,6 @@
1-
import { contextBridge, ipcRenderer } from 'electron';
1+
import { ElectronRendererContext } from '@app/types/preload';
22

3-
import { Log } from '../modules/developers';
4-
import { AppControlAction } from '../modules/general';
5-
import { UpdateEvent, UpdateStatus } from '../modules/update';
6-
import { ConfigStoreValues } from '../stores/config';
7-
8-
export interface ElectronRendererContext {
9-
onUpdate: (callback: (event: UpdateEvent, data: any) => void) => void;
10-
11-
initlizeUpdater: () => void;
12-
appControl: (action: AppControlAction) => void;
13-
openExternal: (link: string) => void;
14-
checkForUpdate: () => void;
15-
quitAndInstall: () => void;
16-
17-
getConfig: () => Promise<ConfigStoreValues>;
18-
setConfig: (config: ConfigStoreValues) => Promise<ConfigStoreValues>;
19-
20-
getVersion: () => Promise<string>;
21-
getUpdaterStatus: () => Promise<UpdateStatus>;
22-
23-
getStorePath: () => Promise<string>;
24-
getLogs: () => Promise<Log[]>;
25-
clearLogs: () => Promise<boolean>;
26-
}
3+
const { contextBridge, ipcRenderer } = require('electron');
274

285
const electronContext: ElectronRendererContext = {
296
onUpdate: callback => ipcRenderer.on('update', (_, event, data) => callback(event, data)),

0 commit comments

Comments
 (0)