Skip to main content

Electron Study Notes

· 4 min read
XOne
webmaster

Webpack + Typescript

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

React code requires, add JSX support

{
"compilerOptions": {
"jsx": "react-jsx"
}
}

Switch npm to pnpm and need to install

pnpm install @electron-forge/plugin-base @electron-forge/maker-base @types/webpack --save-dev

Routing

pnpm install react-router-dom

LESS

pnpm install less less-loader --save-dev

webpack.rules.ts

{
test: /\.less$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
mode: 'local',
localIdentName: '[name]__[local]___[hash:base64:5]',
},
importLoaders: 1,
},
},
'less-loader',
],
}

Ant Design Pro

pnpm install antd --save
pnpm install @ant-design/pro-components --save
pnpm install @ant-design/pro-card
pnpm install @ant-design/pro-descriptions
pnpm install @ant-design/pro-field
pnpm install @ant-design/pro-form
pnpm install @ant-design/pro-layout
pnpm install @ant-design/pro-list
pnpm install @ant-design/pro-provider
pnpm install @ant-design/pro-skeleton
pnpm install @ant-design/pro-table
pnpm install @ant-design/pro-utils

Compile using babel-plugin-import to optimize the packaging volume of antd

pnpm install babel-plugin-import --save-dev
pnpm install @ant-design/icons --save

Data storage electron-store

conf is installed to handle type errors

pnpm install electron-store conf

tsconfig.jsonThe default template is: "moduleResolution": "node", electron-forge seems to find it difficult or does not support configuring "moduleResolution": "node16" or other property values. Here, an opportunistic way to configure aliases is used to fix the type errors of electron-store.
tsconfig.json

{
"compilerOptions": {
"paths": {
"conf": ["node_modules/conf/dist/source"]
}
}
}

Set up path aliases

tsconfig.json

{
"compilerOptions": {
"paths": {
"@/*": ["src/*"]
}
}
}

webpack.renderer.config.ts

{
resolve: {
alias: { '@': path.resolve(__dirname, './src') },
},
}

In addition to tsconfig.json webpack.renderer.config.ts configuring aliases, you also need to fix ESLint prompts

pnpm install eslint-import-resolver-typescript --save-dev

.eslintrc.json

"settings": {
"import/resolver": {
"typescript": {}
}
}

Process Communication (IPC)

Using the ipcMain and ipcRenderer modules: The main process listens for events through the ipcMain module, and the rendering process sends events through the ipcRenderer module to achieve two-way communication.
Using the remote module: Allows direct calling of modules and methods in the main process from the rendering process, achieving simple cross-process communication.
Using the webContents module: You can directly send messages to a specified rendering process through this module to achieve communication.
Using shared variables between processes: Achieve cross-process communication by establishing global variables or shared memory.

Using ipcMain and ipcRenderer modules

Rendering Process -> Main Process
Method one:

// 渲染进程 发出事件
ipcRenderer.send("channel1", 1, 2, 3);
// 主进程 监听事件
ipcMain.on("channel1", (e, a, b, c) => {
console.log("监听到渲染进程的发出的事件(callback)", a, b, c);
})

Method two:

// 渲染进程 发出事件
ipcRenderer.invoke("channel2", 1, 2, 3);
// 主进程 监听事件
ipcMain.handle("channel2", (e, a, b, c) => {
console.log("监听到渲染进程的发出的事件(Promise)", a, b, c)
})

Main Process -> Rendering Process
Method one:

// 渲染进程 监听事件
ipcRenderer.on(channel, handler)
// 主进程 发出事件
mainWindow.webContents.send("channel3");

Network Requests

pnpm install axios
// forge.config.ts 配置Content-Security-Policy 不是配置html中
const config: ForgeConfig = {
plugins: [
new WebpackPlugin({
devContentSecurityPolicy: "default-src 'self'; connect-src *; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline';",
devServer: {
//配置代理 解决跨域
proxy: {
'/login': {
target: 'http://localhost:8080', // 另一个API服务器地址
changeOrigin: true,
},
},
},
}),
],
};


//对应axios拓展文件 requestUtil.ts
const request = axios.create({
baseURL: 'http://localhost:4000',
});

The detailed requestUtil.ts file is as follows

import axios from 'axios';

const request = axios.create({
baseURL: 'http://localhost:4000',
timeout: 1000,
headers: {
'X-Custom-Header': 'foobar',
// 'Content-Type': 'application/json',
},
// withCredentials: true, //保持跨域请求的cookie信息
});

request.interceptors.request.use(
function (config) {
const token = localStorage.getItem('token');
config.headers.Authorization = token ? `Bearer ${token}` : '';
return config;
},
function (error) {
return Promise.reject(error);
}
);

request.interceptors.response.use(
function (response) {
// 对响应数据做一些处理
return response;
},
function (error) {
// 对响应错误做处理
return Promise.reject(error);
}
);

export default request;