Routage AngularJS sans le hachage '#'

223

J'apprends AngularJS et il y a une chose qui m'agace vraiment.

J'utilise $routeProviderpour déclarer des règles de routage pour mon application:

$routeProvider.when('/test', {
  controller: TestCtrl,
  templateUrl: 'views/test.html'
})
.otherwise({ redirectTo: '/test' });

mais quand je navigue vers mon application dans le navigateur, je vois app/#/testau lieu de app/test.

Donc ma question est pourquoi AngularJS ajoute ce hachage #aux URL? Y a-t-il une possibilité de l'éviter?

pikkvile
la source
2
Voici la solution si vous utilisez Angular 1.6.
Mistalis

Réponses:

265

En fait, vous avez besoin du # (hashtag) pour les navigateurs non HTML5.

Sinon, ils feront simplement un appel HTTP au serveur au href mentionné. Le # est un ancien court-circuit du navigateur qui ne déclenche pas la demande, ce qui permet à de nombreux frameworks js de créer leur propre réacheminement côté client en plus de cela.

Vous pouvez utiliser $locationProvider.html5Mode(true)pour indiquer à angular d'utiliser la stratégie HTML5 si elle est disponible.

Voici la liste des navigateurs prenant en charge la stratégie HTML5: http://caniuse.com/#feat=history

plus-
la source
4
D'accord, merci. C'est quelque chose que je soupçonnais. Mais pour moi, c'est assez peu convivial! Disons que je veux qu'une ressource soit disponible via url, app / res. Comment les utilisateurs de mon site peuvent-ils découvrir qu'ils devraient plutôt taper app / # / res?
pikkvile
5
Mais si c'est le cas, pourquoi ai-je besoin que ces chemins soient visibles dans la barre d'emplacement? Si les utilisateurs ne les utilisent pas, je peux simplement créer une application javascript sur une seule page.
pikkvile
6
Il est utile lorsque vous souhaitez suivre l'état de l'application. Les cadres offrent un mécanisme d'historique. De plus, il permet d'accéder directement à un état de votre application via le partage d'url par exemple
plus
6
Le hashtag n'est pas requis dans les navigateurs modernes qui prennent en charge l'API d'historique HTML5. Voir la réponse de @ skeep et les liens fournis. En mode HTML5, Angular n'utilisera des hashtags que si le navigateur ne le prend pas en charge. Notez également que vous n'avez pas besoin d'utiliser $ routeProvider si vous ne le souhaitez pas ... vous pouvez câbler votre propre routage en utilisant ng-clicks et ng-include (en fait, vous devez le faire si vous avez besoin de plusieurs niveaux de routage, car ng-view ne peut apparaître qu'une seule fois par page). Voir aussi stackoverflow.com/questions/12793609/…
Mark Rajcok
2
Pour le Hashbang / pushState / côté serveur rendu cas html, le Twitter est un assez agréable à lire engineering.twitter.com/2012/12/... Il explique comment ils ont réussi à le faire de sorte qu'il est rétrocompatible avec ancien navigateur et recherche moteurs. Je sais que ce n'est pas spécifique à angularjs mais vous pouvez reproduire le flux.
jackdbernier
47

Si vous avez activé html5mode comme d'autres l'ont dit, et créez un .htaccessfichier avec le contenu suivant (ajustez selon vos besoins):

RewriteEngine   On
RewriteBase     /
RewriteCond     %{REQUEST_URI} !^(/index\.php|/img|/js|/css|/robots\.txt|/favicon\.ico)
RewriteCond     %{REQUEST_FILENAME} !-f
RewriteCond     %{REQUEST_FILENAME} !-d
RewriteRule     ./index.html [L]

Les utilisateurs seront dirigés vers votre application lorsqu'ils entreront un itinéraire approprié, et votre application lira l'itinéraire et les amènera à la "page" correcte à l'intérieur.

EDIT: assurez-vous simplement qu'aucun fichier ou nom de répertoire n'entre en conflit avec vos itinéraires.

copain
la source
existe-t-il une version nginx de cela? lorsque je charge /aboutla page échoue, sauf si j'y arrive via l'application.
chovy
Je ne les
ai
3
@chovy - voici la version nGinx: serveur {nom_serveur my-app; racine / chemin / vers / application; location / {try_files $ uri $ uri / /index.html; }}
Moin Haidar
4
rappelez-vous <base href = "/"> </base> dans la balise head
Silvio Troia
Merci! sans cela, un lien profond est impossible. Je ne suis toujours pas sûr que la beauté ou les URI en valent la peine si vous avez besoin de liens profonds, en particulier dans certains environnements cloud / paas où vous pourriez ne pas avoir facilement accès à la configuration httpd.
Pierre Henry
39

Permet d'écrire une réponse simple et courte

Dans le routeur à la fin, ajoutez html5Mode (true) ;

app.config(function($routeProvider,$locationProvider) {

    $routeProvider.when('/home', {
        templateUrl:'/html/home.html'
    });

    $locationProvider.html5Mode(true);
})

Dans la tête html, ajoutez une balise de base

<html>
<head>
    <meta charset="utf-8">    
    <base href="/">
</head>

merci à @plus - pour avoir détaillé la réponse ci-dessus

vijay
la source
Je n'ai pas réussi à faire fonctionner cela. J'ai posté une nouvelle question avec mes détails spécifiques à: stackoverflow.com/questions/36041074/… Veuillez regarder ceci et si vous pouvez aider je l'apprécierais grandement.
Larry Martell
30

essayer

$locationProvider.html5Mode(true)

Plus d'informations sur $ locationProvider
Utilisation de $ location

skeep
la source
6
désolé j'ai ajouté .config (fonction ($ locationProvider) {$ locationProvider.html5Mode (true)}) mais j'ai le résultat index.html #% 2Fhome not index.html / home
zloctb
12

Les informations suivantes proviennent de:
https://scotch.io/quick-tips/pretty-urls-in-angularjs-removing-the-hashtag

Il est très facile d'obtenir des URL propres et de supprimer le hashtag de l'URL dans Angular.
Par défaut, AngularJS acheminera les URL avec un hashtag Par exemple:

Il y a 2 choses à faire.

  • Configuration de $ locationProvider

  • Définition de notre base pour les liens relatifs

  • $ location Service

Dans Angular, le service $ location analyse l'URL dans la barre d'adresse et apporte des modifications à votre application et vice versa.

Je recommande fortement de lire les documents officiels de localisation Angular $ pour avoir une idée du service de localisation et de ce qu'il propose.

https://docs.angularjs.org/api/ng/service/$location

$ locationProvider et html5Mode

  • Nous allons utiliser le module $ locationProvider et définir html5Mode sur true.
  • Nous le ferons lors de la définition de votre application angulaire et de la configuration de vos itinéraires.

    angular.module('noHash', [])
    
    .config(function($routeProvider, $locationProvider) {
    
       $routeProvider
           .when('/', {
               templateUrl : 'partials/home.html',
               controller : mainController
           })
           .when('/about', {
               templateUrl : 'partials/about.html',
               controller : mainController
           })
           .when('/contact', {
               templateUrl : 'partials/contact.html',
               controller : mainController
           });
    
       // use the HTML5 History API
       $locationProvider.html5Mode(true); });

Qu'est-ce que l'API HTML5 History? Il s'agit d'un moyen standardisé de manipuler l'historique du navigateur à l'aide d'un script. Cela permet à Angular de modifier le routage et les URL de nos pages sans actualiser la page. Pour plus d'informations à ce sujet, voici un bon article sur l'API HTML5 History:

http://diveintohtml5.info/history.html

Définition de liens relatifs

  • Pour créer un lien autour de votre application à l'aide de liens relatifs, vous devrez définir <base> dans le <head>de votre document. Cela peut être dans le fichier racine index.html de votre application Angular. Recherchez la <base>balise et définissez-la sur l'URL racine que vous souhaitez pour votre application.

Par exemple: <base href="https://stackoverflow.com/">

  • Il existe de nombreuses autres façons de configurer cela, et le mode HTML5 défini sur true devrait automatiquement résoudre les liens relatifs. Si la racine de votre application est différente de l'url (par exemple / my-base, utilisez-la comme base.

Remplacement pour les anciens navigateurs

  • Le service $ location reprendra automatiquement la méthode hashbang pour les navigateurs qui ne prennent pas en charge l'API HTML5 History.
  • Cela vous arrive de manière transparente et vous n'aurez rien à configurer pour que cela fonctionne. Dans les documents Angular $ location, vous pouvez voir la méthode de secours et comment elle fonctionne.

En conclusion

  • C'est un moyen simple d'obtenir de jolies URL et de supprimer le hashtag de votre application Angular. Amusez-vous à faire ces applications angulaires super propres et super rapides!
zero_cool
la source
3

Si vous souhaitez configurer cela localement sur OS X 10.8 servant Angular avec Apache, vous trouverez peut-être ce qui suit dans votre fichier .htaccess:

<IfModule mod_rewrite.c>
    Options +FollowSymlinks
    RewriteEngine On
    RewriteBase /~yourusername/appname/public/
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !.*\.(css|js|html|png|jpg|jpeg|gif|txt)
    RewriteRule (.*) index.html [L]
</IfModule>

Les options + FollowSymlinks, si elles ne sont pas définies, peuvent vous donner une erreur interdite dans les journaux comme ceci:

Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden

La réécriture de la base est requise, sinon les demandes seront résolues à la racine de votre serveur qui, par défaut, n'est pas votre répertoire de projet sauf si vous avez spécifiquement configuré vos vhosts, vous devez donc définir le chemin afin que la demande trouve votre répertoire racine de projet. Par exemple sur ma machine j'ai un répertoire / Users / me / Sites où je garde tous mes projets. Comme l'ancien OS X configuré.

Les deux lignes suivantes indiquent effectivement si le chemin n'est pas un répertoire ou un fichier, vous devez donc vous assurer que vous n'avez pas de fichiers ou de répertoires identiques à ceux de vos chemins de routage d'application.

La condition suivante indique si la demande ne se termine pas avec les extensions de fichier spécifiées, alors ajoutez ce dont vous avez besoin

Et le [L] dernier dit de servir le fichier index.html - votre application pour toutes les autres demandes.

Si vous avez toujours des problèmes, consultez le journal d'apache, il vous donnera probablement des conseils utiles:

/private/var/log/apache2/error_log
Monsieur P
la source
Si vous utilisez MAMP comme serveur apache localhost, assurez-vous que le premier RewriteBase est un lien relatif. par exemple RewriteBase / angularjs_site_folder /
David Douglas
3

L'utilisation du mode HTML5 nécessite une réécriture d'URL côté serveur, vous devez essentiellement réécrire tous vos liens vers le point d'entrée de votre application (par exemple index.html). L'exigence d'une <base>balise est également importante dans ce cas, car elle permet à AngularJS de différencier la partie de l'URL qui est la base de l'application et le chemin qui doit être géré par l'application. Pour plus d'informations, consultez le Guide du développeur AngularJS - Utilisation du mode serveur $ location HTML5 côté serveur .


Mettre à jour

Comment: configurer votre serveur pour qu'il fonctionne avec html5Mode 1

Lorsque vous avez activé html5Mode, le #caractère ne sera plus utilisé dans vos URL. Le #symbole est utile car il ne nécessite aucune configuration côté serveur. Sans #, l'url semble beaucoup plus agréable, mais elle nécessite également des réécritures côté serveur. Voici quelques exemples:

Apache réécrit

<VirtualHost *:80>
    ServerName my-app

    DocumentRoot /path/to/app

    <Directory /path/to/app>
        RewriteEngine on

        # Don't rewrite files or directories
        RewriteCond %{REQUEST_FILENAME} -f [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^ - [L]

        # Rewrite everything else to index.html to allow html5 state links
        RewriteRule ^ index.html [L]
    </Directory>
</VirtualHost>

Nginx réécrit

server {
    server_name my-app;

    index index.html;

    root /path/to/app;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

Réécriture d'Azure IIS

<system.webServer>
  <rewrite>
    <rules> 
      <rule name="Main Rule" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="/" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>

Réécritures express

var express = require('express');
var app = express();

app.use('/js', express.static(__dirname + '/js'));
app.use('/dist', express.static(__dirname + '/../dist'));
app.use('/css', express.static(__dirname + '/css'));
app.use('/partials', express.static(__dirname + '/partials'));

app.all('/*', function(req, res, next) {
    // Just send the index.html for other files to support HTML5Mode
    res.sendFile('index.html', { root: __dirname });
});

app.listen(3006); //the port you want to use

Voir également

georgeawg
la source
1

Dans Angular 6, avec votre routeur, vous pouvez utiliser:

RouterModule.forRoot(routes, { useHash: false })
gpresland
la source
0

Vous pouvez également utiliser le code ci-dessous pour rediriger vers la page principale (accueil):

{ path: '', redirectTo: 'home', pathMatch: 'full'}

Après avoir spécifié votre redirection comme ci-dessus, vous pouvez rediriger les autres pages, par exemple:

{ path: 'add-new-registration', component: AddNewRegistrationComponent},
{ path: 'view-registration', component: ViewRegistrationComponent},
{ path: 'home', component: HomeComponent}
Arash
la source
0

**

Il est recommandé d'utiliser le style HTML 5 (PathLocationStrategy) comme stratégie de localisation dans Angular

** Parce que

  1. Il produit des URL propres et optimisées pour le référencement qui sont plus faciles à comprendre et à mémoriser pour les utilisateurs.
  2. Vous pouvez profiter du rendu côté serveur, qui accélérera le chargement de notre application, en rendant les pages du serveur avant de le livrer au client.

Utilisez Hashlocationstrtegy uniquement si vous devez prendre en charge les anciens navigateurs.

Cliquez ici pour en savoir plus

Mahendra Waykos
la source