sudo npm install -g yarn
sudo yarn global add lerna
~/work
~/work
git clone https://adresse.des/reposerory
cd odlux
wechselnlerna bootstrap
npm install -g yarn
yarn global add lerna
c:\work
c:\work
git clone https://git-highstreet-technologies.com/highstreet/odlux.git
cd odlux
wechselnlerna bootstrap
cd framework
webpack.config.js
bearbeitendevServer: { /* ... */ }
suchenproxy
suchen/api
auf http://localhost:3001/api
zeigen soll ist folgen der Eintrag hinzuzufügen, wobei http://localhost:3001
die Addresse des ODL Backends auf dem Computer ist:devServer: { // ... proxy: { "/api": { target: "http://localhost:3001/api", secure: false } } }
apps
-Verzeichnis ebenfalls zu wiederholen.cd framework
yarn run build
für Release oder yarn run build:dev
für Entwicklungsversionyarn start
H> Hinweis: Der Port kann in der Datei webpack.config.js
im Abschitt devServer
unter public
ggf. angepaßt werden.
cd apps/demoApp
yarn run build
für die Erstellung einer Release.yarn start
H> Hinweis: Der Port kann in der Datei webpack.config.js
im Abschitt devServer
unter public
ggf. angepaßt werden.
T> Profitip: In der Datei index.html
befindet sich der Aufruf zum laden der einzelnen Apps. Hier könnnen weitere Apps hinzugefügt werden. Dazu ist es allerdings erforderlich entsprechende Proxy Regeln für den Webpack-Dev-Server mit den jeweiligen Pfaden zu erstellen, so dass die Module gefunden werden können.
Zur Zeit gibt es noch keine automatisierte Schablone oder Maven Artefakt Vorlage, die automatisch eine neue Anwendung erstellt. Aus diesem Grund ist der einfachste Weg, die Muster App demoApp
unter apps
zu kopieren.
Anschließend sind die folgenden Anpassungen vorzunehmen.
packages.json
anpassen : "name": "@odlux/demo-app",
H> Hinweis: Anstelle von Großbuchstaben nur Bindestrich Buchstabe verwenden. demoApp wird zu demo-app.webpack.config.js
prüfen ob alle Backend Pfade koniguriert sind (siehe Anpassen der lokalen Umgebung)./plugin.tsx
).entry: { demoApp: ["./plugin.tsx"] },H> Hinweis: Keine Bindesriche oder Sonderzeichen verwenden.
plugin.tsx
.index.html
ist das zu ladende Module (demoApp
) auszutauschen, gegen das eigene Modul:// run the application require(["app","demoApp"], function (app) { app("./app.tsx") });H> Hinweis: Der Name dieses Modules wurde in Schritt 3. festgelgt.
Die Konfiguration der neuen App erfolgt innerhalb der Einstiegsdatei(default: plugin.tsx
). Hier wird der eindeutige Name, das Icon, der Titel der Menueintrag usw. festgelegt.
Icon aus der Bibliothek fontawsome 5
auswählen.
import { faAddressBook } from '@fortawesome/free-solid-svg-icons';
Anpassen der Registration der App in der Einstiegsdatei.
Der eindeutige Name wird vom Framework verwendet, um die Apps voneinander zu unterscheiden. Das Icon wird für die Navigation und die Title-Leiste genutzt. Die Root-Komponente ist die äußrste Komponente dieser App. Der Menu-Eintrag ist optional um einen Namen für dieser App in der Navigation darzustellen.
applicationManager.registerApplication({ name: "demoApp", // eindeutiger Name der App icon: faAddressBook, // Icon der App rootComponent: FinalApp, // Wurzelkomponente der App menuEntry: "Demo App" // Menu Eintrag });
Wenn diese Application einen eigenen Action-Handler enthällt, so ist dieser ebenfalls zu konfigurieren. Die Erstellung von Action Handlern wird ein einem Seperatem Abschitt genauer betrachtet.
applicationManager.registerApplication({ // ... rootActionHandler: demoAppRootHandler, });
Wenn diese Application eigene Komponenten für andere Apps bereit stellen soll, so sind diese auch zu konfigurieren. Dabei ist der Schlüssel der Name mit dem später auf die Komponete zugegriffen werden kann, sowie der Wert die zu exportierende Komponente.
applicationManager.registerApplication({ // ... exportedComponents: { counter: Counter }, });
Optional kann ein Pfad angegeben werden unter dem die App ereicht werden soll. Wird dieser nicht festgelegt wird der Name als Pfad genutzt.
applicationManager.registerApplication({ // ... path: "demoApp", });
Hier können z.B. URL-Parameter spezififiert werden, die der App übergeben werden sollen.
applicationManager.registerApplication({ // ... path: "demoApp/:param1", });
RouteComponentProps
der AppProps
mit anzugeben.// Beispiel ohne Parameter type AppProps = RouteComponentProps & Connect; // Beispiel mit einem Parameter type AppProps = RouteComponentProps<{ param1: number }> & Connect;
const App = (props: AppProps) => ( <Switch> <Route exact path={ `${ props.match.path }/authors` } component={AuthorsList} /> <Route path={ `${ props.match.path }/authors/:authorId` } component={EditAuthor } /> <Redirect to={ `${ props.match.path }/authors` } /> </Switch> );
withRouter
mit dem Router zu verbinden.const FinalApp = withRouter(connect()(App));
Alle Datenmodelle, die innerhalb dieser App verwendet werden sollen werden innerhalb des Ordners models
bzw. in einem Unterordner in diesem Ordner erstellt. Beispiel: Author
für die Darstellen von Autoren.
/** * Represents an author. */ export interface IAuthor { /** * Defines the unique id of the autor. */ id: number; /** * Defines the first name of this author. */ firstName: string; /** * Defines the last name of this author. */ lastName: string; }
Alle Dienste die diese App verwenden soll liegen in dem Ordner services
oder einem darin befindlichem Unterordner. In der Aktuellen Version werden Dienste als Singleton erstellt. Dazu exportiert die Datei mit der Implementierung eine einzelne Instanz als default
.
class AuthorService { // ... } // return as a singleton export const authorService = new AuthorService(); export default authorService;
Jede Application kann einen Root-State
definieren, der alle Zustände speziell für diese App repräsentiert. Dieser sollte als Schnittstelle definiert werden mit dem Namen der sich aus IAppNameStoreState zusammensetzt. Für die demoApp
würde dieser also IDemoAppStoreState
heißen.
export interface IDemoAppStoreState { listAuthors: IListAuthors; editAuthor: IEditAuthor; }
Es bietet sich an, diesesn StoreState innerhalb der Datei mit dem Root-Action-Handler
zu erstellen. Der Name sieser Datei sollte aich wie folgt zusammen setzen appNameRootHandler.ts im Verzeichnis handlers
. Für die demoApp
wäre das demoAppRootHandler.ts
.
Um mit der Typesicherheit von TypeScript auf den Gesamt-Anwendugs-Zustand korreckt zugreifen zu können, ist es erforderlich diesen innerhalb dieser Datei, um den Anwendungszustand der App wie folgt zu erweitern.
declare module '../../../../framework/src/store/applicationStore' { interface IApplicationStoreState { demoApp: IDemoAppStoreState } }
Sollte sich der Zusatand der App aus mehreren ActionHandlern zusammensetzen, so sind diese vor dem exportieren zu verbinden mit der Funktion combineActionHandler
des Frameworks.
const actionHandlers = { listAuthors: listAuthorsHandler, editAuthor: editAuthorHandler, }; export const demoAppRootHandler = combineActionHandler <IDemoAppStoreState>(actionHandlers); export default demoAppRootHandler;
Das O-D-L-UX Framework unterscheidt in Bibliotheken, die nur einer einzelnen App zugeordnet werden. Diese können nicht mit anderen Apps geteilt werden und müssen in jeder App seperat installiert werden. Was zur Folge hat, dass diese auch in dem Bundle jeder App enthalten sind.
Sowie Bibliotheken, die zwischen alle Apps geteilt werden. Diese müssen nicht in jeder App installiert werden und sind auch nur einmal in dem Bundle des Frameworks vorhanden.
Beispiele für geteilte Bibliotheken sind react
, react-dom
, jQuery
oder lodash
. Diese Bibliothek wird zunächst den Abhägnigkeiten der übergeordneten package.json
Datei (im Root-Verzeichnis von O-D-L-UX) im Abschnitt dependencies
hinzugefügt.
"dependencies": { "@types/react": "16.4.14", "@types/react-dom": "16.0.8", "@types/react-router-dom": "4.3.1", "@material-ui/core": "3.1.1", "@material-ui/icons": "3.0.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", "jquery": "3.3.1", "react": "16.5.2", "react-dom": "16.5.2", "react-router-dom": "4.3.1", "@fortawesome/react-fontawesome": "0.1.3", "@fortawesome/fontawesome-svg-core": "1.2.4", "@fortawesome/free-solid-svg-icons": "5.3.1", "jsonwebtoken": "8.3.0", "@types/jsonwebtoken": "7.2.8" },
Anschließend werden die Abhägigkeiten, die jeweils für das Framework und/oder die App erforderlich sind in die package.json
Datei des Frameworks bzw. der App in den Abschitt peerDependencies
übernommen, die jeweils von den geteilten Abhänigkeiten erforderlich sind.
"peerDependencies": { "@types/react": "16.4.14", "@types/react-dom": "16.0.8", "@types/react-router-dom": "4.3.1", "@material-ui/core": "3.1.1", "@material-ui/icons": "3.0.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", "jquery": "3.3.1", "react": "16.5.2", "react-dom": "16.5.2", "react-router-dom": "4.3.1" }
Nachdem ALLE erforderlichen Apps und das Framework mit der neuen Abhägnigkeit konfiguiert wurden wird der Befehl: lerna bootstrap
ausgeführt, um die Abhägigkeiten herunter zu laden und bereit zu stellen für die Apps sowie das Framework.
Wenn eine App eine Bibiotjek verwenden solle, diese aber nicht mit den anderen Apps teilen soll, so ist diese Abhägigkeit nur in die package.json
Datei des App in dem Abschnitt dependencies
einzufügen.
"dependencies": { "object-assign": "3.2.1" }
Auch in diesem Fall ist lerna bootstrap
im Root-Verzeichnis von O-D-L-UX auszuführen.
Eigene Bibliotheken können in einem jeweils in einem seperatem Projekt-Ordner unterhalb des lib
Ordners entwickelt werden.