说明:
Electron是一个能让你使用传统前端技术(Nodejs, Javascript, HTML, CSS)开发一个跨平台桌面应用的框架。这里所说的桌面应用指的是在Windows、OSX及Linux系统上运行的程序。
基于Electron实现的软件:
Electron现已被多个开源应用软件所使用,其中被广大程序员所熟知和使用的Atom和VsCode编辑器就是基于Electron实现的。尝试打开VsCode,点击帮助菜单中的切换开发人员工具
,可以在界面上看到我们熟悉的Chrome devtool,如下图
底层实现:
由于应用场景是在系统平台上开发应用,所以我们开发时需要有能调用原生系统api的能力。为了能让前端语言能跟底层可以交互,Electron集成了Nodejs+Chromium。Nodejs主要负责应用程序主线程逻辑控制、底层交互等功能,Chromium主要负责渲染线程窗口的业务逻辑。主要的架构如下图:
废话不多说,接下来开始一步一步的搭建工作。
创建项目:
mkdir electron-react-ts
cd electron-react-ts
yarn init
配置 ts,根目录下 touch tsconfig.json
{ "compilerOptions":{ "target":"es5", "module":"commonjs", "lib":[ "dom", "es2015", "es2016", "es2017" ], "allowJs":true, "jsx":"react", "sourceMap":true, "outDir":"./dist", "strict":true, "esModuleInterop":true, "baseUrl":"./", "paths":{ "@/*":[ "./src/*" ] } }}
配置 babel,根路径下 touch babel.config.js,(正常的 babel 配置即可)。
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript'
]
}
配置项目文件 根路径下 mkdir public -> cd public -> touch index.html
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>New Electron App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
一、配置 Electron
yarn add -D electron \
webpack webpack-cli webpack-dev-server \
babel-loader @babel/core @babel/preset-env \
@babel/preset-react @babel/preset-typescript
配置 electron webpack,根路径 touch webpack.electron.config.js
const path = require('path');
module.exports = {
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
devtool: 'source-map',
entry: './electron/main.ts',
target: 'electron-main',
module: {
rules: [{
test: /\.(js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
output: {
path: path.resolve(process.cwd(), 'dist/electron'),
filename: '[name].js',
},
};
配置 electron 的入口文件 main.ts ,注意和 webpack 对应,allowRendererProcessReuse 这个属性会 ts 报错,没细究是版本问题还是其他的问题。
import { app, BrowserWindow } from 'electron';import * as path from 'path';import * as url from 'url';let mainWindow: Electron.BrowserWindow | null;function createWindow() { mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, }, }); mainWindow.webContents.openDevTools() if (process.env.NODE_ENV === 'development') { mainWindow.loadURL(`https://juejin.cn/post/7077545184807878692`); } else { mainWindow.loadURL( url.format({ pathname: path.join(__dirname, './public/index.html'), protocol: 'file:', slashes: true }) ); } mainWindow.on('closed', () => { mainWindow = null; });}app.on('ready', createWindow);//@ts-ignoreapp.allowRendererProcessReuse = true;
配置 package.json 中的脚本,注意 main 为 elecrton 必须属性,其文件要注意对应。
{ "name":"electron-react-ts", "version":"1.0.0", "main":"./dist/electron/main.js", "scripts":{ "dev:electron":"NODE_ENV=development webpack --config webpack.electron.config.js --mode development && electron ." }}
windows 注意配置 crossenv,这里不多述;到这里 Electron 就配置好了。
二、配置 React
yarn add react react-dom @types/react @types/react-dom
yarn add -D html-webpack-plugin
配置 react webpack,根路径 touch webpack.react.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
resolve: {
mainFields: ['main', 'module', 'browser'],
extensions: ['.ts', '.tsx', '.js', '.json', '.jsx'],
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
entry: './src/index.tsx',
target: 'web',
devtool: 'source-map',
module: {
rules: [{
test: /\.(js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': '*',
'Access-Control-Allow-Headers': '*',
},
historyApiFallback: true,
compress: true,
hot: true,
port: 4000,
},
output: {
path: path.resolve(process.cwd(), 'dist/react'),
publicPath: '/',
filename: '[name].js',
},
plugins: [new HtmlWebpackPlugin({
inject: 'body',
template: './public/index.html',
}), ],
};
配置 react 的入口文件,注意和 webpack 关联,根路径下 mkdir src -> cd src -> touch index.tsx app.ts
index.tsx
import React from 'react';
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './app';
const rootElement = document.getElementById('root');
const root = createRoot(rootElement!);
root.render(<StrictMode><App /></StrictMode>);
app.tsx
import React from 'react';
function App() {
return <div>sssss</div>;
}
export default App;
配置 package.json 中 react 脚本
{ "name":"electron-react-ts", "version":"1.0.0", "main":"./dist/electron/main.js", "scripts":{ "dev:electron":"NODE_ENV=development webpack --config webpack.electron.config.js --mode development && electron .", "dev:react":"NODE_ENV=development webpack-dev-server --config webpack.react.config.js --mode development" }}