美文网首页
clojurescript编译后用electron打包成桌面应用

clojurescript编译后用electron打包成桌面应用

作者: 小马将过河 | 来源:发表于2019-12-22 08:21 被阅读0次

    clojurescript最终还是编译成javascript在浏览器执行,本文描述的是在项目本身在C/S环境上运行没有问题的情况下,怎么将这些资源文件用electron打包成windows或者mac的B/S应用。

    技术语言和工具:

    第一步:打包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.jspackage.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/位置后执行yarnyarn 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 eallergy@1.0.0: 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. 打包文件

    image.png

    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,会优先使用缓存中的文件。注意版本一致。
      扔上去可能是这样:

      image.png
    • 在出错的命令上手动指定镜像
      执行类似下面的命令,在真正的命令前加参数

    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
    
    > ejs@2.7.4 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 eallergy@1.0.0 No repository field.
    npm WARN eallergy@1.0.0 No license field.
    
    + electron-updater@4.2.0
    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 桌面应用安装程序

    相关文章

      网友评论

          本文标题:clojurescript编译后用electron打包成桌面应用

          本文链接:https://www.haomeiwen.com/subject/zvgdnctx.html