Skip to content

asakiasako/Vite-EVP

Repository files navigation

Vite EVP

Vite EVP means Vite Electron-Vue-Python. This is a template for electron application, using Vue for rendering UI, and python as backend.

Vite is used as bundler (instead of webpack). electron-builder is used for building. gRPC is used to expose python APIs to electron (but you don't need to understand gRPC). Ant-Design of Vue is used as the UI components.

Thanks to Alex Kozack, I started this template based on his vite-electron-builder.

Installation

  • Environment:

    • Node.js >= 16.14.2
    • Python >= 3.8.10
    • Poetry (A python package manager)
  • cd to the project root and run script:

    npm install

    This will install the dependencies for both Node.js and python. And the project is ready to go.

Scripts

  • npm run serve

    Run the app in development environment.

  • npm run build

    Build executables. The default configs in /electron-builder.config.js will build an .exe installer for windows.

Project Structure

The entire source code of the program is divided into 4 packages that are each bundled independently:

  • packages/main: Electron main process.
  • packages/preload: Used in BrowserWindow.webPreferences.preload.
  • packages/renderer: Electron renderer process.
  • packages/backend: A python package, the backend to expose APIs.

RPC (Remote Process Call) between Electron App and python backend

The python backend exposes APIs. The Electron App realizes specific functions by calling these APIs.

Expose API in python package

Refer to /packages/backend/src/apis/example.py for examples.

Note that ApiRoute is singleton, so it can be instantiated in different modules safely.

# /packages/backend/src/apis/examples.py

from datetime import datetime
import platform

from .ApiRouter import ApiRouter

# ApiRouter is singleton so it can be instantiated safely in different modules.
router = ApiRouter()

# --- Example 1: register an API with a decorator
@router.route(':get-current-time')
def get_current_time() -> str:
    return datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')

# --- Example 2: register an API with method
def get_python_info() -> str:
    return {
        'Python Version': platform.python_version(),
        'Architecture': ", ".join(platform.architecture()),
        'Implementation': platform.python_implementation()
    }

router.register(':get-python-info', get_python_info)

# --- Example 3: register API with register_from_map() method
#
# In large projects, it's a good practice to organise APIs in seperated 
# files and use register_from_map() to summarize the APIs.
ROUTES = {
    ':arithmetic:add': lambda x, y: x+y,
    ':arithmetic:multiply': lambda x, y: x+y,
    ':arithmetic:abs': abs
}

router.register_from_map(ROUTES)

Invoke API in electron

In electron renderer process, an rpcClient object is used to invoke those APIs.

An alias $rpcClient is registered as a global property of the Vue app. So you can use it like this in Vue components with options API:

this.$rpcClient.request({
  route: ':route:to:the:api',
  args: [arg1, arg2], // args if any
  kwargs: { key1: value1 } // kwargs if any
}, timeout) // optional timeout parameter to change the default timeout

With composition API, you can import rpcClient, or use inject method:

import rpcClient from '@/rpc-client'
rpcClient.request(...)
// or
const that = inject('app.globals')
that.$rpcClient.request(...)

Please refer to /packages/renderer/src/rpc-client/ for the rpcClient object.

Global Properties

app.config.globalProperties.$rpcClient = rpcClient
app.config.globalProperties.$lodash = lodash

Please refer to /packages/renderer/src/main.js for the source.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published