Ich habe mich in die Codierung verliebt, sobald ich mein erstes CSS: Hover -Effekt erstellt habe. Jahre später führte mich dieser anfängliche Biss in die Interaktivität im Web zu einem neuen Ziel: ein Spiel zu machen.
Diese frühen Momente spielten mit: Hover waren nichts Besonderes oder sogar nützliches. Ich erinnere mich, dass ich ein reaktionsschnelles Gitter aus blauen Quadräten gemacht habe (hergestellt mit Float, wenn Ihnen dies eine Vorstellung von der Zeitleiste gibt), von denen jeder orange wurde, als sich der Cursor über sie bewegte. Ich verbrachte das, was sich wie Stunden anfühlte, die sich über die Kisten machten, das Fenster ändern, um sie zu beobachten, wie sie die Größe und Ausrichtung ändern und dann noch einmal durchführen. Es fühlte sich wie reine Magie an.
Was ich im Internet aufgebaut habe, wurde natürlich komplexer als das Raster von
Manchmal war es nur eine Codepen -Demo; Manchmal war es ein kleines Nebenprojekt, das auf Vercel oder Netlify eingesetzt wurde. Ich mochte die Herausforderung, Spiele wie Farbflut, Hangman oder Vier in einem Browser herzustellen.
Nach einer Weile wurde das Tor jedoch größer: Was wäre, wenn ich ein echtes Spiel gemacht habe? Nicht nur eine Web -App; Ein echtes Live, ehrlich zu Goodness, Download-from-an-App-Store-Spiel. Im vergangenen August habe ich an meinem bisher ehrgeizigsten Projekt gearbeitet und vier Monate später für die Welt veröffentlicht ( lesen: Ich habe es leid, damit zu fummeln ): Eine Word -Spiel -App, die ich Quina nenne.
Der einfachste Weg, Quina zu erklären, ist: Es ist Mastermind, aber mit Fünf-Buchstaben-Wörtern. Tatsächlich ist Mastermind tatsächlich eine Version eines klassischen Pen-and-Paper-Spiels. Quina ist einfach eine weitere Variation desselben Originalspiels.
Das Objekt von Quina ist es, ein geheimes Wort mit fünf Buchstaben zu erraten. Nach jeder Vermutung erhalten Sie einen Hinweis, der Ihnen sagt, wie nahe Ihre Vermutung am Codewort liegt. Sie verwenden diesen Hinweis, um Ihre nächste Vermutung und so weiter zu verfeinern, aber Sie erhalten nur zehn Vermutungen. renn raus und du verlierst.
Der Name "Quina" kam zustande, weil er in Latein "fünf gleichzeitig" bedeutet (oder so sagte es mir sowieso Google). Das traditionelle Spiel wird normalerweise mit Wörtern mit vier Buchstaben oder manchmal vier Ziffern (oder im Fall von Mastermind, vier Farben) gespielt. Quina verwendet Fünf-Buchstaben-Wörter ohne wiederholte Buchstaben, so dass es passend war, dass das Spiel einen Namen haben sollte, der nach seinen eigenen Regeln spielt. (Ich habe keine Ahnung, wie das ursprüngliche lateinische Wort ausgesprochen wurde, aber ich sage es "Quinn-ah", was wahrscheinlich falsch ist, aber hey, es ist mein Spiel, oder?)
Ich verbrachte meine Abende und Wochenenden im Laufe von ungefähr vier Monaten auf und baute die App. Ich möchte diesen Artikel damit verbringen, über die Technologie hinter dem Spiel, die Entscheidungen und die Lektionen zu sprechen, falls dies eine Straße ist, die Sie selbst entlang reisen möchten.
Ich bin ein großer Fan von Vue und wollte dieses Projekt nutzen, um mein Wissen über sein Ökosystem zu erweitern. Ich überlegte, ob ich ein anderes Framework verwendet habe (ich habe auch Projekte in Svelte und React gebaut), aber ich hatte das Gefühl, dass Nuxt den Sweet Spot der Vertrautheit, die Benutzerfreundlichkeit und die Reife erreichte. (Übrigens, wenn Sie nicht wussten oder nicht erraten hätten: Nuxt könnte als Vue -Äquivalent von Next.js.
Ich war zuvor nicht zu tief mit Nuxt gegangen. Nur ein paar sehr kleine Apps. Aber ich wusste, dass Nuxt zu einer statischen App kompilieren kann, genau das, was ich wollte - keine (Knoten-) Server, über die ich mir Sorgen machen musste. Ich wusste auch , dass Nuxt das Routing genauso leicht verarbeiten könnte wie das Ablegen von Vue -Komponenten in einen Ordner mit einem Pages, was sehr ansprechend war.
Obwohl Vuex (das offizielle Staatsmanagement in Vue) für sich selbst nicht besonders komplex ist, schätzte ich die Art und Weise, wie Nuxt nur ein bisschen Zucker hinzufügt, um es noch einfacher zu machen. (Nuxt erleichtert übrigens auf verschiedene Weise, z. B. wenn Sie nicht erforderlich sind, Ihre Komponenten explizit zu importieren, bevor Sie sie verwenden können. Sie können sie einfach in den Markup einfügen, und Nuxt wird es herausfinden und nach Bedarf automatisch importiert.)
Schließlich wusste ich im Voraus, dass ich eine progressive Web -App (PWA) errichtete. Tatsächlich gibt es eine beeindruckende Reihe von Nuxt -Modulen für unsichtbare Hürden. Das machte Nuxt die einfachste und offensichtlichste Wahl, und eine, die ich nie bereut habe.
Am Ende habe ich mehr Module verwendet, einschließlich des Stern -Nuxt -Inhaltsmoduls, mit dem Sie Seiteninhalte in Markdown oder sogar eine Mischung aus Markdown- und VUE -Komponenten schreiben können. Ich habe diese Funktion für die Seite "FAQs" und die Seite "Wie zum Spielen" auch verwendet (da das Schreiben in Markdown so viel schöner ist als hartcodierende HTML-Seiten).
Quina würde irgendwann ein Zuhause im Google Play Store finden, aber unabhängig davon, wie oder wo es gespielt wurde, wollte ich, dass es von Anfang an eine vollwertige App anfühlt .
Zu Beginn bedeutete dies einen optionalen dunklen Modus und eine Einstellung, um die Bewegung für eine optimale Benutzerfreundlichkeit zu verringern, wie es viele native Apps haben (und im Fall von reduzierter Bewegung, wie alles mit Animationen haben sollte ).
Unter der Haube sind beide Einstellungen letztendlich Booleschen im Vuex -Datenspeicher der App. Wenn die Einstellung wahr ist, macht die Einstellung eine bestimmte Klasse im Standardlayout der App. Nuxt -Layouts sind VUE -Vorlagen, die alle Ihre Inhalte „einwickeln“ und auf allen (oder vielen) Seiten Ihrer App (üblicherweise für gemeinsame Header und Fußzeilen verwendet, aber auch für globale Einstellungen nützlich): häufig verwendet):
<semplate> <div :> <nuxt></nuxt> </div> <script> Importieren Sie {MAPTERTERS} aus 'Vuex' ' Standard ausführen { berechnet: { ... MAPTERTERS (['DarkMode', 'Reducemotion']), }, // Andere Layoutkomponentencode hier } </script></semplate>
Apropos Einstellungen: Obwohl die Web -App in verschiedene Seiten aufgeteilt ist - Menü, Einstellungen, Über, Spielen usw. -, hilft der gemeinsame globale Vuex -Datenspeicher dazu, die Dinge synchron zu halten und sich zwischen den Bereichen der App nahtlos zu fühlen (da der Benutzer seine Einstellungen auf einer Seite anpasst und sie für das Spiel auf einer anderen anpasst).
Jede Einstellung in der App wird auch sowohl mit LocalStorage als auch im Vuex Store synchronisiert, wodurch das Speichern und Laden von Werten zwischen den Sitzungen angezeigt wird, um die Einstellungen als Benutzer zwischen den Seiten zu verfolgen.
Und wenn ich von der Navigation spreche: Der Umzug zwischen den Seiten ist ein weiterer Bereich, in dem ich das Gefühl hatte, dass es eine Menge Gelegenheit gab, Quina wie eine native App zu fühlen, indem sie ganzseitige Übergänge hinzufügen.
VUE-Übergänge sind im Allgemeinen ziemlich einfach-Sie schreiben nur speziell benannte CSS-Klassen für Ihre "To" und "aus" Übergangszuständen-, aber Nuxt geht noch einen Schritt weiter und ermöglicht Ihnen, die vollständigen Seitenübergänge mit nur einer einzelnen Zeile in der VUE-Datei einer Seite festzulegen:
<script> Standard ausführen { Übergang: 'Page-Slide' // ... der Rest der Komponenteneigenschaften } </script>
Diese Übergangseigenschaft ist mächtig; Es wird von Nuxt wissen, dass wir den auf diese Seite angewendeten Seitenübergang angewendet haben, wenn wir zu ihm navigieren oder weg von ihm. Von dort aus müssen wir nur die Klassen definieren, die mit der Animation umgehen, wie Sie es bei jedem Vue -Übergang tun würden. Hier ist mein Seiten-Slide-SCSS:
/ * assets/css/_animations.scss *// .PAGE-SLIDE { & -enter-active { Übergang: Alle 0,35s Cubic-Bezier (0, 0,25, 0, 0,75); } & -leave-aktiv { Übergang: Alle 0,35s Cubic-Bezier (0,75, 0, 1, 0,75); } &-eingeben, & -leave-to { Deckkraft: 0; Transformation: Translatey (1REM); .Reduce-Motion & { Transformation: Keine! Wichtig; } } & -leave-to { Transformation: Translatey (-1rem); } }
Beachten Sie die .Reduce-Motion-Klasse; Darüber haben wir in der Layout -Datei genau darüber gesprochen. Es verhindert eine visuelle Bewegung, wenn der Benutzer angegeben hat, dass er reduzierte Bewegungen (entweder über Medienabfrage oder manuelle Einstellung) bevorzugen, indem sie alle Transformationseigenschaften deaktivieren (die die Verwendung der Spaltungsflagge zu rechtfertigen schienen). Die Opazität darf jedoch immer noch ein- und ausblenden, da dies nicht wirklich Bewegung ist.
Randnotiz zu Übergängen und Handhabung 404Ss: Die Übergänge und Routing werden natürlich von JavaScript unter der Haube behandelt (um genau zu sein), aber ich stieß auf ein frustrierendes Problem, bei dem Skripte auf Leerlaufseiten aufhören würden (z. Wenn Vue Router auf diese Leerlaufseiten zurückkehrt und auf einen Link klickt, hätte er nicht mehr ausgeführt, und der Link würde so als relativ und 404 behandelt.
Beispiel: Die Seite /FAQ geht im Leerlauf; Der Benutzer kommt darauf zurück und klickt auf den Link, um die Seite /Optionen zu besuchen. Die App würde versuchen, zu /FAQ /Optionen zu gehen, was natürlich nicht existiert.
Meine Lösung dafür war eine benutzerdefinierte Fehlerseite .
// layouts/error.vue montiert () { const lastPage = '/' this. $ route.fullpath.split ('/'). pop () // Erstellen Sie keine Weiterleitungsschleife if (lastPage! == this. $ route.fullpath) { this. $ router.push ({{ Pfad: LastPage, }) } }
Dies funktionierte für meinen Anwendungsfall, weil a) ich keine verschachtelten Routen habe. und b) am Ende, wenn der Pfad nicht gültig ist, trifft er immer noch einen 404.
Übergänge sind nett, aber ich wusste auch, dass Quina ohne native App - insbesondere auf einem Smartphone - ohne Vibration und Sound - nicht fühlen würde.
Die Vibration ist heutzutage dank der Navigator -API in den Browsern relativ leicht zu erreichen. In den meisten modernen Browsern können Sie einfach Fenster anrufen.
Offensichtlich möchten Sie aus mehreren Gründen Schwingung sparsam verwenden. Erstens, weil zu viel leicht zu einer schlechten Benutzererfahrung werden kann. Und zweitens, da nicht alle Geräte/Browser es unterstützen, müssen Sie sehr vorsichtig sein, wie und wo Sie versuchen, die Funktion Vibrate () aufzurufen, damit Sie einen Fehler verursachen, der das aktuell ausgeführte Skript abschaltet.
Persönlich war meine Lösung, einen Vuex -Getter festzulegen, um zu überprüfen, ob der Benutzer eine Vibration zulässt (er kann von der Seite "Einstellungen" deaktiviert werden). dass der aktuelle Kontext der Client ist, nicht der Server; Und schließlich, dass die Funktion im aktuellen Browser existiert. (ES2020 Optionales Ketten hätte auch hier für diesen letzten Teil gearbeitet.)
// store/gentters.js Vibration (Zustand) { Wenn ( process.client && state.options.vibration && typeof window.navigator.vibrate! == 'undefined' ) { RECHT WAHR } Return falsch },
Randnotiz: Überprüfung auf den Prozess.client ist in Nuxt wichtig - und viele andere Frameworks mit Code, die auf dem Knoten ausgeführt werden können -, da es nicht immer ein Fenster gibt. Dies gilt auch dann, wenn Sie Nuxt im statischen Modus verwenden, da die Komponenten während der Build -Zeit im Knoten validiert werden. Process.client (und sein Gegenteil process.server) sind Nuxt-Nippen, die nur die aktuelle Umgebung des Codes zur Laufzeit validieren, sodass sie perfekt zum Isolieren von Browser-Code isolieren.
Sound ist ein weiterer wichtiger Teil der Benutzererfahrung der App. Anstatt meine eigenen Effekte zu erzielen (was zweifellos Dutzende mehr Stunden in das Projekt hinzugefügt hätte), mischte ich Beispiele von einigen Künstlern, die besser wissen, was sie in diesem Bereich tun, und die einige kostenlose Spielgeräusche online anbot. (Siehe FAQ S der App für vollständige Informationen.)
Benutzer können die von ihnen bevorzugte Lautstärke festlegen oder den Sound vollständig ausschalten. Dies und die Vibration sind auch im Browser des Benutzers in LocalStorage festgelegt und mit dem Vuex -Store synchronisiert. Dieser Ansatz ermöglicht es uns, eine im Browser gespeicherte „permanente“ Einstellung festzulegen, ohne jedoch jedes Mal, wenn er verwiesen wird, aus dem Browser abzurufen. (Klang beispielsweise, überprüfen Sie beispielsweise jedes Mal, wenn man gespielt wird, und die Latenz, jedes Mal auf einen LocalStorage -Anruf zu warten, um die Erfahrung zu töten.)
Es stellt sich heraus, dass Safari aus irgendeinem Grund extrem verzerrt ist, wenn es um Klang geht. Alle Klicks, Boops und Dings würden nach dem Ereignis, das sie ausgelöst hat, um tatsächlich in Safari zu spielen, insbesondere auf iOS, spürbar. Das war ein Deal-Breaker und ein Kaninchenloch, das ich viel Stunden damit verbrachte, verzweifelt abzustimmen.
Glücklicherweise habe ich eine Bibliothek namens Howler.js gefunden, die plattformübergreifende Klangprobleme ganz einfach löst (und auch ein lustiges kleines Logo). Das einfache Installieren von Heuler als Abhängigkeit und Ausführen aller Sounds der App - im Grunde genommen ein oder zwei Codezeilen - reichte aus, um das Problem zu lösen.
Wenn Sie eine JavaScript -App mit synchronem Sound erstellen, würde ich die Verwendung von Howler wärmstens empfehlen, da ich keine Ahnung habe, was Safaris Problem war oder wie Howler es löst. Nichts, was ich ausprobiert habe, habe funktioniert, also bin ich froh, dass das Problem einfach mit sehr wenig Overhead- oder Code -Änderung gelöst wird.
Quina kann ein schwieriges Spiel sein, insbesondere zunächst. Es gibt also einige Möglichkeiten, die Schwierigkeit des Spiels an Ihre persönliche Präferenz anzupassen:
Diese Einstellungen ermöglichen es Spielern verschiedener Fähigkeiten, Alter und/oder Englischkenntnisse, das Spiel auf eigene Faust zu spielen. (Ein grundlegendes Wort mit starken Hinweisen wäre am einfachsten; schwierig oder zufällig ohne Hinweise wäre am schwierigsten.)
Während einfach eine Reihe von einmaligen Spielen mit verstellbarer Schwierigkeitsgrad genügend genug sein würde, fühlt sich dies eher wie eine Standard-Web-App oder -Mo-Demo als ein echtes, vollwertiges Spiel an. In Übereinstimmung mit dem Streben nach diesem nativen App -Gefühl verfolgt Quina Ihre Spielgeschichte, zeigt Ihre Spielstatistik auf verschiedene Arten und bietet mehrere „Auszeichnungen“ für verschiedene Erfolge.
Unter der Motorhaube wird jedes Spiel als Objekt gespeichert, das ungefähr so aussieht:
{ Vermutet: 3, Schwierigkeit: 'Tricky', Gewinn: wahr, Hinweis: 'Keine', }
Die App katalogisiert Ihre Spiele (erneut über Vuex State, die mit LocalStorage synchronisiert wurden) in Form eines GameHistory -Arrays von Spielobjekten, mit denen die App dann Ihre Statistiken anzeigt - wie Ihr Gewinn/Verlust -Verhältnis, wie viele Spiele Sie gespielt haben, und Ihre durchschnittlichen Vermutungen - und Ihre Fortschritte in Richtung des Spiels des Spiels zu zeigen.
Dies alles ist leicht genug mit verschiedenen Vuex -Gettern, von denen jede JavaScript -Array -Methoden wie .Filter () und .Reduce () auf dem GameHistory -Array verwendet. Dies ist beispielsweise der Getter, der zeigt, wie viele Spiele der Benutzer gewonnen hat, während er in der „schwierigen“ Einstellung gespielt hat:
// store/gentters.js trickyGameswon (Zustand) { return state.gamehistory.filter ( (game) => game.win && game.difficulty === 'tricky' ).Länge },
Es gibt viele andere Gitter unterschiedlicher Komplexität. (Die eine, die die längste Siegesserie des Benutzers ermittelt hat, war besonders knorrig.)
Das Hinzufügen von Auszeichnungen war eine Frage der Erstellung einer Reihe von Auszeichnungsobjekten, die jeweils an einen bestimmten Vuex Getter gebunden waren, und jeweils eine Anforderung. Die STREDShold -Eigenschaft zeigt an, wann diese Auszeichnung freigeschaltet wurde (dh, wann der vom Getter zurückgegebene Wert hoch genug war). Hier ist ein Beispiel:
// Assets/JS/Awards.js Standard ausführen [ { Titel: 'Onset', Erfordernis: { Getter: 'Totalgamesspiel', Schwelle: 1,, Text: "Spielen Sie Ihr erstes Spiel von Quina", } }, { Titel: 'Sharp',, Erfordernis: { Getter: 'TrickyGameswon', Schwelle: 10,, Text: "Gewinnen Sie zehn Spiele auf Tricky", }, }, ]
Von dort aus ist es eine ziemlich einfache Angelegenheit, die Erfolge in einer VUE -Vorlagendatei über die endgültige Ausgabe zu schieben, um die Eigenschaft der Anforderungen zu erhalten.
Insgesamt gibt es 25 Auszeichnungen (das sind 5 × 5, entsprechend dem Thema) für verschiedene Erfolge wie das Gewinnen einer bestimmten Anzahl von Spielen, das Ausprobieren aller Spielmodi oder sogar das Gewinnen eines Spiels innerhalb Ihrer ersten drei Vermutungen. (Dieser nennt man „Glück“ - als zusätzliches kleines Osterei ist der Name jeder Auszeichnung auch ein potenzielles Codewort, dh fünf Buchstaben ohne Wiederholungen.)
Das Entsperren von Auszeichnungen macht nichts außer Ihnen prahlerischen Rechte, aber einige von ihnen sind ziemlich schwer zu erreichen. (Ich habe ein paar Wochen gebraucht, nachdem ich sie alle befreit hatte!)
Die Strategie „Einmal, überall einsetzen“ viel zu lieben, aber es kommt auch mit einigen Nachteilen:
Es gibt eine Menge Technologie, die das Versprechen „Build for the Web, Release Everywhere“ - React Native, Cordova, Ionic, Meteor und Nativescript, um nur einige zu nennen.
Im Allgemeinen sind diese auf zwei Kategorien zurückzuführen:
Der erste Ansatz scheint der wünschenswertere der beiden zu sein (da Sie am Ende theoretisch eine „echte“ native App enden), aber ich stellte auch fest, dass er die größten Hürden mit sich bringt. Jede Plattform oder jedes Produkt verlangt, dass Sie ihre Art und Weise lernen, Dinge zu tun, und diese Weise ist ein ganzes Ökosystem und ein ganzer Rahmen für sich selbst. Das Versprechen, „nur zu schreiben, was Sie wissen“, ist eine ziemlich starke Überbeanspruchung meiner Erfahrung. Ich würde in ein oder zwei Jahren vermuten, dass viele dieser Probleme gelöst werden, aber im Moment spüren Sie immer noch eine beträchtliche Lücke zwischen dem Schreiben von Webcode und dem Versand einer nativen App.
Andererseits ist der zweite Ansatz aufgrund einer Sache, die als „TWA“ bezeichnet wird, lebensfähig, was es möglich macht, eine Website zu einer App zu machen.
TWA steht für vertrauenswürdige Webaktivitäten - und da diese Antwort wahrscheinlich überhaupt nicht hilfreich ist, lassen Sie uns das ein bisschen mehr aufschlüsseln, oder?
Eine TWA -App verwandelt im Grunde genommen eine Website (oder eine Web -App, wenn Sie Haare teilen möchten) mit Hilfe eines kleinen UI -Tricks in eine native App.
Sie könnten sich eine TWA -App als in Verkleidung als Browser vorstellen . Es ist eine Android -App ohne Interna, außer einem Webbrowser. Die TWA-App wird auf eine bestimmte Web-URL hingewiesen, und wenn die App gebootet ist, anstatt normale native Apps zu machen, wird diese Website stattdessen nur geladen-Vollbild, ohne Browser-Steuerelemente, wodurch die Website effektiv aussehen und sich so verhalten würde, als wäre sie eine vollwertige native App.
Es ist leicht zu erkennen, dass die Aufnahme einer Website in einer nativen App einbezogen wird. Es ist jedoch nicht nur eine alte Website oder eine URL -Qualifikation; Um Ihre Website/App als TWA -native App zu starten, müssen Sie die folgenden Kästchen überprüfen:
In diesem letzten Punkt kommt der „vertrauenswürdige“ Teil ins Spiel; Eine TWA -App überprüft ihren eigenen Schlüssel und vergewissern Sie sich dann, dass der Schlüssel in Ihrer Web -App mit ihr übereinstimmt, um sicherzustellen, dass sie die richtige Website lädt (vermutlich, um eine böswillige Entführung von App -URLs zu verhindern). Wenn der Schlüssel nicht übereinstimmt oder nicht gefunden wird, funktioniert die App weiterhin, aber die TWA -Funktionalität wird weg sein. Es wird einfach die Website in einem einfachen Browser, Chrom und allem geladen. Der Schlüssel ist daher äußerst wichtig für die Erfahrung der App. (Man könnte sagen, es ist ein Schlüsselteil . Tut mir leid nicht tut mir leid.)
Der Hauptvorteil einer TWA -App besteht darin, dass Sie Ihren Code überhaupt nicht ändern müssen - kein Framework oder keine Plattform zum Lernen. Sie erstellen nur eine Website/Web -App wie normal, und sobald Sie das erledigt haben, haben Sie im Grunde genommen auch den App -Code erledigt.
Der Hauptnachteil ist jedoch, dass Apple (obwohl sie dazu beiträgt, das moderne Zeitalter des Webs und JavaScripts zu erlernen) nicht für TWA -Apps. Sie können sie nicht im Apple App Store auflisten. Nur Google Play.
Dies mag nach einem Deal-Breaker klingen, aber denken Sie an ein paar Dinge:
An diesem Punkt könnten Sie sagen, dass dieses TWA -Geschäft gut und gut klingt, aber wie nehme ich meine Website/App tatsächlich und schiebe es in eine Android -App?
Die Antwort kommt in Form eines schönen kleinen CLI -Werkzeugs namens Bubblewrap.
Sie können sich BubbleWrap als ein Tool vorstellen, das einige Eingaben und Optionen von Ihnen nimmt und eine Android -App (insbesondere eine APK, eines der vom Google Play Store zugelassenen Dateiformate) aus der Eingabe generiert.
Die Installation von BubbleWrap ist etwas schwierig, und obwohl es nicht ganz Plug-and-Play verwendet wird, ist es definitiv weit mehr in Reichweite für einen durchschnittlichen Front-End-Entwickler als alle anderen vergleichbaren Optionen, die ich gefunden habe. Die Readme -Datei auf der NPM -Seite von Bubblewrap geht in die Details ein, aber als kurze Übersicht:
Installieren Sie BubbleWrap, indem Sie NPM I -g @Bubblewrap/CLI ausführen (ich gehe davon aus, dass Sie hier mit NPM vertraut sind und Pakete über die Befehlszeile daraus installieren). Auf diese Weise können Sie Bubblewrap überall verwenden.
Sobald es installiert ist, werden Sie ausgeführt:
Bubblewrap Init-Manifest https: //your-webapp-domain/manifest.json
Hinweis: Die Datei Manifest.json ist von allen PWAs verlangt, und Bubblewrap benötigt die URL für diese Datei, nicht nur für Ihre App. Auch gewarnt: Je nachdem, wie Ihre Manifestdatei generiert wird, kann sein Name für jeden Build eindeutig sein. (Das PWA -Modul von Nuxt findet beispielsweise eine eindeutige UUID an.)
Beachten Sie auch, dass BubbleWrap standardmäßig bestätigt, dass Ihre Web -App als Teil dieses Prozesses eine gültige PWA ist. Als ich diesen Prozess durchlief, kam der Scheck aus irgendeinem Grund immer wieder negativ zurück, obwohl Leuchtturm bestätigte, dass es sich tatsächlich um eine voll funktionsfähige progressive Web -App handelte. Glücklicherweise ermöglicht BubbleWrap mit der Flagge -skippwavalidationsflagge diese Prüfung.
Wenn Sie BubbleWrap zum ersten Mal verwenden, werden Sie gefragt, ob Sie das Java Development Kit (JDK) und das Android Software Development Kit (SDK) für Sie installieren möchten. Diese beiden sind die Dienstprogramme hinter den Kulissen, die erforderlich sind, um eine Android-App zu generieren. Wenn Sie sich nicht sicher sind, schlagen Sie "Y" für Ja.
Hinweis: BubbleWrap erwartet, dass diese beiden Entwicklungskits an sehr bestimmten Orten existieren und nicht richtig funktionieren, wenn sie nicht da sind. Sie können Bubblewrap -Arzt ausführen, um zu überprüfen, oder die vollständige Bubblewrap CLI Readme sehen.
Nachdem alles installiert wurde - vorausgesetzt, es findet Ihre Manifest.json -Datei bei der bereitgestellten URL - wird BubbleWrap einige Fragen zu Ihrer App stellt.
Viele der Fragen sind entweder Präferenz (wie die Hauptfarbe Ihrer App) oder nur die grundlegenden Details (wie die Domäne und der Einstiegspunkt für die App) zu bestätigen, und die meisten werden aus der Manifestdatei Ihrer Website vorgefüllt.
Weitere Fragen, die möglicherweise bereits von Ihrem Manifest vorgefüllt werden, sind, wo Sie die verschiedenen Symbole Ihrer App finden (um als Startbildschirmsymbol, Status-Balken-Symbol usw. zu verwenden). Welche Farbe der Scheinsbildschirm sein sollte, während die App öffnet, und die Bildschirmausrichtung der App, falls Sie Porträt oder Landschaft erzwingen möchten. BubbleWrap fragt auch, ob Sie die Berechtigung für die Geolokalisierung Ihres Benutzers anfordern möchten und ob Sie sich für die Spielabrechnung entscheiden.
Es gibt jedoch einige wichtige Fragen, die möglicherweise ein wenig verwirrend sein können. Lassen Sie uns diese hier abdecken:
Das letzte Stück des Puzzles ist der Signaturschlüssel. Dies ist der wichtigste Teil . Dieser Schlüssel verbindet Ihre progressive Web -App mit dieser Android -App. Wenn der Schlüssel, den die App erwartet, nicht zu dem übereinstimmt, was in Ihrer PWA zu finden ist: Ihre App funktioniert weiterhin, sieht jedoch nicht wie eine native App aus, wenn der Benutzer sie öffnet. Es wird nur ein normales Browserfenster sein.
Hier gibt es zwei Ansätze, die im Detail etwas zu komplex sind, aber ich werde versuchen, einige Hinweise zu geben:
Für die Option, die Sie auswählen, gibt es hier eine ausführliche Dokumentation über die App-Unterzeichnung (geschrieben für Android-Apps, aber das meiste davon ist immer noch relevant).
Der Teil, an dem Sie den Schlüssel auf Ihre persönliche Website erhalten, finden Sie in dieser Anleitung zur Überprüfung von Android -App -Links. Um zusammenfassen: Google sucht nach A /.well-Bekannt/Assetlinks.json-Datei auf diesem Weg auf Ihrer Website. Die Datei muss sowohl Ihren einzigartigen Schlüssel -Hash als auch einige andere Details enthalten:
[{{{ "Beziehung": ["Delegate_permission/Common.handle_all_urls"], "Ziel": {"Namespace": "android_app", "package_name": "your.app.id", "SHA256_CERT_FINGERPRINTS": ["Your: Einzigartig: Hash: Hier"]} }]
Bevor Sie anfangen, gibt es auch einige Hürden, die Sie auf der App Store -Seite der Dinge bewusst sind:
While my goal with Quina was mostly personal — challenge myself, prove I could, and learn more about the Vue ecosystem in a complex real-world app — I had also hoped as a secondary goal that my work might be able to make a little money on the side for me and my family.
Not a lot. I never had illusions of building the next Candy Crush (nor the ethical void required to engineer an addiction-fueled micro-transaction machine). But since I had poured hundreds of hours of my time and energy into the game, I had hoped that maybe I could make something in return, even if it was just a little beer money.
Initially, I didn't love the idea of trying to sell the app or lock its content, so I decided to add a simple “would you care to support Quina if you like it?” prompt after every so many games, and make some of the content unlockable specifically for supporters. (Word sets are limited in size by default, and some game settings are initially locked as well.) The prompt to support Quina can be permanently dismissed (I'm not a monster), and any donation unlocks everything; no tiered access or benefits.
This was all fairly straightforward to implement thanks to Stripe, even without a server; it's all completely client-side. I just import a bit of JavaScript on the /support page, using Nuxt's handy head function (which adds items to the
element specifically on the given page):// pages/support.vue Kopf() { zurückkehren { script: [ { hid: 'stripe', src: 'https://js.stripe.com/v3', defer: true, callback: () => { // Adds all Stripe methods like redirectToCheckout to page component this.stripe = Stripe('your_stripe_id') }, }, ], } },
With that bit in place (along with a sprinkle of templating and logic), users can choose their donation amount — set up as products on the Stripe side — and be redirected to Stripe to complete payment, then returned when finished. For each tier, the return redirect URL is slightly different via query parameters. Vue Router parses the URL to adjust the user's stored donation history, and unlock features accordingly.
You might wonder why I'm revealing all of this, since it exposes the system as fairly easy to reverse-engineer. The answer is: I don't care . In fact, I added a free tier myself, so you don't even have to go to the trouble. I decided that if somebody really wanted the unlockables but couldn't or wouldn't pay for whatever reason, that's fine. Maybe they live in a situation where $3 is a lot of money. Maybe they gave on one device already. Maybe they'll do something else nice instead. But honestly, even if their intentions aren't good: so what?
I appreciate support, but this isn't my living, and I'm not trying to build a dopamine tollbooth. Besides, I'm not personally comfortable with the ethical implications of using a stack of totally open-source and/or free software (not to mention the accompanying mountain of documentation, blog posts, and Stack Overflow answers written about all of it) to build a closed garden for personal profit.
So, if you like Quina and can support it: sincerely, thank you . That means a ton to me. I love to see my work being enjoyed. But if not: that's cool. If you want the “free” option, it's there for you.
Anyway, this whole plan hit a snag when I learned about Google Play's new monetization policy, effective this year. You can read it yourself, but to summarize: if you make money through a Google Play app and you're not a nonprofit, you gotta go through Google Pay and pay a hefty fee — you are not allowed to use any other payment provider.
This meant I couldn't even list the app; it would be blocked just for having a “support” page with payments that don't go through Google. (I suppose I probably could have gotten around this by registering a nonprofit, but that seemed like the wrong way to go about it, on a number of levels.)
My eventual solution was to charge for the app itself on Google Play, by listing it for $2.99 (rather than my previously planned price of “free”), and simply altering the app experience for Android users accordingly.
Fortunately enough, Android apps send a custom header with the app's unique ID when requesting a website. Using this header, it was easy enough to differentiate the app's experience on the web and in the actual Android app.
For each request, the app checks for the Android ID; if present, the app sets a Vuex state boolean called isAndroid to true. This state cascades throughout the app, working to trigger various conditionals to do things like hide and show various FAQ questions, and (most importantly) to hide the support page in the nav menu. It also unlocks all content by default (since the user's already “donated” on Android, by purchasing). I even went so far as to make simple
<!-- /src/components/AndroidOnly.vue --> <template> <div v-if="isAndroid"> <slot></slot> </div> </template> <script> export default { computed: { isAndroid() { return this.$store.state.isAndroid }, }, } </script>
For a time while building Quina, I had Firebase set up for logins and storing user data. I really liked the idea of allowing users to play on all their devices and track their stats everywhere, rather than have a separate history on each device/browser.
In the end, however, I scrapped that idea, for a few reasons. One was complexity; it's not easy maintaining a secure accounts system and database, even with a nice system like Firebase, and that kind of overhead isn't something I took lightly. But mainly: the decision boiled down to security and simplicity.
At the end of the day, I didn't want to be responsible for users' data. Their privacy and security is guaranteed by using localStorage, at the small cost of portability. I hope players don't mind the possibility of losing their stats from time to time if it means they have no login or data to worry about. (And hey, it also gives them a chance to earn those awards all over again.)
Plus, it just feels nice. I get to honestly say there's no way my app can possibly compromise your security or data because it knows literally nothing about you. And also, I don't need to worry about compliance or cookie warnings or anything like that, either.
Building Quina was my most ambitious project to date, and I had as much fun designing and engineering it as I have seeing players enjoy it.
I hope this journey has been helpful for you! While getting a web app listed in the Google Play Store has a lot of steps and potential pitfalls, it's definitely within reach for a front-end developer. I hope you take this story as inspiration, and if you do, I'm excited to see what you build with your newfound knowledge.
Das obige ist der detaillierte Inhalt vonWas ich gelernt habe, eine Word -Spiel -App mit Nuxt auf Google Play zu erstellen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!