为设计师而破解 Tauri
Hacking Tauri for Designer

原始链接: https://yujonglee.com/blog/hacking-tauri-for-designer/

## 直接在浏览器中运行 Tauri 前端 该项目旨在使 Tauri 前端——通常限制在桌面应用程序中——能够直接在 Chrome 或 Cursor 等浏览器中运行。 这旨在简化开发人员的设计和迭代流程,模糊“开发人员”和“设计师”之间的界限,就像 Baby Cursor 等工具所见。 最初,简单地在浏览器中打开本地 Tauri 开发服务器不起作用。 Tauri 依赖于浏览器特定的全局变量 (`__TAURI_INTERNALS__`),这些变量在标准浏览器中不可用,从而破坏了调用 Rust 代码等核心功能。 解决方案通过 `fastrepl/char/plugins/relay` 实现,引入了一个由 Vite 注入的 `shim.js`。 该 shim 替换了缺失的全局变量,并通过 WebSocket 将函数调用路由到 Relay 服务器,然后 Relay 服务器执行 Rust 代码。 为了简化设置,该项目利用现有的“Staging”构建(使用 devtools 启用构建),其中包含必要的 Rust 后端,从而消除了开发人员管理 Rust 依赖项和 UI 迭代的漫长构建时间的需要。 这允许在浏览器环境中进行快速原型设计和开发。

黑客新闻 新 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 为设计师破解 Tauri (yujonglee.com) 5 分,来自 yujonglee 1 小时前 | 隐藏 | 过去 | 收藏 | 讨论 帮助 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系 搜索:
相关文章

原文
yujonglee.com

wdym?

Now I can open up Tauri frontend inside the browser, like this:

And all functionality works the same as using it inside a normal app window.

You might be thinking:

Why is it something to do with the Designer? Tauri is some kind of Devtool, no?

To help them design & iterate fast right inside the codebase, with coding agents.

Tauri is using Webview, so running it in any type of browser should work out-of-the-box, no?

Actually, that’s not the case. We had to build fastrepl/char/plugins/relay to enable it.

motivation

Like Ryo Lu said, the line between "developer" and "designer" is definitely getting blurry.

He even showed how he works, using something called Baby Cursor, within the "Cursor's integrated browser":

After watching this, I wanted to enable something similar to everyone who works in fastrepl/char.

And I first thought it would be simple. Tauri allows typical web frontend stacks to draw UI inside the Webview. So I could just open up localhost:1422 inside the Cursor, right?

Actually, it was not.

problem

  • Tauri relies on __TAURI_INTERNALS__ globals that don't exist in a normal browser.
  • Things like invoke (calling Rust commands) and event subscriptions break immediately outside the managed webview.

solution

fastrepl/char/plugins/relay does it. fastrepl/char#4007 is almost all it takes. (I pushed a bit more commits after this though)

How it works:

  • A shim.js injected by a Vite plugin replaces the missing __TAURI_INTERNALS__ globals in the browser
  • invoke() calls route over WebSocket to the Relay server, which runs the real Rust handler
  • Events (emit / listen) are bridged the same way
flowchart LR
  Browser -->|invoke| Shim[shim.js]
  Shim -->|WebSocket| Relay[Relay]
  Relay --> Backend[Tauri]
  Backend -->|response| Browser
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  window.__TAURI_INTERNALS__ = {
    metadata: metadata,
    _metadata: metadata,
    plugins: {
      path: {
        sep: env.isWindows ? "\\" : "/",
        delimiter: env.isWindows ? ";" : ":",
      },
    },
    invoke: relay.invoke,
    transformCallback: function (callback, once) {
      var id = relay.nextId();
      window["_" + id] = function (response) {
        if (once) delete window["_" + id];
        if (callback) callback(response);
      };
      return id;
    },
    convertFileSrc: function (path) {
      return path;
    },
  };

At this point, the problem is solved. But there is one more concern left.

  1. tauri dev command requires Rust and other dependencies.
  2. most people are familiar with running some web app, but setting up Rust and waiting build is not very approachable. It need lots of compute resource, storage, and time.

Then I realized that we have a Staging build that we don't distribute, but just exists for testing. Staging is built with devtools which enables custom devtools we built(like seeding data etc) and right click context menu in webview(like inspect menu).

133
134
135
136
137
          FEATURES_FLAG=""
          if [[ "${{ inputs.channel }}" == "staging" ]]; then
            FEATURES_FLAG="--features devtools"
          fi
          pnpm -F desktop tauri build --target ${{ matrix.target }} --config ${{ env.TAURI_CONF_PATH }} --verbose $FEATURES_FLAG

Now anyone with the Staging build can just run it as Rust backend, and make code changes in TypeScript side for UI iteration.

"type": "module",

"scripts": {

"dev": "vite",

+ "dev:relay": "echo 'Make sure Char Staging app is running, then open http://localhost:1423' && vite",

"build": "tsc && vite build",

"preview": "vite preview",

"tauri": "dotenvx run --ignore MISSING_ENV_FILE -f ../../.env.supabase -f .env -- tauri",

.plugin(tauri_plugin_windows::init())

.plugin(tauri_plugin_js::init())

.plugin(tauri_plugin_flag::init())

- .plugin(tauri_plugin_relay::init())

.plugin(tauri_plugin_window_state::Builder::default().build())

.plugin(tauri_plugin_listener::init())

.plugin(tauri_plugin_listener2::init())

builder = builder.plugin(tauri_plugin_sentry::init_with_no_injection(client));

}

+ #[cfg(any(debug_assertions, feature = "devtools"))]

+ {

+ builder = builder.plugin(tauri_plugin_relay::init());

+ }

+

#[cfg(all(not(debug_assertions), not(feature = "devtools")))]

{

let plugin = tauri_plugin_prevent_default::init();

联系我们 contact @ memedata.com