Skip to content

ldbv-by/bav4

Repository files navigation

BayernAtlas v4

GitHub Workflow Status Coveralls branch GitHub code style: prettier

Next-generation web-map viewer based on web standards (live example).

Table of Contents

  1. Concept
  2. Setup
  3. Structure
  4. Details
  5. Best Practices
  6. Links

Concept

Setup

Prerequisites

  • Node.js 20
  • npm 10.5.x or higher

Having nvm installed, just run nvm install && nvm use

Install

npm i

Configuration

The app can be run without any configuration and uses default values and fallback mechanisms for that case. That is also the case when the BACKEND_URL property is missing.
To enable the showcase component, the SOFTWARE_INFO property must be set.

Configuration properties are read at build time from a .env file located in the project's root directory. Currently used properties are:

key default value description
DEFAULT_LANG en current locale (available locales are en and de)
FRONTEND_URL ${location.protocol}//${location.host} (external) URL of the app
BACKEND_URL
PROXY_URL
SHORTENING_SERVICE_URL
SOFTWARE_INFO e.g. build information

List of npm scripts

Run/Build
npm run start Compiles and hot-reloads for development. Will serve the project under http://localhost:8080 (or the next available port if 8080 is already used, see console output)
npm run start:nohostcheck Compiles and hot-reloads for development. Will serve the project under http://0.0.0.0:8080 (or the next available port if 8080 is already used, see console output) with disabled host checking so that the application is reachable from another device
npm run build:dev Compiles all files without bundling and minification
npm run build:prod Compiles and minifies for production
Test Tests can be run against multiple browsers. Available browsers are ChromeHeadless, FirefoxHeadless, WebkitHeadless.
npm run test Runs unit and component tests against all available browsers. A (combined) code coverage report can be found under ./coverage/lcov-report. Target browsers can be individually specified by the --browsers option (comma-separated).
npm run test:single Runs a single test. Usage npm run test:single --spec=MyTest.test.js . The target browser can be individually specified by the --browser option. The default is FirefoxHeadless
npm run test:debug Runs unit and component tests against headless Chrome (Chromium) with remote debugging enabled
E2E Test E2E tests are based on Playwright and can be run against multiple browsers. Available browsers are chromium, firefox, webkit.
npm run e2e Runs E2E tests against all available browsers. A single browser can be individually specified by the --browser option
npx playwright test --help Shows information about all options
Other
npm run lint Lints and fixes js and css files
npm run prettier Formats all code files
npm run es-check Checks if js files use only allowed es-version language features
npm run doc Generates jsdoc files (see: ./docs)
npm run doc:check Checks if all required JSDoc module names exists
npm run doc:apply Adds or updates the JSDoc module names
npm run bundlesize Checks the bundle size of the webpack compiled chunks
npm run analyze-bundle Visualize the size of webpack chunks with an interactive zoomable tree map
npm run optimize-svg Optimize all SVG vector graphics files

Available Pages

Path
/ /index.html Serves the default page
/embed.html Serves a page that can be embedded via an iframe
/embed/wrapper Serves a wrapper page for the embed.html. Useful for dev and testing purposes (passes its query parameters to embed.html)

Structure

The project's source code is under src, unit, component and e2e tests are under test.

The source code is distributed among the following directories:

src/domain

Contains global domain-specific classes and type definitions.

src/i18n

Contains and registers the global i18n provider

src/injection

Contains the built-in dependency injection. The central configuration is done in config.js.

The common types of injection are service classes. Service classes may retrieve data from an external source by using a provider function. Such provider functions are also interchangeable. Services and provider functions whose names start with 'BVV' focus on the LDBV context and infrastructure.

src/modules

Modules are each as much as possible independent units of code. They have a concrete context and/or focus on one or more similar use cases of the application (single responsibility, high cohesion).

Modules meet the following conventions:

  1. Each module must have an index.js as an entry point, which states all of its dependencies.

  2. Each module must be registered within the main.js.

  3. Each module may contain further directories:

    • /components : Components and all of their dependencies like CSS, assets (see Components)
    • /services : service, provider, and domain classes of the module
    • /i18n : i18n provider and loader for this module
  4. Outside their package, modules are only allowed to use global services, actions, and components from other modules for composition.

src/plugins

Contains all plugins (see Plugins).

src/services

All global services like the HttpService and their providers are located here.

src/store

All redux-related files like reducers and actions.

src/utils

Contains global utilities.

src/chunks

Contains chunk definitions for dynamically loading js resources (code splitting).

Overview

Here's an overview of what the project folder structure looks like:

    .
    + -- src # source code
    |    + -- index.html # here's where you should declare your top-level web components
    |    + -- main.js # here's where you should import your modules  to the app
    |    + -- injection
    |    + -- modules
    |    |    + -- moduleName
    |    |    |    + -- index.js
    |    |    |    # other moduleName related files such as a components folder or a services folder
    |    + -- plugins
    |    + -- services
    |    + -- store
    |    + -- utils
    + -- test # test code

Details

Global State

Global state and its management are realized by Redux (reducers and actions).

Components

Components are based on MvuElement. This class inherits from HTMLElement and provides the Model-View-Update pattern and a well-defined component lifecycle as the programming model. For more information have a look at the MvuElement docs. Components hold the local state within their model.

Plugins

BaPlugins implementations are a second important place for structuring code and logic.
In contrast to components, they often act as a Controller on a higher abstraction level managing the global state being consumed by components afterward.
For example, they could be responsible for setting an initial state or reacting to global state changes during the runtime of the app.

Best practices

  • Mutation of the same parts of the global state should be done in just one place at the same moment (single source of truth)
    ("At the same moment" means the phase when parts of the application react to an event, e.g. user interaction, initial setup)

  • Common places for updating the global state are:

    • MvuElement based components
    • BaPlugin implementations
  • If an update of the global state has an event-like character, it's recommended to wrap the payload within another object. This makes it possible to track changes and avoids second dispatching in order to "reset" the state. For this purpose, you can use use EventLike in storeUtils.js

  • Avoid adding huge objects or arrays to the Redux store (e.g. large arrays of coordinates). Detecting changes can be expensive in that case. Instead, try to reference them by an identifier and push this identifier to the store.

Links

Various topics relating to Web Components

CSS

lit-html

Redux

Webpack

Other

USE THE PLATFORM