Xray插件开发入门:使用xray_js创建第一个WASM扩展
你还在为Xray编辑器功能扩展发愁吗?本文将带你从零开始,使用xray_js开发第一个WebAssembly(WASM)插件,无需复杂的C++知识,只需基础的JavaScript和Rust语法,30分钟即可完成一个能实际运行的插件。读完本文后,你将掌握WASM扩展的创建流程、Rust代码编写、JavaScript桥接以及插件测试的完整步骤。
插件开发准备工作
在开始之前,请确保你的开发环境已安装以下工具:
- Node.js(v14+)和Yarn包管理器
- Rust编译器(通过rustup安装)
- wasm-pack工具(用于将Rust编译为WASM)
Xray项目中提供了完整的插件开发基础设施,核心模块包括:
# 克隆项目仓库
git clone https://gitcode.com/gh_mirrors/xray/xray
cd xray/xray
# 安装依赖
cd xray_js && yarn install
理解Xray插件架构
Xray采用分层架构设计,WASM插件运行在独立的沙箱环境中,通过预定义的接口与主程序通信。这种设计确保了插件的安全性和稳定性,同时提供接近原生的性能。
核心通信流程如下:
- 主程序通过JsSink发送消息到WASM插件
- 插件通过Receiver接收消息并处理
- 处理结果通过Sender返回给主程序
- 所有通信采用JSON格式序列化
详细的协议规范可参考客户端-服务器协议文档。
创建WASM插件项目
Xray提供了现成的插件开发模板,我们可以基于xray_js模块快速创建新项目:
# 创建插件项目目录
mkdir -p xray_plugins/hello-wasm
cd xray_plugins/hello-wasm
# 初始化Rust项目
cargo init --lib
# 创建package.json
yarn init -y
修改Cargo.toml文件,添加必要的依赖:
[package]
name = "hello_wasm"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
wasm-bindgen = "0.2.83"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
xray_core = { path = "../../xray_core" }
编写Rust核心代码
创建src/lib.rs文件,这是我们插件的核心逻辑部分。以下是一个简单的"Hello World"示例,实现文本转换功能:
use wasm_bindgen::prelude::*;
use serde::{Serialize, Deserialize};
#[wasm_bindgen]
#[derive(Serialize, Deserialize)]
pub struct TextTransformRequest {
    input: String,
    operation: String,
}
#[wasm_bindgen]
#[derive(Serialize, Deserialize)]
pub struct TextTransformResponse {
    output: String,
    success: bool,
}
#[wasm_bindgen]
pub fn transform_text(request_json: &str) -> String {
    let request: TextTransformRequest = serde_json::from_str(request_json).unwrap();
    
    let output = match request.operation.as_str() {
        "uppercase" => request.input.to_uppercase(),
        "lowercase" => request.input.to_lowercase(),
        "reverse" => request.input.chars().rev().collect(),
        _ => format!("Unsupported operation: {}", request.operation),
    };
    
    let response = TextTransformResponse {
        output,
        success: true,
    };
    
    serde_json::to_string(&response).unwrap()
}
这段代码定义了一个文本转换函数,支持三种操作:大写转换、小写转换和字符串反转。通过JSON格式与JavaScript进行数据交换。
编译Rust代码为WASM
使用wasm-pack工具将Rust代码编译为WASM模块:
# 在xray_js目录下执行编译
wasm-pack build --target web --out-dir pkg
编译成功后,会在pkg目录下生成以下文件:
- hello_wasm_bg.wasm: 编译后的WASM二进制文件
- hello_wasm.js: JavaScript包装器
- hello_wasm.d.ts: TypeScript类型定义
Xray的构建系统已内置WASM编译支持,相关配置可查看xray_js/webpack.config.js。
创建JavaScript桥接层
接下来需要创建JavaScript桥接代码,将WASM模块集成到Xray插件系统中。在xray_js/src目录下创建hello_wasm.ts:
import { transform_text } from '../pkg/hello_wasm';
import { WorkTree } from './index';
// 注册插件
export function registerHelloWasmPlugin(workTree: WorkTree) {
    // 添加自定义命令
    workTree.registerCommand('hello-wasm:uppercase', async (path: string) => {
        const content = await workTree.readFile(path);
        const request = {
            input: content,
            operation: 'uppercase'
        };
        const response = JSON.parse(transform_text(JSON.stringify(request)));
        if (response.success) {
            await workTree.writeFile(path, response.output);
            return { success: true, message: 'Text converted to uppercase' };
        }
        return { success: false, message: response.output };
    });
    // 注册右键菜单
    workTree.registerContextMenuItem({
        label: 'Hello WASM',
        submenu: [
            {
                label: 'Convert to Uppercase',
                command: 'hello-wasm:uppercase'
            },
            {
                label: 'Convert to Lowercase',
                command: 'hello-wasm:lowercase'
            },
            {
                label: 'Reverse Text',
                command: 'hello-wasm:reverse'
            }
        ]
    });
}
这段代码实现了:
- 导入WASM模块的transform_text函数
- 注册自定义命令
- 添加右键菜单选项
完整的API文档可参考memo_js README。
测试插件功能
Xray提供了完善的测试框架,在xray_js/test目录下创建hello_wasm.test.ts:
import { WorkTree } from '../src/index';
import { registerHelloWasmPlugin } from '../src/hello_wasm';
describe('Hello WASM Plugin', () => {
    let workTree: WorkTree;
    
    beforeEach(async () => {
        // 初始化测试环境
        workTree = await WorkTree.create(
            'test-replica',
            'base-commit',
            [],
            {
                baseEntries: async () => [],
                baseText: async () => 'test content'
            }
        );
        registerHelloWasmPlugin(workTree);
    });
    
    test('uppercase command', async () => {
        // 创建测试文件
        await workTree.createFile('test.txt', 'text');
        await workTree.writeFile('test.txt', 'hello world');
        
        // 执行命令
        const result = await workTree.executeCommand('hello-wasm:uppercase', 'test.txt');
        
        // 验证结果
        expect(result.success).toBe(true);
        const content = await workTree.readFile('test.txt');
        expect(content).toBe('HELLO WORLD');
    });
});
运行测试:
# 在xray_js目录下执行
yarn test
测试框架配置可参考xray_js/test/tsconfig.json。
插件打包与分发
插件开发完成后,需要打包为Xray支持的格式。创建plugin.json配置文件:
{
    "name": "hello-wasm",
    "version": "0.1.0",
    "main": "dist/hello_wasm.js",
    "author": "Your Name",
    "description": "A simple WASM plugin for Xray",
    "engines": {
        "xray": ">=0.1.0"
    }
}
使用webpack打包插件:
yarn build
打包后的插件位于dist目录,可通过Xray的插件管理器安装。
总结与进阶方向
通过本文,你已掌握使用xray_js开发WASM插件的基础流程:
- 搭建开发环境
- 编写Rust核心逻辑
- 编译为WASM模块
- 创建JavaScript桥接层
- 测试与打包
进阶学习方向:
Xray的插件系统还支持更多高级功能,如自定义UI组件、快捷键绑定、文件系统操作等。查看Xray插件开发指南获取更多信息。
现在,你已经具备开发Xray WASM插件的基本能力,快去扩展你喜爱的编辑器功能吧!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

 
       
           
            


 
            