FERS aus JavaScript verwenden
Der FERS-Solver ist als WebAssembly-Build derselben Rust-Rechenmaschine veröffentlicht, die auch die Web-App antreibt. Er läuft im Browser oder in Node, rechnet ohne Server-Roundtrip und benötigt im kostenlosen Tarif keinen API-Schlüssel.
Installation
Aus derselben Rechenmaschine werden zwei Pakete mit identischer Schnittstelle veröffentlicht — nur Installation und Bundler-Einrichtung unterscheiden sich. Nehmen Sie -web für alles, was durch einen Bundler läuft, und das Paket ohne Suffix für Node auf dem Server.
# Browser apps (Vite, Next.js, webpack):
npm install @ferscloud/fers-calculation-web
# Node.js / server-side:
npm install @ferscloud/fers-calculationBeide Pakete tragen die Version der Rechenmaschine und werden gemeinsam aktualisiert. Binden Sie sie an dieselbe exakte Version statt an einen Caret-Bereich.
Bundler einrichten
@ferscloud/fers-calculation-web ist ein WASM-ES-Modul, das sich über ein Top-Level-await initialisiert. Die meisten Bundler brauchen dafür eine einmalige Konfigurationsänderung; das Node-Paket braucht keine.
Vite
Das Plugin hinzufügen und anschließend ein Build-Target setzen, das Top-Level-await unterstützt.
npm i -D vite-plugin-wasmVite-Konfiguration
// vite.config.ts
import wasm from "vite-plugin-wasm";
// The package initialises with a top-level await, so the build target
// has to be one that supports it. esnext needs no second plugin.
export default {
plugins: [wasm()],
build: { target: "esnext" },
};Next.js und webpack
Das Paket transpilieren und asynchrones WebAssembly aktivieren. asyncFunction ist nötig, weil sich das Modul mit einem Top-Level-await initialisiert.
// next.config.js
module.exports = {
transpilePackages: ["@ferscloud/fers-calculation-web"],
webpack(config) {
config.experiments = { ...config.experiments, asyncWebAssembly: true };
config.output.environment = {
...config.output.environment,
asyncFunction: true,
};
return config;
},
};Der Solver ist synchron und rechenlastig. Führen Sie ihn bei größeren Modellen in einem Web Worker aus, damit der UI-Thread frei bleibt.
Ein Modell rechnen
Kein init()-Aufruf und kein API-Schlüssel. Der kostenlose Tarif deckt jedes Modell bis 100 Stäbe ab.
import { calculate_from_json } from "@ferscloud/fers-calculation";
// No init() call needed — the nodejs and bundler builds initialise the
// WASM module automatically on import.
const res = JSON.parse(calculate_from_json(JSON.stringify(myModel)));
if (res.ok) {
const data = res.result; // displacements, member_results, unity_checks, …
} else {
console.error(res.error.code, res.error.message);
}Das Ergebnis-Envelope
Jeder Solver-Aufruf liefert ein JSON-Envelope, Sie parsen also einmal und verzweigen über ok — nie müssen Sie prüfen, ob die zurückgegebene Zeichenkette wie ein Fehler aussieht. Der Rückgabewert ist immer gültiges JSON.
// success
{ "ok": true, "result": { /* the full result document */ } }
// failure (invalid model, over the member limit, malformed JSON, …)
{ "ok": false, "error": { "code": "LimitExceeded",
"message": "Number of members (250) exceeds allowed maximum of 100" } }| error.code | Bedeutung |
|---|---|
InvalidJson | Die Modellzeichenkette war kein gültiges JSON. |
LimitExceeded | Mehr Stäbe als der aktive Tarif erlaubt (100 kostenlos, 10,000 Pro). |
SolveError | Das Modell wurde gelesen, ließ sich aber nicht lösen — meist eine singuläre Steifigkeitsmatrix wegen fehlender oder unzureichender Auflager. |
InternalPanic | Ein Fehler in der Rechenmaschine. Bitte melden Sie ihn. |
InternalSerialization | Die Ergebnisse ließen sich nicht serialisieren. Ebenfalls ein meldenswerter Fehler. |
TypeScript-Typen
Das Browser-Paket liefert generierte Modelltypen neben den Funktionssignaturen mit. Sie werden aus dem OpenAPI-Schema der Rechenmaschine erzeugt und folgen damit der veröffentlichten Version, statt von Hand gepflegt zu werden.
import type {
FERS,
ResultsBundle,
} from "@ferscloud/fers-calculation-web/fers-models";
// FERS — the input model
// ResultsBundle — the `result` payload of a successful envelope
// Both are generated from the engine's OpenAPI schema, so they track
// the published version.FERS im kostenlosen Tarif nennen
Ergebnisse im kostenlosen Tarif tragen ein attribution-Objekt, das im Solver erzeugt wird. Pro-Ergebnisse, die mit gültigem Token gerechnet wurden, tragen es nicht — derselbe Code zeigt also im kostenlosen Tarif einen Hinweis und liefert unter Pro White-Label-Ausgabe, ohne dass ein Schalter zu setzen wäre.
Daneben werden getFersAttribution, fersAttributionText und createFersBadge exportiert. Alle nehmen das Envelope, das geparste Modell oder das Ergebnispaket entgegen und geben bei einem Pro-Ergebnis oder einem Fehler-Envelope nichts zurück.
import { fersAttributionHtml } from "@ferscloud/fers-calculation-web/badge.js";
// Free-tier results carry result.attribution; this renders the credit.
// With a Pro solve token the field is absent and this returns "" — the
// same code white-labels, with no flag to set.
const credit = fersAttributionHtml(res);Wenn Sie den kostenlosen Tarif in einer Anwendung einsetzen, zeigen Sie den Hinweis bitte an. Es ist das Einzige, worum der kostenlose Tarif bittet. Verfügbar ab Engine 0.2.61.
Pro-Grenzen mit einem Solve-Token
Die Pro-Grenzen werden über ein kurzlebiges signiertes Token freigeschaltet, das der FERS-Cloud-Server ausstellt. Das Token wird innerhalb des WebAssembly-Moduls gegen einen im Binary hinterlegten Ed25519-Public-Key geprüft und ist daher nicht fälschbar.
Ihr Server hält den API-Schlüssel und tauscht ihn gegen ein 30-Minuten-Token; der Browser sieht immer nur das Token. Halten Sie FERS_API_KEY serverseitig — niemals im Browser-Code.
// pages/api/solve-token.ts
const FERS_API_KEY = process.env.FERS_API_KEY!;
let cached: { token: string; expiresAt: number } | null = null;
export default async function handler(req, res) {
const now = Date.now();
// Re-use if more than 5 minutes remain
if (cached && cached.expiresAt - now > 5 * 60 * 1000) {
return res.json({ token: cached.token });
}
const resp = await fetch("https://ferscloud.com/api/solver/token", {
method: "POST",
headers: { "X-API-Key": FERS_API_KEY },
});
if (!resp.ok) return res.status(502).json({ error: "Token fetch failed" });
const { token, expiresAt } = await resp.json();
cached = { token, expiresAt: new Date(expiresAt).getTime() };
return res.json({ token });
}Den Solver mit Token aufrufen
Fehlt das Token oder ist es abgelaufen oder ungültig, fällt der Solver auf die kostenlose Stabgrenze zurück — er wirft nie eine Ausnahme. Ein echter Berechnungsfehler kommt weiterhin als { ok: false, error } zurück und nicht als Exception.
import { calculate_from_json_with_token } from "@ferscloud/fers-calculation";
const { token } = await fetch("/api/solve-token").then((r) => r.json());
const res = JSON.parse(
calculate_from_json_with_token(JSON.stringify(myModel), token),
);
if (!res.ok) throw new Error(`${res.error.code}: ${res.error.message}`);
const data = res.result;| Kostenlos | Pro | |
|---|---|---|
| Maximale Stabzahl | 100 | 10,000 |
| Funktion | calculate_from_json | calculate_from_json_with_token |
| Token erforderlich | Nein | Ja |
| Gültigkeit des Tokens | — | 30 Minuten |
Biegelinie
Setzen Sie include_member_deflected_shape in den Analyseoptionen des Modells, um je Stab eine unmittelbar zeichenbare, lastexakte Biegelinie zu erhalten — die globale Verformung des Stabes entlang seiner Länge abgetastet — statt die Kurve selbst zu rekonstruieren.
Sie ist standardmäßig aus, damit die Antwort schlank bleibt, und fehlt in member_results, wenn sie nicht angefordert wurde.
const model = {
/* … model + load cases … */
analysis: {
/* … */
options: {
/* … */
include_member_deflected_shape: true,
},
},
};
const res = JSON.parse(calculate_from_json(JSON.stringify(model)));
const mr = res.result.results.loadcases["…"].member_results["1"];
// mr.member_displacements: [{ x_frac, displacement: [dx, dy, dz] }, …]
// x_frac 0–1 along the member; displacement in the global input frame.Andere Zugänge
- Warum Tragwerke in JavaScript rechnen — die Argumente für einen clientseitigen Solver.
- REST-API — den Solver aus jeder Sprache über HTTP aufrufen.
- MCP-Server — Claude, ChatGPT, Cursor oder VS Code FERS direkt steuern lassen.
- Python-Paket — dieselbe Rechenmaschine aus einem Skript.
Verwandte Seiten
REST-API-Referenz
Jeder SDK-Endpunkt mit Anfrage und Antwort — Anmeldung, Schlüssel, Berechnung, Validierung, Trägernachweis und Modellverwaltung.
Schnellstart: Ihr erstes Modell im Browser
3D-Rahmen im Browser aufbauen und berechnen: Materialien, Querschnitte, Knoten, Auflager, Stäbe, Lasten, Berechnen.
Siehe auch
Häufige Fragen
Brauche ich einen API-Schlüssel, um im Browser zu rechnen?
calculate_from_json funktioniert ohne Schlüssel und ohne Konto für Modelle bis 100 Stäbe. Ein Schlüssel wird nur benötigt, um das Pro-Solve-Token auszustellen.Verlässt das Modell den Browser?
Warum braucht Vite zusätzliche Konfiguration?
await initialisiert. vite-plugin-wasm übernimmt den WebAssembly-Import, und build.target: "esnext" behält dieses await in der Ausgabe — das setzt Chrome, Edge oder Firefox 89+ bzw. Safari 15+ voraus. webpack braucht asyncWebAssembly und asyncFunction in den Experiments- und Output-Einstellungen. Steht vite-plugin-top-level-await noch aus einer früheren Fassung dieser Seite in Ihrer Konfiguration, können Sie es entfernen: mit aktuellen @swc/core-Versionen schlägt damit vite build fehl.Sollte ich den Solver in einem Web Worker ausführen?
Brauche ich einen init()-Aufruf?
await init(); das ist nicht mehr nötig.Was passiert, wenn das Solve-Token abgelaufen ist?
LimitExceeded.Welches Paket nehme ich auf dem Server?
@ferscloud/fers-calculation, gebaut für das Node-Target. Es braucht keine Bundler-Konfiguration und initialisiert sich beim Import selbst.