今天,我们很高兴地介绍 dart_node,一个让你能够完全使用 Dart 构建 React、React Native 和 Express 应用程序的框架。
为什么选择 dart_node?
如果你是 React 开发者,你可能曾希望 TypeScript 的类型能在运行时存在。你可能与复杂的 webpack 配置斗争过。你可能疑惑过为什么仅仅启动一个项目就需要三个不同的配置文件。
如果你是 Flutter 开发者,你可能曾希望能在 Web 生态系统中使用你的 Dart 技能。你可能想要访问 React 庞大的组件库。你可能想要在 Flutter 应用和 React Native 版本之间共享代码。
dart_node 正是为你们两者而生。
Dart 的独特之处
Dart 和 TypeScript 都为动态语言添加了类型安全。但它们做出了不同的设计选择:
TypeScript 选择了最大化 JavaScript 兼容性。 这是明智的——这意味着可以立即访问 npm 生态系统,并能在现有代码库中逐步采用。但这也有代价:类型在编译时被擦除。
Dart 选择了最大化类型安全。 类型在运行时存在。空安全是健全的。泛型不会被擦除。当你序列化一个对象时,你可以验证它的结构。当你反序列化时,你确切地知道你得到了什么。
这里有一个具体的例子:
// TypeScript
interface User {
name: string;
age: number;
}
const user: User = JSON.parse(apiResponse);
// user 真的是 User 吗?我们只能希望如此!
console.log(user.name.toUpperCase());
// 如果 name 是 undefined,运行时会崩溃
// Dart
class User {
final String name;
final int age;
User({required this.name, required this.age});
factory User.fromJson(Map<String, dynamic> json) => User(
name: json['name'] as String, // 已验证!
age: json['age'] as int, // 已验证!
);
}
final user = User.fromJson(jsonDecode(apiResponse));
// 如果执行到这里,user.name 一定是 String
print(user.name.toUpperCase()); // 安全!
这并不是说 TypeScript 不好——而是针对不同需求的不同权衡。
dart_node 技术栈
我们构建了五个包,为你提供全栈能力:
dart_node_core
基础层。提供 JavaScript 互操作工具、Node.js 绑定,以及将所有组件整合在一起的胶水代码。
dart_node_express
类型安全的 Express.js 绑定。使用你熟悉的 Express 模式构建 REST API,同时享有 Dart 的类型安全。
import 'dart:js_interop';
import 'package:dart_node_express/dart_node_express.dart';
final app = express();
app.get('/users/:id', handler((req, res) {
final id = req.params['id'];
res.jsonMap({'user': {'id': id}});
}));
app.listen(3000, () {
print('Server running on port 3000');
}.toJS);
dart_node_react
带有 hooks、组件和类 JSX 语法的 React 绑定。你喜欢的 React 的一切,都在 Dart 中实现。
ReactElement counter() {
final count = useState(0);
return button(
onClick: (_) => count.setWithUpdater((c) => c + 1),
children: [text('Count: ${count.value}')],
);
}
dart_node_react_native
用于移动开发的 React Native 绑定。配合 Expo 使用,获得完整的移动开发体验。
ReactElement app() {
return safeAreaView(children: [
view(style: {'padding': 20}, children: [
rnText(children: [text('Hello from Dart!')]),
]),
]);
}
dart_node_ws
用于实时通信的 WebSocket 绑定。构建聊天应用、仪表盘等。
final server = createWebSocketServer(port: 8080);
server.onConnection((client, url) {
client.onMessage((message) {
client.send('Echo: ${message.text}');
});
});
快速开始
入门非常简单:
mkdir my_app && cd my_app
dart create -t package .
dart pub add dart_node_core dart_node_express
编写你的服务器:
import 'dart:js_interop';
import 'package:dart_node_express/dart_node_express.dart';
void main() {
final app = express();
app.get('/', handler((req, res) {
res.jsonMap({'message': 'Hello from Dart!'});
}));
app.listen(3000, () {
print('Server running on port 3000');
}.toJS);
}
编译并运行:
dart compile js lib/server.dart -o build/server.js
node build/server.js
就这样。不需要 webpack。不需要 babel。不需要复杂的配置。
适用人群
React 开发者:想要更好的类型安全,同时不失去熟悉的 React 模式。
Flutter 开发者:想要在 JavaScript 生态系统中使用 Dart 技能。
全栈开发者:想要在前端、后端和移动端之间共享代码。
所有人:厌倦了用三种不同的语言维护三个不同的代码库。
下一步计划
这只是开始。我们正在努力开发:
- 更多 React hooks 和组件绑定
- React Native 导航库
- 状态管理解决方案
- 构建工具改进
- 更多文档和示例
试一试
查看入门指南来构建你的第一个 dart_node 应用程序。浏览 API 文档查看可用功能。如果有问题,请在 GitHub 上提交 issue。
我们迫不及待想看到你的作品。
dart_node 是开源的,采用 MIT 许可证。欢迎贡献!