0%

官方推荐的打包分发工具。

2026-07 修订:Electron Forge 现在更适合作为新项目的默认入口:它覆盖创建项目、开发启动、打包、maker、publisher,并且官方模板已明显转向 Vite / TypeScript 等现代前端工具链。electron-builder 仍然可用,尤其适合已有项目和复杂 NSIS/自动更新配置,但新项目可以先从 Forge 起步。

已有 Electron 项目迁移到 Forge:

1
2
npm install --save-dev @electron-forge/cli
npx electron-forge import

或使用 Electron Forge 脚手架创建项目:

1
npm init electron-app@latest my-app -- --template=vite-typescript

--template=webpack-typescript 仍可用于历史项目或 Webpack 生态依赖较重的场景,但新项目优先考虑 vite-typescript,开发启动更轻,和现代前端项目更贴近。

常用命令

1
2
3
npm start
npm run package
npm run make

2026-07 新增:项目结构关注点

  • main:窗口、菜单、系统能力、自动更新、原生模块。
  • preload:通过 contextBridge 暴露安全白名单 API。
  • renderer:React/Vue/Angular/Svelte 等前端页面。
  • makers:为不同平台生成安装包,如 Windows Squirrel/NSIS、macOS zip/dmg、Linux deb/rpm。
  • publishers:发布到 GitHub Releases 或企业内部更新源。

Why React Native

React Native 和前端技术生态重合度很高,学习成本低, 一份源码可以同时编译成 Android 和 iOS 原生应用. 适合更新迭代较快的项目
同时 其底层架构师根植于移动端原生API 可以自定义原生模块 以及优化性能

本质(nature)

>

在 Android 开发中是使用 Kotlin 或 Java 来编写视图;在 iOS 开发中是使用 Swift 或 Objective-C 来编写视图。在 React Native 中,则使用 React 组件通过 JavaScript 来调用这些视图。在运行时,React Native 为这些组件创建相应的 Android 和 iOS 视图。由于 React Native 组件就是对原生视图的封装,因此使用 React Native 编写的应用外观、感觉和性能与其他任何原生应用一样。我们将这些平台支持的组件称为原生组件。

在较早的React Native中通过称为Bridge的异步机制完成js与原生代码之间的通信,0.74版本开始默认使用Bridgeless mode,调用JSI访问原生代码从而提高性能和响应速度

React Native 允许您为 Android 和 iOS 构建自己的 Native Components(原生组件),以满足您开发应用程序的独特需求。React Native 还包括一组基本的,随时可用的原生组件,您可以使用它们来构建您的应用程序。这些是 React Native 的核心组件

环境配置

React Native项目

1
2
3
npx @react-native-community/cli@latest init AwesomeProject
yarn start # 启动 Metro 构建工具
yarn android

Android设备

  • USB连接Android手机
  • AVD(Android Virtual Device)模拟器

Android Studio—>工具栏Device Manager—>Add a new device—>Create Virtual Device—>选择任意设备—>Next—>UpsideDownCake API Level 34 image

开发

Android Studio开发js/ts很不习惯,可以使用vscode调试,添加react-native-tool,配置emulator到环境变量以使能被vscode调起

1
2
3
4
npm i -g react-native
react-native init mobileApp
npm run android
npm run ios

项目终端执行 npm run android 输出

1
2
3
4
5
6
7
$ react-native run-android
info Launching emulator
...
info Installing the app
> IDLE
> IDLE
...

安装完毕后
会另外启动四个窗口

  • NodeJS 窗口
  • emulator\crashpad_handle.exe
  • emulator\qemu\windows-x86_64\qemu-system-x86_64.exe
  • Android Emulator 移动设备界面

调试
在Android Emulator界面上按 Ctrl + M 弹出Emulator菜单,在菜单中点击Open DevTools启动React Native Cli自带DevTools

打包

1
2
cd android
./gradlew assembleRelease

android emulator

命令行输入emulator —help查看工具参数手册

1
2
emulator -list-avds
...

对于应用crash导致系统崩溃,尝试不加载snapshot后冷启动

1
2
3
4
emulator -avd myavd -no-snapshot-load -no-snapshot-save
emulator -avd myavd -cold-boot
# 擦除用户数据(恢复设置)
emulator -avd myavd -no-snapshot-load -wipe-data

将本地文件放入虚拟设备

1
avd push D:\Download\Game.apk /sdcard/Download/Game.apk

Internet

Platform

1
2
3
4
5
import {Platform, StyleSheet} from 'react-native';

const styles = StyleSheet.create({
height: Platform.OS === 'ios' ? 200 : 100,
});

Platform.OS返回’ios’ 或者’android’
Platform.version返回OS版本号
Platform.select根据平台返回以平台字符串为key的map中对应的value

1
2
3
4
5
6
const Component = Platform.select({
ios: () => require('ComponentIOS'),
android: () => require('ComponentAndroid'),
})();

<Component />;

Metro

The JavaScript bundler for React Native 打包器

视图

视图是React Native UI的基本组成。视图的概念可以小到屏幕上的一个小矩形元素、可用于显示文本、图像或响应用户输入。甚至应用程序最小的视觉元素(例如一行文本或一个按钮)也都是各种视图。View可以嵌套View。全部都是视图。

核心组件

  • View
  • Text
  • Image
  • ScrollView
  • TextInput
  • StyleSheet
  • Button
  • Switch
  • FlatList
  • SectionList

样式

与网页的不同

  • 子元素不继承样式
  • 驼峰命名fontSize
  • 不使用单位(px等)

StyleSheet:

1
2
3
4
5
6
7
8
9
10
11
12
13
import { StyleSheet, Text } from 'reat-native'

const styles = StyleSheet.create({
sectionTitle: {
fontSize: 24
}
})

return (
<>
<Text style={{styles.sectionTitle}}>
</>
)

css px是逻辑像素,物理像素/逻辑像素叫设备像素比 这里css省略px,强调逻辑像素,具体显示的物理像素数量由设备根据屏幕种类换算

PPI(pixels per inch)每英寸物理像素点

RN中的Flexbox规则和Web中Css FlexBox基本一致,主要的不同就是flex-direction默认不同,css中默认是水平方向,rn中默认是垂直方向。

阴影样式

1
2
3
4
5
6
7
8
shadowBorder:{
shadowColor:'#000',
shadowOffset:{width:0, height:0},
shadowOpacity:0.6,
shadowRadius:8,

elevation:1
}

对应css

1
box-shadow: '0 0 8px 8px #000a'

即iOS 通过 shadowOffset shadowOpacity shadowRadius 来实现阴影,而 Android 则通过 elevation 来实现阴影,
ios

React Native Navigation
React Native 中导航变得很复杂,原因在于页面url不会加入window.history

  • Stack Navigator
  • Tab Navigator
  • Drawer Navigator
1
2
3
4
yarn add @react-navigation/native
yarn add react-native-screens react-native-safe-area-context

yarn add @react-navigation/native-stack --> stack导航器

编辑位于 android/app/src/main/java// 下的 MainActivity.kt 或 MainActivity.java 文件。
添加以下代码

1
2
3
4
5
6
7
8
9
10
//...
import android.os.Bundle;

class MainActivity: ReactActivity() {
// ...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(null)
}
// ...
}

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const Stack = createNativeStackNavigator();

function App(): React.JSX.Element {

return (
// <SafeAreaView style={backgroundStyle}>
<NavigationContainer>
<Stack.Navigator initialRouteName='Home'>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="List" component={PatientList} />
<Stack.Screen name="Detail" component={PatientDetail} />
</Stack.Navigator>
</NavigationContainer>

// </SafeAreaView>
);
}

响应式

Dimensions API

1
2
3
4
import { Dimensions } from 'react-native'

const { width, height } = Dimensions.get('screen')//包括状态栏和底部导航
const { width, height } = Dimensions.get('window')//Android不包括, IOS上与screen相同

监听屏幕尺寸改变(横竖屏切换,折叠屏)

1
2
3
4
5
6
7
8
9
10
11
useEffect(() => {
const subscription = Dimensions.addEventListener(
'change',
({ window }) => {
setWindowSize({
width: window.width,
height: window.height,
})
})
return () => subscription?.remove() //组件unmount时移除监听
}, [])

AndroidManifest.xml

声明安卓应用版本信息,元数据,权限声明等,相应的ios应用是Info.plist

1
<uses-permission android:name="android.permission.CAMERA" />

build.gradle

配置应用的构建过程,包含依赖的仓库和插件等等
使用react-native-vector-icons需要配置build.gradle

1
apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle")

使用icons:

1
2
3
import Icon from "react-native-vector-icons/FontAwesome"

<Icon name="camera" color="#ccc" size={36} onPress={openCamera} />

从命令行安装安卓模拟器

不使用Android Studio IDE, 从命令行安装安卓模拟器

下载cmdline-tools其中包含 sdkmanager 工具和 avdmanager 工具

cmdline-tools解压到一个D:/Environment/android-sdk目录(实际上要再加一层latest),并配置到环境变量

1
2
export ANDROID_HOME=D:/Environment/android-sdk
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin

使用sdkmanager安装 platform-tools、emulator、platforms、system-images,(注sdkmanager依赖 jdk 17)

1
2
3
4
5
6
7
8
9
10
11
sdkmanager --sdk_root="D:\Environment\android-sdk" "platform-tools" "emulator"  "platforms;android-34" "system-images;android-34;google_apis;x86_64"

# 创建并启动模拟器 命名为ExpoTest
# 现在可以直接运行(自动读取 ANDROID_HOME)
avdmanager create avd `
-n ExpoTest `
-k "system-images;android-34;google_apis;x86_64" `
-d "pixel_5" `
--force
emulator -avd ExpoTest -gpu swiftshader_indirect -no-audio
npx expo start # 按 a 自动连接

Android是一个基于Linux内核的开源操作系统, 由谷歌开发.它被广泛用于各种设备, 包括智能手机, 平板电脑, 电视和智能手表.

目前, 安卓是世界上移动设备使用最多的操作系统

Kotlin是由JetBrains开发的一种编程语言. 由谷歌推荐, 无论你是不是安卓新手, 都应该把 Kotlin 作为首选 见Android 的 Kotlin 优先方法

Kotlin Doc

Jetpack Compose

Flip

  • First 元素的初始状态(比如位置、透明度等等)
  • Last 元素的最终状态
  • Invert
  • Play

A 状态到 B 状态,不用手动计算每一帧的改变,而是计算从 B 到 A 的反向动画,然后下一帧直接切换 B 状态,在把反向动画应用在 B 上。
其实真实元素是直接从 A->B,但是由于在 B 状态上加了反向动画,所以用户看起来像是过渡。

不明白 暂时没看明白

Go编程语言是Google中一些大牛(尤其是有着plan9前科的大牛们)如Rob Pike,Ken Thomason这两位赫赫有名的程序高手、技术作于2007年9月开始建造。 Pike指出,Go代码的编译基本上可以达到C语言的速度,几乎可以在瞬间完成,“就像是在使用交互式语言”。现有的语言都没有针对多核心处理器 进行优化,为了解决此类编程问题,Google工程师们开发了Go语言。从源文件的copyright可以看到,很多基础代码来自plan9. Go 已在Google公司内部测试过,现在已经发布 Go 1 RC1 版本。Google开放Go的代码,希望籍此帮助Go语言的发展。首席软件工程师Rob Pike说:我们开发Go,是因为近10年左右开发程序之难让我们有点沮丧。Google两年前开始开发Go,1年前开始有一只团队专职于此。目前只支持 unix平台, windows平台的支持由于资源的原因,需要更多的参与者来移植。 Go的定位 是系统编程,比如Web服务器、存储系统和数据库等,但也欢迎在其它方面的应用。 Go 语言官方网站

java 和 go,谁才是最终答案
java优势:

  • 1.1 比较强大的地方是那个jvm,他让你有一些字节码增强的技,jvm层面的语言自带的aop。
  • 1.2 有泛型。
  • 1.3 有annotation技术,这个貌似是java5才出来的。
  • 1.4 面向对象语言。
  • 1.5 有threadlocal技术

go的优势:

  • 1.1 go有多协程的能力,有select和channel让协程能通讯。
  • 1.2 可以定义对象为指针还是对象本体,如果返回对象本体则肯定不会出现空指针。而且go的空对象调用方法也不一定会npe,因为空对象本身不是真的空,是有类型的空对象。
  • 1.3 面向接口的语言,有些面向对象的设计模式不太好写,不过不是重点。
  • 1.4 方法能返回多个对象,编程不会再创建这么多class去包对象了。
  • 1.5 异常处理机制比较特别,go官方建议大家每个函数返回err,这样当你调用方法的时候,会强制让你回答:”如果这个方法异常,你应该怎么做”。不像java,都是throw出去,所以go编程的异常case会少一些。不过这样也让代码很臃肿,到处都是if err!= nil 。

队列的特点是先进先出,以C#的Queue为例

1
2
3
4
5
6
7
8
9
10
11
Queue<string> numbers = new Queue<string>();
// 进
numbers.Enqueue("one");
numbers.Enqueue("two");
numbers.Enqueue("three");
numbers.Enqueue("four");
numbers.Enqueue("five");
// 出
Console.WriteLine("\nDequeuing '{0}'", numbers.Dequeue()); // Dequeuing 'one'
Console.WriteLine("\nQueue Size '{0}'", numbers.)
Console.WriteLine("\nDequeuing '{0}'", numbers.Dequeue()); // Dequeuing 'one'

队列不能直接操作任意指定位置元素 必要时转换为Array

search for topic: Awesome xxx

1
pnpm add -D gh-pages
1
2
3
4
5
6
{
"scripts": {
"build": "vite build",
"deploy": "npm run build && gh-pages -d dist"
}
}

无意在网上看到了编程语言的鄙视链,我anyscript(ts)位列末端,Rust以其编码效率和执行效率、面向现代化,没有历史包袱的优点成为鄙视链上高于C/C++的存在

关于webassembly的开发需求 LLM建议我从原本薄弱的C++路径直接转到Rust上

C++基础薄弱,想要写出能在浏览器安全、高效运行的 Wasm 代码,需要补齐的短板太多. 挑战 Wasm 80% 的精力花在“如何不写崩内存”和“如何配通编译环境”上,而不是业务逻辑。Rust 的设计初衷就包含了内存安全和现代工具链,这与 Wasm 的需求完美契合

Rust学习曲线陡峭 所有权和生命周期概念确实比 C++ 难懂 好在 Rust 一旦通过编译,代码大概率就是正确的

《Rust and WebAssembly》

Rust 在图形学领域(尤其是涉及 WebAssembly、现代 API 如 Vulkan/Metal、以及引擎开发)已经展现出了独特的、甚至超越 C++ 的优势

维度 C++ 传统路线 Rust 现代路线
入门门槛 低(语法简单),但上手难(内存管理陷阱多) 高(概念如所有权、生命周期较难理解),但上手稳(编译报错即修复)
调试难度 极高(崩溃往往是随机且难以复现的) 较低(编译器会告诉你哪里错了,极少运行时崩溃)
图形库生态 极其丰富 (OpenGL, Vulkan, DirectX, SDL2) 快速增长 (wgpu, winit, bevy, cgmath)
Web 集成 需通过 Emscripten 编译,体积大,启动慢 原生支持 Wasm,体积小,启动快,JS 互操作友好
社区趋势 存量巨大,维护旧项目必备 增量巨大,新引擎(如 Bevy, Godot 4+)首选

Start up

1
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

windows 下载Rust

Crate

Rust中 Crate是编译单元 可以理解成一个代码包 每个Crate都是一个独立项目 可以是一个二进制可执行文件或一个库。
使用 Rust 编译器,也就是 rustc 来编译

1
2
3
$ rustc hello.rs
$ ./hello
Hello, world!

Cargo

Rust包管理器 在 Windows 上,下载并运行 rustup-init.exe。它将在控制台中启动安装

强制开发模式下使用全面优化编译策略

1
2
3
[profile.dev]
opt-level = 2 # 默认是 0,改为 2 表示全面优化
debug = true # 建议保留调试信息,否则无法调试

Trait

在 Rust 语言中,Trait(特质) 是极其核心且灵魂的一个概念。简单来说,它定义了类型必须具备的行为(即“能做什么”),而不是描述类型包含的数据(即“是什么”) 可以把它类比为:

  • Java / C# 中的 接口(Interface)
  • C++ 中的纯虚函数 / 抽象类

所有权系统和借用检查器

1
2
3
4
5
6
7
8
9
10
fn main() {
let s = String::from("hello"); // s拥有这个字符串的所有权
println!("s: {}", s);
let s1 = s; // s的所有权转移到s1
println!("s1: {}", s1);
// 这里s已经不再有效,不能再使用它
// 下面这行代码会报错,因为s已经不再有效
// println!("{}", s);
let r1 = &s1; // 不可变引用
let r2 = &s1; // 多个不可变引用是允许的

Rust Wasm

1
2
cargo install wasm-pack
cargo new --lib hello_wasm
1
2
3
4
5
6
7
8
9
10
[package]
name = "hello_wasm"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"
1
wasm-pack build --target web

无间

刘邦被围

安史之乱潼关失守