The underlying technologies used to compose Synectic have changed over the years. This document serves as a guide to the current technologies, as well as a historical record of the evolution in the architecture and design.
Synectic began as a simple editor using web-based technologies to create a flexible desktop application. We initially settled on Electron for its ability to create desktop applications using web technologies (mainly HTML, CSS, and JavaScript) that are rendered using a version of the Chromium V8 browser engine and a backend using the Node.js runtime environment.
Using Electron means several decisions were already made for us, not least of which is that our application needs to compiled to JavaScript and run in a Node.js environment. This meant that we initially wrote in JavaScript. However, we transitioned to TypeScript in v0.7.0
.
TypeSript includes:
- A superset of JavaScript that adds optional static typing to the language.
- The ability to use the latest JavaScript features such as classes, arrow functions, generators, async/await, and modules.
- Support for IntelliSense in Visual Studio Code for code completion, syntax linking, and code hinting.
We also use HTML for structuring the web content displayed within Synectic, and CSS for styling the presentation of those HTML elements.
We initially started using the npm package manager due to its defacto status as the standard for JavaScript applications that pull packages from the npm
registry. We transitioned to Yarn in v1.0.0
.
In order to transform JavaScript and other front-end assets such as HTML, CSS, and images, we use a module bundler that is capable of taking modules with dependencies and generating static assets representing those modules. This is also a necessary step before packaging Synectic into distributable installers for the various platforms (Linux, MacOS, and Windows).
Synectic used Webpack for v0.7.0
to v4.4.0
. However, we replaced it with Vite in more recent releases to take advantage of the next-generation of bundlers.
Vite includes:
- A dev server for serving source files over native ES modules, with built-in features and fast Hot Module Replacement (HMR).
- Built-in support for Rollup to compile and bundle source code for production.
- Supports reading
.env
files for environment variables. - Code formatting rules follow the latest TypeScript recommendations and best practices thanks to @typescript-eslint/eslint-plugin.
See all Vite features
Prior to v1.0.0
, we relied on Electron Builder for building and publishing Electron distributables. However, we restructured the project to use the project scaffolding included in Electron Forge during that first production release.
In the v5.0.0
release we migrated to Hydraulic Conveyor for its support of cross-building/signing of all packages from any OS without the need for multi-platform CI, the ability to do synchronous web-style updates on each start of the app, and for the ability to use plain HTTP servers for updates. Conveyor replaces the Electron auto-updaters with Sparkle on MacOS, MSIX on Windows, and Linux package repositories.
We initially relied on TSLint as it was the recommended linter for TypeScript projects up until being deprecated in 2019 in favor of the ESLint static code analysis tool. We switched to using ESLint during the v1.0.0
release.
We also added the opinionated code formatter Prettier during the v4.0.0
release to enforce a consistent code style that is automatically formatted on save.
Originally written as native HTML components and JavaScript event handlers, we transitioned to using React in v1.0.0
for building our user interfaces.
React includes:
- Declarative nature of components that describe the user interface and how it should change as state changes.
- Component-based architecture that allows for encapsulation of state and behavior.
- A Virtual DOM for fast rendering of components.
- TSX/JSX syntax that allows HTML to be written in TypeScript/JavaScript files.
- One-way data bindings using props and state.
- Interactivity using event handlers.
We also use the Material-UI component library for React to provide a consistent look and feel across the application. Added in the v1.0.0
release, MUI provides an open-source React component library that implements Google's Material Design specification.
Redux is a predictable state container for TypeScript/JavaScript apps that helps write applications that behave consistently, run in different environments (client, server, and native), and are easy to test. It provides a centralized store for the entire application that is updated by dispatching actions that are handled by reducers. We added Redux as part of the v1.0.0
release.
We also include the React-Redux bindings for React to allow React components to interact with the Redux store, and the Redux Toolkit to simplify the creation of Redux stores and reducers.
Originally, we used a combination of the Mocha JavaScript testing framework and the Chai BDD/TDD assertion library for Node.js and browser targets. However, we switched to using the Jest JavaScript testing framework in combination with the React Testing Library (RTL) during the v1.0.0
release.
This has been updated to use Vitest, a Vite-native testing framework, for the testing platform. We also employ Playwright for end-to-end testing.
Vitest includes:
- A flexible set of configs, transformers, resolvers, and plugins.
- A built-in test runner that runs tests in parallel, and includes a watch mode for HMR-like performance in tests.
- Component testing for Vue, React, Svelte, Lit, Marko and more.
- Built-in support for TypeScript, JSX, and CSS modules.
- ESM support that includes top-level await and dynamic imports.
- Workers multi-threaded via Tinypool.
- Benchmarking support with Tinybench.
- Filtering, timeouts, and concurrent for suite and tests.
- Workspace support.
- Jest-compatible Snapshots.
- Chai built-in for assertions and Jest
expect
compatible APIs. - Tinyspy built-in for mocking.
- happy-dom or jsdom built-in for DOM testing.
- Code coverage via v8 or istanbul.
- Rust-like in-source testing.
- Type testing via
expect-type
.