Roteamento AngularJS sem o hash '#'

223

Estou aprendendo o AngularJS e há uma coisa que realmente me incomoda.

Uso $routeProviderpara declarar regras de roteamento para meu aplicativo:

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

mas quando navego para o meu aplicativo no navegador, vejo em app/#/testvez de app/test.

Então, minha pergunta é por que o AngularJS adiciona esse hash #aos URLs? Existe alguma possibilidade de evitá-lo?

pikkvile
fonte
2
Aqui está a solução se você estiver usando o Angular 1.6.
Mistalis 29/03

Respostas:

265

Na verdade, você precisa do # (hashtag) para navegadores não HTML5.

Caso contrário, eles apenas farão uma chamada HTTP para o servidor no href mencionado. O # é um curto-circuito do navegador antigo que não aciona a solicitação, o que permite que muitas estruturas js construam seus próprios roteamentos no lado do cliente.

Você pode usar $locationProvider.html5Mode(true)para dizer ao angular para usar a estratégia HTML5, se disponível.

Aqui está a lista de navegadores que suportam a estratégia HTML5: http://caniuse.com/#feat=history

mais-
fonte
4
OK obrigado. Isso é algo que eu suspeitava. Mas quanto a mim, isso é bastante hostil ao usuário! Digamos que eu queira que algum recurso esteja disponível via URL, app / res. Como os usuários do meu site descobrem que devem digitar app / # / res?
pikkvile
5
Mas, se sim, por que preciso que esses caminhos sejam visíveis na barra de localização? Se os usuários não os usarem, eu posso apenas criar um aplicativo javascript de página única.
Pikkvile
6
É útil quando você deseja acompanhar o estado do aplicativo. As estruturas oferecem um mecanismo de histórico. Além disso, permite o acesso directo um estado do seu pedido através de compartilhamento de url, por exemplo
mais-
6
A hashtag não é necessária em navegadores modernos que suportam a API de histórico HTML5. Veja a resposta de @ skeep e os links fornecidos. No modo HTML5, o Angular usará hashtags apenas se o navegador não suportar. Observe também que você não precisa usar $ routeProvider se não quiser ... pode conectar seu próprio roteamento usando ng-clicks e ng-include (na verdade, você deve fazer isso se precisar de vários níveis de roteamento, pois o ng-view pode aparecer apenas uma vez por página). Veja também stackoverflow.com/questions/12793609/…
Mark Rajcok 15/01/13
2
No caso de hashbang / pushstate / renderização do lado do servidor, o Twitter é muito bom de ler engineering.twitter.com/2012/12/… Explica como eles conseguiram fazê-lo, por isso é compatível com versões anteriores do navegador antigo e com a pesquisa motores. Eu sei que não é angularjs específico, mas você pode reproduzir o fluxo.
jackdbernier
47

Se você ativou o html5mode como já foi dito, e crie um .htaccessarquivo com o seguinte conteúdo (ajuste para suas necessidades):

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]

Os usuários serão direcionados ao seu aplicativo quando entrarem em uma rota adequada, e o aplicativo lerá a rota e os levará para a "página" correta.

EDIT: Apenas certifique-se de não ter nenhum nome de arquivo ou diretório em conflito com suas rotas.

bearfriend
fonte
existe uma versão nginx disso? quando carrego /abouta página falha, a menos que eu chegue a ela através do aplicativo.
Chovy
Nunca usou-los, mas tente o seguinte: stackoverflow.com/questions/5840497/convert-htaccess-to-nginx
bearfriend
3
@chovy - aqui vai a versão do nGinx: server {server_name my-app; raiz / caminho / para / app; location / {try_files $ uri $ uri / /index.html; }}
Moin Haidar
4
lembre-se <base href = "/"> </base> na tag head
Silvio Troia
Obrigado! sem isso, a ligação profunda é impossível. Ainda não tenho certeza de que a beleza ou os URIs valham a pena mantê-lo, se você precisar de links diretos, especialmente em alguns ambientes de nuvem / paas em que talvez você não tenha acesso fácil à configuração do httpd.
Pierre Henry
39

Permite escrever uma resposta simples e curta

No roteador no final, adicione html5Mode (true) ;

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

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

    $locationProvider.html5Mode(true);
})

No cabeçalho html, adicione a tag base

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

graças a @plus - por detalhar a resposta acima

vijay
fonte
Não consegui fazer isso funcionar. Publiquei uma nova pergunta com meus detalhes específicos em: stackoverflow.com/questions/36041074/… Por favor, observe isso e se você puder ajudar, eu agradeceria muito.
Larry Martell
30

experimentar

$locationProvider.html5Mode(true)

Mais informações em $ locationProvider
Using $ location

skeep
fonte
6
desculpe eu adicionei .config (function ($ LocationProvider) {$ locationProvider.html5Mode (true)}), mas eu tenho resultar index.html #% 2Fhome não index.html / home
zloctb
12

As informações a seguir são de:
https://scotch.io/quick-tips/pretty-urls-in-angularjs-removing-the-hashtag

É muito fácil obter URLs limpos e remover a hashtag da URL no Angular.
Por padrão, o AngularJS roteará URLs com uma hashtag. Por exemplo:

Há duas coisas que precisam ser feitas.

  • Configurando $ locationProvider

  • Definindo nossa base para links relativos

  • Serviço $ location

No Angular, o serviço de localização $ analisa o URL na barra de endereço e faz alterações no seu aplicativo e vice-versa.

Eu recomendo a leitura dos documentos oficiais de localização do Angular $ para ter uma idéia do serviço de localização e do que ele fornece.

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

$ locationProvider e html5Mode

  • Usaremos o módulo $ locationProvider e definiremos html5Mode como true.
  • Faremos isso ao definir seu aplicativo Angular e configurar suas rotas.

    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); });
    

O que é a API de histórico do HTML5? É uma maneira padronizada de manipular o histórico do navegador usando um script. Isso permite que o Angular altere o roteamento e os URLs de nossas páginas sem atualizar a página. Para obter mais informações, veja um bom artigo sobre a API de histórico de HTML5:

http://diveintohtml5.info/history.html

Configuração para links relativos

  • Para vincular seu aplicativo usando links relativos, você precisará definir o <base>no <head>documento. Isso pode estar no arquivo index.html raiz do seu aplicativo Angular. Encontre a <base>tag e defina-a no URL raiz que você deseja para o seu aplicativo.

Por exemplo: <base href="https://stackoverflow.com/">

  • Existem várias outras maneiras de configurar isso, e o modo HTML5 definido como true deve resolver automaticamente os links relativos. Se a raiz do seu aplicativo for diferente da URL (por exemplo / my-base, use-a como sua base.

Fallback para navegadores mais antigos

  • O serviço $ location fará o fallback automático para o método hashbang para navegadores que não suportam a API de histórico do HTML5.
  • Isso acontece de forma transparente e você não precisará configurar nada para que ele funcione. Nos documentos de localização do Angular $, você pode ver o método de fallback e como ele funciona.

Em conclusão

  • Esta é uma maneira simples de obter URLs bonitos e remover a hashtag no seu aplicativo Angular. Divirta-se criando aplicativos Angular super limpos e super rápidos!
zero_cool
fonte
3

Se você deseja configurá-lo localmente no OS X 10.8, servindo o Angular com Apache, poderá encontrar o seguinte em seu arquivo .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>

Opções + FollowSymlinks, se não definido, pode fornecer um erro proibido nos logs da seguinte forma:

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

É necessário reescrever a base, caso contrário, as solicitações serão resolvidas para a raiz do servidor que, localmente, por padrão, não é o diretório do projeto, a menos que você tenha configurado seus vhosts especificamente, portanto, é necessário definir o caminho para que a solicitação encontre o diretório raiz do projeto. Por exemplo, na minha máquina, tenho um diretório / Users / me / Sites onde mantenho todos os meus projetos. Como o antigo OS X configurado.

As próximas duas linhas dizem efetivamente se o caminho não é um diretório ou arquivo, portanto, você precisa ter arquivos ou diretórios iguais aos caminhos de rota do aplicativo.

A próxima condição diz que, se a solicitação não terminar com as extensões de arquivo especificadas, adicione o que você precisa lá

E o último [L] está dizendo para servir o arquivo index.html - seu aplicativo para todos os outros pedidos.

Se você ainda tiver problemas, verifique o log do apache, provavelmente ele fornecerá dicas úteis:

/private/var/log/apache2/error_log
Senhor P
fonte
Se você usar o MAMP como seu servidor apache localhost, verifique se o primeiro RewriteBase é um link relativo. por exemplo, RewriteBase / angularjs_site_folder /
David Douglas
3

O uso do modo HTML5 requer a reescrita de URL no servidor, basicamente você precisa reescrever todos os seus links no ponto de entrada do seu aplicativo (por exemplo, index.html). Exigir uma <base>tag também é importante para este caso, pois permite ao AngularJS diferenciar entre a parte da URL que é a base do aplicativo e o caminho que deve ser tratado pelo aplicativo. Para obter mais informações, consulte o AngularJS Developer Guide - Usando $ location no modo HTML5 no lado do servidor .


Atualizar

Como configurar o servidor para funcionar com o html5Mode 1

Quando você tiver o html5Mode ativado, o #personagem não será mais usado em seus URLs. O #símbolo é útil porque não requer configuração do lado do servidor. Sem #, o URL parece muito melhor, mas também requer reescritas no lado do servidor. aqui estão alguns exemplos:

Apache Rewrites

<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 Rewrites

server {
    server_name my-app;

    index index.html;

    root /path/to/app;

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

Regravações do IIS do Azure

<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>

Reescrições Expressas

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

Veja também

georgeawg
fonte
1

No Angular 6, com o seu roteador, você pode usar:

RouterModule.forRoot(routes, { useHash: false })
Gpresland
fonte
0

Você também pode usar o código abaixo para redirecionar para a página principal (home):

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

Depois de especificar seu redirecionamento como acima, você pode redirecionar as outras páginas, por exemplo:

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

**

Recomenda-se usar o estilo HTML 5 (PathLocationStrategy) como estratégia de localização no Angular

** porque

  1. Ele produz URLs limpas e amigáveis ​​ao SEO, que são mais fáceis para os usuários entenderem e lembrarem.
  2. Você pode tirar proveito da renderização do lado do servidor, que agilizará o carregamento do aplicativo, renderizando as páginas no servidor antes de entregá-lo ao cliente.

Use Hashlocationstrtegy apenas se você precisar dar suporte aos navegadores mais antigos.

Clique aqui para saber mais

Mahendra Waykos
fonte