前言#
BOS 的全称是 Blockchain Operation System,是由 NEAR 开发的一个框架,旨在为用户开发开放网络应用程序提供支持。擅长 React 的开发者可以在 NEAR Sandbox 直接编写 React 代码来构建应用程序。发布后的 React 代码将托管到 IPFS,实现了去中心化前端。
在智能合约方面,为了提高前端开发者的操作体验,NEAR 通过内置对象 NEAR,提供了便捷的智能合约调用方式,开发者只需使用 NEAR.call 和 NEAR.view 函数即可轻松调用智能合约。
由于 BOS 相当于一个单页应用程序,构建小型应用特别方便。但对于构建稍微大型的应用程序,诞生了两个框架:ROC 和 Além。
本文主要介绍 BOS 的这两个框架之间的对比。
介绍#
1. BWE#
BWE 全称是 BOS Web Engine,是 NEAR 官方开发的一个引擎。官方介绍如下。
BOS Web Engine (BWE) 是下一代去中心化前端执行环境。BWE 使去中心化前端开发更加接近标准 React 开发,并提供增强的、浏览器支持的安全性。Note: “BOS Web Engine” 是一个暂定名称,将在发布前更改
2. Além#
Além 是由推特用户 wpdas 开发。据推文介绍,该产品通过在 NEAR 的 BOS 上显着加快页面加载速度来优化用户体验。 Além 是一个 web3 JavaScript/TypeScript 库,允许您在 NEAR 协议的区块链操作系统上创建 Web3 应用程序。所有组件和其他资源都转换为 Near VM 可以理解的文件,允许您以与 React 类似的方式创建应用程序。您可以利用 JSX 的全部功能,因为 Além 管理有状态组件和无状态组件的子组件,确保它们得到正确处理和理解。
IDE 和预览对比#
1. BWE#
BWE 可以使用在线编辑器 Sandbox 进行编辑。可以进行实时预览。适合短期做活动,和快速开发原型并发布的产品。
2. Além#
Além 可以通过脚手架进行本地开发,如 Installation 页面展示,该软件可以通过 alem 脚手架进行创建一个项目。本地 vscode 编辑,和 react 一样方便。
预览方面,在开发中通过本地链接可以实时预览。http://127.0.0.1:8080/alem-lib.testnet/widget/Index 。同样,如果要通过本地 bos 进行实时预览,可以在 https://test.near.org/flags 这个网址,将 flags 设置为 http://127.0.0.1:8080/api/loader,即可在 https://test.near.org/alem-lib.testnet/widget/Index 这边预览发布后的地址。
react hooks 兼容性#
1. BWE#
通过以下代码测试
import {useState, useEffect, useRef, useCallback, useMemo} from 'react';
function MyComponent() {
const [msg, setMsg] = useState("");
const ref = useRef(null);
useEffect(( ) => {
setMsg("Message");
console.log({ref: ref.current})
}, []);
const res = useMemo(() => {
return 123;
}, []);
console.log({res})
return (
<div ref={ref}>
<p>{msg}</p>
<button onClick={
useCallback(()=> {
console.log("123")
}, [])
}>Click Me</button>
</div>
);
}
export default MyComponent as BWEComponent;
- useState ✅
- useEffect ✅
- useRef ✅
- useCallback ✅
- useMemo ✅
2. Alem#
Alem 使用同样的代码进行测试,结果为 useRef 不存在这个函数。
import { useState, useEffect, useCallback, useMemo } from 'react';
const App = () => {
const [msg, setMsg] = useState("");
useEffect(() => {
setMsg("Message");
console.log({ ref: ref.current })
}, []);
const res = useMemo(() => {
return 123;
}, []);
console.log({ res })
return (
<div>
<p>{msg}</p>
<button onClick={
useCallback(() => {
console.log("123")
}, [])
}>Click Me</button>
</div>
);
};
export default App;
- useState ✅
- useEffect ✅
- useRef ❌
- useCallback ✅
- useMemo ✅
packages 和兼容性#
我列举了下 web3 前端常见会需要的一些库。进行对比他们的是否可以正常使用。
1. BWE#
使用如下代码进行测试
import Big from 'big.js';
import dayjs from 'dayjs';
import clsx from 'classnames';
import lodash from 'lodash';
import s from './styles.module.css';
import toast, { Toaster } from 'react-hot-toast';
const notify = () => toast('Here is your toast.');
function HelloWorld() {
return (
<div>
<p>Num: {Big(10).pow(8).minus(1).toFixed()}</p>
<p>Date: {dayjs('1713161771413').format('YYYY MMMM DD')}</p>
<button className={s.red}>AAA</button>
<button className={clsx(
s.Red,
s.Small
)}>
Click Me
</button>
<p>{lodash.uniq([2, 1, 2, 3, 3, 3]).join(", ")}</p>
<button onClick={notify}>Make me a toast</button>
<Toaster />
</div>
);
}
export default HelloWorld as BWEComponent;
渲染后的效果:
- big.js ✅
- classnames ✅
- dayjs ✅
- lodash ✅
- react-hot-toast ❌
优点:
- 无须定义 esm 地址
- 可以通过 import 导入包
- 支持 typescript
缺点:
- 在测试 classnames 的时候,发现 css modules 似乎无法正常运行。
- button click 在渲染的时候也无法运行。
2. Alem#
- 首先定义 esm 导包,新建一个文件,名字叫
alem.modules.json
{
"javascript-time-ago": "https://unpkg.com/[email protected]/bundle/javascript-time-ago.js",
"dayjs": "https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.10/dayjs.min.js",
"classnames": "https://cdnjs.cloudflare.com/ajax/libs/classnames/2.5.2/index.min.js",
"big.js": "https://cdnjs.cloudflare.com/ajax/libs/big.js/6.2.1/big.min.js",
"lodash": "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"
}
- 新建一个
HomePage.jsx
import { useModule, useState } from "alem";
const HomePage = () => {
const [date, setDate] = useState("");
const [cn, setCn] = useState("");
const [big, setBig] = useState("");
const [lo, setLo] = useState("");
useEffect(() => {
useModule({
code: `dayjs('1713161771413').format('YYYY MMMM DD')`,
onComplete: (data) => {
setDate(data)
},
});
useModule({
code: `classNames("Red", "Small")`,
onComplete: (data) => {
setCn(data)
},
});
useModule({
code: `Big(10).pow(8).minus(1).toFixed()`,
onComplete: (data) => {
setBig(data)
},
});
useModule({
code: `_.uniq([2, 1, 2, 3, 3, 3]).join(", ")`,
onComplete: (data) => {
setLo(data)
},
});
}, []);
return <div>
<p>Date: {date}</p>
<p className={cn}>Small Red</p>
<p>Big: {big}</p>
<p>Lodash: {lo}</p>
</div>
};
export default HomePage;
- 修改
index.jsx
import HomePage from "./components/HomePage";
import { ModulesProvider } from "alem";
const App = () => {
return (
<div>
<p>dayjs testing:</p>
<ModulesProvider />
<HomePage />
</div>
);
};
export default App;
预览效果:
- big.js ✅
- classnames ✅
- dayjs ✅
- lodash ✅
- react-hot-toast ❌
优点:
- 可以自定义 esm 的路径,选择版本
- css 运行良好
- button click 运行良好
缺点:
- 不支持 typescript
- useModule 使用不简单,只能调用一些简单的 js 文件并运算成结果