neptune-privacy/TAURI_WASM_SETUP.md

310 lines
6.4 KiB
Markdown

# Tauri + WASM Setup Guide
## 🐛 Problem
**Symptom:**
- ✅ WASM works in browser (`npm run dev`)
- ❌ WASM fails in Tauri (`npm run tauri:dev`)
- Error: `Cannot assign to read only property 'toString'`
**Root Cause:** Tauri webview requires special configuration to load WASM files correctly.
---
## ✅ Solution: Vite Plugins for WASM
### 1. Install Required Plugins
```bash
pnpm add -D vite-plugin-wasm vite-plugin-top-level-await
```
**Why these plugins?**
- `vite-plugin-wasm`: Handles WASM file loading and initialization
- `vite-plugin-top-level-await`: Enables top-level await (required by WASM)
### 2. Update `vite.config.ts`
```typescript
import wasm from 'vite-plugin-wasm'
import topLevelAwait from 'vite-plugin-top-level-await'
export default defineConfig({
plugins: [
vue(),
tailwindcss(),
wasm(), // ✅ Add WASM support
topLevelAwait(), // ✅ Add top-level await support
// ... other plugins
],
// Rest of config...
})
```
### 3. Tauri CSP Configuration
**File:** `src-tauri/tauri.conf.json`
Ensure CSP includes:
```json
{
"security": {
"csp": {
"script-src": "'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval'"
}
}
}
```
**Key directive:** `'wasm-unsafe-eval'` is **REQUIRED** for WASM in Tauri 2.x
---
## 🎯 How It Works
### Before (Without Plugins)
```
Tauri loads index.html
Vite bundles JS (WASM as regular asset)
Browser tries to load WASM
💥 WASM initialization fails
Error: Cannot assign to read only property
```
**Why it fails:**
- Vite doesn't know how to bundle WASM for Tauri
- WASM file is treated as regular asset
- Tauri webview can't initialize WASM correctly
### After (With Plugins)
```
Tauri loads index.html
vite-plugin-wasm handles WASM bundling
WASM file served with correct headers
vite-plugin-top-level-await enables async init
✅ WASM loads successfully
```
**Why it works:**
- `vite-plugin-wasm` handles WASM as special asset type
- Correct MIME type (`application/wasm`)
- Proper initialization order
- Compatible with Tauri's security model
---
## 📊 Comparison
| Aspect | Browser (dev) | Tauri (without plugins) | Tauri (with plugins) |
|--------|---------------|-------------------------|----------------------|
| WASM Loading | ✅ Works | ❌ Fails | ✅ Works |
| MIME Type | Auto | ❌ Wrong | ✅ Correct |
| Initialization | ✅ Success | ❌ Conflict | ✅ Success |
| CSP Compatibility | N/A | ❌ Issues | ✅ Compatible |
---
## 🔍 Debugging
### Check if WASM is Loading
**In Browser DevTools (F12 in Tauri window):**
1. **Network Tab:**
```
Look for: neptune_wasm_bg.wasm
Status: 200 OK
Type: application/wasm
```
2. **Console Tab:**
```
Should see: ✅ WASM initialized successfully
Should NOT see: ❌ WASM init error
```
3. **Sources Tab:**
```
Check if WASM file is listed under "webpack://" or "(no domain)"
```
### Common Issues
#### Issue 1: WASM file not found (404)
**Cause:** WASM not bundled correctly
**Fix:** Ensure `vite-plugin-wasm` is installed and configured
#### Issue 2: CSP violation
**Cause:** Missing `'wasm-unsafe-eval'` in CSP
**Fix:** Add to `script-src` in `tauri.conf.json`
#### Issue 3: Module initialization error
**Cause:** Top-level await not supported
**Fix:** Install `vite-plugin-top-level-await`
---
## 🧪 Testing Steps
### 1. Test in Browser (Should Work)
```bash
npm run dev
```
- Open http://localhost:5173
- Navigate to `/auth` → Create Wallet
- Check console: Should see "✅ WASM initialized successfully"
### 2. Test in Tauri (Now Should Work)
```bash
npm run tauri:dev
```
- Tauri window opens
- Navigate to `/auth` → Create Wallet
- Open DevTools (F12)
- Check console: Should see "✅ WASM initialized successfully"
- Should NOT see any `toString` errors
### 3. Test Wallet Generation
```typescript
// In CreateWalletFlow.vue
const { generateWallet } = useNeptuneWallet()
// Click "Create Wallet" button
const result = await generateWallet()
// Should return:
{
receiver_identifier: "...",
seed_phrase: ["word1", "word2", ..., "word18"]
}
```
---
## 📦 Package Versions
**Installed:**
```json
{
"devDependencies": {
"vite-plugin-wasm": "^3.5.0",
"vite-plugin-top-level-await": "^1.6.0"
}
}
```
**Compatible with:**
- Vite 7.x
- Tauri 2.x
- Vue 3.x
---
## 🔧 Configuration Files
### `vite.config.ts`
```typescript
import wasm from 'vite-plugin-wasm'
import topLevelAwait from 'vite-plugin-top-level-await'
export default defineConfig({
plugins: [
vue(),
wasm(),
topLevelAwait(),
// ... other plugins
],
})
```
### `tauri.conf.json`
```json
{
"app": {
"security": {
"csp": {
"script-src": "'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval'"
}
}
}
}
```
### `package.json`
```json
{
"dependencies": {
"@neptune/wasm": "file:./packages/neptune-wasm"
},
"devDependencies": {
"vite-plugin-wasm": "^3.5.0",
"vite-plugin-top-level-await": "^1.6.0"
}
}
```
---
## 💡 Why Browser Works But Tauri Doesn't
### Browser (Chrome/Firefox)
- **Permissive WASM loading:** Browsers automatically handle WASM
- **Built-in support:** No special config needed
- **Dev server:** Vite dev server serves WASM with correct headers
### Tauri (Webview)
- **Strict security:** CSP enforced by default
- **Custom protocol:** Assets loaded via `tauri://` protocol
- **WASM restrictions:** Requires `'wasm-unsafe-eval'` in CSP
- **Asset handling:** Needs proper Vite configuration
**Tauri = Embedded Browser + Rust Backend**
- More secure (CSP enforced)
- More restrictive (needs explicit config)
- Different asset loading (custom protocol)
---
## 🚀 Result
**Before:**
```bash
npm run dev # ✅ WASM works
npm run tauri:dev # ❌ WASM fails (toString error)
```
**After:**
```bash
npm run dev # ✅ WASM works
npm run tauri:dev # ✅ WASM works! 🎉
```
---
## 📚 Resources
- [vite-plugin-wasm GitHub](https://github.com/Menci/vite-plugin-wasm)
- [vite-plugin-top-level-await GitHub](https://github.com/Menci/vite-plugin-top-level-await)
- [Tauri Security Documentation](https://tauri.app/v2/reference/config/#securityconfig)
- [WebAssembly with Vite](https://vitejs.dev/guide/features.html#webassembly)
---
## 🎯 Summary
**Problem:** Tauri can't load WASM without proper Vite configuration
**Solution:** Install `vite-plugin-wasm` + `vite-plugin-top-level-await`
**Result:** WASM works in both browser AND Tauri! 🚀