Maison > interface Web > tutoriel CSS > Ce que j'ai appris en créant une application de jeu de mots avec Nuxt sur Google Play

Ce que j'ai appris en créant une application de jeu de mots avec Nuxt sur Google Play

Christopher Nolan
Libérer: 2025-03-24 10:00:17
original
812 Les gens l'ont consulté

Ce que j'ai appris en créant une application de jeu de mots avec Nuxt sur Google Play

Je suis tombé amoureux du codage au moment où j'ai créé mon premier effet CSS: Hover. Des années plus tard, cette piqûre initiale dans l'interactivité sur le Web m'a conduit à un nouvel objectif: faire un jeu.

Table des matières

  • Quel est le jeu (et quel est ce nom)?
  • Choisir Nuxt
  • Atteindre la sensation d'application native avec le Web
  • Vibration et son
    • Un côté de côté sur le son
  • Gameplay, histoire et récompenses
  • Pour les avantages et les inconvénients de cette approche
    • Pros
    • Inconvénients
  • Logistique: transformer une application Web en une application native
  • Qu'est-ce qu'une application TWA?
    • TWA Exigences
    • Avantages et inconvénients de la construction d'une application TWA
  • Comment générer l'application Android APK
  • La clé de signature
  • Ce que vous devez savoir sur la liste d'une application
  • Monétisation, déverrouillage et contourner Google
  • Personnalisation de l'expérience de l'application pour Google Play
  • Comptabilité des comptes
  • Emballage

Ces premiers moments jouant avec: Hover n'étaient rien de spécial, ni même utile. Je me souviens avoir fait une grille réactive de carrés bleus (fait avec du flotteur, si cela vous donne une idée de la chronologie), chacun devenu orange lorsque le curseur s'est déplacé sur eux. J'ai passé ce qui ressemblait à des heures à soutenir les boîtes, à redimensionner la fenêtre pour les regarder changer la taille et l'alignement, puis tout recommencer. C'était comme une pure magie.

Ce que j'ai construit sur le Web est naturellement devenu plus complexe que cette grille d'éléments au fil des ans, mais le frisson de donner vie à quelque chose de vraiment interactif m'a toujours collé. Et comme je l'ai appris de plus en plus sur JavaScript, j'ai particulièrement adoré faire des jeux.

Parfois, c'était juste une démo de codepen; Parfois, c'était un petit projet parallèle déployé sur Vercel ou Netlify. J'ai adoré le défi de recréer des jeux comme Color Flood, Hangman ou Rendre quatre dans un navigateur.

Après un certain temps, cependant, le but est devenu plus grand: que se passe-t-il si je faisais un match réel ? Pas seulement une application Web; Un véritable jeu en direct, honnête à la bonne et au téléchargement, au téléchargement. En août dernier, j'ai commencé à travailler sur mon projet le plus ambitieux à ce jour, et quatre mois plus tard, je l'ai publié au monde ( lire: je suis fatigué de jouer avec lui ): une application de jeu de mots que j'appelle Quina.

Quel est le jeu (et quel est ce nom)?

La façon la plus simple d'expliquer Quina est: c'est le cerveau, mais avec des mots à cinq lettres. En fait, Mastermind est en fait une version d'un jeu classique stylo et papier; Quina est simplement une autre variation de ce même jeu original.

L'objet de Quina est de deviner un mot secret à cinq lettres. Après chaque supposition, vous obtenez un indice qui vous indique à quel point votre supposition est proche du mot de code. Vous utilisez cet indice pour affiner votre prochaine supposition, etc., mais vous n'obtenez que dix suppositions totales; Courez et vous perdez.

Le nom «Quina» est né parce que cela signifie «cinq à la fois» en latin (ou du moins me l'a dit, de toute façon). Le jeu traditionnel est généralement joué avec des mots à quatre lettres, ou parfois à quatre chiffres (ou dans le cas de cerveau, quatre couleurs); Quina utilise des mots à cinq lettres sans lettres répétées, il semblait donc approprié que le jeu ait un nom qui joue selon ses propres règles. (Je ne sais pas comment le mot latin original a été prononcé, mais je le dis "Quinn-ah", ce qui est probablement faux, mais bon, c'est mon jeu, non?)

J'ai passé mes soirées et mes week-ends au cours d'environ quatre mois à construire l'application. J'aimerais passer cet article à parler de la technologie derrière le jeu, des décisions impliquées et des leçons apprises en cas de route que vous souhaitez voyager vous-même.

Choisir Nuxt

Je suis un grand fan de Vue et je voulais utiliser ce projet comme un moyen d'élargir ma connaissance de son écosystème. J'ai envisagé d'utiliser un autre framework (j'ai également construit des projets dans Svelte et React), mais je me suis senti que Nuxt a frappé le point idéal de la familiarité, de la facilité d'utilisation et de la maturité. (Au fait, si vous ne saviez pas ou si vous n'aviez pas deviné: Nuxt pourrait être décrit équitablement comme l'équivalent Vue de Next.js.)

Je n'étais pas allé trop profondément avec Nuxt auparavant; Juste quelques très petites applications. Mais je savais que Nuxt peut compiler avec une application statique, ce qui est exactement ce que je voulais - pas de serveurs (nœud) à craindre. Je savais également que Nuxxt pouvait gérer le routage aussi facilement que la suppression des composants Vue dans le dossier A / Pages, ce qui était très attrayant.

De plus, bien que Vuex (la direction officielle de l'État de Vue) ne soit pas terriblement complexe en soi, j'ai apprécié la façon dont Nuxt ajoute un peu de sucre pour le rendre encore plus simple. (Nuxt facilite les choses de diverses manières, comme ne vous oblige pas à importer explicitement vos composants avant de pouvoir les utiliser; vous pouvez simplement les mettre dans le balisage et Nuxt le comprendra et l'importance automatique selon les besoins.)

Enfin, je savais qu'à l'avance, je construisais une application Web progressive (PWA), donc le fait qu'il existe déjà un module PWA NUXT pour aider à développer toutes les fonctionnalités impliquées (comme un employé de service pour une capacité hors ligne) déjà emballée et prête à partir était un gros tirage. En fait, il y a un ensemble impressionnant de modules Nuxxt disponibles pour tous les obstacles invisibles. Cela a fait de Nuxt le choix le plus facile et le plus évident, et je n'ai jamais regretté.

J'ai fini par utiliser davantage de modules au fur et à mesure que je suis allé, y compris le module de contenu Nuxt Stellar, qui vous permet d'écrire du contenu de la page dans Markdown, ou même un mélange de composants Markdown et Vue. J'ai utilisé cette fonctionnalité pour la page "FAQ" et la page "Comment jouer" (car l'écriture dans Markdown est tellement plus agréable que les pages HTML codant en dur).

Atteindre la sensation d'application native avec le Web

Quina finirait par trouver une maison sur le Google Play Store, mais peu importe comment ou où il était joué, je voulais qu'il se sente comme une application à part entière dès le départ.

Pour commencer, cela signifiait un mode sombre en option et un paramètre pour réduire le mouvement pour une convivialité optimale, comme de nombreuses applications natives l'ont fait (et dans le cas d'un mouvement réduit, comme tout ce qui devrait avoir des animations).

Sous le capot, les deux paramètres sont finalement des booléens dans le magasin de données Vuex de l'application. Lorsque cela est vrai, le paramètre rend une classe spécifique dans la disposition par défaut de l'application. Les dispositions Nuxxt sont des modèles Vue qui «enveloppent» tout votre contenu et rendent sur toutes les (ou plusieurs) pages de votre application (couramment utilisées pour des choses comme les en-têtes et les pieds partagés, mais également utiles pour les paramètres globaux):

 
<mpelate>
  <div :>
    <nuxt></nuxt>
  </div>
 template>

<cript>
import {mapgetters} à partir de 'Vuex'

Exporter par défaut {
  calculé: {
    ... mapgetters (['darkmode', 'reducemotion']),
  },
  // autre code de composant de mise en page ici
}
</cript></mpelate>
Copier après la connexion

En parlant de paramètres: bien que l'application Web soit divisée en plusieurs pages différentes - menu, paramètres, sur, play, etc. - le magasin de données Vuex partagé aide à maintenir les choses en synchronisation et à se sentir transparente entre les zones de l'application (puisque l'utilisateur ajustera ses paramètres sur une page et les voir s'appliquer au jeu à un autre).

Chaque paramètre de l'application est également synchronisé à la fois avec LocalStorage et le Vuex Store, ce qui permet d'enregistrer et de charger des valeurs entre les sessions, en plus de garder une trace des paramètres à mesure que l'utilisateur navigue entre les pages.

Et en parlant de navigation: se déplacer entre les pages est un autre domaine où je sentais qu'il y avait beaucoup d'occasions de faire en sorte que Quina se sente comme une application native, en ajoutant des transitions pleine page.

Les transitions Vue sont assez simples en général - vous écrivez simplement des cours CSS spécifiquement nommé pour vos états de transition «à» et «à partir» - mais Nuxt va plus loin et vous permet de définir des transitions pleine page avec une seule ligne dans le fichier Vue d'une page:

 
<cript>
Exporter par défaut {
  Transition: 'Page-Slide'
  // ... le reste des propriétés des composants
}
</cript>
Copier après la connexion

Cette propriété de transition est puissante; Il permet à Nuxt de savoir que nous voulons que la transition de glissement de page appliquée à cette page chaque fois que nous nous le navigons ou nous éloignons. De là, tout ce que nous devons faire est de définir les classes qui gèrent l'animation, comme vous le feriez avec n'importe quelle transition Vue. Voici mon SCSS de la glisse de page:

 / * actifs / css / _animations.scss * /

.Page-Slide {
  & -enter-active {
    Transition: tous les 0,35 s cubic-bezier (0, 0,25, 0, 0,75);
  }

  & -Leave-activ {
    Transition: tous les 0,35 s cubes-Bezier (0,75, 0, 1, 0,75);
  }

  &-entrer,
  & -Leave-to {
    Opacité: 0;
    Transform: Translatey (1Rem);

    .reduce-motion & {
      Transformer: aucun! IMPORTANT;
    }
  }

  & -Leave-to {
    Transform: tradlatey (-1rem);
  }
}
Copier après la connexion

Remarquez la classe .reduce-Motion; C'est ce dont nous avons parlé dans le fichier de mise en page juste au-dessus. Il empêche le mouvement visuel lorsque l'utilisateur a indiqué qu'il préfère le mouvement réduit (soit via la requête multimédia, soit par un paramètre manuel), en désactivant toute propriété de transformation (qui semblait justifier l'utilisation du drapeau de division! Important). L'opacité est toujours autorisée à s'estomper, cependant, car ce n'est pas vraiment un mouvement.

Note latérale sur les transitions et la manipulation 404S: les transitions et le routage sont, bien sûr, gérés par JavaScript sous le capot (Vue Router, pour être exact), mais j'ai rencontré un problème frustrant où les scripts cesseraient de fonctionner sur des pages inactives (par exemple, si l'utilisateur a laissé l'application ou un onglet ouvert à l'arrière-plan pendant un certain temps). Lorsque vous revenons à ces pages inactives et en cliquant sur un lien, le routeur Vue aurait cessé de fonctionner, et donc le lien serait traité comme relatif et 404.

Exemple: la page / FAQ devient inactive; L'utilisateur y revient et clique sur le lien pour visiter la page / Options. L'application tenterait d'aller à / FAQ / Options, qui n'existe bien sûr pas.

Ma solution à cela était une page Error.Vue personnalisée (il s'agit d'une page Nuxt qui gère automatiquement toutes les erreurs), où j'exécuterais la validation sur le chemin entrant et rediriger vers la fin du chemin.

 // Disseuts / Error.vue
monté () {
  const lastpage = '/' this. $ Route.fullpath.split ('/'). Pop ()
  // Ne créez pas de boucle de redirection
  if (lastpage! == this. $ Route.fullpath) {
    this. $ router.push ({
      Chemin: Lastpage,
    })
  }
}
Copier après la connexion

Cela a fonctionné pour mon cas d'utilisation car a) Je n'ai pas de routes imbriquées; et b) à la fin, si le chemin n'est pas valide, il frappe toujours un 404.

Vibration et son

Les transitions sont bien, mais je savais aussi que Quina ne se sentirait pas comme une application native - en particulier sur un smartphone - sans vibration et son.

Les vibrations sont relativement faciles à réaliser dans les navigateurs de nos jours, grâce à l'API Navigator. La plupart des navigateurs modernes vous permettent simplement d'appeler Window.Navigator.Vibrate () pour donner à l'utilisateur un peu de buzz ou une série de bourdonnements - ou, en utilisant une très courte durée, un tout petit peu de commentaires tactiles, comme lorsque vous appuyez sur une clé sur un clavier de smartphone.

De toute évidence, vous voulez utiliser des vibrations avec parcimonie, pour plusieurs raisons. Tout d'abord, car trop peut facilement devenir une mauvaise expérience utilisateur; Et deuxièmement, parce que tous les appareils / navigateurs ne le prennent pas en charge, vous devez donc faire très attention à la façon et à l'endroit où vous essayez d'appeler la fonction vibrée (), de peur que vous ne provoquez une erreur qui arrête le script en cours d'exécution.

Personnellement, ma solution était de définir un Getter Vuex pour vérifier que l'utilisateur autorise les vibrations (elle peut être désactivée à partir de la page Paramètres); que le contexte actuel est le client, pas le serveur; et enfin, que la fonction existe dans le navigateur actuel. (ES2020 Le chaînage facultatif aurait également fonctionné ici pour cette dernière partie.)

 // Store / Getters.js
vibration (état) {
  si (
    process.client &&
    state.options.vibration &&
    typeof window.navigator.vibrate! == 'Undefined'
  ) {
    Retour vrai
  }
  retourner faux
},
Copier après la connexion

Remarque latérale: Vérification du processus. Cela est vrai même si vous utilisez Nuxt en mode statique, car les composants sont validés dans le nœud pendant le temps de construction. Process.client (et son opposé, process.server) sont des nucés Nuxt qui valident simplement l'environnement actuel du code à l'exécution, ils sont donc parfaits pour isoler le code du navigateur uniquement.

Le son est un autre élément clé de l'expérience utilisateur de l'application. Plutôt que de faire mes propres effets (qui auraient sans aucun doute ajouté des dizaines d'heures au projet), j'ai mélangé des échantillons de quelques artistes qui savent mieux ce qu'ils font dans ce domaine et qui offrait des sons de jeu gratuits en ligne. (Voir la FAQ de l'application pour les informations complètes.)

Les utilisateurs peuvent définir le volume qu'ils préfèrent ou d'arrêter entièrement le son. Ceci, et la vibration, sont également définis dans LocalStorage sur le navigateur de l'utilisateur ainsi que synchronisé avec le magasin Vuex. Cette approche nous permet de définir un paramètre «permanent» enregistré dans le navigateur, mais sans avoir besoin de le récupérer du navigateur à chaque fois qu'il est référencé. (Les sons, par exemple, vérifient le niveau de volume actuel à chaque fois que l'on est joué, et la latence d'attendre un appel local-storage à chaque fois que cela se produit pourrait être suffisante pour tuer l'expérience.)

Un côté de côté sur le son

Il s'avère que pour une raison quelconque, Safari est extrêmement retardé en ce qui concerne le son. Tous les clics, Boops et Dings prendraient un temps notable après l'événement qui les a déclenchés pour jouer en safari, en particulier sur iOS. C'était un rupture de transactions et un terrier de lapin, j'ai passé une bonne quantité d'heures à désespérer des tunnels.

Heureusement, j'ai trouvé une bibliothèque appelée Howler.js qui résout assez facilement les problèmes sonores (et qui a également un petit logo amusant). L'installation de Hurler comme dépendance et exécutant tous les sons de l'application à travers lui - essentiellement une ou deux lignes de code - a été suffisante pour résoudre le problème.

Si vous construisez une application JavaScript avec un son synchrone, je recommanderais fortement d'utiliser Hurler, car je n'ai aucune idée du problème de Safari ou de la façon dont Hurler le résout. Rien que j'ai essayé n'a fonctionné, donc je suis heureux de simplement résoudre le problème facilement avec très peu de frais généraux ou de modification de code.

Gameplay, histoire et récompenses

Quina peut être un jeu difficile, surtout au début, donc il y a quelques façons d'ajuster la difficulté du jeu en fonction de votre préférence personnelle:

  1. Vous pouvez choisir le type de mots que vous souhaitez obtenir en tant que mots de code: de base (mots anglais communs), délicats (des mots qui sont soit plus obscurs ou plus difficiles à épeler), ou aléatoires (un mélange pondéré des deux).
  2. Vous pouvez choisir s'il faut recevoir un indice au début de chaque match, et si oui, combien cet indice révèle.

Ces paramètres permettent aux joueurs de diverses compétences, âge et / ou en anglais de jouer au jeu à leur propre niveau. (Un ensemble de mots de base avec des indices forts serait le plus simple; délicat ou aléatoire sans indice serait le plus difficile.)

Bien que simplement jouer à une série de jeux ponctuels avec des difficultés réglables puisse être assez agréable, cela ressemblerait plus à une application Web ou une démo standard qu'un vrai jeu à part entière. Ainsi, conformément à la poursuite de cette application native, Quina suit votre historique de jeu, montre vos statistiques de jeu de différentes manières et offre plusieurs «récompenses» pour diverses réalisations.

Sous le capot, chaque jeu est enregistré comme un objet qui ressemble à quelque chose comme ceci:

 {
  deviner: 3,
  Difficulté: «délicate»,
  gagner: vrai,
  Astuce: «Aucun»,
}
Copier après la connexion

L'application catalogue que vos jeux ont joué (encore une fois, via Vuex State synchronisé avec LocalStorage) sous la forme d'un tableau de jeu d'objets de jeu, que l'application utilise ensuite pour afficher vos statistiques - telles que votre rapport gagnant / perte, le nombre de jeux que vous avez joué et vos suppositions moyennes - ainsi que pour montrer votre progression vers les «récompenses» du jeu.

Tout cela se fait assez facilement avec divers Getters Vuex, chacun utilise des méthodes de tableau JavaScript, comme .Filter () et .reduce (), sur le tableau de jeu. Par exemple, c'est le Getter qui montre le nombre de jeux que l'utilisateur a gagné en jouant sur le paramètre «délicat»:

 // Store / Getters.js
TrickyGameswon (état) {
  return state.gamehistory.filter (
    (jeu) => game.win && game.difficulty === 'Tricky'
  ).longueur
},
Copier après la connexion

Il existe de nombreux autres getters d'une complexité variable. (Celui pour déterminer la plus longue séquence de victoires de l'utilisateur a été particulièrement noueux.)

L'ajout de récompenses a été une question de créer un tableau d'objets de récompense, chacun lié à un Getter Vuex spécifique, et chacun avec une propriété exigence. Lethershold indiquant quand cette attribution a été déverrouillée (c'est-à-dire lorsque la valeur renvoyée par le Getter était suffisamment élevée). Voici un échantillon:

 // Assets / JS / Awards.js
Exporter par défaut [
  {
    Titre: «début»,
    exigence: {
      Getter: «TotalGamesplayed»,
      Seuil: 1,
      Texte: «Jouez votre premier jeu de Quina»,
    }
  },
  {
    Titre: «Sharp»,
    exigence: {
      Getter: «Trickygameswon»,
      Seuil: 10,
      Texte: «Gagnez dix matchs au total sur Tricky»,
    },
  },
]]
Copier après la connexion

À partir de là, il s'agit d'une question assez simple de boucler sur les réalisations dans un fichier de modèle VUE pour obtenir la sortie finale, en utilisant sa propriété exigence.Text (bien qu'il y ait beaucoup de mathématiques et d'animation ajoutées pour remplir les jauges pour montrer les progrès de l'utilisateur vers la récompense):

Il y a 25 récompenses en tout (c'est 5 × 5, conformément au thème) pour diverses réalisations comme gagner un certain nombre de jeux, essayer tous les modes de jeu ou même gagner un jeu dans vos trois premières suppositions. (Celui qui est appelé «chanceux» - en tant que petit œuf de Pâques supplémentaire, le nom de chaque prix est également un mot de code potentiel, c'est-à-dire cinq lettres sans répétition.)

Le déverrouillage des prix ne fait rien, sauf vous donner des droits de vantardise, mais certains d'entre eux sont assez difficiles à réaliser. (Il m'a fallu quelques semaines après la sortie pour les obtenir tous!)

Pour les avantages et les inconvénients de cette approche

Il y a beaucoup à aimer dans la stratégie «Build une fois, déploie partout», mais il est également livré avec quelques inconvénients:

Pros

  • Vous n'avez besoin de déployer votre application de magasin qu'une seule fois. Après cela, toutes les mises à jour peuvent simplement être des déploiements de sites Web. (C'est beaucoup plus rapide que d'attendre une version de l'App Store.)
  • Construire une fois . C'est en quelque sorte vrai, mais il s'est avéré être aussi simple que je le pensais en raison de la politique de paiement de Google (plus à ce sujet plus tard).
  • Tout est un navigateur. Votre application s'exécute toujours dans l'environnement auquel vous êtes habitué, que l'utilisateur le réalise ou non.

Inconvénients

  • Les gestionnaires d'événements peuvent devenir vraiment difficiles. Étant donné que votre code s'exécute simultanément sur toutes les plates-formes, vous devez anticiper tout type d'entrée utilisateur à la fois. Certains éléments de l'application peuvent être exploités, cliqués, pressés depuis longtemps et également répondre différemment à diverses touches de clavier; Il peut être difficile de gérer tous ceux à la fois sans aucun des gestionnaires qui se précipitent les uns sur les autres.
  • Vous devrez peut-être diviser les expériences. Cela dépendra de ce que fait votre application, mais il y avait certaines choses que je devais afficher uniquement pour les utilisateurs sur l'application Android et d'autres uniquement pour le Web. (Je vais dans un peu plus de détails sur la façon dont j'ai résolu cela dans une autre section ci-dessous.)
  • Tout est un navigateur . Vous n'êtes pas inquiet de la version d'Android sur vos utilisateurs, mais vous vous inquiétez de leur navigateur par défaut (car l'application utilisera leur navigateur par défaut dans les coulisses). En règle générale, sur Android, cela signifie Chrome, mais vous devez tenir compte de toutes les possibilités.

Logistique: transformer une application Web en une application native

Il y a beaucoup de technologies qui font la promesse «Build for the Web, Release Everywhere» - React Native, Cordova, Ionic, Meteor et Nativescript, pour n'en nommer que quelques-uns.

Généralement, cela se résume à deux catégories:

  1. Vous écrivez votre code comme un framework le souhaite (pas exactement comme vous le feriez normalement), et le framework le transforme en une application native légitime;
  2. Vous écrivez votre code de la manière habituelle, et la technologie enveloppe simplement un «shell» natif autour de votre technologie Web et le déguise essentiellement en application native.

La première approche peut sembler la plus désirable des deux (car à la fin de cela, vous vous retrouvez théoriquement avec une «vraie» application native), mais j'ai également trouvé que cela s'accompagne des plus gros obstacles. Chaque plate-forme ou produit vous oblige à apprendre sa façon de faire les choses, et de cette façon est forcément tout un écosystème et un cadre en soi. La promesse de «écrire ce que vous savez» est une surestimation assez forte dans mon expérience. Je suppose que dans un an ou deux, beaucoup de ces problèmes seront résolus, mais en ce moment, vous ressentez toujours un écart considérable entre la rédaction du code Web et l'expédition d'une application native.

D'un autre côté, la deuxième approche est viable à cause d'une chose appelée «TWA», ce qui permet de faire un site Web en un site Web en premier lieu.

Qu'est-ce qu'une application TWA?

TWA signifie une activité Web de confiance - et comme cette réponse ne sera probablement pas du tout utile, décomposons un peu plus, n'est-ce pas?

Une application TWA transforme essentiellement un site Web (ou une application Web, si vous souhaitez diviser les cheveux) en une application native, avec l'aide d'une petite supercherie d'interface utilisateur.

Vous pourriez penser à une application TWA comme un navigateur déguisé . Il s'agit d'une application Android sans internes, à l'exception d'un navigateur Web. L'application TWA est indiquée vers une URL Web spécifique, et chaque fois que l'application est démarrée, plutôt que de faire des trucs d'applications natifs normaux, il charge simplement ce site Web à la place - à l'écran complet, sans contrôle de navigateur, ce qui rend le site Web et se comporte comme s'il s'agissait d'une application native à part entière.

TWA Exigences

Il est facile de voir l'attrait de terminer un site Web dans une application native. Cependant, pas n'importe quel ancien site ou URL se qualifie; Afin de lancer votre site Web / application en tant qu'application native TWA, vous devrez cocher les cases suivantes:

  • Votre site / application doit être un PWA. Google propose une vérification de validation dans le cadre du phare, ou vous pouvez vérifier avec Bubblewrap (plus à ce sujet dans un peu).
  • Vous devez générer vous-même le bundle d'applications / apk; Ce n'est pas aussi simple que de simplement soumettre l'URL de votre application Web progressive et avoir tout le travail pour vous. (Ne vous inquiétez pas; nous couvrirons un moyen de le faire même si vous ne savez rien du développement d'applications natives.)
  • Vous devez avoir une touche sécurisée correspondante, à la fois dans l'application Android et téléchargée sur votre application Web à une URL spécifique.

Ce dernier point est l'endroit où se trouve la partie «de confiance»; Une application TWA vérifiera sa propre clé, puis vérifiera que la clé de votre application Web correspond, pour s'assurer qu'elle charge le bon site (vraisemblablement, pour empêcher le détournement malveillant des URL de l'application). Si la clé ne correspond pas ou n'est pas trouvée, l'application fonctionnera toujours, mais la fonctionnalité TWA sera partie; Il chargera simplement le site Web dans un navigateur ordinaire, Chrome et tout. La clé est donc extrêmement importante pour l'expérience de l'application. (On pourrait dire que c'est un élément clé . Désolé pas désolé.)

Avantages et inconvénients de la construction d'une application TWA

Le principal avantage d'une application TWA est qu'il ne vous oblige pas du tout à modifier votre code - pas de cadre ni de plate-forme pour apprendre; Vous créez simplement une application site Web / Web comme Normal, et une fois que vous l'avez fait, vous avez également fait le code d'application.

Le principal inconvénient , cependant, est que (malgré le fait d'aider à inaugurer l'ère moderne du Web et du JavaScript), Apple n'est pas en faveur des applications TWA; Vous ne pouvez pas les énumérer dans l'App Store d'Apple. Seul Google Play.

Cela peut ressembler à un discours, mais gardons quelques choses à l'esprit:

  • N'oubliez pas que pour répertorier votre application en premier lieu, il doit être un PWA - ce qui signifie qu'il est installable par défaut. Les utilisateurs de n'importe quelle plate-forme peuvent toujours l'ajouter à l'écran d'accueil de leur appareil à partir du navigateur. Il n'a pas besoin d'être dans l'App Store Apple pour être installé sur les appareils Apple (bien qu'il manque certainement de la découverte). Vous pouvez donc toujours créer une page de destination marketing dans votre application et inciter les utilisateurs à l'installer à partir de là.
  • Il n'y a pas non plus pour vous empêcher de développer une application iOS native en utilisant une stratégie complètement différente. Même si vous vouliez à la fois des applications iOS et Android, tant qu'une application Web fait également partie du plan, un TWA supprime efficacement la moitié de ce travail.
  • Enfin, alors qu'iOS a environ 50% de part de marché dans les pays à prédominance anglophone et le Japon, Android détient bien plus de 90% du reste du monde. Donc, selon votre public, manquer l'App Store peut ne pas avoir aussi un impact que vous le pensez.

Comment générer l'application Android APK

À ce stade, vous dites peut-être que cette entreprise TWA sonne bien, mais comment prendre mon site / application et le pousser dans une application Android?

La réponse se présente sous la forme d'un charmant petit outil CLI appelé Bubblewrap.

Vous pouvez considérer Bubblewrap comme un outil qui prend des entrées et des options de votre part, et génère une application Android (en particulier, un APK, l'un des formats de fichiers autorisés par le Google Play Store) hors de l'entrée.

L'installation de Bubblewrap est un peu délicate, et bien que l'utilisation ne soit pas tout à fait plug-and-play, il est certainement beaucoup plus à portée de main pour un développeur frontal moyen que toutes les autres options comparables que j'ai trouvées. Le fichier ReadMe sur la page NPM de Bubblewrap entre dans les détails, mais comme bref aperçu:

Installez Bubblewrap en exécutant NPM I -g @ bubblewrap / CLI (je suppose ici que vous connaissez NPM et en installant des packages via la ligne de commande). Cela vous permettra d'utiliser Bubblewrap n'importe où.

Une fois installé, vous courerez:

 bubblewrap init --manifest https: //your-webapp-domain/manifest.json
Copier après la connexion

Remarque: Le fichier manifeste.json est requis de tous les PWA, et Bubblewrap a besoin de l'URL de ce fichier, pas seulement de votre application. Soyez également averti: selon la façon dont votre fichier manifeste est généré, son nom peut être unique à chaque version. (Le module PWA de Nuxt ajoute un UUID unique au nom du fichier, par exemple.)

Notez également que par défaut, Bubblewrap validera que votre application Web est un PWA valide dans le cadre de ce processus. Pour une raison quelconque, lorsque je traversais ce processus, le chèque a continué de revenir négatif, malgré le phare confirmant qu'il s'agissait en fait d'une application Web progressive entièrement fonctionnelle. Heureusement, Bubblewrap vous permet de sauter ce chèque avec le drapeau - skippwavalidation.

Si c'est la première fois que vous utilisez Bubblewrap, il vous demandera alors si vous souhaitez qu'il installe le kit de développement Java (JDK) et le kit de développement de logiciels Android (SDK) pour vous. Ces deux sont les utilitaires en coulisses nécessaires pour générer une application Android. Si vous n'êtes pas sûr, frappez «Y» pour oui.

Remarque: Bubblewrap s'attend à ce que ces deux kits de développement existent dans des endroits très spécifiques et ne fonctionneront pas correctement s'ils ne sont pas là. Vous pouvez exécuter Bubblewrap Doctor pour vérifier, ou voir le Readme CLI Full Bubblewrap.

Une fois que tout a été installé - en supposant qu'il trouve votre fichier manifeste.json sur l'URL fournie - Bubblewrap posera quelques questions sur votre application.

Beaucoup de questions sont soit la préférence (comme la couleur principale de votre application) ou simplement confirmer les détails de base (comme le domaine et le point d'entrée de l'application), et la plupart seront pré-remplies à partir du fichier manifeste de votre site.

D'autres questions qui peuvent déjà être pré-remplies par votre manifeste comprennent où trouver les différentes icônes de votre application (à utiliser comme icône d'écran d'accueil, l'icône de la barre d'état, etc.), quelle couleur l'écran Splash devrait être pendant l'ouverture de l'application et l'orientation de l'écran de l'application, au cas où vous souhaitez forcer le portrait ou le paysage. Bubblewrap vous demandera également si vous souhaitez demander l'autorisation de la géolocalisation de votre utilisateur et si vous optez pour la facturation de jeu.

Cependant, il y a quelques questions importantes qui peuvent être un peu déroutantes, alors couvrons-les ici:

  • ID d'application: il semble que ce soit une convention Java, mais chaque application a besoin d'une chaîne d'ID unique qui est généralement de 2 à 3 sections séparées par DOT (par exemple, Collinsworth.Quina.App). Peu importe ce que c'est ; Ce n'est pas fonctionnel, c'est juste une convention. La seule chose importante est que vous vous en souvenez et que c'est unique. Mais notez que cela fera partie de l'URL unique de votre application Google Play Store. (Pour cette raison, vous ne pouvez pas télécharger un nouveau pack avec un ID d'application précédemment utilisé, alors assurez-vous que vous êtes satisfait de votre identifiant.)
  • Version de démarrage: cela n'a pas d'importance pour le moment, mais le Play Store vous obligera à incrémenter la version lorsque vous téléchargez de nouveaux paquets, et vous ne pouvez pas télécharger la même version deux fois. Je recommanderais donc de commencer à 0 ou 1.
  • Mode d'affichage : il existe en fait quelques façons dont les applications TWA peuvent afficher votre site. Ici, vous voulez probablement choisir soit autonome (plein écran, mais avec la barre d'état native en haut), soit en plein écran (pas de barre d'état). J'ai personnellement choisi l'option autonome par défaut, car je n'ai vu aucune raison de masquer la barre d'état de l'utilisateur dans l'application, mais vous pouvez choisir différemment en fonction de ce que fait votre application.

La clé de signature

La dernière pièce du puzzle est la clé de signature. C'est la partie la plus importante . Cette clé est ce qui connecte votre application Web progressive à cette application Android. Si la clé que l'application attend ne correspond pas à ce qui se trouve dans votre PWA, encore une fois: votre application fonctionnera toujours, mais elle ne ressemblera pas à une application native lorsque l'utilisateur l'ouvre; Ce sera juste une fenêtre de navigateur normale.

Il y a deux approches ici qui sont un peu trop complexes pour entrer en détail, mais je vais essayer de donner quelques conseils:

  1. Générez votre propre stage de clés . Vous pouvez demander à Bubblewrap de le faire, ou utiliser un outil CLI appelé Keytool (de manière appropriée), mais dans les deux cas: soyez très prudent . Vous devez suivre explicitement le nom exact et les mots de passe pour vos clés de clés, et comme vous créez les deux sur la ligne de commande, vous devez faire très attention aux caractères spéciaux qui pourraient gâcher l'ensemble du processus. (Les caractères spéciaux peuvent être interprétés différemment sur la ligne de commande, même lorsqu'ils sont entrés dans le cadre d'une invite de mot de passe.)
  2. Permettez à Google de gérer vos clés. Honnêtement, cela n'est pas dramatiquement plus simple dans mon expérience, mais cela évite certains des problèmes de disputer vos propres clés de signature en vous permettant d'entrer dans la console de développeur Google Play et de télécharger une clé pré-générée pour votre application.

Quelle que soit l'option que vous choisissez, il y a une documentation approfondie sur la signature des applications ici (écrite pour les applications Android, mais la plupart sont toujours pertinentes).

La partie où vous obtenez la clé sur votre site personnel est couverte dans ce guide pour vérifier les liens d'application Android. Pour résumer grossièrement: Google recherchera un fichier a /.well-known/assetlinks.json sur ce chemin exact sur votre site. Le fichier doit contenir votre hachage de clé unique ainsi que quelques autres détails:

 [{
  "relation": ["Delegate_permission / Common.handle_all_urls"],
  "Target": {"namespace": "android_app", "package_name": "your.app.id",
               "SHA256_CERT_FINGERPRINTS": ["votre: Unique: Hash: ici"]}
}]
Copier après la connexion

Ce que vous devez savoir sur la liste d'une application

Avant de commencer, il y a aussi quelques obstacles à connaître du côté des choses:

  • D'abord et avant tout, vous devez vous inscrire avant de pouvoir publier sur le Google Play Store. Cette éligibilité coûte des frais de 25 $ USD.
  • Une fois approuvé, sachez que la liste d'une application n'est ni rapide ni facile. C'est plus fastidieux que difficile ou technique, mais Google passe en revue chaque application et mise à jour sur le magasin, et vous oblige à remplir beaucoup de formulaires et d'informations sur vous-même et votre application avant même de pouvoir commencer le processus d'examen - qui peut lui-même prendre plusieurs jours, même si votre application n'est même pas encore publique. (Friendly Heads-Up: Il y a eu une bannière d'avertissement «Nous vivons plus longtemps que d'habitude» dans le tableau de bord de la console de jeu depuis au moins six mois maintenant.)
    • Parmi les parties les plus fastidieuses: vous devez télécharger plusieurs images de votre application en action avant que votre avis ne puisse commencer. Ceux-ci deviendront éventuellement les images indiquées dans la liste des magasins - et gardez à l'esprit que les modifier leur lancera également une nouvelle critique, alors venez à la table préparée si vous souhaitez minimiser le délai d'exécution.
    • Vous devez également fournir des liens vers les conditions d'utilisation de votre application et la politique de confidentialité (ce qui est la seule raison pour laquelle mon application les a même, car elles sont presque inutiles).
    • Il y a beaucoup de choses que vous ne pouvez pas défaire . Par exemple, vous ne pouvez jamais modifier une application gratuite à payer, même si elle n'a pas encore lancé publiquement et / ou n'a aucun téléchargement. You also have to be strict on versioning and naming with what you upload, because Google doesn't let you overwrite or delete your apps or uploaded bundles, and doesn't always let you revert other settings in the dashboard, either. If you have a “just jump in and work out the kinks later” approach (like me), you may find yourself starting over from scratch at least once or twice.
  • With a few exceptions, Google has extremely restrictive policies about collecting payments in an app. When I was building, it was charging a 30% fee on all transactions (they've since conditionally lowered that to 15% — better, but still five times more than most other payment providers would charge). Google also forces developers (with a few exceptions) to use its own native payment platform; no opting for Square, Stripe, PayPal, etc. in-app.
    • Fun fact: this policy had been announced but wasn't in effect yet while I was trying to release Quina, and it still got flagged by the reviewer for being in violation. So they definitely take this policy very seriously.

Monetization, unlockables, and getting around Google

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
tête() {
  retour {
    scénario: [
      {
        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')
        },
      },
    ],
  }
},
Copier après la connexion

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.

Customizing the app experience for Google Play

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 and Vue wrapper components to wrap content only meant for one of the two. (Obviously, users on Android who can't visit the support page shouldn't see FAQs on the topic, as an example.)

 <!-- /src/components/AndroidOnly.vue -->
<template>
  <div v-if="isAndroid">
    <slot></slot>
  </div>
</template>

<script>
export default {
  computed: {
    isAndroid() {
      return this.$store.state.isAndroid
    },
  },
}
</script>
Copier après la connexion

Accounting for accounts

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.

Wrapping up

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.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal