众所周知,Electron的体积十分庞大,于是设想可以采用一种调用系统Webview和NodeJS的方式来编写跨平台应用。
此时最终一个应用打包好的目录结构可能是这样的:
/
/app // 存储NodeJS应用代码
/node_modules
/src // 存储应该在WebView中运行的HTML、CSS和JavaScript
-main.js // NodeJS应用入口点
/package.json
/main.exe // 使用Rust编写的启动器
Rust的思路是运行后检测系统是否安装有NodeJS,若有则调用其运行/src/main.js
,在该文件中调用系统WebView。若没有则弹出对话框。
在这里,我们需要使用到Rust的msgbox(Jang Ryeol,MIT)包和npm中的webview-nodejs(Winterreisender,MIT)模块等。
按照上述目录结构,Rust代码如下:
extern crate msgbox;
use msgbox::IconType;
use std::{env::*, process::Command};
fn main() {
let mut cmd=Command::new("node");
let nodeVersionOutputResult=cmd.args(["--version",">log.txt"]).output();
match nodeVersionOutputResult{
Ok(nodeVersionOutput)=>{
let nodeVersionResult=String::from_utf8(nodeVersionOutput.stdout);
match nodeVersionResult{
Ok(nodeVersion)=>{
// 版本比较和运行
println!("Start Running NodeJS");
let exePath=current_exe().unwrap();
let basePathArr:Vec<&str>=exePath.to_str().unwrap().split("/").collect();
let mut basePath=String::new();
for i in 0..basePathArr.len()-1{
basePath+=basePathArr[i];
if(i!=basePathArr.len()-2){
basePath+="/";
}
}
let nodeSrcRootPath=String::from(basePath+"/app/main.js");
println!("Run : {}",nodeSrcRootPath);
let mut cmd2=Command::new("node");
cmd2.args([nodeSrcRootPath]).output().expect("failed");
},
Err(errMsg)=>{
msgbox::create("Tips","You need install NodeJS Runtime",IconType::Info);
}
}
},
Err(errMsg)=>{
msgbox::create("Tips","You need install NodeJS Runtime",IconType::Info);
}
}
}
/src/main.js
代码如下:
const {Webview}=require("webview-nodejs")
const wv=new Webview();
wv.size(800,600);
wv.navigate(`file://${__dirname}/src/index.html`)
wv.bind("runInNode",(w,s)=>{
return eval(s);
})
wv.show();
这样整个大小也就8M左右。