clojurescript最终还是编译成javascript在浏览器执行,本文描述的是在项目本身在C/S环境上运行没有问题的情况下,怎么将这些资源文件用electron打包成windows或者mac的B/S应用。
技术语言和工具:
- clojurescript
- electronjs
- electron-builder
第一步:打包cljs成可通过浏览器浏览的网络资源
我这个项目是用figwheel编译的,打包命令如下:
lein cljsbuild once min-doctor
如果是用shadow-cljs编译项目的话,命令应该是这样的:
shadow-cljs release app
重点来了:这些编译文件只是将cljs打包成app.js文件,目录一般在target目录的某个问题,这两种方式都是这样的。
但是众所周知,运行一个网页只要一个js肯定是不行的,在用luminus创建出来的模板里,css和image文件都在resource/public
目录下,包括入口的index.html文件。
用nginx等部署时需要将这些文件也一并copy到nginx服务器上,这一步就不说了。
第二步:将这些网络资源打包成electron安装程序
有了上面的入口文件,css和image,以及唯一的一个js文件,我们只需要将这些文件和electron的配置文件放在一起便可以了进行下一步了。
1. 构建electron的打包目录
我在项目根目录创建了个electron
文件夹,会将资源文件copy到这个位置下。所以整个项目结构大概如下:
├── project
│ ├── resource
│ │ └──public
│ │ └── img
│ │ ├── logo.png
│ │ ├── user-header.png
│ │ └── css
│ │ └── js
│ │ └── index.html
│ ├── src
│ ├── electron
│ │ └──public
│ │ └── img
│ │ ├── logo.png
│ │ ├── user-header.png
│ │ └── css
│ │ └── js
│ │ └── index.html
│ │ └──package.json
│ │ └──main.js
其中electron下的public文件夹内容结构就跟往nginx部署时是一样的,main.js
和package.json
是为electron手动加入的。main.js是win的默认行为的指定文件,内容如下:
// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
const mainWindowURL = 'http://localhost:10386/doc.html';
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
//fullscreen: true,
webPreferences: {
},
})
// and load the index.html of the app.
// mainWindow.loadFile('index.html')
mainWindow.loadURL(mainWindowURL)
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
function bootstrapServer() {
const handler = require('serve-handler');
const http = require('http');
const server = http.createServer((request, response) => {
// You pass two more arguments for config and middleware
// More details here: https://github.com/zeit/serve-handler#options
return handler(request, response, {
public: 'resources/app.asar/public',
});
})
server.listen(10386, () => {
createWindow()
});
}
app.on('ready', bootstrapServer)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
package.json的内容如下:
{
"name": "eallergy",
"version": "1.0.0",
"license": "",
"main": "main.js",
"scripts": {
"start": "electron .",
"dist": "electron-builder -c.extraMetadata.main=main.js",
"dist-32": "electron-builder -c.extraMetadata.main=main.js --ia32"
},
"build": {
"productName": "eallergy",
"appId": "alk.doctor",
"copyright":"小马***公司",
"directories": {
"buildResources": "public"
},
"files": [
"main.js",
"public/**/*",
"node_modules/**/*"
],
"mac": {
"category": "your.app.category.type"
}
},
"devDependencies": {
"electron": "^5.0.7",
"electron-builder": "^21.0.15"
},
"dependencies": {
"serve-handler": "^6.1.0"
}
}
将资源文件copy到electron/public/
位置后执行yarn
和yarn dist
命令(执行出错的请看下面的解决方案)。
2. 打包
执行打包之前还有点环境准备工作
安装node
安装yarn
安装electron
安装electron-builder
然后可以在electron目录下载执行打包操作
# yarn
yarn install v1.21.1
warning package.json: License should be a valid SPDX license expression
warning [email protected]: License should be a valid SPDX license expression
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 13.47s.
$
$
$
$ yarn dist
yarn run v1.21.1
warning package.json: License should be a valid SPDX license expression
$ electron-builder -c.extraMetadata.main=main.js
• electron-builder version=21.0.15 os=10.0.18363
• loaded configuration file=package.json ("build" field)
• description is missed in the package.json appPackageFile=Z:\git\redcreation\alk-wxapi\alk-web\electron\package.json
• author is missed in the package.json appPackageFile=Z:\git\redcreation\alk-wxapi\alk-web\electron\package.json
• packaging platform=win32 arch=x64 electron=5.0.7 appOutDir=dist\win-unpacked
• default Electron icon is used reason=application icon is not set
• building target=nsis file=dist\eallergy Setup 1.0.0.exe archs=x64 oneClick=true perMachine=false
• building block map blockMapFile=dist\eallergy Setup 1.0.0.exe.blockmap
Done in 45.81s.
$
3. 打包文件
electron和electron-builder相关文件安装失败解决方案
错误版本不尽相同,但是大概如下吧
$ yarn dist
yarn run v1.21.1
warning package.json: License should be a valid SPDX license expression
$ electron-builder -c.extraMetadata.main=main.js
• electron-builder version=21.0.15 os=10.0.18363
• loaded configuration file=package.json ("build" field)
• description is missed in the package.json appPackageFile=Z:\git\redcreation\alk-wxapi\alk-web\electron\package.json
• author is missed in the package.json appPackageFile=Z:\git\redcreation\alk-wxapi\alk-web\electron\package.json
• packaging platform=win32 arch=x64 electron=5.0.7 appOutDir=dist\win-unpacked
• default Electron icon is used reason=application icon is not set
• building target=nsis file=dist\eallergy Setup 1.0.0.exe archs=x64 oneClick=true perMachine=false
• downloading url=https://github.com/electron-userland/electron-builder-binaries/releases/download/nsis-3.0.3.2/nsis-3.0.3.2.7z size=1.4 MB parts=1
• retrying attempt=1
• retrying attempt=2
• retrying attempt=3
⨯ part download request failed with status code 403
github.com/develar/app-builder/pkg/download.(*Part).doRequest
/Volumes/data/Documents/app-builder/pkg/download/Part.go:126
github.com/develar/app-builder/pkg/download.(*Part).download
/Volumes/data/Documents/app-builder/pkg/download/Part.go:67
github.com/develar/app-builder/pkg/download.(*Downloader).DownloadResolved.func1.1
/Volumes/data/Documents/app-builder/pkg/download/downloader.go:107
github.com/develar/app-builder/pkg/util.MapAsyncConcurrency.func2
/Volumes/data/Documents/app-builder/pkg/util/async.go:68
runtime.goexit
/usr/local/Cellar/go/1.12.7/libexec/src/runtime/asm_amd64.s:1337
⨯ Z:\git\redcreation\alk-wxapi\alk-web\electron\node_modules\app-builder-lib\node_modules\app-builder-bin\win\x64\app-builder.exe exited with code ERR_ELECTRON_BUILDER_CANNOT_EXECUTE stackTrace=
Error: Z:\git\redcreation\alk-wxapi\alk-web\electron\node_modules\app-builder-lib\node_modules\app-builder-bin\win\x64\app-builder.exe exited with code ERR_ELECTRON_BUILDER_CANNOT_EXECUTE
at ChildProcess.childProcess.once.code (Z:\git\redcreation\alk-wxapi\alk-web\electron\node_modules\app-builder-lib\node_modules\builder-util\src\util.ts:239:14)
at Object.onceWrapper (events.js:273:13)
at ChildProcess.emit (events.js:182:13)
at maybeClose (internal/child_process.js:962:16)
at Process.ChildProcess._handle.onexit (internal/child_process.js:251:5)
From previous event:
at processImmediate (timers.js:632:19)
From previous event:
at NsisTarget.buildInstaller (Z:\git\redcreation\alk-wxapi\alk-web\electron\node_modules\app-builder-lib\src\targets\nsis\NsisTarget.ts:202:29)
安装electron依赖时被墙基本上躲不过去的,运气不好的时候就是一定躲不过去,这时候有三种方案
- 设置electron的镜像为淘宝镜像,然后继续执行(推荐此方案)
set ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/
set SELENIUM_CDNURL=http://npm.taobao.org/mirrorss/selenium
set CHROMEDRIVER_CDNURL=https://npm.taobao.org/mirrors/chromedriver
set SASS_BINARY_SITE=https://npm.taobao.org/mirrors/node-sass/
-
使用迅雷或者浏览器手动下载download失败的文件
下载完后拖到C:\Users\mahaiqiang\AppData\Local\electron-builder\Cache\
这个目录,解压好,重新dist,会优先使用缓存中的文件。注意版本一致。
扔上去可能是这样:
在出错的命令上手动指定镜像
执行类似下面的命令,在真正的命令前加参数
ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/ yarn install
推荐方案一。
第三步:配置更新----这一步没有成功就换方案了,不值得看
$ npm install electron-updater --save
npm WARN rm not removing /Users/mahaiqiang/git/redcreation/alk-wxapi/alk-web/electron/node_modules/.bin/semver as it wasn't installed by /Users/mahaiqiang/git/redcreation/alk-wxapi/alk-web/electron/node_modules/semver
> [email protected] postinstall /Users/mahaiqiang/git/redcreation/alk-wxapi/alk-web/electron/node_modules/ejs
> node ./postinstall.js
Thank you for installing EJS: built with the Jake JavaScript build tool (https://jakejs.com/)
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN [email protected] No repository field.
npm WARN [email protected] No license field.
+ [email protected]
added 20 packages from 19 contributors, removed 10 packages, updated 289 packages and audited 909 packages in 304.234s
found 0 vulnerabilities
为了配合打包 package.json 需要给 build 新增配置项:
"build": {
"publish": [
{
"provider": "generic",
"url": "http://127.0.0.1:5500/" #这里是我本地开的服务器的地址
}
],
...
}
参考文档:
electron入门心得
使用 electron-builder 与 electron-packager 的 JSAPI 构建 electron 桌面应用安装程序