之前写过一个使用 electron 进行打包的文章, 但是现在公司又有需求是需要在 xp 上适配, 而 electron 是不支持 xp 的, 于是就想到了另一款打包工具, nwjs.
nwjs全称 Node-Webkit, 可以同时使用 DOM 和 node.js 的所以模块.所以就赋予了桌面端的功能.
这里使用 nwjs-builder-phoenix, 可以支持命令行打包.环境选择 windows, mac 类似, 但 mac 我只打出了 .app 包, 没有 developer 账号, 没法进行签名.所以体验不如 windows 好.
1.npm init 生成 package.json, yarn add nwjs-builder-phoenix -D 安装库
2.添加待打包文件到 build 文件夹下:index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>NWJS-demo</title>
</head>
<body>
<h1>This is one demo for application built by nwjs</h1>
<button onclick="nw.Window.open('http://www.baidu.com')">open default</button>
<button onclick="nw.Window.open('http://www.baidu.com', {
title: 'I Love China', // 不会生效的, 只对应用的第一个窗口有效
width: 100,
height: 100,
position: 'mouse',
focus: true
}, (new_window) => console.log('after new window created:', new_window))">open customer</button>
<button onclick="nw.Window.open('http://docs.nwjs.io/en/latest/References/Window/#windowopenurl-options-callback')">see window detail</button>
</body>
</html>
3.添加配置生成文件, application_generator.js
var shell = require('shelljs');
var fs = require('fs');
var readline = require('readline');
var length = process.argv.length;
// 获取应用平台类型
var platform = process.argv[length - 1];
// 获取版本号
var version_json = JSON.parse(fs.readFileSync('./versions.json', 'utf8'));
if (platform == 'win') {
var new_package_json = JSON.parse(fs.readFileSync('./application/win_package.json', 'utf8'));
new_package_json.version = version_json.current;
shell.rm('-rf', 'application_win');
shell.mkdir('application_win');
shell.cp('-R', 'build/', 'application_win/');
shell.cp('-R', 'nsis/', 'application_win/');
generate_nsis_file('application_win/nsis/kitten.nsi');
fs.writeFileSync('application_win/package.json', JSON.stringify(new_package_json, null, 2));
} else if (platform == 'xp') {
var new_package_json = JSON.parse(fs.readFileSync('./application/xp_package.json', 'utf8'));
new_package_json.version = version_json.current;
shell.rm('-rf', 'application_xp');
shell.mkdir('application_xp');
shell.cp('-R', 'build/', 'application_xp/');
shell.cp('-R', 'nsis/', 'application_xp/');
generate_nsis_file('application_xp/nsis/kitten.nsi');
fs.writeFileSync('application_xp/package.json', JSON.stringify(new_package_json, null, 2));
}
// 动态更新 version
function generate_nsis_file(path) {
var fread = fs.createReadStream('./nsis/kitten.nsi');
var version_line = 6;
var obj_readline = readline.createInterface({
input: fread,
});
var count = 1;
var str = '';
obj_readline.on('line', (line) => {
if (version_line == count) {
str = `${str}!define DEMO_VERSION ${version_json.current}\r\n`;
} else {
str += line + '\r\n';
}
count ++;
});
obj_readline.on('close', () => {
fs.writeFileSync(path, str);
});
}
4.添加打包用的 win_package.json, mac_package.json, xp_package.json 对应不同的平台, 一下配置基本上涵盖了所有的 build 参数也都写了注释.这些参数也可以在打开新窗口 nw.Window.open(‘url’, {options})中使用
{
"name": "nwjs-demo",
"main": "build/index.html",
"build": {
"nwVersion": "0.32.0",
"packed": false,
"nwFlavor": "sdk", // 是否允许打开 devtools, normal 表示最小化 build , 不包含 devtool 和 NaCI
"mute": false,
"ffmpegIntegration": true, // 是否集成 iteufel/nwjs-ffmpeg-prebuilt 以播放 .mp3等媒体资源, 如果设置为 true, nwVersion 不能使用符号
// 哪些文件需要打包进去, 排除 output 的文件夹
"files": [
"build/**",
"package.json"
],
// 以下内容会显示在文件的属性中
"win": {
"productName": "nwjs-demo",
"companyName": "lorry ltd",
"fileDescription": "This is a demo",
"productVersion": "1.0.0",
"fileVersion": "1.0.0",
"icon": "" // 放可执行文件的图标路径
},
"nsis": {
"icon": "这里是打包成 nsis 安装包后的 icon 路径",
"diffUpdaters": false
}
},
"user-agent": "用于覆盖应用 HTTP 请求的 User-Agent 请求头, %name 表示 manifest 的 name, %ver 表示 manifest 的 version,%nwver 表示 NW.js 的版本号 %webkit_ver 表示 Blink 引擎的版本, %osinfo 表示系统的 OS 和 CPU 信息",
"window": {
"title": "nwjs-demo", // 这是桌面应用上的标题
"width": 1200,
"height": 768,
"min-width": 900,
"min-height": 500,
"max-width": 900,
"max-height": 500,
"position": "center", // 可选 null, center, mouse
"resizable": true,
"icon": "", // 这是应用程序的左上角 icon和任务栏地址必须用128*128的 png 格式
"always_on_top": false,
"fullscreen": false,
"show_in_taskbar": true, // 默认为 true, 在任务栏显示 icon
"kiosk": false, // 特殊模式, 强制全屏且无法退出, 主要用于展示时使用
"transparent": false, //默认为 false
"frame": false, // 使整个界面没有框, 注意一定不能再设置为全屏, 那样就无法在边缘捕获到鼠标
"visible_on_all_workspaces": false, // mac和 linux 下可用, 表示界面是否对所有的workspace可见
"id": "abc" // 如果再次打开相同 id 的 window, 会恢复窗口上次打开的大小和位置.
},
"domain": "", // 这是chrome-extension://xxxxx 的 xxxxx, 表示应用的主机名, 可以与网站共享同一个域的 cookies
// 表示chromium的命令, 可以设置跨域, cookies,等等
"chromium-args": "--enable-file-cookies --allow-running-insecure-content --ignore-certificate-errors --enable-logging --log-level=0"
}
5.添加打包成 installer的 nsis 文件, 记住一定要将格式转换为 utf8 with DOM, 不然里面写的中文会报字符编码的错误
; Unicode is not enabled by default.
Unicode true
!include "MUI2.nsh"
; The version value is updated in script
!define DEMO_VERSION 1.0.0
;;;General
Name "nwjsDemo"
OutFile "..\dist\nwjsDemo_${DEMO_VERSION}_安装包.exe"
; Icons
!define MUI_ICON "demo.ico"
;Default installation folder
InstallDir "$LOCALAPPDATA\nwjs-demo"
;Request application privileges for Windows Vista
RequestExecutionLevel user
;;;Interface Settings
!define MUI_ABORTWARNING
;;;Pages
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_LANGUAGE "SimpChinese"
;;; Languages
;LoadLanguageFile "${NSISDIR}\Contrib\Language files\SimpChinese.nlf"
VIProductVersion "${DEMO_VERSION}.0"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "ProductName" "nwjs-demo"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "Comments" "nwjs-demo"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "CompanyName" "lorry ltd"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "LegalCopyright" "Copyright (c) 2015-2019 Lorry"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "FileDescription" "nwjs-demo客户端"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "FileVersion" "${DEMO_VERSION}"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "ProductVersion" "${DEMO_VERSION}.0";版本号
;;;Installer Section
Section "Install Section" InstallSection
SetOutPath "$INSTDIR"
;Put files
;自有格式
File jlr.ico
File demo.ico
File demo_tab.png
;File /r demo/*
File /r ..\dist\nwjs-demo-${DEMO_VERSION}-win-x86\*
;Create uninstaller
WriteUninstaller "$INSTDIR\uninst.exe"
;;Write registry
;Save installation path
WriteRegStr HKCU SOFTWARE\demo "InstallDir" "$INSTDIR"
;定义卸载路径变量
!define UNINST "Software\Microsoft\Windows\CurrentVersion\Uninstall\demo"
;Write uninstall keys, 这里是显示在控制面板的卸载程序里.
WriteRegStr HKCU UNINST "DisplayName" "nwjs-demo" ;应用名
WriteRegStr HKCU UNINST "UninstallString" "$INSTDIR\uninst.exe";卸载程序位置
WriteRegStr HKCU UNINST "ProductVersion" "${DEMO_VERSION}.0";版本号
WriteRegStr HKCU UNINST "DisplayIcon" "$INSTDIR\ jlr.ico";icon
WriteRegStr HKCU UNINST "Publisher" " 蒋礼锐";开发者
;Associate jlr file format 自有格式
;First delete any existing file extension bindings.
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.jlr";
WriteRegStr HKCU "Software\Classes\.jlr" "" "JLRFile"
WriteRegStr HKCU "Software\Classes\JLRFile\shell\open\command" "" "$\"$INSTDIR\nwjs-demo.exe$\" $\"%1$\""
WriteRegStr HKCU "Software\Classes\JLRFile\DefaultIcon" "" "$INSTDIR\jlr.ico,0"; 显示 icon
SectionEnd
Section "Start Menu Shortcuts"
CreateDirectory "$SMPROGRAMS\nwjs-demo"
CreateShortcut "$SMPROGRAMS\nwjs-demo\nwjs-demo.lnk" "$INSTDIR\nwjs-demo.exe" "" "$INSTDIR\nwjs-demo.exe" 0
CreateShortcut "$SMPROGRAMS\nwjs-demo\uninst.lnk" "$INSTDIR\uninst.exe" "" "$INSTDIR\uninst.exe" 0
; Also create desktop shortcut.
CreateShortCut "$desktop\nwjs-demo.lnk" "$INSTDIR\nwjs-demo.exe" "" "$INSTDIR\nwjs-demo.exe" 0
SectionEnd
Section "Finish Installation" FinishInstall
ExecShell "" "$INSTDIR\nwjs-demo.exe";完成之后自动打开应用
SetAutoClose true;是否自动关闭
SectionEnd
;;;Uninstaller Section
Section "Uninstall"
;Delete program folder
RMDIR /r "$INSTDIR"
;Delete shortcut in startup menu
Delete "$SMPROGRAMS\nwjs-demo\nwjs-demo.lnk";要全部删除应用程序和卸载程序的快捷方式才能移除掉文件夹
Delete "$SMPROGRAMS\nwjs-demo\uninst.lnk"
RMDIR "$SMPROGRAMS\nwjs-demo";移除文件夹
Delete "$desktop\nwjs-demo.lnk";移除桌面快捷方式
;Cleanup registry
DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\demo" "DisplayName"
DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\demo" "UninstallString"
DeleteRegValue HKCU SOFTWARE\demo "InstallDir"
;Unregister file association
;${unregisterExtension} ".jlr" "jlr Format"
DeleteRegKey HKCU "Software\Classes\.jlr"
DeleteRegKey HKCU "Software\Classes\JLRFile\shjell\open\command"
SectionEnd
6.添加打包命令, package.json
{
"name": "nw",
"version": "1.0.0",
"description": "",
"main": "build/index.html",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"application:generator:win7": "node application_generator.js win",
"dist:nw:win7": "build --tasks win-x86 --mirror https://npm.taobao.org/mirrors/nwjs/ ./application_win",
"dist:nsis:win7": "cd application_win/nsis && ../../node_modules/nwjs-builder-phoenix/assets/nsis/makensis.exe demo.nsi"
},
"author": "Lorry",
"license": "ISC",
"devDependencies": {
"fs": "^0.0.1-security",
"nwjs-builder-phoenix": "^1.15.0",
"shelljs": "^0.8.3"
}
}
7.然后依次执行 application:generator:win7
, dist:nw:win7
, dist:nsis:win7
即可打包出一个安装包
然后需要注意的点是如果需要打包成 xp 的话, 请使用nwVersion: 0.14.7的版本即可, 就是换了个壳, 如果网页版在 xp 下打不开那nwjs 也无能为力.
所有文件及项目结构均在我的仓库中, 可 clone 下来把你的 build 文件拷入即可用