Skip to content
Merged

Lynx #1643

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions source/_posts/2025/20250825a_夏の自由研究連載_2025.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ lede: "夏の自由研究2025のブログリレーのインデックス記事で
| 8/28(木) | 大前七奈 | [dbt fusion engine・dbt profiler](/articles/20250828a/) |
| 8/29(金) | 澁川喜規 | [PostgreSQLの標準の全文検索](/articles/20250829a/) |
| 🌻 | - | - |
| 9/1(月) | 清水雄一郎 | Cursor+GitHub Actionsで、自分でソースコード書かずにiOSアプリをApp Storeに公開できるか |
| 9/2(火) | 永井優斗 | クロスプラットフォームフレームワークLynX |
| 9/1(月) | 清水雄一郎 | [Cursor+GitHub Actionsで、自分でソースコード書かずにiOSアプリをApp Storeに公開できるか](/articles/20250901a/) |
| 9/2(火) | 永井優斗 | [クロスプラットフォームフレームワークLynX](/articles/20250902a/) |
| 9/3(水) | 真野隼記 | ソフトスキル |
| 9/4(木) | 神崎林太郎 | nftablesを使った透過型プロキシの構築 |
| 9/5(金) | 仲田帆志弥 | 情報に溺れないためのDeep Researchの活用方法 |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
---
title: "新しいマルチプラットフォームフレームワークLynxを触ってみた。"
date: 2025/09/02 00:00:00
postid: a
tag:
- Lynx
- クロスプラットフォーム
- React
- React Native
category:
- Mobile
thumbnail: /images/2025/20250902a/thumbnail.png
author: 永井優斗
lede: "![image.png]"
---

<img src="/images/2025/20250902a/image.png" alt="image.png" width="1200" height="347" loading="lazy">

[夏の自由研究2025](/articles/20250825a/)ブログ連載の6日目です。

## はじめに

こんにちは、HealthCare Innovation Group(HIG)[^1]の永井優斗です。

2025年3月にTikTokの運営会社である、ByteDance社が [Lynx](https://lynxjs.org/)というクロスプラットフォームフレームワークを公開しました。

LynxはJavaScriptベースでのマルチプラットフォームフレームワークです。そう書かれると、React Nativeを思い浮かべない人はいないでしょう。React Nativeの競合になりうるフレームワークです。

まだまだLynx自体の知名度は低く、LynxとGoogle検索すると、元の意味であるオオヤマネコが出てきます。リンクスティップ(耳の先から出ている、狩りに役立つ毛)が可愛いですね

<img src="/images/2025/20250902a/image_2.png" alt="image.png" width="700" height="473" loading="lazy">

- Lynx lynx, Nationalpark Bayerischer Wald, Deutschland の写真
- 著作者:Martin Mecnarowski
- CC表示-継承 3.0 https://commons.wikimedia.org/wiki/File:Lynx_lynx_1_(Martin_Mecnarowski).jpg による

この記事では、Lynx を触ってみた体験を簡単にまとめます。なお、開発した環境は、私物のMac mini(2020 M1)で、iPhone上での動作を試してみました。

## セットアップ

※セットアップにはNode.js 18以上がインストールされている必要があります。

まずは公式の `create-rspeedy` でプロジェクトを作成します。

```bash
npm create rspeedy@latest
cd <project-name>
npm install
npm run dev
```

- セットアップについては、[公式ドキュメントの[Quick Start](https://lynxjs.org/guide/start/quick-start.html#ios-simulator-platform=macos-arm64,explorer-platform=ios-simulator)もご確認ください

`npm run dev`でビルド成功後、QRコードとURLがターミナルに表示されます。

動作確認には、「Lynx Explorer」というアプリが必要です。

公式サイトに記載の「Download LynxExplorer-arm64.app.tar.gz.」のリンクから落として解凍し、XCodeのシミュレーターにドロップすることで、アプリをシミュレーターにインストールできます。ターミナルに表示されたURLをシミュレーター上の「Lynx Explorer」のCard URLに入力することで、動作確認ができます。

<img src="/images/2025/20250902a/image_3.png" alt="image.png" width="450" height="899" loading="lazy">

また、「Lynx Explorer」は、[App Store](https://apps.apple.com/us/app/lynx-go-dev-explorer/id6743227790)でも公開されており、スマホ実機にもインストールすることが可能です。

同じく、ターミナルに表示されたURLを入力するか、QR コードをアプリで読み込むと、そのままスマホ実機で動作確認できます。
開発している横で、ケーブルに繋ぐこともなく、即実機で試せるのは便利だなと感じました。

## カウンターアプリを作ってみた。

あまり時間をかけずに触ってみたいと思ったため、簡単なカウンターアプリを作成することにしました。

Lynx では HTML タグではなく、 **`<view>`** や **`<text>`** を使います。
イベントハンドラも React っぽくはなく、 **`bindtap`** , **`bindlongpress`** のように書くのが特徴的です。

```jsx App.jsx
<view class="btn" bindtap={() => setCount(c => c + 1)}>
<text>+1</text>
</view>
```

CSS もそのまま使えるので、スタイリングは Web の知識でいけそうです。

## イベント拡張:「長押し」「ダブルタップ」

次に、イベントAPIを活かしてカウンターを拡張しました。

- **+ボタン** → タップで +1、長押しで +10
- **–ボタン** → タップで –1、ダブルタップで –10
- **Resetボタン** → 0 にリセット

### ダブルタップ判定の実装例

```jsx App.jsx
const lastTapTimeStampRef = useRef(0);
const singleTapTimeoutIdRef = useRef(null);
const DOUBLE_TAP_GAP = 250;

// -1 ボタンのtapハンドラ
const handleMinusTap = () => {
const now = Date.now();
const gap = now - lastTapTimeStampRef.current;

if(gap < DOUBLE_TAP_GAP){
// ダブルタップと判定する
if(singleTapTimeoutIdRef.current) {
// ダブルタップが成立したらシングルタップ予約をキャンセル
clearTimeout(singleTapTimeoutIdRef.current);
singleTapTimeoutIdRef.current = null;
}

lastTapTimeStampRef.current = 0;
setCount((c) => c - 10);
return;
}
// シングルタップかもしれない場合は、少し待って確定する。
lastTapTimeStampRef.current = now;
singleTapTimeoutIdRef.current = setTimeout(() => {
setCount((c) => c - 1);
lastTapTimeStampRef.current = 0;
singleTapTimeoutIdRef.current = null;
}, DOUBLE_TAP_GAP);
};
```

標準で「ダブルタップ」イベントがあるわけではないので、`useRef` を使って「直前のタップ時刻」を保存し、一定時間内にもう一度押されたらダブルタップとみなすようにしました。

作成したアプリのUIはこんな感じになりました。

<img src="/images/2025/20250902a/image_4.png" alt="image.png" width="520" height="1018" loading="lazy">

[GitHubでソースを公開](https://github.com/yut0naga1/counter-lynx)しています。

## 触ってみて感じた疎結合感

カウンターアプリを作っていてまず感じたのは、**「ReactとLynxががっちり結合しているわけではない」** という点です。

イベントの書き方ひとつ取っても、React Native なら `onPress` を書くところを Lynx では `bindtap` を書きます。Reactのクリックイベントが`onClick`であるのに対してのReact Nativeの`onPress`はとてもわかりやすいなと思いますが、そのまま持ってきたという感じもします。

LynxはReactのAPIをそのまま持ってきたのではなく、Lynx側に独自のインターフェースがあり、それをReactでラップしているんだなと感じました。

また、スタイルが素のCSSで書けるのも印象的です。React Native のように StyleSheet API に閉じていないため、「Webの知識をそのまま活かせる」一方で「別のフロントエンドフレームワークからも同じ描画基盤を使える」余地があると感じました。

## React Nativeとの違いとしてのフレームワーク依存性

React NativeはReactに強く結合しており、他のUIフレームワークを載せることはできません。Lynxは描画基盤とフレームワークが、(React Nativeと比較してという意味で)疎結合です。React 以外に他のJSフレームワークを載せることもできるかもしれません。

実際、公式のLynx公開時の説明でもLynxが対応するフレームワークReactに限らないことを表明しています。

> We are open-sourcing ReactLynx ("React on Lynx") as Lynx's initial frontend framework flavor, enabling componentized, declarative UI on Lynx.
> **However, Lynx isn't limited to React.** In fact, other frameworks already represent roughly half of Lynx's overall usage, demonstrating its neutrality in hosting different flavors.

※太字はこちらでつけたものです。

実際、[GitHub Issue #193](https://github.com/lynx-family/lynx/issues/193) のとおりVue.jsをLynxに載せられないかというディスカッションはすでに始まっており、今後Vue.jsに対応するかもしれません。その話はまた、[別の機会](https://vuefes.jp/2025/speaker/yut0naga1)で深掘りしたいと思います。

## 最後に

Lynxはまだ3月に出たばかりでもあり、エコシステムの発展やLynx自体も「枯れる」までにはもうちょっと時間がかかるとは思います。
いますぐ業務で使えるというわけではないですが、今後React NativeやFlutterの対抗馬として、マルチプラットフォーム開発に使える日が来るかもしれません。

その頃にはVue.jsにも対応しているといいな。

## おまけ

今回Lynxを触るということまでは決めていたのですが、何つくろっかなーと悩んでいました。ChatGPT5と相談することで、簡単に試すことができました。

カウンターアプリを作ることや、作ったカウンターの拡張(長押し、ダブルタップ)はChatGPTのアイデアです。また、ChatGPTが生成したサンプルのソースコードに対して「この行何やってるんだろうか」と質問したり、逆にChatGPTが明らかにおかしいところを指摘しながら、対話を進めるとだいぶ理解が捗りました。

新しいプログラミング言語に入門するとき、LLMは大きなアシスタントになってくれるんだなと感じました。

[^1]:医療・ヘルスケア分野での案件や新規ビジネス創出を担う、2020年に誕生した事業部です。設立エピソードは[未来報の記事](https://note.future.co.jp/n/n8b57d4bf4604)をご覧ください。
Binary file added source/images/2025/20250902a/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/images/2025/20250902a/image_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/images/2025/20250902a/image_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/images/2025/20250902a/image_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/images/2025/20250902a/thumbnail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading