今、ますます多くのシングルページウェブサイトが「このウェブページを開くだけで使える」と言っています! そして、ますます多くのフレームワークがこのように書こうとしていますが、私は逆流に逆らう若者として非常に反対しています。
ユーザー体験#
美団、饿了吗、淘宝、支付宝を使ったことがある人は、言うまでもありません。
体験ひどすぎる
ウェブページは本当にクロスプラットフォームなのか?#
ご存知の通り、HTML5、CSS3、JS262、WebAssembly、WebGPU などはすべてブラウザの標準です。標準に従っているもの、標準を策定しているもの、事実上の標準、そして全くルールに従わないものがあり、さらに新しい技術標準の実行はますます混乱しており、標準が混乱すればするほど、標準から外れた UB はますます奇妙になります。したがって、これらの SPA はさまざまなポリフィルのノードモジュールを使用してこの問題を解決しようとします。昨日の polyfill.js、babel、そして今日の eslint などです。そして、ますます多くのフロントエンドツールの誕生に伴い、フロントエンドコミュニティのプロジェクトはしばしば過剰な期待をもたらし、日々変化するいわゆるワークフローを生み出します。
フロントエンド開発者は、自分のフレームワークを 2 年ごとに変更しなければならず、時代に遅れないようにする必要があります。これは非常に苦痛です。一方、Qt や Gtk、Android、Winform などの従来のアプリ開発者は、ウェブのように頻繁に変更されることはありません。最新の Windows 11 上で、当時 Delphi で開発された GUI ソフトウェアを実行することさえできます。さらには、Windows 3 のために書かれた、Turbo Pascal を使って WinAPI を直接呼び出す GUI ソフトウェアもあります。
しかし、あなたの前の時代の Flash の Action Script は、現在のブラウザではすでに読み込むことすらできません。
セキュリティは本当に良くなったのか?#
従来のアプリとは異なり、WPA はこの小さなウェブページの中で独自のライフサイクルコンポーネントを維持しながら、高いレンダリング速度を保証し、同時にバックエンドとのデータ交換を処理しなければなりません。性能の問題はさておき、セキュリティも非常に厄介になります。
私たちは、時々クッキーやウェブストレージ(もちろん、サポートがあまり良くないブラウザもあります😄)を使用して、さまざまなセッションデータを保存し、あなたが本当にあなたであることを認証することを知っています。しかし、さまざまな XSS 攻撃の手法も次々と現れ、現在では XSS 攻撃がバッファオーバーフロー攻撃(ああ、私の Apple、あなたの M1 暗号チップは初日にシェルコードで爆破されました)に次ぐ最大の攻撃手段となっています。サーバーへの影響はさておき、顧客への影響について考えてみましょう。
もし、あるスクリプトがあなたのクッキーを取得し、あなたのクッキーのパターンを成功裏に推測し、それに一定の変換を加えてバックエンドが本当にあなたがログインしていると思わせた場合、あなたのアカウント内のデータは非常に危険になります。
次にバックエンドですが、多くの SPA はフロントエンド検証を使用してバックエンドの負担を軽減しています。私たちも知っているように、JS は非常にひどい言語です。もし、脳に障害のある開発者が特定の情報を厳密に検証しなかった場合、独創的なユーザーがユーザー名にこのような情報を入力することができます...
これはかつて私が最も好きだったことの一つであり、多くの PHP ウェブページを打ち負かしました(
これはバックエンドにとっても非常に大きな脅威です。私たちは同時に JS というひどい言語には eval があることを知っています。私たちは XSS を行いながら、ユーザー名に eval を入力することさえできます...
そして、ローカルアプリの場合、開発者が訓練を受け、さまざまな手法で逆向きに行うことができれば... この種の攻撃に対して非常に大きな挑戦となります。一方、SPA は F12 を押すだけでデバッガーを開けるブラウザに直面しています。これはハッカーの学習コストを... 骨折させました。
脱落した性能は本当に問題ないのか?#
言わざるを得ませんが、Google のエンジニアは素晴らしいです。JS という大便をここまで JIT できるとは
しかし、私たちはネイティブのオペレーティングシステムが提供する API は通常ネイティブ言語で書かれていることを知っています。C/C++/Swift/ObjC など、これらの言語はどんなにひどくても、せいぜい最良の C の速度の 3 倍の最適化です。一方、JS はこれほど速い(C の 5 倍)ですが、ブラウザ上には単なる抽象層が構築されています。まず、2D 描画ですが、ブラウザは Skia(Chrome)を使用しており、Windows が提供するデフォルトの 2D 描画は GDI や DirectX などのより包括的な API です。Skia は自身の呼び出しを OpenGL/Vulkan のような類似機能を提供するものに変換し、次に Angle のようなものでクロスプラットフォーム呼び出しを行います。これは単にレンダリングの面での話です。
マルチスレッドに関しては、JS 自体はシングルスレッド言語であり、何の同期セマンティクスも持っていません。WebWorker というこの簡素なインターフェースは、複雑な要求に直面するとしばしば力不足です。ここでは、HHLAB の CPU 計算性能が各種科学計算フレームワークに打ち負かされている事実を見ることができます。アルゴリズムの問題は無視して、ネイティブ言語の C++ には MPI があり、SIMD やマルチコアの大きな棒を高く掲げることができます。あなたはなぜ彼らと戦えるのでしょうか?
私の Bluetooth、USB デバイス、周辺機器は?#
現実には、ほとんどのソフトウェアは直接ハードウェアにアクセスすることはありませんが、ハードウェアのインターフェースはほぼすべてのソフトウェアでうまく行われています。しかし、最近人気のあるブロックチェーンウォレットのハードウェアウォレットのように、ドライバとやり取りする必要があるソフトウェアもあります。
現在、私たちの Chrome は napi を放棄しようとしており、今後はローカルの USB ポートや Bluetooth とどのようにコミュニケーションを取るのか分かりません。
誰かが言うかもしれません、「USB や Bluetooth の JS インターフェースを使えばいいじゃない!」
これらのインターフェースがどれほど使いにくいかを見てみましょう!
まずは互換性を見てみましょう
次に、鬼畜な構文を見てみましょう
let button = document.getElementById('request-device');
button.addEventListener('click', async () => {
let device;
try {
device = await navigator.usb.requestDevice({ filters: [{
vendorId: 0xABCD, // emm
classCode: 0xFF, // 行ける
protocolCode: 0x01 // よし!君の勝ちだ
}]});
while (true) {
let result = await device.transferIn(1, 6);
if (result.data && result.data.byteLength === 6) {
console.log('Channel 1: ' + result.data.getUint16(0)); // この美しいrawを見て
console.log('Channel 2: ' + result.data.getUint16(2));
console.log('Channel 5: ' + result.data.getUint16(4));
}
if (result.status === 'stall') { // この愚かな文字列を見て
console.warn('エンドポイントが停止しました。クリア中。');
await device.clearHalt(1); // この痙攣するawaitを見て
}
}
} catch (err) {
// デバイスが選択されませんでした。
}
if (device !== undefined) {
// UIに|device|を追加します。
}
});
現在、このインターフェースを実装しているところはほとんどないでしょう。これは説明文書です。
そして、もしあなたが Windows で USB デバイスを接続したい場合は? (*nix デバイスは Android を含め、libusb を統一して使用しています)
あなたは簡単に MSDN を調べて必要な文書を見つけ、VS を使用して美しい C# を書き、自由にデバッグして機能に制限を設けることなく行えます。
protected override async void OnLaunched(LaunchActivatedEventArgs args){
// vidとpidを探す
UInt32 vid = 0x045E;
UInt32 pid = 0x078F;
string aqs = UsbDevice.GetDeviceSelector(vid, pid);
var myDevices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(aqs, null);
if (myDevices.Count == 0){
ShowError("デバイスが見つかりません!");
return;
}
UsbDevice device = await UsbDevice.FromIdAsync(myDevices[0].Id);
// 制御信号
UsbSetupPacket initSetupPacket = new UsbSetupPacket() {
Request = initRequest,
RequestType = new UsbControlRequestType()
{
Recipient = UsbControlRecipient.DefaultInterface,
ControlTransferType = UsbControlTransferType.Vendor
}
};
await device.SendOutControlTransferAsync(initSetupPacket);
}
Bluetooth... ウェブで Bluetooth を操作したいですか?
そんなことは考えないでください!
それでは、PCIE デバイスについては何も言うまい。
JS 言語は最初からアプリを書くためのものではなく、現在の DOM システムが提供するクロスプラットフォームのレンダリングの一貫性のおかげで、誰もがより簡単に各プラットフォームで動作するソフトウェアを書くことを望んでいます。#
私は個人的には、ウェブページを情報の表示と交流のプラットフォームとして十分だと考えています。他の機能は必ずしもブラウザに完了させる必要はなく、オペレーティングシステムのネイティブまたはクロスプラットフォームのネイティブ言語で書かれたフレームワークは、使いやすさや安全性の面でフロントエンド技術を使用するよりもはるかに優れています。
現在、この状況が生じているのは、ネイティブプラットフォームの機能不足ではなく、使いやすさの面で、ネイティブのオペレーティングシステムや GUI ソフトウェアのメーカーがユーザーや開発者を意識して学習曲線を最適化する努力をしていないからです。できる人が少ないため、自然と書かれるソフトウェアも少なく、効果も満足のいくものではありません。
私が望むのは、1 秒以内にこのウェブページで必要な情報を迅速に取得できることであり、このウェブページがアプリのような雑多なコンポーネントやディレクトリを読み込むのを待つことではありません。