Skip to content

Commit

Permalink
WIP: switch from create-react-app to vite
Browse files Browse the repository at this point in the history
create-react-app is apparently deprecated, so the cool kids use vite,
I guess.

Working on mergeability...
  • Loading branch information
scottlamb committed Dec 18, 2023
1 parent 79af39f commit 5bce5e5
Show file tree
Hide file tree
Showing 17 changed files with 7,508 additions and 25,832 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
- uses: actions/upload-artifact@v3
with:
name: moonfire-nvr-ui-${{ github.ref_name }}
path: ui/build
path: ui/dist
if-no-files-found: error
- uses: actions/upload-artifact@v3
with:
Expand Down Expand Up @@ -69,7 +69,7 @@ jobs:
uses: actions/download-artifact@v3
with:
name: moonfire-nvr-ui-${{ github.ref_name }}
path: ui/build
path: ui/dist

# actions-rust-cross doesn't actually use cross for x86_64.
# Install the needed musl-tools in the host.
Expand All @@ -79,7 +79,7 @@ jobs:
- name: Build
uses: houseabsolute/actions-rust-cross@v0
env:
UI_BUILD_DIR: ../ui/build
UI_BUILD_DIR: ../ui/dist

# cross doesn't install `git` within its Docker container, so plumb
# the version through rather than try `git describe` from `build.rs`.
Expand Down
4 changes: 2 additions & 2 deletions guide/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ $ npm install
$ npm run build
$ sudo mkdir /usr/local/lib/moonfire-nvr
$ cd ..
$ sudo rsync --recursive --delete --chmod=D755,F644 ui/build/ /usr/local/lib/moonfire-nvr/ui
$ sudo rsync --recursive --delete --chmod=D755,F644 ui/dist/ /usr/local/lib/moonfire-nvr/ui
```

### Running interactively straight from the working copy
Expand All @@ -100,7 +100,7 @@ the binaries in the working copy will run via just `nvr`:

```console
$ sudo mkdir /usr/local/lib/moonfire-nvr
$ sudo ln -s `pwd`/ui/build /usr/local/lib/moonfire-nvr/ui
$ sudo ln -s `pwd`/ui/dist /usr/local/lib/moonfire-nvr/ui
$ sudo mkdir /var/lib/moonfire-nvr
$ sudo chown $USER: /var/lib/moonfire-nvr
$ ln -s `pwd`/server/target/release/moonfire-nvr $HOME/bin/moonfire-nvr
Expand Down
27 changes: 10 additions & 17 deletions guide/developing-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

The UI is presented from a single HTML page (index.html) and any number
of Javascript files, css files, images, etc. These are "packed" together
using [webpack](https://webpack.js.org).
using [vite](https://vitejs.dev/).

For ongoing development it is possible to have the UI running in a web
browser using "hot loading". This means that as you make changes to source
Expand All @@ -26,12 +26,12 @@ Checkout the branch you want to work on and type

```
$ cd ui
$ npm run start
$ npm run dev
```

This will pack and prepare a development setup. By default the development
server that serves up the web page(s) will listen on
[http://localhost:3000/](http://localhost:3000/) so you can direct your browser
[http://localhost:5173/](http://localhost:5173/) so you can direct your browser
there. It assumes the Moonfire NVR server is running at
[http://localhost:8080/](http://localhost:8080/) and will proxy API requests
there.
Expand All @@ -45,32 +45,25 @@ process, but some will show up in the browser console, or both.

## Overriding defaults

The UI is setup with [Create React App](https://create-react-app.dev/).
`npm run start` will honor any of the environment variables described in their
[Advanced Configuration](https://create-react-app.dev/docs/advanced-configuration/),
as well as Moonfire NVR's custom `PROXY_TARGET` variable. Quick reference:
Currently there's only one supported environment variable override defined in
`ui/vite.config.ts`:

| variable | description | default |
| :------------- | :----------------------------------------------------------------------- | :----------------------- |
| `PROXY_TARGET` | base URL of the backing Moonfire NVR server (see `ui/src/setupProxy.js`) | `http://localhost:8080/` |
| `PORT` | port to listen on | 3000 |
| `HOST` | host/IP to listen on (or `0.0.0.0` for all) | `0.0.0.0` |
| variable | description | default |
| :------------- | :------------------------------------------ | :----------------------- |
| `PROXY_TARGET` | base URL of the backing Moonfire NVR server | `http://localhost:8080/` |

Thus one could connect to a remote Moonfire NVR by specifying its URL as
follows:

```
$ PROXY_TARGET=https://nvr.example.com/ npm run start
$ PROXY_TARGET=https://nvr.example.com/ npm run dev
```

This allows you to test a new UI against your stable, production Moonfire NVR
installation with real data.

**Note:** the live stream currently does not work in combination with
`PROXY_TARGET` due to [#290](https://github.com/scottlamb/moonfire-nvr/issues/290).

You can also set environment variables in `.env` files, as described in
[Adding Custom Environment Variables](https://create-react-app.dev/docs/adding-custom-environment-variables/).
[vitejs.dev: Env Variables and Modes](https://vitejs.dev/guide/env-and-mode).

## A note on `https`

Expand Down
8 changes: 4 additions & 4 deletions server/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use std::fmt::Write;
use std::path::{Path, PathBuf};
use std::process::Command;

const UI_BUILD_DIR_ENV_VAR: &str = "UI_BUILD_DIR";
const DEFAULT_UI_BUILD_DIR: &str = "../ui/build";
const UI_DIST_DIR_ENV_VAR: &str = "UI_DIST_DIR";
const DEFAULT_UI_DIST_DIR: &str = "../ui/dist";

type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;

Expand Down Expand Up @@ -53,7 +53,7 @@ impl FileEncoding {
/// Map of "bare path" to the best representation.
///
/// A "bare path" has no prefix for the root and no suffix for encoding, e.g.
/// `favicons/blah.ico` rather than `../../ui/build/favicons/blah.ico.gz`.
/// `favicons/blah.ico` rather than `../../ui/dist/favicons/blah.ico.gz`.
///
/// The best representation is gzipped if available, uncompressed otherwise.
type FileMap = fnv::FnvHashMap<String, File>;
Expand All @@ -78,7 +78,7 @@ fn handle_bundled_ui() -> Result<(), BoxError> {
}

let ui_dir =
std::env::var(UI_BUILD_DIR_ENV_VAR).unwrap_or_else(|_| DEFAULT_UI_BUILD_DIR.to_owned());
std::env::var(UI_DIST_DIR_ENV_VAR).unwrap_or_else(|_| DEFAULT_UI_DIST_DIR.to_owned());

// If the feature is on, also re-run if the actual UI files change.
println!("cargo:rerun-if-env-changed={UI_BUILD_DIR_ENV_VAR}");
Expand Down
2 changes: 1 addition & 1 deletion ui/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/coverage

# production
/build
/dist

# misc
.DS_Store
Expand Down
38 changes: 38 additions & 0 deletions ui/FixJSDomEnvironment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// This file is part of Moonfire NVR, a security camera network video recorder.
// Copyright (C) 2023 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
// SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception

// Environment based on `jsdom` with some extra globals, inspired by
// the following comment:
// https://github.com/jsdom/jsdom/issues/1724#issuecomment-1446858041

import JSDOMEnvironment from "jest-environment-jsdom";

// https://github.com/facebook/jest/blob/v29.4.3/website/versioned_docs/version-29.4/Configuration.md#testenvironment-string
export default class FixJSDOMEnvironment extends JSDOMEnvironment {
constructor(...args: ConstructorParameters<typeof JSDOMEnvironment>) {
super(...args);

// Tests use fetch calls with relative URLs + msw to intercept.
this.global.fetch = (
resource: RequestInfo | URL,
options?: RequestInit
) => {
throw "must use msw to fetch: " + resource;
};

class MyRequest extends Request {
constructor(input: RequestInfo | URL, init?: RequestInit | undefined) {
input = new URL(input as string, "http://localhost");
super(input, init);
}
}

this.global.Headers = Headers;
this.global.Request = MyRequest;
this.global.Response = Response;

// `src/LiveCamera/parser.ts` uses TextDecoder.
this.global.TextDecoder = TextDecoder;
}
}
11 changes: 6 additions & 5 deletions ui/public/index.html → ui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,24 @@
<link
rel="apple-touch-icon"
sizes="180x180"
href="%PUBLIC_URL%/favicons/apple-touch-icon-94a09b5d2ddb5af47.png"
href="favicons/apple-touch-icon-94a09b5d2ddb5af47.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="%PUBLIC_URL%/favicons/favicon-32x32-ab95901a9e0d040e2.png"
href="favicons/favicon-32x32-ab95901a9e0d040e2.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="%PUBLIC_URL%/favicons/favicon-16x16-b16b3f2883aacf9f1.png"
href="favicons/favicon-16x16-b16b3f2883aacf9f1.png"
/>
<link rel="manifest" href="%PUBLIC_URL%/site.webmanifest" />
<link rel="manifest" href="site.webmanifest" />
<link
rel="mask-icon"
href="%PUBLIC_URL%/favicons/safari-pinned-tab-9792c2c82f04639f8.svg"
href="favicons/safari-pinned-tab-9792c2c82f04639f8.svg"
color="#e04e1b"
/>
<meta name="theme-color" content="#e04e1b" />
Expand All @@ -42,5 +42,6 @@
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root" style="display: flex; flex-direction: column"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>
36 changes: 36 additions & 0 deletions ui/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// This file is part of Moonfire NVR, a security camera network video recorder.
// Copyright (C) 2023 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
// SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception

import type { Config } from "jest";

const config: Config = {
testEnvironment: "./FixJSDomEnvironment.ts",

transform: {
// https://github.com/swc-project/jest
"\\.[tj]sx?$": [
"@swc/jest",
{
// https://swc.rs/docs/configuration/compilation
// https://github.com/swc-project/jest/issues/167#issuecomment-1809868077
jsc: {
transform: {
react: {
runtime: "automatic",
},
},
},
},
],
},

setupFilesAfterEnv: ["<rootDir>/src/setupTests.ts"],

// https://github.com/jaredLunde/react-hook/issues/300#issuecomment-1845227937
moduleNameMapper: {
"@react-hook/(.*)": "<rootDir>/node_modules/@react-hook/$1/dist/main",
},
};

export default config;
Loading

0 comments on commit 5bce5e5

Please sign in to comment.