警告:阅读下面内容前请详细阅读
下面的内容是我在尝试构建RailgunMediaEncoder
中尝试使用的方法, 我无法保证下面的方法绝对符合"最佳实践".
USE IT AT YOUR OWN RISK.
如果有任何问题及建议,欢迎提出.
0. 开始之前
一个标准的Electron的应用由两部分组成: 用于在后台运行的主线程项目和在前台运行的ui线程项目. 这两部分是相对独立的, 其间的通讯只能通过ipc(线程间通讯)完成. 在开发时, 这两部分也应该作为两个独立的项目来管理.
这里我们主线程使用纯TypeScript完成主线程项目, 使用Angular + TypeScript完成ui线程项目.
下面的例子中我们希望的源代码目录结构:
1. 创建Angular项目
首先确保你已经全局安装了Angular CLI,如果没有, 使用下面的命令安装:
1
| npm install -g @angular/cli
|
安装后,首先使用以下命令来创建一个空白项目(不包含app)
1
| ng new --createApplication=false --newProjectRoot="./" HelloElectron
|
完成后,建议使用vscode打开项目目录(这里为HelloElectron
)来继续我们的下一步操作.
继续执行以下命令来创建前端应用
在 cli 询问 ? Would you like to add Angular routing? (y/N)
时, 输入y来添加路由, 其它选项按需选择.
以上命令跑完后, 运行ng serve --open
应该可以在浏览器中看到angular的hello world页面.
接下来,打开angular.json
修改生成设置.
- 修改
outputPath
为dist/app/ui
- 修改
outputHashing
为none
打开ui/src/index.html
, 修改base href:
1 2 3
| <base href="/"> 修改为: <base href="./">
|
2.配置Electron
安装以下必备库
- Electron
npm install --save-dev electron
- ngx-electron
npm install --save ngx-electron
- @types/node
npm install --save-dev @types/node
- electron-builder (用于打包electron应用, 若手动打包可不安装)
npm install --save-dev electron-builder
PS: 如果你深受The Girl Friend Wall
困扰的话, 安装Electron时post-install部分可能会卡非常非常非常久(npm需要下载90MB左右的Electron包). 此时可以参考http-proxy设置代理.
3. 建立主线程项目
首先, 创建目录core/
, 在之中创建tsconfig.json
, 内容参考如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| { "compileOnSave": false, "compilerOptions": { "module": "commonjs", "target": "es2015", "sourceMap": true, "outDir": "../dist/app", "typeRoots": [ "../node_modules/@types" ], "moduleResolution": "node", "experimentalDecorators": true } }
|
创建tslint.json
,配置可自行按需设定,或直接复制ui/tslint.json
中的内容.
创建index.ts
作为整个Electron应用的入口点, 内容如下
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
| import * as path from 'path'; import {app, BrowserWindow} from 'electron';
let mainWindow: BrowserWindow = null;
function singleInstance() { app.requestSingleInstanceLock();
app.on('second-instance', () => { if (mainWindow) { if (mainWindow.isMinimized()) { mainWindow.restore(); } mainWindow.focus(); } }); }
function createWindow() { mainWindow = new BrowserWindow({ width: 1080, minWidth: 680, height: 840, frame: false, title: app.name, webPreferences: { nodeIntegration: true, experimentalFeatures: true } });
mainWindow.loadURL(path.join('file://', __dirname, 'ui/index.html')); mainWindow.webContents.on('will-navigate', (event, url) => { if (url !== path.join('file://', __dirname, 'ui/index.html')) { event.preventDefault(); mainWindow.loadURL(path.join('file://', __dirname, 'ui/index.html')); } }); }
function init() { singleInstance(); app.on('ready', () => { createWindow(); });
app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } });
app.on('activate', () => { if (mainWindow === null) { createWindow(); } }); }
init();
|
4. 配置生成脚本
打开package.json
, 将script节替换为以下内容:
1 2 3 4 5 6 7
| "scripts": { "build": "tsc -p core && ng build", "build-prod": "tsc -p core && ng build --prod", "start": "npm run build && electron ./dist/app/index.js", "clean": "rm ./dist -rf", "lint": "echo Linting UI && ng lint && echo Linting Core... && tslint -p core" },
|
5. 配置自动打包(可选)
首先请确保你已经安装了electron-builder 在package.json中添加build
节
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
| "build": { "appId": "net.example.HelloElectron", "productName": "Hello Electron", "directories": { "app": "dist/app", "output": "dist/pack", }, "nsis": { "oneClick": false, "perMachine": true, "allowToChangeInstallationDirectory": true, "license": "LICENSE", "artifactName": "${productName}.Setup.${version}.${ext}" }, "win": { "target": [ { "target": "nsis" }, { "target": "zip" } ] }, "mac": { "target": "dmg" }, "linux": { "target": [ { "target": "deb" }, { "target": "rpm" }, { "target": "tar.gz" } ] } },
|
有关以上json的更多信息,可参见Configuration.
然后在script节添加publish:
1
| "publish": "cp package.release.json dist/app/package.json && electron-builder",
|
接下来,创建package.build.json
, 内容参考如下
1 2 3 4 5 6 7 8 9 10 11
| { "name": "HelloElectron", "version": "1.0.0", "author": "EdgeNeko", "homepage": "https://example.com", "private": true, "license": "MIT", "dependencies": { } }
|
在dependencies
中,添加需要打包到最终应用的node库. 有关双package.json结构, 可参考此文档.
运行以下命令即可打包:
1 2 3
| npm run clean npm run build-prod npm run publish
|
打包结果会保存在dist/pack
6. 示例:在ui线程调用Node
创建一个服务,名为NodeService, 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import {Injectable} from '@angular/core'; import fs from 'fs'; import {ElectronService} from 'ngx-electron';
@Injectable({ providedIn: 'root' }) export class NodeService {
public fs: typeof fs; public childProcess: typeof childProcess;
constructor( electronService: ElectronService ) { this.fs = electronService.remote.require('fs'); } }
|
接下来,就可以通过注入NodeService
并以nodeService.fs
来调用node中的fs了.
7. 配置调试
这部分目前我还没有什么好的解决方案,如果米娜桑有解决方案欢迎在下面提出QAQ