NW.js开发环境搭建
文章目录
- NW.js开发环境搭建
- 简介:NW.js是什么?
- 1. 选择Build Flavors SDK
- 2. 下载安装NWJS
- 3. 创建第一个应用
- 4. 运行应用
- 5. 打包应用
- 6. APIs
- 扩展
- 1. 配置文件(package.json)
- 2. 使用NW.js APIs
- 3. 使用Node.js API(`require`)
- 4. 开发工具与调试
- 5. NW.js中独立环境和混合环境模式
- 5.1 独立环境模式
- 5.1.1 浏览器环境
- 5.1.2 Node环境
- 5.2 混合环境模式
- 5.3 混合环境模式和独立环境模式对比
- 6. JavaScript源码保护
- 7. 应用签名
- 7. 自动更新
- 8. Node.js 自定义模块
- 9. ES6与NodeJS模块导入导出区别
- NodeJs
- ES6
- 10. [ES6 入门教程](https://es6.ruanyifeng.com/)
简介:NW.js是什么?
NW.js基于Chromium和Node.js。它使您可以直接从浏览器中调用Node.js代码和模块,也可以在应用程序中使用Web技术。此外,您可以轻松地将Web应用程序打包到本机应用程序。
NW.js官网
NW.js中文网
1. 选择Build Flavors SDK
NW.js支持各种构建样式以减小应用程序大小。当前,NW.js支持以下构建风格:
- SDK风格(SDK):内置了对DevTools和NaCl插件的支持。SDK风味与0.13.0之前的版本具有相同的功能(适用于开发调试环境);
- 正常风格(Normal):是不带DevTools和NaCl插件支持的最低版本(适用于发布环境)。
建议您选择SDK构建风格来开发应用程序,这使您可以使用DevTools调试应用程序。
2. 下载安装NWJS
对于国内用户,如果下载连接下载速度太慢的话,可以考虑的可选项是:
- 淘宝NPM镜像
- 百度网盘链接,提取码为: ivh3
或者进入官网下载根据自己需要下载对应的版(我这里下载的是mac版本的v0.44.5,osx-x64,normal
v0.44.5,osx-x64,sdk
-
下载后直接解压,将
nwjs.app 拖到应用程序中(便于从桌面点击图标启动)
-
设置别名和环境变量(以便从命令行可直接启动)
1
2
3
4
5
6
7
8
9
10
11#打开bash_profile环境变量配置文件
vim ~/.bash_profile
#设置环境变量-nwjs的别名
alias nw="/Applications/nwjs.app/Contents/MacOS/nwjs"
#应用环境变量
source ~/.bash_profile
#命令行输入nw 回车启动即可(等同于桌面点击图标启动)
nw启动后如下如:
3. 创建第一个应用
-
创建package.json文件
通过node.js初始化一个项目(首先,确保你已经安装好了
node.js 的环境),生成package.json 文件,package.json 是JSON 格式格式的配置文件.main 属性定义了应用首页, 如本例的"index.html" .name 则定义了应用名称. 具体查看 配置文件章节.1
2
3
4
5
6#创建项目目录
mkdir NWDemo
#进入项目根目录
cd NWDemo
#执行初始化生成package.json
npm initpackage.json
1
2
3
4
5
6
7
8
9
10
11
12{
"name": "test1",
"version": "1.0.0",
"description": "",
"main": "index.html",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}您可以将
"main" 属性设置如"main.js" 的js文件. 该文件在应用启动时默认不打开窗口并在后台执行。 您可以稍后进行一些初始化并手动打开窗口。 例如:1
2// 初始化你的应用程序之后 ...
nw.Window.open('index.html', {}, function(win) {}); -
创建入口页面
index.html 1
2
3
4
5
6
7
8
9<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
4. 运行应用
进入我们创建的项目中,执行
- Windows系统中是
nw.exe ; - Linux系统中是
nw ; - Mac系统中是
nwjs.app/Contents/MacOS/nwjs ;
1 2 3 4 | #进入项目根目录 cd NWDemo #运行 nw . |
【注意】
Windows系统中 , 可拖拽包含
5. 打包应用
可以使用以下工具自动完成打包NW.js应用进行发布 .
- nwjs-builder-phoenix (推荐:用于为Windows,macOS和Linux构建和打包可分发的NW.js应用程序。)
- nw-builder
或者可以使用以下步骤手动构建应用 ,具体步骤参考手动构建应用
这里使用
6. APIs
详细使用参见地址
扩展
1. 配置文件(package.json)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | { "name": "nw-demo", #应用名称,应确保该字段内容全局唯一性 "main": "index.html", #应用起始页 "nodejs":true, #是否支持Node "node-main":"xxxx", #指定Node.js脚本文件路径并且它将在加载DOM窗口之前启动Node环境时执行 "domain":"xxxx", #指定主机域名 "single-instance":false, #是否以单实例运行(false则允许应用多开,默认 true) "bg-script":"xxxx", #应用启动时执行的后台脚本 /** *窗体样式控制(窗口子字段默认情况被继承到使用 window.open()或 <a target="_blank">打开的子窗口 *未继承子字段将被设置为打开窗口时的默认值) *列表如下: * fullscreen -> false * kiosk -> false * position -> null * resizable -> true * show -> true */ "window":{ "id":"xxx", #内含窗口尺寸与位置的状态的窗口ID,打开同ID的窗口时会还原该状态 "title":"xxx", #NW.js创建的窗口标题 . 在应用启动时显示的标题信息 "width":200, #窗口宽高 "height":200, #窗口高 "toolbar":true, #是否显示导航栏中的工具条 "icon":"xxxx", #窗口图标路径 "position":"xxx", #窗口位置:默认 null(不固定) , center(屏幕居中) , mouse(鼠标所在位置) "min_width":100, #窗口最小宽高 "min_height":100, "max_width":500, #窗口最大宽高 "max_height":500, "as_desktopLinux":false, #X11环境下,作为桌面背景显示(true显示, false不显示) "resizable":true, #是否可调整窗口大小(在OS X上将该属性设置为 false,并将frame设置true, #用户还是可以将窗口全屏显示。只有将全屏也设置为 false才可禁用全屏控件。 "always_on_top":false, #是否允许窗口始终置顶(在其余窗口之上,true允许, false不允许) "visible_on_all_workspaces Mac & Linux",: #支持多工作区的系统(如Mac & Linux)中,将窗口同时显示 #在所有工作区中(true允许, false不允许) "fullscreen":false, #是否允许窗口全屏(窗体和全屏框架(frame)应当一致,窗口设置为 false时, #则全屏框架(frame)不应设为 true,避免窗体将阻止鼠标获取屏幕边缘) "frame":true, #窗口是否为框架(窗体和全屏框架应当一致,窗口设置为 false时,则全屏框架 #不应设为 true,避免窗体将阻止鼠标获取屏幕边缘.) "show_in_taskbar":true, #是否允许显示在任务栏或停靠栏中(true允许, false不允许,默认 true) "show":true, #启动时是否显示应用(true显示, false不显示) "kiosk":true, #是否使用 Kiosk模式(该模式即应用将全屏并阻止用户离开(关闭)应用,比如常见 #的公共触摸屏演示,银行排队取票机洁界面,直到页面返回响应) "transparent":false, #窗口是否透明(true允许, false不允许,默认 false) #窗口的透明度由CSS中的背景透明值控制, #使用命令行参数 --disable-transparency 可完全禁止透明功能. #使用命令行参数 --disable-gpu 禁用GPU后,可实现透明窗体的穿透点击 }, /** *WebKit特性控制 */ "webkit":{ "double_tap_to_zoom_enabled":false, #是否启用两指缩放功能(true允许, false不允许,默认 false) "plugin":true, #是否可加载扩展插件,比如Flash插件(true允许, false不允许,默认 true), }, "user-agent":"xxx", #重写应用请求页面中的 User-Agent信息 #以下变量内容可以动态设置 User-Agent内容: #%name: 替换配置文件中的name字段 . #%ver: 替换配置文件中的version字段 . #%nwver: 替换NW.js版本 . #%webkit_ver: 替换WebKit引擎版本 . #%osinfo: 替换系统以及CPU信息 . "chromium-args":"xxx", #分发应用时自定义chromium命令行参数至应用(想要禁用GPU加速视频显示, #只需添加添加参数 "chromium-args" : "--disable-accelerated- #video".) "crash_report_url":"xxx", #应用崩溃时,崩溃转存报告将被发送到设定的服务器 "inject_js_start":"xxx", #CSS文件执行之后 , 其他DOM或脚本运行之前 , 执行的JavaScript代码 "inject_js_end":"xxx", #页面document对象加载之后 , 触发 onload之前 , 执行的JavaScript #代码 . 主要作为新窗口中 Window.open()的参数执行JavaScript代码 "additional_trust_anchors", #证书作为附加可用的根证书使用 , 允许连接自签名证书或者CA签发机构颁发 #证书的服务(Array - 数多个PEM编码的证书组成的数组) "dom_storage_quota":500, #Mb为单位的DOM存数限制数量(建议设置为期望值的两倍) /** *其他字段 */ "description":"xxx" #配置的描述说明,以.结束 "version":1.0, #应用版本信息 "maintainers":[{ #维护成员 "name": "Bill Bloggs", "email": "[email protected]", "web": "http://www.bblogmedia.com", }], "contributors":[{ #贡献者,与维护成员格式一致,但首个应为作者 "name": "xxx", "email": "xxx", "web": "xxx", }], "bugs":"xxx", #提交错误的网址,如mail或http地址 "licenses":"xxx", #许可证列表 "dependencies":"xxx", #必要依赖,组的顺序非常重要,较前条目具有较高优先级. "homepage":"xxx", #网站URL地址 } |
2. 使用NW.js APIs
旧版本加载
nw 方式为require('nw.gui') ,返回nw 对象。
举个??:通过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <html> <head> <title>创建上下文菜单</title> </head> <body> <P>右击显示上下文菜单</P> <script> //1.通过NW.js 创建一个空菜单 let menu = new nw.Menu(); //js中可直接使用 nw 对象,已经被加载到全局对象中 //2.创建三个菜单项目 let menuItem1 = new nw.MenuItem({label:'菜单1',click:()=>{alert('选择菜单1')}}); let menuItem2 = new nw.MenuItem({label:'菜单2',click:()=>{alert('选择菜单2')}}); let menuItem3 = new nw.MenuItem({label:'菜单3',click:()=>{alert('选择菜单3')}}); //3.将菜单项添加到菜单中 menu.append(menuItem1); menu.append(menuItem2); menu.append(menuItem3); //4.对当前html文档body标签内的正文内容设置监听事件 document.body.addEventListener('contextmenu',(ev)=>{ //阻止默认的弹出框 ev.preventDefault(); //弹出自定义的Menu菜单 menu.popup(ev.x,ev.y); return false; },false); </script> </body> </html> |
效果如下图:
PS:
- 更多HTML DOM Event事件可参见**《HTML DOM 事件》**
3. 使用Node.js API(require )
我们除了上述在DOM中直接使用
举个??:利用Node.js的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <html> <head> <title>创建上下文菜单</title> </head> <body> <!--这里使用Flex弹性布局--> <div style="display:flex;flex-direction:row;justify-content:center;align-item:center"> <div style="flex:30%">您的当前系统为:</div> <div style="flex:70%" id='os_platform'></div> </div> <script> //1.将node.js中os模块脚本赋值给 mOS对象 let mOS = require('os'); //2.通过document的getElementById方法获取对应的div对象,然后通过innerHTML修改div内容 document.getElementById('os_platform').innerHTML=mOS.platform(); </script> </body> </html> |
PS:
- 您可以在NW.js中通过
npm 进行模块的安装然后使用。 - 详细Flex布局参见《Flex 布局语法教程》
- 【注意】当使用
npm install 构建原生模块时无法兼容 NW.js ABI. 如需使用则需要根据nw-gyp 进行NW.js的重建. 详细参考使用原生模块章节.
4. 开发工具与调试
开发工具只能在SDK构建方式中使用。
-
Open Developer Tools 开启开发工具
Windows和Linux系统中使用快捷键
F12 开启 , Mac系统中使用??i .此外 , windows系统中可以使用win.showDevTools()`开启开发工具进行编程
-
调试Node.js模块
NW.js默认进行独立环境模式运行,调试Node.js模块需要在引用中右键并选择
Inspect Background Page ,当运行到Node.js模块代码时,调试器会自动聚焦并暂停运行。混合模式下,Node.js模块可以在开发工具中直接进行调试。
-
远程调试
使用命令行参数
--remote-debugging-port=port 指定端口进行监听。例如,运行nw --remote-debugging-port=9222 ,通过浏览器访问http://localhost:9222/进行远程调试 。 -
开发工具扩展
开发工具支持全部扩展,包括
ReactJS 等使用扩展需要在配置文件
manifest.json 添加chrome-extension://* 权限,并在nw运行时增加--load-extension=path/to/extension 命令行参数 . 扩展的文件从Chrome应用商店安装之后拷贝到本地Chrome浏览器目录下 .
5. NW.js中独立环境和混合环境模式
NW.js基于Chrome应用构建,因此NW.js在开始运行时候,自动完成后台加载。当创建一个窗口时,同时创建一个JavaScript环境。
NW.js中,默认情况下,Node.js模块加载到后台运行环境。
5.1 独立环境模式
除浏览器环境,NW.js默认在后台增加Node.js环境运行Node模块,这样NW.js同时拥有两个JavaScript环境:
5.1.1 浏览器环境
-
加载脚本
标签 - jQuery的
$.getScript() - RequireJS 。
-
全局对象
- JS内建对象(如
Date ,Error ,TypedArray ) - Web API (如DOM API) .
- JS内建对象(如
-
创建新浏览器环境
创建新的frame或者窗口时 , 将得到一个新的浏览器环境
-
访问
Node.js 和NW.js 的API将Node环境对象拷贝到浏览器环境中 , 这样运行在浏览器环境的脚本能够访问Node.js对象
nw – 所有NW对象 NW.js APIsglobal – NW环境全局对象; 等同nw.global require – 加载Node.js模块的方法; 等同nw.require() , 但不支持通过require('nw.gui') 加载NW.js模块.process – Node.js模块中process模块; 等同nw.process Buffer – Node.js模块中Buffer类
5.1.2 Node环境
-
加载脚本
- 通过Node.js的API中的
require() 加载脚本; - 通过配置文件中
node-main 加载脚本;
- 通过Node.js的API中的
-
全局对象
- js内建对象
- Node.js全局对象(如
__dirname ,process ,Buffer 等)
【注意】Node环境不能使用Web APIs,下面会介绍访问浏览器环境和NW.js的API
-
创建新的Node环境
- 通过
Window.open() 创建新窗口,并且参数new_instance 设置为true时; - 命令行启动NW.js时,参数增加
--mixed-context 进入混合环境模式;
- 通过
-
访问浏览器环境和NW.js的API
Node环境中,没有浏览器或NW.js APIS,如
alert() 、document.* 、new.Clipboard 等,想访问浏览器APIs**必须传递相应的对象 **,如window 举个??
Node脚本(
test.js )1
2
3
4//node环境中访问浏览器的API需要浏览器环境传入对应的el对象
exports.setText = (el) => {
el.innerHTML = 'hello';
};浏览器(
index.html )1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<html>
<head>
...
</head>
<body>
<div id="el"></div>
<script>
//加载 test.js Node模块
var myscript = require('./test.js');
//调用Node模块setText方法将`el`元素传入Node函数
myscript.setText(document.getElementbyId('el'));
// "hello"将显示在`el`标签中
</script>
</body>
</html>
5.2 混合环境模式
当使用
-
混合模式中加载脚本
NW.js可以通过两种方式使用混合环境模式 , 一是使用
--mixed-context 命令行参数 , 二是在配置文件中添加chromium-args 属性.package.json 1
2
3
4
5{
"name": "test-context",
"main": "index.html",
"chromium-args": "--mixed-context" //chromium-args属性指定使用混合模式
}页面或Node.js中使用
require() 方式加载脚本运行在同样的环境中 . -
全局对象
混合环境模式 , 您可以在Node模块中使用所有浏览器和NW.js API,反之亦然 node.js文件(test.js)
1
2
3
4
5//导出showAlert函数
exports.showAlert = function() {
//因为开启了混合环境摸模式,可以在Node中直接使用浏览器的alert API
alert("我正在Node模块中运行!");
};Index.html
1
2
3
4
5
6
7
8
9
10
11<html>
...
<body>
<script>
//加载 test node模块
var test = require('./test');
//调用模块的showAlert方法
myscript.showAlert(); // 我正在Node模块中运行!
</script>
</body>
</html>
5.3 混合环境模式和独立环境模式对比
独立环境模式的优势是不会出现类型检查问题 .
混合环境模式的缺点是不能轻易的分享变量 . 环境间分享变量 , 需要将变量放入其他环境能够访问的通用环境中 . 或者可以使用
6. JavaScript源码保护
-
源码保护目的
应用中的javascript源代码能够编译为本地二进制代码进行保护,NW.js能够加载编译之后的代码,应用作为产品发布时可以将代码进行编译!
-
如何编译和加载
-
编译
JS源码编译为本地二进制代码需要使用
nwjc 工具,同时需要提供SDK构建方式的NW.1nwjc source.js binary.bin*.bin 文件需要发布到应用中,可以任意命名bin文件。 -
加载
NW.js 加载已编译的JS文件
1nw.Window.get().evalNWBin(frame,'binary.bin');Win.evalNWBin()方法中的参数与
Window.eal() 方法相同,第一个参数为目标frame(null为主frame),第二个参数为已编译的bin文件 -
加载远程已编译的JS文件
NW.js可以从远程(例如AJAX)获取已编译的JavaScropt,并且即时执行。
1
2
3
4
5
6
7
8
9
10
11
12
13//创建请求实例HMLHttpRequest
var xhr = new HMLHttpRequest();
//设置响应类型-ArrayBuffer对象二进制数据(告诉服务器期望的响应格式)
xhr.responseType = 'arraybuffer';
//设置请求方式和地址
xhr.open('GET',url,true);
//发起请求
xhr.send();
//接收响应
xhr.onload=()=>{
//接收到响应使用NW加载已编译的js文件
nw.Window.get().evalNWBin(null,xhr.response);
}
**PS:**已编译代码在浏览器环境中执行 . 可以像其他运行在浏览器环境中的其他脚本 , 就像您使用任何Web API(如DOM)以及NW.js API和Node API
-
-
不足
已编译代码不支持跨平台也不兼容不同版本的NW.js的版本,因此在打包应用时需要在各自系统平台中运行
nwjc .
7. 应用签名
应用签名可阻止正式应用中加载未签名的文档。
注意:应用签名并不能阻止别有用心的人黑进你的应用,或者使用其他NW代码加载你的应用,可考虑使用C++编写,并使用Node.js模块和NaCl加载,或者结合使用
-
签名文件
NW.js的应用签名文件为
verified_contents.json ,它提供了密钥对,该文件由sign.py 工具与私钥文件private_key.pem 所创建,公钥已经内置于NW.js应用中。 -
如何签名
要运行签名的应用程序,在应用程序目录中调用
nw --verify-content=enfore_strict 命令执行严格验证模式,之后显示签名页面,完成签名动作。在此之后对
index.html 进行任意修改,NW将报告文件已损坏并立即退出。 -
签名步骤
使用密钥对签名应用,步骤如下:
- 切换到应用目录中
- 确认
verified_contents.json 或computed_hashes.json 文件不在当前目录(如果存在删除) - 运行
payload 生成sign.py 所需的配置文件payload.json 文件 - 运行
python sign.py > /tmp/verifid_content.json ,需要注意 tmp目录不能是应用所在目录 - 将生成的
verified_contents.json 文件拷贝到应用目录,完成签名动作。
-
使用自己密钥对重新构建应用
要使用您自己的密钥对,您需要重建NW,并命令行参数
--verify-content= 默认设置为enfoce_strict openssl genrsa -out private_key.pem 2048 生成密钥对,输出公私钥文件- 运行
python convertkey.py ,它会将公钥转换为C源代码 - 将生成的代码复制到NW安装包的
content/nw/src/nw_content_verifier_delegate.cc ,替换原文件默认的key值 - 更改文件中第73行为
Mode experiment_value = ContentVerifierDelegate::ENFORCE_STRICT; - 重新构建NW
7. 自动更新
详细使用参见此链接
8. Node.js 自定义模块
Node应用由模块组成,
它的exports属性(即
-
module.export(
导出模块 )module.exports 是对外的接口。加载某个模块 ,其实是加载该模块的module.exports属性。举个??
1
2
3
4
5
6
7
8
9/**
*创建一个名为test.js的 Node.js文件
*/
var x = 5;
var addX = (value)=>{
return value + x;
}
module.export.x = x;
module.export.addX = addX;上面代码通过
module.export 导出变量x和函数addX -
require(
加载模块 )1
2
3
4
5
6
7
8/**
*创建名为 index.js 的 javascript文件
*/
//通过require加载模块
var example = require('./test.js');
//调用模块中的变量和函数
console.log(example.x); // 5
console.log(example.addX(1)); // 6 -
exports 与 module.exports区别
为了方便我们可以直接在exports
对象 上添加方法,表示对外输出的接口,如同在module.exports 上添加的一样。注意:不能直接将exports变量指向一个值,因为这样等于切段了exports与module.exports的联系错误写法
1export='将exports变量指向该值'正确写法(car.js)
-
导出变量
1
2//导出color变量
export.carColor='red' -
导出函数
1
2
3
4//导出setCarColor函数
export.setCarColor=(color)=>{
console.log('color:' + color);
} -
导出对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30/**
*导出Car对象包含如下属性和方法
*@attribute:[brand,color,price]
*@method:[setCarColor,]
*/
export.Car={
brand:'', //品牌
color:'', //颜色
price:20000, //价格
//设置品牌
setBrand:(brand)=>{
this.brand = brand;
},
//设置颜色
setCarColor:(color)=>{
this.color = color;
},
//设置价格
setPrice:(price)=>{
this.price=price;
},
//获取汽车信息
getCarInfo:()=>{
return '这是一辆'+this.price+this.color+this.brand+'汽车';
},
}
在JS(index.js)中使用Node.js
1
2
3
4
5
6
7
8//加载car.js 模块
let carNodeJs = require('./car');
_printLog=()=>{
custom.Car.setBrand('兰博基尼');
custom.Car.setColor('红色');
custom.Car.setPrice(2000000);
alert(custom.Car.getCarInfo());
} -
9. ES6与NodeJS模块导入导出区别
详细参见该链接
NodeJs
-
在Node模块中,采用的是commonjs规范,也就是使用**
require 方式引入模块,而使用module.exports **导出接口 -
如何检测Node.js对ES6的支持
- 命令行全局安装
es-checker - 执行 es-checker
- 红色表示暂不支持的
- 命令行全局安装
ES6
- Es6模块中并没有采用node中require导入模块的方式,导入(import),导出(export)