310 lines
6.4 KiB
Markdown
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! 🚀
|
|
|