Secure boilerplate for Electron app based on Vite. TypeScript + Vue/React/Angular/Svelte/Vanilla

Overview

Vite Electron Builder Boilerplate

Stand With Ukraine

GitHub issues by-label Required Node.JS >= v16.13 Required npm >= v8.1

Vite+Electron = đŸ”Ĩ

This is a template for secure electron applications. Written following the latest safety requirements, recommendations and best practices.

Under the hood is Vite — A next-generation blazing fast bundler, and electron-builder for packaging.

Get started

Follow these steps to get started with the template:

  1. Click the Use this template button (you must be logged in) or just clone this repo.
  2. If you want to use another package manager don't forget to edit .github/workflows -- it uses npm by default.

That's all you need. 😉

Note: This template uses npm v7 feature — Installing Peer Dependencies Automatically. If you are using a different package manager, you may need to install some peerDependencies manually.

Note: Find more useful forks here.

Features

Electron Electron version

  • This template uses the latest electron version with all the latest security patches.
  • The architecture of the application is built according to the security guides and best practices.
  • The latest version of the electron-builder is used to package the application.

Vite Vite version

  • Vite is used to bundle all source codes. It's an extremely fast bundler, that has a vast array of amazing features. You can learn more about how it is arranged in this video.
  • Vite supports reading .env files. You can also specify the types of your environment variables in types/env.d.ts.
  • Automatic hot-reloads for the Main and Renderer processes.

Vite provides many useful features, such as: TypeScript, TSX/JSX, CSS/JSON Importing, CSS Modules , Web Assembly and much more.

See all Vite features.

TypeScript TypeScript version (optional)

  • The latest version of TypeScript is used for all the source code.
  • Vite supports TypeScript out of the box. However, it does not support type checking.
  • Code formatting rules follow the latest TypeScript recommendations and best practices thanks to @typescript-eslint/eslint-plugin.

See this discussion if you want completely remove TypeScript.

Vue Vue version (optional)

  • By default, web pages are built using Vue. However, you can easily change that. Or not use additional frameworks at all.
  • Code formatting rules follow the latest Vue recommendations and best practices thanks to eslint-plugin-vue.

See examples of web pages for different frameworks.

Continuous Integration

  • The configured workflow will check the types for each push and PR.
  • The configured workflow will check the code style for each push and PR.
  • Automatic tests used Vitest Vitest version -- A blazing fast test framework powered by Vite.
    • Unit tests are placed within each package and are ran separately.
    • End-to-end tests are placed in the root tests directory and use playwright.

Publishing

  • Each time you push changes to the main branch, the release workflow starts, which creates a new draft release. For each next commit will be created and replaced artifacts. That way you will always have draft with latest artifacts, and the release can be published once it is ready.
    • Code signing supported. See release workflow.
    • Auto-update is supported. After the release is published, all client applications will download the new version and install updates silently.

This template configured for GitHub, but electron-builder supports multiple auto-update servers. See docs.

How it works

The template requires a minimum amount dependencies. Only Vite is used for building, nothing more.

Project Structure

The structure of this template is very similar to the structure of a monorepo.

flowchart TB;

packages/preload <-. IPC Messages .-> packages/main

subgraph packages/main
M[index.ts] --> EM[Electron Main Process Modules]
M --> N2[Node.js API]
end


subgraph packages/preload
P[index.ts] --> N[Node.js API]
P --> ED[External dependencies]
P --> ER[Electron Renderer Process Modules]
end


subgraph packages/renderer
R[index.html] --> W[Web API]
R --> BD[Bundled dependencies]
R --> F[Web Frameforks]
end

packages/renderer -- Call Exposed API --> P

The entire source code of the project is divided into three modules (packages) that are each bundled independently:

  • packages/renderer. Responsible for the contents of the application window. In fact, it is a regular web application. In developer mode, you can even open it in a browser. The development and build process is the same as for classic web applications. Access to low-level API electrons or Node.js is done through the preload layer.
  • packages/preload. Acts as an intermediate bridge between the renderer process and the API exposed by electron and Node.js. Runs in an isolated browser context, but has direct access to the full Node.js functionality. See Checklist: Security Recommendations .
  • packages/main Electron main script. This is the main process that powers the application. It manages creating and handling the spawned BrowserWindow, setting and enforcing secure permissions and request handlers. You can also configure it to do much more as per your need, such as: logging, reporting statistics and health status among others.

Build web resources

The main and preload packages are built in library mode as it is simple javascript. The renderer package builds as a regular web app.

Compile App

The next step is to package a ready to distribute Electron app for macOS, Windows and Linux with "auto update" support out of the box.

To do this, use electron-builder:

  • Using the npm script compile: This script is configured to compile the application as quickly as possible. It is not ready for distribution, it is compiled only for the current platform and is used for debugging.
  • Using GitHub Actions: The application is compiled for any platform and ready-to-distribute files are automatically added as a draft to the GitHub releases page.

Working with dependencies

Because the renderer works and builds like a regular web application, you can only use dependencies that support the browser or compile to a browser-friendly format.

This means that in the renderer you are free to use any frontend dependencies such as Vue, React, lodash, axios and so on.However, you CANNOT use any native Node.js APIs, such as, systeminformation. These APIs are only available in a Node.js runtime environment and will cause your application to crash if used in the renderer layer. Instead, if you need access to Node.js runtime APIs in your frontend, export a function form the preload package.

All dependencies that require Node.js api can be used in the preload script.

Expose in main world

Here is an example. Let's say you need to read some data from the file system or database in the renderer.

In the preload context, create a function that reads and returns data. To make the function announced in the preload available in the render, you usually need to call the electron.contextBridge.exposeInMainWorld. However, this template uses the unplugin-auto-expose plugin, so you just need to export the method from the preload. The exposeInMainWorld will be called automatically.

// preload/index.ts
import { readFile } from 'node:fs/promises';

// Encapsulate types if you use typescript
interface UserData {
  prop: string
}

// Encapsulate all node.js api
// Everything you exported from preload/index.ts may be called in renderer
export function getUserData(): Promise<UserData> {
  return readFile('/path/to/file/in/user/filesystem.json', {encoding:'utf8'}).then(JSON.parse);
}

Now you can import and call the method in renderer

// renderer/anywere/component.ts
import { getUserData } from '#preload'
const userData = await getUserData()

Read more about Security Considerations.

Working with Electron API

Although the preload has access to all of Node.js's API, it still runs in the BrowserWindow context, so a limited electron modules are available in it. Check the electron docs for full list of available methods.

All other electron methods can be invoked in the main.

As a result, the architecture of interaction between all modules is as follows:

sequenceDiagram
renderer->>+preload: Read data from file system
preload->>-renderer: Data
renderer->>preload: Maximize window
activate preload
preload-->>main: Invoke IPC command
activate main
main-->>preload: IPC response
deactivate main
preload->>renderer: Window maximized
deactivate preload

Read more about Inter-Process Communication

Modes and Environment Variables

All environment variables are set as part of the import.meta, so you can access them vie the following way: import.meta.env.

If you are using TypeScript and want to get code completion you must add all the environment variables to the ImportMetaEnv in types/env.d.ts.

The mode option is used to specify the value of import.meta.env.MODE and the corresponding environment variables files that need to be loaded.

By default, there are two modes:

  • production is used by default
  • development is used by npm run watch script

When running the build script, the environment variables are loaded from the following files in your project root:

.env                # loaded in all cases
.env.local          # loaded in all cases, ignored by git
.env.[mode]         # only loaded in specified env mode
.env.[mode].local   # only loaded in specified env mode, ignored by git

To prevent accidentally leaking env variables to the client, only variables prefixed with VITE_ are exposed to your Vite-processed code.

For example let's take the following .env file:

DB_PASSWORD=foobar
VITE_SOME_KEY=123

Only VITE_SOME_KEY will be exposed as import.meta.env.VITE_SOME_KEY to your client source code, but DB_PASSWORD will not.

Contribution

See Contributing Guide.

Comments
  • I can't reference any 3rd Part Node.js modules in preload pkg.

    I can't reference any 3rd Part Node.js modules in preload pkg.

    image

    Like this, I declare such a global method in preload pkg, but it gives me this error.

    image

    It is the first time for me to use electron with Vitejs. I had read many docs and consulted many materials, but I still can't solve this problem. So is this problem related to this template? Or some other common problem? Ask for help 🙏 @cawa-93

    bug 
    opened by dohooo 20
  • Somehow get the `node` and `chrome` versions  at the `build` time

    Somehow get the `node` and `chrome` versions at the `build` time

    I want to somehow get the node and chrome versions that are sewn into the electron, and pass those versions to the esbuild config and browserslist config.

    The following solution is currently in use: Separate workflow has been update electron-vendors.config.json and .browserslistrc files on push to main branch.

    I would like to receive the versions directly at the build time.

    enhancement help wanted 
    opened by cawa-93 17
  • feat: Add prettier support and reformat code.

    feat: Add prettier support and reformat code.

    Summary This pr add prettier support and does not intend to change any functions.

    Prettier is an automatic formatter for many languages including JavaScript and TypeScript. It is now widely used in frontend projects to keep the devs focusing on programming rather than maintaining code formats, which saves time and allows effective collaboration. This repo is already have an EditorConfig but it is not as powerful as prettier is so I want to push it even further.

    eslint Integration Deps like eslint-config-prettier and eslint-plugin-prettier allows prettier to further integration with eslint, since this project is already have an lint-staged check, it will make sure all submitted code must be formatted in the same way.

    The Chosen Style & Limitations I tried as much as I can to keep the original coding style reflected in prettier config (.prettierrc), but there are still limitations beyond the capability of prettier now.

    Here's are styles kept:

    • "semi": true leaves semicolons at end of lines.
    • "vueIndentScriptAndStyle": false leaves no indent at Vue SFC's <script> and <style> blocks.
    • "singleAttributePerLine": true leaves only one attribute per line at <template> blocks.
    • "singleQuote": true forces to use single quotes, but nested quotes will be double quotes. This is explained at pr #815.
    • "arrowParens": "avoid" avoids parens at arrow functions.
    • "trailingComma": "all" forces trailing commas.
    • "htmlWhitespaceSensitivity": "strict" keeps strict html whitespace consistency while formatting. Some formatted code seems ugly (see 6459e5e6cac893c49fcbb3784a064b50c4a9af8c) which is actually prettier trying to keep the consistency. You can either edit manually to change whitespace outcome to get a better-looking code or wrap them with <span> to keep it. There are some tests in the project which requires whitespace consistency (see packages\renderer\tests\ElectronVersions.spec.ts). If the consistency is not important, 'ignore' option is best to make code looks better.
    • "endOfLine": "lf" keeps the EOL the same as the EditorConfig does.

    ... And the limitations:

    • The html void elements such as <br>, <img> and <input> WILL ends with />. But it should be okay since it is still valid HTML5 code. More info at https://github.com/prettier/prettier/issues/5246
    • Some eslint rules cannot be used or only used with limitations alongside with prettier. But it is normally ok because much of those are taken care by prettier.

    Using Prettier

    Check prettier docs for finding plugins for your editor. Afaik popular editors like VSCode and JetBrains IDEs are supported. Or use prettier via its CLI. The commit 89eccb7e817b780951282cc6fb17152045e40517 is done by running the following command:

    npx prettier --write "**/*.{vue,js,jsx,ts,tsx}"
    

    In this case prettier will read config found at currend folder (.prettierrc and .prettierignore) and format all files matching pattern **/*.{vue,js,jsx,ts,tsx} except those ignored in .prettierignore.

    enhancement help wanted RFC 
    opened by Tanimodori 12
  • Main package should be compiled for node env

    Main package should be compiled for node env

    I had an issue with the axios library when I was using axios in the main package, the code was resolving to the XHR adapter. It was happening due to this field in package.json of axios:

      "browser": {
        "./lib/adapters/http.js": "./lib/adapters/xhr.js"
      },
    

    It means that for browser env ./lib/adapters/http.js file should be replaced with ./lib/adapters/xhr.js, but main package is running under node environment, and it was causing the error. Here is the more detailed issue https://github.com/vitejs/vite/issues/6382 .

    So, I fixed it with ssr: true in the build section of config.vite.js. What do you think about this? I can provide PR if you want 🙂

    bug help wanted 
    opened by quolpr 12
  • Multiple sourcemap sources

    Multiple sourcemap sources

    Describe the bug When running in development mode the sourcemaps are multiplied, resulting errors during debug

    To Reproduce Steps to reproduce the behavior:

    1. npm run watch
    2. Click on DevTools/Sources
    3. See multiple referenced sources in the Source tree (screenshot below)
    4. Click on the "About" link
    5. In the terminal you see the following error: 5:01:31 PM [main] [20564:0818/170131.504:ERROR:CONSOLE(1)] "Could not load content for http://localhost:3000/src/components/C:/B/packages/renderer/src/components/About.vue (HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE)", source: devtools://devtools/bundled/core/sdk/sdk.js (1)

    Please note the weird concatenated link.

    I'm using Windows 10 and VS Code attaching debugger to the renderer process

    It is also causing problems when I try to debug the renderer process, and the breakpoints are being hit, but the lines are off.

    I'm not sure whether this is a vite issue or a local config problem, I have a hunch it might be related to the way how alias resolve is working, but I might be totally wrong

    Expected behavior Have all sources appear once in a source tree

    Screenshots image

    bug help wanted 
    opened by peterbud 10
  • Cannot open the .exe file after compiling on mac.

    Cannot open the .exe file after compiling on mac.

    Describe the bug Cannot open the .exe file after compiling on mac.

    To Reproduce

    1. git clone
    2. npm install
    3. npm run compile -w // build for windows platform.
    4. Open the vite-electron-builder.exe, then nothing happened. No error, No alert, No process..

    Expected behavior The application running normally.

    Screenshots Nothing happened. No error, No alert, No process.

    Additional context building platform: mac running platform: windows11 in parallels.

    opened by dohooo 8
  • Auto-updater does not find new releases from the same day.

    Auto-updater does not find new releases from the same day.

    Describe the bug The auto-updater does not find new releases if they are released in the same day as the most recent release.

    To Reproduce

    1. Create a new release draft.
    2. Publish the release.
    3. Repeat steps 1 and 2 in the same day.
    4. Attempt to have auto-update work.

    Expected behavior If the latest.yml in /<repo>/releases/latest has a different version than the current, it should be considered the latest.

    Screenshots N/A

    Additional context This seems to stem from the fact that in semantic versioning, v1.2.3-456, the 456 would be considered a pre-release. It might be best to identify a way to utilize package.json and npm version to use proper semantic versioning for releases to avoid this problem.

    bug 
    opened by ryanbarr 8
  • Sharing code between main and renderer processes

    Sharing code between main and renderer processes

    Is your feature request related to a problem? Please describe. This repository is posited as an alternative to electron-webpack as the library is now in "maintenance mode" as stated in readme.

    In electron-webpack, is it possible to share resources between main and renderer processes. This allows for best practices such as avoiding the hard-coding of event name strings for IPC communication via constants. In this case, common code resources are located in a folder which is a sibling to main and renderer folders.

    Describe the solution you'd like This repo should include configuration that enables sharing of code between main and renderer builds.

    Describe alternatives you've considered I've attempted to use the solution posited in this issue but this causes typescript errors. Aliases present DX issues because one can't use regular import statements like in webpack and must resort to some kind of module resolver which is beyond the scope of someone who wants to get started on an electron project quickly and easily.

    Another solution I've attempted: move index.html file directly inside packages folder, setting the PACKAGE_ROOT to be packages folder. For renderer, main, and preload folders, in vite config files, change build.lib.entry value to be "[folderName]/src/index.ts" and change index.html script src to be "./renderer/src/index.tsx". This does not fix the issue and the watch tasks errors out:

    Error: Cannot find module '../../common/constants'
    Require stack:
    - /home/user/code/polyhedral-net-factory/packages/main/dist/index.cjs
    - /home/user/code/polyhedral-net-factory/node_modules/electron/dist/resources/default_app.asar/main.js
    
    enhancement 
    opened by justin-hackin 8
  • Watch script ignores configuration of renderer/vite.config.js

    Watch script ignores configuration of renderer/vite.config.js

    Describe the bug We are using the vite-electron-builder template together with react-native-web. Building works fine, but the watch script does not work as expected.

    Many react-native libs do not use .jsx as file extension for JSX files, they just use .js. The metro bundler which is used by react-native is fine with this. For vite we needed to add this config to the renderer:

      esbuild: {
        loader: 'tsx',
        include: [/(src|react-native-.*)\/.*\.[tj]sx?$/],
        exclude: [],
      },
    

    This way, also .js files get treated as .jsx. However, it seems that the watch script is ignoring the packages/renderer/vite.config.js configuration.

    To Reproduce Steps to reproduce the behavior:

    1. Create a project based on vite-electron-builder
    2. Create a JSX component with the file extension .js
    3. Add the esbuild config to packages/renderer/vite.config.js
    4. Run npm run watch
    5. See error
    opened by maximilize 7
  • Use pnpm instead of npm

    Use pnpm instead of npm

    Is your feature request related to a problem? Please describe. pnpm makes a better use of your drive, is faster than npm and results in more predictable behaviors (you cannot use packages not listed in the dependencies because they are not located in node_modules). I have seen a lot of people in the Vue ecosystem starting to use it and since this template is Vue by default I think it makes sense to switch as well.

    Describe the solution you'd like Remove npm lockfile, generate pnpm lockfile and replace all npm instructions with pnpm counterparts (cli is largely the same though)

    Additional context Comparison between npm and pnpm version if this template.

    git clone https://github.com/cawa-93/vite-electron-builder.git npm
    cd npm
    npm install
    

    results in a 580.8 MB directory

    git clone https://github.com/cawa-93/vite-electron-builder.git pnpm
    cd pnpm
    rm package-lock.json
    pnpm install
    

    results in a 424.2 kB directory

    I know that the space is still used somewhere else, but since those version of required packages can be reused for other node projects the space is utilized in a much better. If you have 2 electron apps based on this template you save 580.1 MB of space (size of node_modules with npm). If you have 3 of them you save 1160.2 MB and so on.

    Will make a PR if the author approves.

    enhancement 
    opened by StarLederer 7
  • [main] [6368:0130/195648.904:ERROR:CONSOLE(1)]

    [main] [6368:0130/195648.904:ERROR:CONSOLE(1)] "SyntaxError: Unexpected end of JSON input", source: devtools://devtools/bundled/entrypoints/main/main.js (1)

    Describe the bug When i open devtools i have this message

    371 modules transformed.
    dist/index.cjs   4.10 KiB
    dist/index.cjs.map 9.67 KiB
    built in 3359ms.
    19:56:48 [main] [6368:0130/195648.904:ERROR:CONSOLE(1)] "SyntaxError: Unexpected end of JSON input", source: devtools://devtools/bundled/entrypoints/main/main.js (1)
    

    To Reproduce Steps to reproduce the behavior:

    1. run node scripts/watch.js
    2. check console
    3. See error

    image

    bug help wanted 
    opened by WhiteBite 6
Owner
Alex Kozack
Alex Kozack
Vite-solid-electron - A simple Vite, SolidJS, Electron integration template

vite-solid-electron Overview Very simple Vite, SolidJS, Electron integration tem

Christian Hansen 25 Dec 18, 2022
Electron-mirror - Electron application for Smart Mirror using React via the electron-react-boilerplate repository.

Electron-Mirror Electron application for Smart Mirror using React via the electron-react-boilerplate repository. Starting Development Start the app in

null 1 Feb 8, 2022
:electron: Electron + Vite + React + Sass boilerplate.

electron-vite-react English | įŽ€äŊ“中文 ?? Overview ?? Ready out of the box ?? Based on the official template-react-ts, project structure will be familiar

Electron âšĄī¸ Vite 652 Jan 3, 2023
âšĄī¸ Super-fast electron + vite boilerplate. Support React/Vue template.

electron-vite-template Run Setup # clone the project git clone [email protected]:caoxiemeihao/electron-vite-template.git # enter the project directory c

č‰éž‹æ˛Ąåˇ 641 Dec 30, 2022
Electron-app - A ready-to-go with a well-thought-out structure Electron app boilerplate with ReactJS, TypeScript

Electron App ??  A ready-to-go with a well-thought-out structure Electron app bo

Dalton Menezes 155 Dec 29, 2022
Small ES6 Native Speed jQuery for Svelte, Vue3, React, Angular, and WEB

sQuery This is a Very Small ES6 Native Speed jQuery for Svelte, Vue3, React, Angular, and WEB. Are you fed up with the modern js frameworks? But you'r

Exis 2 Sep 24, 2022
Micro frontend template for starter using qiankun + Vite + TypeScript + Vue3 + React.js + Svelte 🚀

Micro frontend template for starter using qiankun + Vite + TypeScript + Vue3 + React.js + Svelte ??

Yuga Sun 28 Dec 20, 2022
Electron React Boilerplate uses Electron, React, React Router, Webpack and React Fast Refresh.

Electron React Boilerplate uses Electron, React, React Router, Webpack and React Fast Refresh.

Heikki Lotvonen 2 Oct 6, 2021
A tiny (258 bytes) state manager for React/RN/Preact/Vue/Svelte with many atomic tree-shakable stores

Nano Stores A tiny state manager for React, React Native, Preact, Vue, Svelte, and vanilla JS. It uses many atomic stores and direct manipulation. Sma

Nano Stores 2.2k Dec 28, 2022
âšĄī¸ Super-fast Vite + React + Antd + Electron boilerplate.

vite-react-electron English | įŽ€äŊ“中文 Run Setup # clone the project git clone [email protected]:caoxiemeihao/vite-react-electron.git # enter the project di

č‰éž‹æ˛Ąåˇ 641 Dec 30, 2022
Electron 11 + TypeScript 4.0 + Vite 2 + React 17 + Tailwind 2 + twstyled starter

Electron 11 + TypeScript 4.0 + Vite 2 + React 17 + Tailwind 2 + twstyled starter

coased 16 Nov 12, 2022
Electron-react-template - Electron React Template uses React Router and Styled Components

Electron React Template This template uses Create React App, Electron and Electr

Pedro Bzz 7 May 17, 2022
React-electron - dagimsolomon: minimalstic setup of Reactjs with electron

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 2 Jan 23, 2022
Build-electron - Use ES modules in Electron

build-electron Use ES modules in Electron now! build-electron is a simple build

Mikael Finstad 19 Dec 21, 2022
Vite-react-template: A starter for React with Typescript with the fast Vite

vite-react-template vite + react + router + ts A starter for React with Typescript with the fast Vite directory src assets components layout pages ins

ė„¤ė•„ė•„ëš  1 Mar 22, 2022
An Electron boilerplate featuring typescript, react, webpack, tailwind and redux - ready to use!

A secure, modular, and easy to use Electron Forge boilerplate featuring Typescript, React, Webpack, TailwindCSS, Redux and persistance (with redux-persist support)

Daniel 43 Jan 1, 2023
Boilerplate for a project using Electron, React and Typescript.

An Electron boilerplate including TypeScript, React, Jest and ESLint.

Diego Fernandes 1.4k Jan 6, 2023
Lightweight, modern boilerplate built with electron, typescript, react, and material-ui.

This app was designed for the intent of being able to select participants in an auction to be selected and displayed on all the devices connected to a web-socket server running on a device. Without the server running and properly connected, it will not work as intended. You can find the web-socket here.

null 2 Aug 19, 2022
Minimal Electron boilerplate built with Typescript, Webpack 5 and Babel 7

electron-webpack-boilerplate Minimal Electron Starter Kit built with Typescript, React, Webpack 5 and Babel 7 To create a JS library, check out js-lib

Francisco Hodge 10 Aug 16, 2022