Skip to content

Latest commit

 

History

History
120 lines (78 loc) · 9.21 KB

DEVELOPMENT.md

File metadata and controls

120 lines (78 loc) · 9.21 KB

Development

Table of Contents

Architecture

Processes

The following directories can be found in src/ and approximately represent the Electron processes of interest:

Electron Runtime

The following use cases should generally be defined and set up in a preload script:

  • communication between renderer and main processes
  • any usage of Electron's renderer modules
  • usage of a Node API (either directly or through a module) that's supported by the preload script sandbox

For example, in src/preload/main-window.js, we expose an API to interact with the main process on window.runtime. This may change in the future but it's actually quite nice because it becomes more accessible for debugging purposes (e.g. testing the API using the devtools console).

Developing locally

Make sure you have the desired Node version installed. For this project we encourage using the version that's specified in the .nvmrc (or .tool-versions) file. We recommend using a proper version management tool to install and manage Node versions, such as nvm, fnm, asdf, or mise.

Environment variables

Create a copy of the .env.template and call it .env. Update the following variables:

  • ONLINE_STYLE_URL: Full URL that points to a compatible map's StyleJSON.

Running the app

Run the following commands to start the app:

npm install                # Install dependencies
npm start                  # Build translations, then build the app in development mode and start the development server

Helpful tips about workflow

  • Changes in the src/renderer/ should immediately automatically be reflected in the app
  • Changes in the src/preload/ require the window to be refreshed to be reflected in the relevant window. Either go to the View > Reload menu option or use the keyboard shortcut (e.g. CMD + R on macOS, CTRL + R on Linux, Windows)
  • Changes to src/main/ or src/services/ require restarting the app. You can either:
    1. Stop the process that is running npm start and rerun it.
    2. Type R + S + Enter in the process that is running npm start, which tells Forge to restart the main process.
  • In development, the userData directory is set to the data/ directory by default. This provides the following benefits:
    • Avoids conflicting with the existing app if it's installed. Assuming the same app id is used, Electron will default to using the OS-specific user data directory, which means that if you have a production version of the app installed, starting the development version will read and write from the production user data directory. Most of the time this is not desired (you generally don't want to mix production data and settings with your development environment). If it is desired, comment out the line that calls app.setPath('userData', ...) in src/main/index.js
    • Easier to debug because you don't have to spend as much time to figure out which directory to look at (it changes based on operating system)
  • If you want to change the userData directory, define an environment variable called USER_DATA_PATH that can be used when calling npm start. For example, running USER_DATA_PATH=./my_data npm start will create a my_data directory relative to the project root. This is useful for creating different "profiles" and isolating data for the purpose of testing features or reproducing bugs
  • If you are installing a package that is only going to be used by code the renderer (e.g. a React component library), you most likely should install it as a dev dependency instead of a direct dependency. This differs from typical development workflows you see elsewhere, but the reasoning is that during the packaging stage of the app, @electron/packager avoids copying dev dependencies found in the node_modules directory. Since we bundle our renderer code, we do not need to copy over these dependencies, which results in a significant decrease in disk space occupied by the app.
  • We use debug for much of our logging in the main process. In order to see them, you can specify the DEBUG environment variable when running the app e.g. DEBUG=comapeo:* npm start.

Helpful tips about configuration

Testing

The renderer app (aka React code) can run unit test with Vitest (and integration tests with React Testing Library).

To run unit or integration tests run npm run vitest:run or npm run vitest:watch. See vitest run and vitest watch to understand the difference.

Translations

The messages/ directory contains the translation strings used by the app. Within this directory are directories for the main process (messages/main/) and renderer process (messages/renderer/). Messages found in messages/main/ are typically needed for translating text that lives in native UI (e.g. the menu bar), whereas messages in messages/renderer/ are needed for translating text that's used in the rendered web app.

In order to update translations, run npm run intl:translations, which will extract messages and place them in the relevant messages/ directory and then compile those messages into translated strings and place them in the translations/ directory.

Translations workflow

  • For the main process:

    1. Use defineMessage (or defineMessages) from @formatjs/intl to create messages and use in the main process code.
    2. Run npm run intl:translations:main (ornpm run intl:translations).
  • For the renderer process:

    1. Use defineMessage (or defineMessages) from react-intl to create messages and use in the renderer process code.
    2. Run npm run intl:translations:renderer (ornpm run intl:translations).

Building the app

The Electron Forge docs are pretty informative (especially https://www.electronforge.io/core-concepts/build-lifecycle) but in a nutshell:

  • npm run forge:package: generate an executable app bundle i.e. an executable that you can run in the command-line.

  • npm run forge:make: generate an distributable installer or archives that you can install by opening using your filesystem.

  • npm run forge:publish: upload the distributable to some cloud storage for distribution.

All commands place the built assets in the out/ directory.

Our build process requires a .env.production file to exist at the project root in order for these commands to work. Usually this file will be generated as a prerequisite to packaging the app (e.g. in continuous deployment environments like GitHub Actions). If you are just debugging locally, you can create a copy of your .env file and call it .env.production in order to avoid errors at build time.

If you're running into an error with any of the Forge-related commands but not seeing any output in the console, you probably have to prefix the command with DEBUG=electron-forge e.g. DEBUG=electron-forge npm run forge:package.

By default, we package the app in the ASAR format. However, it can be helpful to avoid doing that for debugging purposes (e.g. building locally), in which case you can specify a ASAR=true environment variable when running the relevant Forge command e.g. ASAR=true npm run forge:package.