SEO angular em ação:


Este repositório é mantido pelo Trilon.io e pela equipe universal angular e deve ser um iniciador avançado para o ASP.NET Core 2.1 usando o Angular 7.0+, não apenas para o lado do cliente, mas para ser renderizado no servidor para tintas de aplicativos instantâneos (NOTA: Se você não precisar de SSR aqui sobre como a detectar).
Este deve ser um aplicativo inicial rico em recursos contendo todas as tecnologias mais recentes, os melhores sistemas de construção disponíveis e incluem muitos exemplos e bibliotecas do mundo real necessários nos aplicativos de página única de hoje (spas).
Isso utiliza todos os padrões mais recentes, sem gulp, sem bower, sem tímidos, sem "construir" nada manualmente. NPM, Webpack e .Net lidam com tudo para você!
Estes são apenas alguns dos recursos encontrados nesta partida!
ASP.NET 2.1 - VS2017 Suporte agora!
Angular 7.0.0 :
ng gc components/example-componentng gs shared/some-serviceWebpack Build System (Webpack 4)
Estruturas de teste
Produtividade
ASP.NET CORE 2.1
Azure
npm i -S @markpieszak/ng-application-insights como uma dependência. // Add the Module to your imports
ApplicationInsightsModule . forRoot ( {
instrumentationKey : 'Your-Application-Insights-instrumentationKey'
} )Docker
Certifique -se de ter o .NET Core 2.1 instalado e/ou vs2017 15.3. O VS2017 instalará automaticamente todas as dependências NECESSARY NPM & .NET quando você abrir o projeto.
Simplesmente empurre o F5 para começar a depurar!
Docker-Support : Altere o projeto de inicialização para o Docker-Comppose e pressione F5
NOTA : Se você receber algum erro depois disso, como module not found: boot.server (ou similar), abra a linha de comando e execute npm run build:dev para garantir que todos os ativos tenham sido criados corretamente pelo WebPack.
Nota: verifique se você tem a extensão C# e o depurador .NET Core instalado.
O projeto vem com os arquivos iniciados do lançamento configurado para permitir que você apenas pressione F5 para iniciar o projeto.
# cd into the directory you cloned the project into
npm install && npm run build:dev && dotnet restore
# or yarn install Se você estiver executando o projeto da linha de comando com dotnet run certifique -se de definir suas variáveis de ambiente para o desenvolvimento (caso contrário, coisas como o HMR podem não funcionar).
# on Windows:
set ASPNETCORE_ENVIRONMENT=Development
# on Mac/Linux
export ASPNETCORE_ENVIRONMENT=Development Usando dotnet publish , quando terminar, coloque a pasta gerada no seu servidor e use o IIS para acionar tudo.
git remote add azure https://[email protected]:443/my-angular2-site.git
// ^ get this from Azure (Web App Overview section - Git clone url)
git push --set-upstream azure master NOTA: Este aplicativo possui configuração WebAPI (nossa API REST) dentro do mesmo projeto, mas é claro que tudo isso pode ser abstraído em um projeto completamente separado ('s) idealmente. .NET As coisas principais são feitas no mesmo projeto por uma questão de simplicidade.
Arquivos de nível raiz
Aqui temos os suspeitos usuais encontrados no nível da raiz.
Arquivos orientados para o front-end:
package.json - Dependências e scripts do projeto NPM.tsconfig - Configuração do TypeScript (aqui também configuramos caminhos)webpack - Arquivos de configuração (Bundling modular + muito mais)karma - Arquivos de configuração (teste de unidade)protractor - arquivos de configuração (teste E2E)tslint - Regras de linha de código TypeScriptVamos dar uma olhada em como isso é estruturado para que possamos entender tudo!
Com o Angular Universal, precisamos dividir nossa lógica de aplicação por plataforma ; portanto, se procurarmos dentro desta pasta, você verá os 2 arquivos root, que ramificam toda a lógica para navegador e servidor, respectivamente.
Aqui, configuramos algumas coisas, o cliente angular do cliente.
Você mal precisará tocar nesse arquivo, mas algo a observar, este é o arquivo em que você importaria bibliotecas que deseja ser usado apenas no navegador. (Apenas saiba que você teria que fornecer uma implementação simulada para o servidor ao fazer isso).
Observe a estrutura da pasta aqui em ./ClientApp/ :
+ /ClientApp/
+ /app/
App NgModule - our Root NgModule (you'll insert Components/etc here most often)
AppComponent / App Routes / global css styles
* Notice that we have 2 dividing NgModules:
app.module.browser & app.module.server
You'll almost always be using the common app.module, but these 2 are used to split up platform logic
for situations where you need to use Dependency Injection / etc, between platforms.
Note: You could use whatever folder conventions you'd like, I prefer to split up things in terms of whether they are re-usable
"components" or routeable / page-like components that group together and organize entire sections.
+ + > ++ > /components/
Here are all the regular Components that aren't "Pages" or container Components
+ + > ++ > /containers/
These are the routeable or "Page / Container" Components, sometimes known as "Dumb" Components
+ + > ++ > /shared/
Here we put all shared Services / Directives / Pipes etc Ao adicionar novos recursos/componentes/etc ao seu aplicativo, você geralmente adiciona coisas ao ngmodule raiz (localizado em /ClientApp/app/app.module.ts ), mas por que existem outros dois ngmodules nesta pasta?
Isso ocorre porque queremos dividir nossa lógica por plataforma , mas observe que ambos compartilham o ngmodule comum chamado app.module.ts . Ao adicionar a maioria das coisas ao seu aplicativo, este é o único lugar que você precisará adicionar ao seu novo componente / diretiva / tubo / etc. Você precisará apenas adicionar manualmente as coisas específicas da plataforma a app.module.browser || app.module.server .
Para ilustrar esse ponto com um exemplo, você pode ver como estamos usando a injeção de dependência para injetar um StorageService diferente para o navegador e servidor.
// For the Browser (app.module.browser)
{ provide : StorageService , useClass : BrowserStorage }
// For the Server (app.module.server)
{ provide : StorageService , useClass : ServerStorage }Lembre -se de que você geralmente só precisa se preocupar com
app.module.ts, pois é aí que você adicionará a maioria dos seus aplicativos novos aspectos!
Como apontamos, estes estão aqui por causa das simplificações e, realisticamente, você pode querer projetos separados para todos os seus projetos de microsserviços / API REST / etc.
Estamos utilizando o MVC nesse aplicativo, mas precisamos apenas e temos um controlador, chamado HomeController . É aqui que todo o nosso aplicativo angular é serializado em uma corda, enviada ao navegador, juntamente com todos os ativos necessários para que ele inicialize no lado do cliente e se torne um spa completo depois.
A versão curta é que invocamos esse processo de nó, passando em nosso objeto de solicitação e invocamos o arquivo boot.server , e recebemos um bom objeto que passamos para o objeto .Nets ViewData e folheamos nossas Views/Shared/_Layout.cshtml e/views /Views/Home/index.cshtml home/index.cshtml!
Uma explicação mais detalhada pode ser encontrada aqui: NG-ASPNETCORE-MEGINE README
// Prerender / Serialize application
var prerenderResult = await Prerenderer . RenderToString (
/* all of our parameters / options / boot.server file / customData object goes here */
) ;
ViewData [ "SpaHtml" ] = prerenderResult . Html ;
ViewData [ "Title" ] = prerenderResult . Globals [ "title" ] ;
ViewData [ "Styles" ] = prerenderResult . Globals [ "styles" ] ;
ViewData [ "Meta" ] = prerenderResult . Globals [ "meta" ] ;
ViewData [ "Links" ] = prerenderResult . Globals [ "links" ] ;
return View ( ) ; // let's render the MVC View Dê uma olhada no arquivo _Layout.cshtml , por exemplo, observe como deixamos o .NET manusear e injetar toda a nossa mágica de SEO (que extraímos do próprio Angular)!
<!DOCTYPE html >
< html >
< head >
< base href =" / " />
<!-- Title will be the one you set in your Angular application -->
< title > @ViewData["Title"] - AspNET.Core Angular 7.0.0 (+) starter </ title >
< meta charset =" utf-8 " />
< meta name =" viewport " content =" width=device-width, initial-scale=1.0 " />
@Html.Raw(ViewData["Meta"]) <!-- <meta /> tags -->
@Html.Raw(ViewData["Links"]) <!-- <link /> tags -->
< link rel =" stylesheet " href =" ~/dist/vendor.css " asp-append-version =" true " />
@Html.Raw(ViewData["Styles"]) <!-- <style /> tags -->
</ head >
... etc ... Nossas Views/Home/index.cshtml simplesmente renderizam o aplicativo e serve os arquivos WebPack agrupados nele.
@Html.Raw(ViewData["SpaHtml"])
< script src =" ~/dist/vendor.js " asp-append-version =" true " > </ script >
@section scripts {
< script src =" ~/dist/main-client.js " asp-append-version =" true " > </ script >
}Bem, agora, seu Angular do lado do cliente assumirá o controle e você terá um spa totalmente em funcionamento. (Mas obtivemos todos esses ótimos benefícios de SEO de ser renderizado no servidor)!
Ao construir componentes no Angular 7, há algumas coisas a serem lembradas.
Certifique -se de fornecer URLs absolutos ao chamar qualquer APIs. (O servidor não pode entender os caminhos relativos, SO /api/whatever for falhar).
As chamadas da API serão executadas durante um servidor e, mais uma vez, durante a renderização do cliente, portanto, verifique se você está usando dados de transferência que são importantes para você, para não ver um piscar.
window , document , navigator e outros tipos de navegador - não existem no servidor - portanto, usá -los ou qualquer biblioteca que os use (jQuery, por exemplo) não funcionará. Você tem algumas opções, se realmente precisa de parte dessa funcionalidade:
import { PLATFORM_ID } from '@angular/core' ;
import { isPlatformBrowser , isPlatformServer } from '@angular/common' ;
constructor ( @ Inject ( PLATFORM_ID ) private platformId : Object ) { ... }
ngOnInit ( ) {
if ( isPlatformBrowser ( this . platformId ) ) {
// Client only code.
...
}
if ( isPlatformServer ( this . platformId ) ) {
// Server only code.
...
}
}setTimeout . Ele diminuirá o processo de renderização do lado do servidor. Certifique -se de removê -los ngOnDestroy em componentes.Não manipule diretamente o nativo . Use o renderer2 . Fazemos isso para garantir que, em qualquer ambiente, possamos mudar nossa visão.
constructor ( element : ElementRef , renderer : Renderer2 ) {
this . renderer . setStyle ( element . nativeElement , 'font-size' , 'x-large' ) ;
}sass-loader requer node-sass > = 4: no contêiner do docker ou no host npm reconstrua nó-sass -f Basta comentar a lógica no HomeController e substituir @Html.Raw(ViewData["SpaHtml"]) por apenas o seu aplicativo root appComponent tag ("app-root" em nosso caso): <app-root></app-root> .
Você também pode remover qualquer lógica
isPlatformBrowser/etce excluir os arquivos boot.server, app.module.browser & app.module.server, apenas verifique se o seu arquivoboot.browseraponta paraapp.module.
Verifique os Gotchas sobre como usar isPlatformBrowser() .
Você deseja remover o SSR por enquanto, ou aguarde o suporte que deve lidar com a renderização do servidor da plataforma. Agora isso é possível, com as mudanças de material angular recentemente atualizadas. Ainda não temos um tutorial disponível para isso.
NOTA: Se possível, tente evitar o uso de jQuery ou bibliotecas dependentes dele, pois existem maneiras melhores e mais abstratas de lidar com o DOM no Angular (5+), como o uso do renderizador, etc.
Sim, é claro, mas há algumas coisas que você precisa configurar antes de fazer isso. Primeiro, verifique se o jQuery está incluído no arquivo de fornecedores do WebPack e se você tem uma configuração de plug -in do WebPack para ele. new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' })
Agora, verifique se os "plugins" etc. que você possui, estão incluídos apenas no seu arquivo boot.browser.ts . (ou seja: import 'slick-carousel'; ) Em um componente que você deseja usar jQuery, certifique-se de importá-lo perto do topo como assim:
import * as $ from 'jquery' ; Sempre certifique -se de embrulhar qualquer coisa orientada para o jQuery no isPlatformBrowser() condicional do Angular!
Para suportar o IE9 através do IE11, abra o arquivo polyfills.ts na pasta polyfills e descomemente os 'Polyfills de importação', conforme necessário. Além disso - verifique se a opção webpack.config e webpack.config.vendor Alterar a opção de TerserPlugin de ecma: 6 para ecma: 5 .
Muito obrigado a Steve Sanderson (@SteveSandernsonms) da Microsoft e seu incrível trabalho no JavaScriptServices e integrar o mundo do nó com o Asp.net Core.
Também obrigado aos muitos colaboradores!
Confira nossos problemas mais fáceis aqui
Nada é perfeito, mas por favor me avise criando um problema (verifique se ainda não existe sobre isso) e tentaremos resolver uma correção para isso! Se você tiver boas idéias ou deseja contribuir, sinta -se à vontade para fazer um problema com a proposta ou apenas fazer um PR do seu garfo.
Copyright (c) 2016-2019 Mark Pieszak
Confira Trilon.io para mais informações! Twitter @trilon_io
Entre em contato conosco em [email protected] e vamos falar sobre as necessidades de seus projetos.
Twitter: @trilon_io