NW.js开发环境搭建

NW.js开发环境搭建

简介: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

对于国内用户,如果下载连接下载速度太慢的话,可以考虑的可选项是:

或者进入官网下载根据自己需要下载对应的版(我这里下载的是mac版本的v0.44.5,osx-x64,normal
v0.44.5,osx-x64,sdk

  • 下载后直接解压,将nwjs.app拖到应用程序中(便于从桌面点击图标启动)
    <img

  • 设置别名和环境变量(以便从命令行可直接启动)

    #打开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.jsonJSON 格式格式的配置文件. main 属性定义了应用首页, 如本例的 "index.html". name则定义了应用名称. 具体查看 配置文件章节.

    #创建项目目录
    mkdir NWDemo
    #进入项目根目录
    cd NWDemo
    #执行初始化生成package.json
    npm init
    

    package.json

    {
      "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文件. 该文件在应用启动时默认不打开窗口并在后台执行。 您可以稍后进行一些初始化并手动打开窗口。 例如:

    // 初始化你的应用程序之后 ...
    nw.Window.open('index.html', {}, function(win) {});
    
  • 创建入口页面index.html

    <!DOCTYPE html>
    <html>
      <head>
        <title>Hello World!</title>
      </head>
      <body>
        <h1>Hello World!</h1>
      </body>
    </html>
    

4. 运行应用

进入我们创建的项目中,执行nw . 运行当前应用(nw .是NW.js执行文件)

  • Windows系统中是 nw.exe;
  • Linux系统中是 nw;
  • Mac系统中是 nwjs.app/Contents/MacOS/nwjs;
#进入项目根目录
cd NWDemo
#运行
nw .

【注意】

Windows系统中 , 可拖拽包含 package.json的文件夹至 nw.exe直接运行应用。

5. 打包应用

可以使用以下工具自动完成打包NW.js应用进行发布 .

或者可以使用以下步骤手动构建应用 ,具体步骤参考手动构建应用

这里使用nwjs-builder-phoenix构建方式详细使用参见github

6. APIs

详细使用参见地址

扩展

1. 配置文件(package.json)
{
  "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": "billblogs@bblogmedia.com",
       "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.js中的APIs都被加载到nw全局对象中,并能够在javascript代码中直接使用

旧版本加载nw方式为require('nw.gui'),返回nw对象。

举个🌰:通过NW.js提供的API来创建应用此单(当用户鼠标右击打开上下文菜单显示)

<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:

3. 使用Node.js API(require

我们除了上述在DOM中直接使用NW.js的APIS之外,还可以在DOM中直接调用node.js代码及模块。这样就可以通过NW.js轻松开发PC桌面应用了。

举个🌰:利用Node.js的os模块擦护心操作系统的信息

<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环境:

浏览器环境Node环境

5.1.1 浏览器环境
  • 加载脚本

    • <script>标签
    • jQuery的$.getScript()
    • RequireJS
  • 全局对象

  • 创建新浏览器环境

    创建新的frame或者窗口时 , 将得到一个新的浏览器环境

  • 访问Node.jsNW.js的API

    将Node环境对象拷贝到浏览器环境中 , 这样运行在浏览器环境的脚本能够访问Node.js对象

    • nw – 所有NW对象 NW.js APIs
    • global – 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加载脚本;
  • 全局对象

    • 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

    //node环境中访问浏览器的API需要浏览器环境传入对应的el对象
    exports.setText = (el) => {
        el.innerHTML = 'hello';
    };
    

    浏览器(index.html)

    <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 混合环境模式

当使用--mixed-context命令行参数运行NW.js时 , 当浏览器环境被创建的同时创建了Node环境 .

  • 混合模式中加载脚本

    NW.js可以通过两种方式使用混合环境模式 , 一是使用--mixed-context命令行参数 , 二是在配置文件中添加chromium-args属性.

    package.json

    {
        "name": "test-context",
        "main": "index.html",
        "chromium-args": "--mixed-context"   //chromium-args属性指定使用混合模式
    }
    

    页面或Node.js中使用require()方式加载脚本运行在同样的环境中 .

  • 全局对象

    混合环境模式 , 您可以在Node模块中使用所有浏览器和NW.js API,反之亦然

    node.js文件(test.js)

    //导出showAlert函数
    exports.showAlert = function() {
      //因为开启了混合环境摸模式,可以在Node中直接使用浏览器的alert API
        alert("我正在Node模块中运行!");
    };
    

    Index.html

    <html>
      ...
      <body>
      <script>
        //加载 test node模块
         var test = require('./test');
         //调用模块的showAlert方法
         myscript.showAlert(); // 我正在Node模块中运行!
      </script>
      </body>
    </html>
    
    
5.3 混合环境模式和独立环境模式对比

独立环境模式的优势是不会出现类型检查问题 .

混合环境模式的缺点是不能轻易的分享变量 . 环境间分享变量 , 需要将变量放入其他环境能够访问的通用环境中 . 或者可以使用window.postMessage() API在环境之间发送和接收信息 .

6. JavaScript源码保护
  • 源码保护目的

    应用中的javascript源代码能够编译为本地二进制代码进行保护,NW.js能够加载编译之后的代码,应用作为产品发布时可以将代码进行编译!

  • 如何编译和加载

    • 编译

      JS源码编译为本地二进制代码需要使用nwjc工具,同时需要提供SDK构建方式的NW.

      nwjc source.js binary.bin
      

      *.bin文件需要发布到应用中,可以任意命名bin文件。

    • 加载

      NW.js 加载已编译的JS文件

      nw.Window.get().evalNWBin(frame,'binary.bin');
      

      Win.evalNWBin()方法中的参数与Window.eal()方法相同,第一个参数为目标frame(null为主frame),第二个参数为已编译的bin文件

    • 加载远程已编译的JS文件

      NW.js可以从远程(例如AJAX)获取已编译的JavaScropt,并且即时执行。

      //创建请求实例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加载,或者结合使用nwjc对源码进行编译为本地二进制文件后使用!

  • 签名文件

    NW.js的应用签名文件为verified_contents.json,它提供了密钥对,该文件由sign.py工具与私钥文件private_key.pem所创建,公钥已经内置于NW.js应用中。

  • 如何签名

    要运行签名的应用程序,在应用程序目录中调用nw --verify-content=enfore_strict命令执行严格验证模式,之后显示签名页面,完成签名动作。

    在此之后对index.html进行任意修改,NW将报告文件已损坏并立即退出。

  • 签名步骤

    使用密钥对签名应用,步骤如下:

    1. 切换到应用目录中
    2. 确认verified_contents.jsoncomputed_hashes.json文件不在当前目录(如果存在删除)
    3. 运行payload生成sign.py所需的配置文件payload.json文件
    4. 运行python sign.py > /tmp/verifid_content.json,需要注意 tmp目录不能是应用所在目录
    5. 将生成的verified_contents.json文件拷贝到应用目录,完成签名动作。
  • 使用自己密钥对重新构建应用

    要使用您自己的密钥对,您需要重建NW,并命令行参数--verify-content=默认设置为enfoce_strict

    1. openssl genrsa -out private_key.pem 2048生成密钥对,输出公私钥文件
    2. 运行python convertkey.py,它会将公钥转换为C源代码
    3. 将生成的代码复制到NW安装包的content/nw/src/nw_content_verifier_delegate.cc,替换原文件默认的key值
    4. 更改文件中第73行为Mode experiment_value = ContentVerifierDelegate::ENFORCE_STRICT;
    5. 重新构建NW
7. 自动更新

详细使用参见此链接

8. Node.js 自定义模块

Node应用由模块组成,每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。每个模块内部,module变量代表当前模块。这个变量是一个对象

它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。

  • module.export(导出模块)

    module.exports是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。

    举个🌰

    /**
     *创建一个名为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(加载模块)

    /**
     *创建名为 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的联系

    错误写法

    export='将exports变量指向该值'
    

    正确写法(car.js)

    • 导出变量

      //导出color变量
      export.carColor='red'
      
    • 导出函数

      //导出setCarColor函数
      export.setCarColor=(color)=>{
        console.log('color:' + color);
      }
      
    • 导出对象

      /**
       *导出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

    //加载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的支持

    1. 命令行全局安装es-checker
    2. 执行 es-checker
    3. 红色表示暂不支持的

    在这里插入图片描述

ES6
10. ES6 入门教程
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值