Datascanner frontend architecture
Applications
Presently, Datascanner's main web GUIs are the admin and report modules. The source code for both resides in src/os2datascanner/projects.
HTML markup
Markup is mostly generated using Django templates.
Shared static resources
The static resources are located in
src/os2datascanner/projects/static. Django is configured to look in this path (actually on the corresponding dist
path in the Docker container) when it collects static resources. This allows both apps to use the same set of static resources without
having to maintain duplicate copies.
Webpack setup
Static resources are bundled up via
Webpack and output in a dist
subfolder to src/os2datascanner/projects/static
; consult
src/os2datascanner/projects/static/webpack.base.js
for the configuration. Note that since the JS code isn't really modularized,
most of what Webpack does is statically copy over the folders js
†, 3rdparty
, admin
, css
, favicons
, fonts
, recurrence
and svg
with CopyWebpackPlugin
. † The exception to the JS files is the file index.js
which serves as the Webpack entry point. Finally, the scss
folder is also not copied over, as its contents need to be transpiled into CSS first. This is achieved by importing master.scss
into index.js
and then using sass-loader
for Webpack to handle that import statement.
For hot reloading to work, we define the CMD ["npm", "run", "dev", "--prefix", "static"]
in /docker/admin/Dockerfile
(and /docker/report/Dockerfile
). This CMD is defined
in the frontend
stage of those Dockerfiles and will boot up a webpack dev server
that listens for changes to the static frontend files. We stop at that stage in
development when using the frontend
service; consult /docker-compose.yml
.
This means that we can then mount in the static files from the host into the
frontend
container, and the webpack dev server will refresh when we edit the
files on the host. Since the dist
folder that webpack outputs its files to is
shared with the admin
and report
services (our two Django apps), changes
to the static files will automatically be picked up by Django.
For all this to work, however, we need to explicitly define
/code/src/os2datascanner/projects/static/node_modules/
as volumes in the frontend
service. If we don't, mounting in the static directory from the host into the
container will lead to errors, if the directory of the host doesn't contain a
node_modules
folder (which it won't, unless you happened to run npm install
on the host). The caveat to this is that if you install new dependencies with
npm
on the host (which will make them appear in the host's node_modules
folder),
they won't automatically appear in the container's node_modules
. You need to
rebuild the frontend
and boot up the container again.
docker-compose up --build -d frontend
should do the trick.
CSS styling
An effort has been made to establish SASS as the guiding workflow for CSS builds but it is mixed with other approaches. Amongst others:
- CSS built from SASS and bundled up via Webpack (via plugins)
- CSS imported directly or from 3rd parties
JavaScript
A minimal set of JS is bundled as described in "Shared static resources" above. Other scripts are just added via script tags in the Django templates.
Admin app also includes Bootstrap Javascript but without the accompanying bootstrap.css
- Package management
npm. At the time of writing, NPM packages are exclusively used for the bundling setup (you'll only see
devDependencies
inpackage.json
, nodependencies
). JS code imports no modules. - Old browser support
Babel is currently neither installed nor configured. IE support is achieved via conditional comments in
<head>
.
Fonts
Admin and Report app use the "Inter" font.
Icons
Admin and Report app use Google's Material Icons and in some cases custom SVG icons. For more info see the icon guide here
Build & package management
Webpack is used for building frontend assets.
Admin app specifics
- Django template files
- src/os2datascanner/projects/admin/adminapp/templates
- Templates that load JS
- src/os2datascanner/projects/admin/adminapp/templates/components/user.html
- src/os2datascanner/projects/admin/adminapp/templates/os2datascanner/regexrule_form.html
- src/os2datascanner/projects/admin/adminapp/templates/os2datascanner/rules.html
- src/os2datascanner/projects/admin/adminapp/templates/os2datascanner/scanner_askrun.html
- src/os2datascanner/projects/admin/adminapp/templates/os2datascanner/scanner_form.html
- src/os2datascanner/projects/admin/adminapp/templates/os2datascanner/scanner_run.html
- src/os2datascanner/projects/admin/adminapp/templates/os2datascanner/scanners.html
- src/os2datascanner/projects/admin/adminapp/templates/partials/base.html
- Templates that load CSS
- src/os2datascanner/projects/admin/adminapp/templates/os2datascanner/scanner_form.html
- src/os2datascanner/projects/admin/adminapp/templates/partials/base.html
Report app specifics
- Django template files
- src/os2datascanner/projects/report/reportapp/templates
- Templates that load JS
- src/os2datascanner/projects/report/reportapp/templates/components/user.html
- src/os2datascanner/projects/report/reportapp/templates/partials/header.html
- src/os2datascanner/projects/report/reportapp/templates/partials/scripts.html
- src/os2datascanner/projects/report/reportapp/templates/statistics.html
- Templates that load CSS
- src/os2datascanner/projects/report/reportapp/templates/partials/header.html
TODOS for a simpler frontend architecture
Decisions to make:
- IE11-support by Babel/bundling vs. IE11 by old school coding (no bundling)?
- JS bundling vs decentralised JS (see above)?
One hybrid approach includes both bundling and decentralized code:
- Decide on what is core JS/CSS. Bundle only that. Embed it on every page (base|index.html). Adding eventlisteners to certain elements is probably not core.
- Load component-specific JS/CSS from their specific templates. Use script/styling/extra_head blocks. Most eventlisteners go here.
- Put component-specific JS/CSS/SCSS with related templates (if possible)
- Decide on what icon system to use. Use only that.