Electron + React + Typescript + Webpack
如果您现在需要构建桌面应用程序,Electron是一个越来越常见的选择。它是跨平台的,使用您可能已经知道的相同web技术构建。
本文将从一个基本的Electron项目开始,介绍一种建立Electron、TypeScript、React和Webpack的有效方法,逐步将其构建为企业级解决方案。
您也可以直接下载源码,直接在此基础上进行开发。
源码下载
以下是项目架构:
electron-react-rs
|- dist
|- src
| |- electron.js
| |- index.html
| |- react.tsx
|
|- package.json
|- tsconfig.json
|- webpack.config.js
一、初始化空的Electron项目
首先,我们需要创建一个基本的Electron项目,这个过程与官方的 Electron First App教程和 Electron Quickstart repository几乎是一样的。
Electron有两个独立的进程:一个主进程,即Electron本身,以及一个渲染过程,它本质上是Electron在基于Chromium的浏览器中加载的网页。
1.1 创建根目录并安装依赖
mkdir electron-react-ts
cd ./electron-react-ts
npm init -y
npm install --save-dev electron
1.2 创建Electron主入口文件
在官方教程中,Electron入口文件通常为main.js,为了和React命名产生奇异,本文以electron.js作为入口文件。
在根目录下创建src/electron.js
文件并编辑内容如下:
/**
* Electron (main) entry point
* src/electron.js
*/
const { app, BrowserWindow } = require('electron')
/**
* Create the browser window.
*/
function createWindow() {
let win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// load the index.html of the app
win.loadFile('index.html')
}
app.on('ready', createWindow)
1.3 创建Electron渲染入口文件
创建文件src/index.html
并编辑内容如下:
<!--
Electron (render) entry point
src/index.html
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Electron React Typescript</title>
</head>
<body>
<div id="app">
<h1>Getting Started with Electron, Typescript, React and Webpack</h1>
</div>
</body>
</html>
如果一切正常的话,我们就可以使用命令npx electron .\src\electron.js
启动应用了!
当然我们会将命令添加到package.json
文件中作为启动脚本。
// package.json
...
"scripts": {
"start": "electron src/electron.js"
}
...
此时,我们就可以在根路径下使用npm start
启动我们的Electron应用了。
二、添加Typescript
在添加Typescript之前,我们需要先把src/electron.js
重命名为src/electron.ts
,然后再安装并配置Typescript。
2.1 安装依赖
npm install --save-dev typescript
2.2 配置Typescript
我们需要在根路径下创建Typescript配置文件,文件名为tsconfig.json
。
touch tsconfig.json
2.3 更新npm脚本
更新package.json
文件中的scripts
脚本,添加build
指令。
//package.json
"scripts": {
"build": "tsc src/electron.ts"
}
三、增加Webpack
接下来,我们将设置Webpack以优化应用程序。Webpack配置由一组入口点组成。Webpack通过将文件(及其依赖项)传递给加载器来处理每个入口点。加载器是通过规则选择的,通常每个文件扩展名都有一个加载器。最后,Webpack将输出转储到指定位置。
我们将为我们的Electron主进程创建一个单一入口点,为所有*.ts
文件添加一个加载器以通过 TypeScript 编译器,并告诉 Webpack 将输出与源文件一起存储。
3.1 安装依赖
npm install --save-dev webpack webpack-cli ts-loader
3.2 配置Webpack
在项目根路径下创建webpack.config.js
文件,并编辑内容如下:
// webpack.config.js
module.exports = [
{
mode: 'development',
entry: './src/electron.ts',
target: 'electron-main',
module: {
rules: [{
test: /\.ts$/,
include: /src/,
use: [{ loader: 'ts-loader' }]
}]
},
output: {
path: __dirname + '/src',
filename: 'electron.js'
}
}
];
简单介绍配置项作用:
-
mode:develop
开发模式(与生产模式相反) -
entry:'./src/electron.ts'
入口文件的位置 -
target:'electron-main'
指定目标环境 -
test:/\.ts$/
指明当前规则匹配所有以.ts
结尾的文件 -
include:/src/
指明src
文件夹下的所有文件匹配此规则 -
use:[{loader:'ts-loader'}]
指明当规则匹配后使用哪个加载器 -
path:__dirname + '/src'
所有的输出文件将会放在这个文件夹 -
filename:'electron.js'
主输出包文件名
3.3 更新npm脚本
// package.json
"scripts": {
"build": "webpack --config ./webpack.config.js",
"start": "npm run build && electron ./src/electron.js"
}
此时,如果我们使用npm run build
命令,在项目的src
目录下会生成electron.js
文件。
如果使用npm start
命令,则会和之前一样启动应用。
测试执行后,记得删除生成的electron.js文件
四、添加React
React 渲染过程不需要知道它正在 Electron 上下文中使用,因此设置 React 类似于设置一个普通的 React 项目。
4.1 安装依赖
npm install --save-dev react react-dom @types/react @types/react-dom
4.2 React入口文件
创建src/react.tsx
文件并编辑内容如下:
/**
* React entry point
* src/react.tsx
*/
import * as React from 'react'
import * as ReactDOM from 'react-dom'
const Index = () => {
return <div> Hello React!</div>
}
ReactDOM.render(<Index />, document.getElementById('app'))
4.3 TypeScript配置
我们的渲染入口点是.tsx
,而不是.ts
。TypeScript编译器内置了对tsx
(与JSX等价的TypeScript)的支持,但我们需要告诉TypeScript如何处理tsx资源。
// tsconfig.json
{
"compilerOptions": {
"jsx": "react"
}
}
接下来,我们将在Webpack的配置中创建一个新的入口点。Webpack将处理入口点(及其依赖项)并将结果通过 html-webpack-plugin
加载到index.html
。
4.4 安装依赖
npm install --save-dev html-webpack-plugin
4.5 Webpack配置
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = [
...
{
mode: 'development',
entry: './src/react.tsx',
target: 'electron-renderer',
devtool: 'source-map',
module: { rules: [{
test: /\.ts(x?)$/,
include: /src/,
use: [{ loader: 'ts-loader' }]
}] },
output: {
path: __dirname + '/dist',
filename: 'react.js'
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
}
];
此配置与Electron主流程配置类似,但有一些新参数:target:'electron-renderer
指定目标的环境
plugins:...
指定生成过程中使用的所有插件。插件与加载器的不同之处在于,插件在捆绑包级别运行,并且可以通过hooks与构建过程进行更深入的集成。加载器在文件级运行。HtmlWebpackPlugin
将自动在指定的模板文件中添加对输出包的引用。react.tsx
文件的输出路径不再是src
目录,我们已指示Webpack将资源放在新的dist
目录中。
修改主进程节点的输出路径:
// webpack.config.js
...
output: {
path: __dirname + '/dist',
filename: 'electron.js'
}
现在,所有文件的输出都在dist
文件夹下了,相应的,我们还需要更新npm脚本:
// package.json
"scripts": {
...
"start": "npm run build && electron ./dist/electron.js"
}
至此,所有配置工作都完成了,赶快执行指令测试一下是否成果吧!
如果我们执行npm run build
指令,会在根路径下生成dist
文件夹,并在其中生成相应的文件。
如果我们执行npm start
指令,会直接启动应用
五、总结
所谓“授人以鱼不如授人以渔”,只有真正掌握了整个框架的运行机制,才能写出更好的代码。