Merge branch 'no-dev-tools' into 'v3'

Remove dev tools from production app

Closes #768

See merge request openflexure/openflexure-microscope-server!582
This commit is contained in:
Joe Knapper 2026-05-15 13:38:11 +00:00
commit 96d58a2d0f
8 changed files with 265 additions and 1051 deletions

View file

@ -22,9 +22,21 @@ When developing it is useful to use the development server so Vue changes happen
npm run serve
The development server is accessed on a different port from the microscope API. The port to access the development server is printed on the command line when you run the above command.
The development server is accessed on a different port from the microscope API. When Vite starts, it creates a proxy that proxies all routes starting with `/api` to `http://localhost:5000/api`. This is useful when using either the simulation server or when developing directly on a microscope.
When the development webapp starts it cannot locate the microscope API as this is served by the microscope on port 5000. Instead it will present you with a page giving you the option to "override API origin". If you are running a development server on your computer, you should enter `http://localhost:5000/`.
If developing the webapp on a different computer you can run:
npm run serve:microscope
This will proxy all routes starting with `/api` to `http://microscope.local:5000/api`.
If your microscope hostname is not `microscope`, you can use local environment files to override this route. Create the file `.env.local` within the `/webapp/` directory, and in that file add the line
VITE_MICROSCOPE_HOST=http://myhostname.local:5000
(changing `myhostname` to the correct host name.)
**Note:** If you have performance issues with lag, this can be caused by mDNS speed for your setup. To avoid mDNS, overload `VITE_MICROSCOPE_HOST` with the IP address of your microscope, rather than the host name.
# Javascript: Formatting and linting

1103
webapp/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,8 @@
},
"scripts": {
"gv": "genversion src/version.js",
"serve": "vite serve --mode development",
"serve": "cross-env VITE_API_TARGET=local vite serve --mode development",
"serve:microscope": "cross-env VITE_API_TARGET=microscope vite serve --mode development",
"build": "vite build --mode production",
"lint": "eslint . --ignore-pattern .gitignore --max-warnings=0",
"lint:fix": "eslint . --fix --ignore-pattern .gitignore",
@ -34,6 +35,7 @@
"@vue/eslint-config-prettier": "9.0.0",
"autoprefixer": "^10.4.24",
"core-js": "^3.46.0",
"cross-env": "^10.1.0",
"eslint": "^9.39.2",
"eslint-plugin-pinia": "^0.4.2",
"eslint-plugin-prettier": "^5.1.0",

View file

@ -4,18 +4,14 @@
<div uk-spinner="ratio: 3"></div>
<p>Loading...</p>
</div>
<span class="material-symbols-outlined uk-align-center error-icon">error_outline</span>
<div v-if="error" class="uk-align-center">
{{ error }}
</div>
<div class="uk-align-center">
<devTools class="uk-width-medium"></devTools>
<div v-if="error" id="error-container" class="uk-align-center">
<span class="material-symbols-outlined uk-align-center error-icon">error_outline</span>
<p>{{ error }}</p>
</div>
</div>
</template>
<script>
import devTools from "./tabContentComponents/aboutComponents/devTools.vue";
import { mapWritableState } from "pinia";
import { useSettingsStore } from "@/stores/settings.js";
@ -23,10 +19,6 @@ import { useSettingsStore } from "@/stores/settings.js";
export default {
name: "LoadingContent",
components: {
devTools,
},
computed: {
...mapWritableState(useSettingsStore, ["error", "waiting"]),
},
@ -34,6 +26,10 @@ export default {
</script>
<style scoped lang="less">
#error-container {
text-align: center;
}
.error-icon {
font-size: 120px;
}

View file

@ -1,47 +0,0 @@
<template>
<div>
<form class="uk-form-stacked" action="" method="GET" @submit="overrideAPIHost">
<label class="uk-form-label">Override API origin</label>
<input v-model="overrideOrigin" name="overrideOrigin" class="uk-input" type="text" />
<label class="uk-form-label">
<input v-model="reloadWhenOverridingOrigin" class="uk-checkbox" type="checkbox" />
Reload web app with new origin
</label>
<button class="uk-button uk-button-default uk-margin-small">Apply</button>
</form>
</div>
</template>
<script>
import { mapWritableState } from "pinia";
import { useSettingsStore } from "@/stores/settings.js";
export default {
name: "DevTools",
data() {
return {
reloadWhenOverridingOrigin: true,
};
},
computed: {
...mapWritableState(useSettingsStore, ["overrideOrigin", "origin"]),
},
methods: {
overrideAPIHost(event) {
if (!this.reloadWhenOverridingOrigin) {
this.origin = this.overrideOrigin;
event.preventDefault();
}
},
},
};
</script>
<style scoped lang="less">
.error-icon {
font-size: 120px;
}
</style>

View file

@ -14,22 +14,16 @@
Report an issue
</a>
</div>
<div class="uk-padding-small">
<h2>Developer tools</h2>
<devTools class="uk-width-large" />
</div>
</div>
</template>
<script>
import devTools from "./aboutComponents/devTools.vue";
import statusPane from "./aboutComponents/statusPane.vue";
export default {
name: "AboutContent",
components: {
devTools,
statusPane,
},
};

View file

@ -3,15 +3,9 @@ import { ref, computed } from "vue";
function getOriginFromLocation() {
// This will default to the same origin that's serving
// the web app - but can be overridden by the URL.
// See also devTools.vue which can change the origin.
// the web app.
let url = new URL(window.location.href);
let origin = url.searchParams.get("overrideOrigin");
if (origin) {
return origin;
} else {
return `${url.origin}/api/v3`;
}
return `${url.origin}/api/v3`;
}
// Define Pinia store
@ -50,7 +44,8 @@ export const useSettingsStore = defineStore(
function resetState() {
waiting.value = false;
available.value = false;
error.value = ""; // TODO: verify that "" is needed to match initial state
// On resetState there is no connection.
error.value = "Microscope is not connected.";
}
function setConnected() {

View file

@ -4,58 +4,81 @@
// Note: Comments are generated to explain relevant configuration options.
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import { defineConfig, loadEnv } from "vite";
import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
export default defineConfig(({ command, mode }) => {
const env = loadEnv(mode, process.cwd(), "");
build: {
// Output directory for production builds
outDir: "../src/openflexure_microscope_server/static",
// Clear output directory before build
emptyOutDir: true,
chunkSizeWarningLimit: 400,
rollupOptions: {
output: {
manualChunks: {
"vue-vendor": ["vue", "pinia", "pinia-plugin-persistedstate"],
openseadragon: ["openseadragon"],
uikit: ["uikit"],
utils: ["axios", "mitt", "mousetrap", "@vueuse/core"],
var target;
if (command === "serve") {
if (env.VITE_API_TARGET === "local") {
target = "http://localhost:5000";
} else if (env.VITE_API_TARGET === "microscope") {
target = env.VITE_MICROSCOPE_HOST || "http://microscope.local:5000";
} else {
throw new Error(`Invalid VITE_API_TARGET: ${env.VITE_API_TARGET}`);
}
// Allow a console log as we were serving for development.
// eslint-disable-next-line no-console
console.log(`Proxying /api → ${target}`);
}
return {
plugins: [vue()],
build: {
// Output directory for production builds
outDir: "../src/openflexure_microscope_server/static",
// Clear output directory before build
emptyOutDir: true,
chunkSizeWarningLimit: 400,
rollupOptions: {
output: {
manualChunks: {
"vue-vendor": ["vue", "pinia", "pinia-plugin-persistedstate"],
openseadragon: ["openseadragon"],
uikit: ["uikit"],
utils: ["axios", "mitt", "mousetrap", "@vueuse/core"],
},
},
},
},
},
resolve: {
alias: {
// Setup path alias for src directory.
// This allows importing modules using '@/path/to/module'.
"@": fileURLToPath(new URL("./src", import.meta.url)),
resolve: {
alias: {
// Setup path alias for src directory.
// This allows importing modules using '@/path/to/module'.
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
// Recognize these file extensions for module resolution.
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"],
},
// Recognize these file extensions for module resolution.
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"],
},
server: {
host: true,
// Set the development server port to 8080.
// OFM uses port 5000, so we avoid conflicts. run, and override by using the address:
// http://microscope.local:8080/?overrideOrigin=http://microscope.local:5000/api/v3#
port: 8080,
strictPort: true,
},
css: {
preprocessorOptions: {
less: {
// Always include math in Less files.
math: "always",
// Enable relative URLs in Less files.
relativeUrls: true,
// Enable JavaScript in Less files
javascriptEnabled: true,
server: {
host: true,
// Set the development server port to 8080.
port: 8080,
strictPort: true,
proxy: {
"/api": {
target,
changeOrigin: true,
},
},
},
},
css: {
preprocessorOptions: {
less: {
// Always include math in Less files.
math: "always",
// Enable relative URLs in Less files.
relativeUrls: true,
// Enable JavaScript in Less files
javascriptEnabled: true,
},
},
},
};
});