为什么我反对Single-Page App(SPA)

现在越来越多的single-page website称只要打开这个网页就可以使用了! 而且越来越多的框架尝试这么写, 但是我作为一个逆流而上的愣头青缺非常的反对这个.

用户体验

用过美团, 饿了吗, 淘宝, 支付宝的都知道, 别说了.

体验奇差无比

网页就真的跨平台了吗?

众所周知, HTML5 CSS3 JS262 webassembly 和 WebGPU 等均为浏览器标准, 有按照标准的, 有制定标准的, 有事实标准也有完全不按照套路出牌的, 而且越新的技术标准的执行就越混乱, 标准就越混乱, 脱离标准的UB就越离奇, 所以, 这些SPA都会采用各种各样的pollyfill的node模组去尝试解决这个问题, 无论是昨天的polyfill.js, babel, 还是今天的 eslint, 而伴随着越来越多的前端工具的诞生, 前端社区项目往往带来过高的期待, 以及日新月异的所谓的工作流.

前端开发者不得不两年更换一次自己的框架来保证自己紧跟这个时代, 这往往是非常痛苦的, 而传统的APP开发者如Qt和Gtk, 又或者是Android, Winform等都并不会像web一样变更频繁, 你甚至可以在最新的windows 11上运行当年拿Delphi开发的GUI软件, 甚至是为windows 3写的, 拿 turbo pascal 包的对WinAPI直接调用的GUI软件.

而你的上个时代的Flash的Action script在现在的浏览器甚至已经不可以加载了.

安全性就真的更好了吗?

与传统的App不同的是WPA既要在这个小小的网页里维护一套自己的生命周期组件的同时保证较高的渲染速度的同时还要处理与后端的数据交互, 先不谈他的性能问题, 就算是安全也变得尤为棘手.

我们都知道我们有时候会使用什么cookies和什么web storage(当然有的浏览器支持的并不好😄)存各种session 数据来认证你确实是你, 然而各种XSS攻击的套路也层出不穷, 甚至现在XSS攻击已经成为了既缓冲区溢出攻击(哦, 我的苹果, 你的M1加密芯片在第一天就被shellcode干爆了)之后最大的攻击手段, 先不谈对服务器的影响, 先谈谈对客户的影响.

假如有一个脚本能获取到你的cookies并且成功的猜出了你的cookies的pattern并对其进行了一定的变换使得后端以为你真的在登陆, 那么你账号里面的任何的数据将变得非常的危险.

其次就是后端, 很多SPA通过使用前端验证的方式来降低后端的开销, 我们也知道JS是多烂的语言, 万一时候遇到脑瘫开发者并没有对某个信息进行严格验证, 某个别出心裁的用户就可以在用户名上填入这种信息…

这也是曾经我最喜欢干的事情之一, 而且成功打趴了很多php网页(

这对于后端也是非常大的威胁, 我们同时知道JS这门烂语言有eval, 我们可以甚至一边XSS一边注入一边在用户名里面填什么eval…

而本地的App如果开发者训练有素通过各种各样加壳的手法进行反逆向后…这将对这类攻击造成极大的挑战, 而SPA面对这的就是一个个按 F12 就能打开调试器的浏览器, 这对黑客的学习成本…打了骨折.

牺牲的性能真的不要紧吗?

不得不说, 谷歌的工程师你们太吊了, 把JS这一坨大粪能JIT成这样

但是, 我们知道原生的操作系统提供的API往往都是native 语言写的, 诸如C/C艹/Swift/ObjC, 这些语言再烂也就顶多是3x优化最好的C的速度, 而JS虽然速度这么快(5xC)但浏览器上面可不止搭建了一个抽象层, 先就是2D绘画, 浏览器采用的是Skia(Chrome), windows所提供的默认的2D绘图是GDI, 或者是DirectX等更加全面的API, Skia将会对自身的调用转译成提供类似功能的OpenGL/Vulkan, 然后再用诸如Angle这类的进行跨平台调用, 这仅仅是渲染层面上.

多线程上JS本身是一个单线程语言, 它并不具备什么同步语义之类的东西, WebWorker这种简陋的接口在面对复杂需求时往往是力不从心的, 这里我们可以看到 HHLAB 的 CPU 计算性能被各大科学计算框架吊打的事实, 先忽略掉算法层面的问题, 人家native语言如C艹有什么MPI可以高举SIMD和多核大棒, 你凭什么跟人家打?

我的蓝牙, USB设备, 外设呢?

现实当中, 大部分软件虽然都没有直接访问硬件或者对硬件的接口大家都已经做的差不多了, 但还是有一些软件需要跟驱动打交道, 如最近挺火的区块链钱包的硬件钱包.

现在我们的Chrome已经要放弃napi了不知道以后拿什么对本机的USB端口也好, 蓝牙也好进行沟通.

有人可能会说, 欸你用USB和蓝牙的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('Endpoint stalled. Clearing.');
        await device.clearHalt(1); // 看着抽搐的await
      }
    }
  } catch (err) {
    // No device was selected.
  }

  if (device !== undefined) {
    // Add |device| to the UI.
  }
});

目前应该没几家对这个接口落地了, 这是描述文档

然后假如你想在windows上连接USB设备呢? (*nix设备包括安卓都统一使用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("Device not found!");
        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);
}

蓝牙…你想用web操作蓝牙?

别妄想了!

那就更别说什么PCIE设备了

JS语言从一开始就不是给你写App的, 只不过得益于现在的DOM系统提供的跨平台渲染一致性大家都想更轻松的写出各个平台都凑合能跑的软件.

我个人还是崇尚于使网页作为信息的展示和交流平台就足够了, 其他的功能并一定要让浏览器完成, 使用操作系统原生的或者是跨平台的原生语言写的框架不论是易用性还是安全性都要远远的高于使用前端技术.

现在产生这个的原因不是因为原生平台功能不足, 而是在易用性上, 原生的操作系统和GUI软件厂商并没有抱着面向用户和面向开发者的观念努力优化学习曲线, 会的人少自然写出的软件就少, 效果就差强人意.

我所希望看到的是一秒钟之内我能够在这个网页上快速的获取我所需要的信息而不是等待这个网页加载一些杂七杂八杂如App的组件和目录.

评论

  1. 搅局
    1月前
    2022-5-16 18:10:44

    这个网站的风格,让这篇文章显得极其不可信。

    • 博主
      搅局
      1月前
      2022-5-16 18:11:22

      你可以选择订阅rss(

    • javaswing
      搅局
      1月前
      2022-5-17 11:11:50

      哈哈哈哈,我还以为来了b站

  2. laseb
    1月前
    2022-5-16 19:34:10

    x.x 每次滑动页面都要刹车

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇