SEO เชิงมุมในการดำเนินการ:


พื้นที่เก็บข้อมูลนี้ได้รับการดูแลโดย trilon.io และทีม Angular Universal และมีความหมายว่าจะเป็นผู้เริ่มต้นขั้นสูงสำหรับทั้ง ASP.NET Core 2.1 โดยใช้ Angular 7.0+ ไม่เพียง แต่สำหรับฝั่งไคลเอ็นต์เท่านั้น
นี่คือแอปพลิเคชั่นเริ่มต้นที่อุดมไปด้วยคุณสมบัติที่มีเทคโนโลยีล่าสุดทั้งหมดระบบการสร้างที่ดีที่สุดที่มีอยู่และรวมถึงตัวอย่างและห้องสมุดที่จำเป็นในโลกแห่งความเป็นจริงมากมายในแอปพลิเคชันหน้าเดียวในปัจจุบัน (SPAs)
สิ่งนี้ใช้มาตรฐานล่าสุดทั้งหมดไม่มีอึกไม่มี Bower ไม่มีการพิมพ์ไม่มี "การสร้าง" ด้วยตนเอง NPM, WebPack และ. NET จัดการทุกอย่างให้คุณ!
นี่เป็นเพียงคุณสมบัติบางอย่างที่พบในผู้เริ่มต้นนี้!
ASP.NET 2.1 - VS2017 สนับสนุนตอนนี้!
Angular 7.0.0 :
ng gc components/example-componentng gs shared/some-serviceระบบสร้างเว็บแพ็ค (WebPack 4)
เฟรมเวิร์กการทดสอบ
การผลิต
ASP.NET CORE 2.1
สีฟ้า
npm i -S @markpieszak/ng-application-insights เป็นการพึ่งพา // Add the Module to your imports
ApplicationInsightsModule . forRoot ( {
instrumentationKey : 'Your-Application-Insights-instrumentationKey'
} )นักเทียบท่า
ตรวจสอบให้แน่ใจว่าคุณมี. NET Core 2.1 ติดตั้งและ/หรือ VS2017 15.3 VS2017 จะติดตั้งการพึ่งพา NECCESSARY NPM & .NET ทั้งหมดโดยอัตโนมัติเมื่อคุณเปิดโครงการ
เพียงผลักดัน F5 เพื่อเริ่มการดีบัก!
Docker-Support : เปลี่ยนโครงการเริ่มต้นเป็น Docker-compose และกด F5
หมายเหตุ : หากคุณได้รับข้อผิดพลาดใด ๆ หลังจากนี้เช่น module not found: boot.server (หรือคล้ายกัน) ให้เปิดบรรทัดคำสั่งและเรียกใช้ npm run build:dev เพื่อให้แน่ใจว่าสินทรัพย์ทั้งหมดถูกสร้างขึ้นอย่างถูกต้องโดย Webpack
หมายเหตุ: ตรวจสอบให้แน่ใจว่าคุณติดตั้ง C# Extension & .NET Core Debugger แล้ว
โครงการมาพร้อมกับไฟล์ launch.json ที่กำหนดค่าเพื่อให้คุณเพียงแค่กด F5 เพื่อเริ่มโครงการ
# cd into the directory you cloned the project into
npm install && npm run build:dev && dotnet restore
# or yarn install หากคุณกำลังใช้งานโครงการจากบรรทัดคำสั่งด้วย dotnet run ให้แน่ใจว่าคุณตั้งค่าตัวแปรสภาพแวดล้อมของคุณเป็นการพัฒนา (มิฉะนั้นสิ่งต่าง ๆ เช่น HMR อาจไม่ทำงาน)
# on Windows:
set ASPNETCORE_ENVIRONMENT=Development
# on Mac/Linux
export ASPNETCORE_ENVIRONMENT=Development การใช้ dotnet publish เมื่อเสร็จสิ้นการวางโฟลเดอร์ที่สร้างขึ้นบนเซิร์ฟเวอร์ของคุณและใช้ IIS เพื่อยิงทุกอย่าง
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 หมายเหตุ: แอปพลิเคชันนี้มีการตั้งค่า WebAPI (REST API ของเรา) ภายในโครงการเดียวกัน แต่แน่นอนว่าทั้งหมดนี้อาจถูกแยกออกเป็นโครงการที่แยกจากกันอย่างสมบูรณ์ .net Core Things ทั้งหมดทำในโครงการเดียวกันเพื่อเห็นแก่ความเรียบง่าย
ไฟล์ระดับรูท
ที่นี่เรามี ผู้ต้องสงสัยตามปกติ ที่พบในระดับราก
ไฟล์ที่มุ่งเน้นด้านหน้า:
package.json - การพึ่งพาโครงการและสคริปต์ของ NPM.tsconfig - การกำหนดค่า TypeScript (ที่นี่เราตั้งค่าพา ธ ด้วย)webpack - ไฟล์การกำหนดค่า (Modular Bundling + อีกมากมาย)karma - ไฟล์การกำหนดค่า (การทดสอบหน่วย)protractor - ไฟล์กำหนดค่า (การทดสอบ E2E)tslint - กฎการตัดแต่งรหัส TypeScriptลองมาดูกันว่าสิ่งนี้มีโครงสร้างอย่างไรเพื่อให้เราสามารถเข้าใจได้ทั้งหมด!
ด้วย Angular Universal เราจำเป็นต้องแยกตรรกะ applicatoin ของเรา ต่อแพลตฟอร์ม ดังนั้นหากเรามองเข้าไปในโฟลเดอร์นี้คุณจะเห็นไฟล์รูท 2 ไฟล์นั้นจะแยกตรรกะทั้งหมดสำหรับเบราว์เซอร์และเซิร์ฟเวอร์ตามลำดับ
ที่นี่เราตั้งค่าบางสิ่งบางอย่างไคลเอ็นต์ bootstrapping ไคลเอ็นต์
คุณแทบจะไม่ต้องแตะไฟล์นี้ แต่สิ่งที่ควรทราบนี่คือไฟล์ที่คุณจะนำเข้าไลบรารีที่คุณต้องการใช้ในเบราว์เซอร์ เท่านั้น (เพียงแค่รู้ว่าคุณต้องจัดให้มีการใช้งานจำลองสำหรับเซิร์ฟเวอร์เมื่อทำเช่นนั้น)
สังเกตโครงสร้างโฟลเดอร์ที่นี่ใน ./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 เมื่อเพิ่มคุณสมบัติ/ส่วนประกอบใหม่/etc ลงในแอปพลิเคชันของคุณคุณจะเพิ่มสิ่งต่าง ๆ ลงในรูท ngmodule (อยู่ใน /ClientApp/app/app.module.ts ) แต่ทำไม ngmodules อีก สอง ตัวในโฟลเดอร์นี้?
นี่เป็นเพราะเราต้องการแยกตรรกะของเรา ต่อแพลตฟอร์ม แต่สังเกตว่าพวกเขาทั้งคู่แบ่งปัน ngmodule ทั่วไปชื่อ app.module.ts เมื่อเพิ่มสิ่งต่าง ๆ ส่วนใหญ่ลงในแอปพลิเคชันของคุณนี่เป็นสถานที่เดียวที่คุณจะต้องเพิ่มในส่วนประกอบ / คำสั่ง / ท่อ / ฯลฯ ใหม่ของคุณคุณจะต้องเพิ่มความจำเป็นในการเพิ่มสิ่งต่าง ๆ ในแพลตฟอร์มเฉพาะใน app.module.browser || app.module.server ด้วยตนเอง app.module.browser || app.module.server
เพื่อแสดงให้เห็นถึงจุดนี้ด้วยตัวอย่างคุณสามารถดูว่าเราใช้การฉีดพึ่งพาเพื่อฉีด StorageService ที่แตกต่างกันสำหรับเบราว์เซอร์และเซิร์ฟเวอร์อย่างไร
// For the Browser (app.module.browser)
{ provide : StorageService , useClass : BrowserStorage }
// For the Server (app.module.server)
{ provide : StorageService , useClass : ServerStorage }เพียงจำไว้ว่าคุณมักจะต้องกังวลเกี่ยวกับ
app.module.tsเนื่องจากเป็นที่ที่คุณจะเพิ่มแอปพลิเคชันส่วนใหญ่ของคุณในแง่มุมใหม่!
ตามที่เราชี้ให้เห็นสิ่งเหล่านี้อยู่ที่นี่เพื่อความเรียบง่ายและในความเป็นจริงคุณอาจต้องการโครงการแยกต่างหากสำหรับโครงการ Microservices / REST API ทั้งหมดของคุณ / ฯลฯ
เราใช้ MVC ภายในแอปพลิเคชันนี้ แต่เราต้องการและมีคอนโทรลเลอร์หนึ่งตัวชื่อ HomeController นี่คือที่ที่แอปพลิเคชันเชิงมุมทั้งหมดของเราได้รับการจัดลำดับเป็นสตริงส่งไปยังเบราว์เซอร์พร้อมกับสินทรัพย์ทั้งหมดที่ต้องการจากนั้น bootstrap บนฝั่งไคลเอ็นต์และกลายเป็นสปาที่เต็มไปด้วยเป่าลมหลังจากนั้น
รุ่นสั้นคือเราเรียกใช้กระบวนการโหนดผ่านไปในวัตถุคำขอของเรา & เรียกใช้ไฟล์ boot.server และเราได้รับวัตถุที่ดีที่เราส่งผ่านไปยังวัตถุ. nets ViewData และโรยหน้ามุม Views/Shared/_Layout.cshtml /Views/Home/index.cshtml
คำอธิบายโดยละเอียดเพิ่มเติมสามารถพบได้ที่นี่: ng-aspnetcore-engine 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 ลองดูที่ไฟล์ _Layout.cshtml ตัวอย่างเช่นสังเกตว่าเราปล่อยให้. NET จับและฉีด SEO Magic ทั้งหมดของเราได้อย่างไร (ที่เราสกัดจาก 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 ... Views/Home/index.cshtml ของเราเพียงแค่แสดงแอปพลิเคชันและให้บริการไฟล์ webpack ที่รวมอยู่ในนั้น
@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 >
}ตอนนี้เชิงมุมฝั่งไคลเอ็นต์ของคุณจะเข้าครอบครองและคุณจะมีสปาที่ทำงานได้อย่างสมบูรณ์ (แต่เราได้รับประโยชน์จาก SEO ที่ยอดเยี่ยมเหล่านี้ทั้งหมดจากการแสดงเซิร์ฟเวอร์)!
เมื่อสร้างส่วนประกอบใน Angular 7 มีบางสิ่งที่ควรคำนึงถึง
ตรวจสอบให้แน่ใจว่าคุณมี URL ที่แน่นอนเมื่อโทรหา API ใด ๆ (เซิร์ฟเวอร์ไม่เข้าใจเส้นทางที่สัมพันธ์กันดังนั้น /api/whatever จะล้มเหลว)
การโทร API จะถูกเรียกใช้ระหว่างเซิร์ฟเวอร์และอีกครั้งในระหว่างการแสดงผลไคลเอนต์ดังนั้นให้แน่ใจว่าคุณใช้การถ่ายโอนข้อมูลที่สำคัญสำหรับคุณเพื่อที่คุณจะได้ไม่เห็นการสั่นไหว
window document navigator และประเภทเบราว์เซอร์อื่น ๆ - ไม่มีอยู่บนเซิร์ฟเวอร์ - ดังนั้นการใช้พวกเขาหรือไลบรารีใด ๆ ที่ใช้ (jQuery ตัวอย่าง) จะไม่ทำงาน คุณมีตัวเลือกบางอย่างหากคุณต้องการฟังก์ชั่นนี้อย่างแท้จริง:
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 มันจะทำให้กระบวนการเรนเดอร์ฝั่งเซิร์ฟเวอร์ช้าลง ตรวจสอบให้แน่ใจว่าได้ลบ ngOnDestroy ในส่วนประกอบอย่าจัดการกับชนพื้นเมืองโดยตรง ใช้ Renderer2 เราทำสิ่งนี้เพื่อให้แน่ใจว่าในสภาพแวดล้อมใด ๆ ที่เราสามารถเปลี่ยนมุมมองของเราได้
constructor ( element : ElementRef , renderer : Renderer2 ) {
this . renderer . setStyle ( element . nativeElement , 'font-size' , 'x-large' ) ;
}sass-loader ต้องการ node-sass > = 4: ในคอนเทนเนอร์ Docker หรือ localhost run npm rejuild node-sass -f เพียงแสดงความคิดเห็นตรรกะภายใน homecontroller และแทนที่ @Html.Raw(ViewData["SpaHtml"]) ด้วยแท็กแอปพลิเคชันของคุณรูทแอปพลิเคชัน ("App-Root" ในกรณีของเรา): <app-root></app-root>
นอกจากนี้คุณยังสามารถลบตรรกะ
isPlatformBrowser/etcและลบ boot.server, app.module.browser & app.module.server ไฟล์เพียงตรวจสอบให้แน่ใจว่าไฟล์boot.browserของคุณชี้ไปที่app.module
ตรวจสอบ gotchas เกี่ยวกับวิธีการใช้ isPlatformBrowser()
คุณจะต้องการลบ SSR ในตอนนี้หรือรอเนื่องจากการสนับสนุนควรมาเพื่อจัดการการแสดงผลของเซิร์ฟเวอร์แพลตฟอร์ม ตอนนี้เป็นไปได้ด้วยการเปลี่ยนแปลงวัสดุเชิงมุมที่ได้รับการปรับปรุงเมื่อเร็ว ๆ นี้ เรายังไม่มีบทช่วยสอนสำหรับเรื่องนี้
หมายเหตุ: หากเป็นไปได้ให้พยายามหลีกเลี่ยงการใช้ jQuery หรือห้องสมุดขึ้นอยู่กับมันเนื่องจากมีวิธีที่ดีกว่าและเป็นนามธรรมมากขึ้นในการจัดการกับ DOM ในเชิงมุม (5+) เช่นการใช้ Renderer ฯลฯ
ใช่แน่นอน แต่มีบางสิ่งที่คุณต้องติดตั้งก่อนทำสิ่งนี้ ก่อนอื่นให้แน่ใจว่า jQuery รวมอยู่ในไฟล์ผู้ขาย WebPack และคุณมีการตั้งค่าปลั๊กอิน WebPack สำหรับมัน new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' })
ตอนนี้ตรวจสอบให้แน่ใจว่า "ปลั๊กอิน" ฯลฯ ที่คุณมีจะรวมอยู่ในไฟล์ boot.browser.ts ของคุณเท่านั้น (เช่น: import 'slick-carousel'; ) ในส่วนประกอบที่คุณต้องการใช้ jQuery ตรวจสอบให้แน่ใจว่าได้นำเข้าใกล้ด้านบนเหมือนอย่างนั้น:
import * as $ from 'jquery' ; ตรวจสอบให้แน่ใจว่าได้ห่อสิ่งใด ๆ ที่มุ่งเน้น jQuery ใน isPlatformBrowser() ของ Angular!
เพื่อรองรับ IE9 ถึง IE11 เปิดไฟล์ polyfills.ts ในโฟลเดอร์ polyfills และไม่ทำให้รู้สึกถึง 'การนำเข้า polyfills' ตามต้องการ นอกจากนี้ - ตรวจสอบให้แน่ใจว่า webpack.config และ webpack.config.vendor ตัวเลือกการเปลี่ยนแปลงของ TerserPlugin จาก ecma: 6 ถึง ecma: 5
ขอบคุณมากไปที่ Steve Sanderson (@stevesandersonms) จาก Microsoft และผลงานที่น่าทึ่งของเขาใน JavaScriptservices และรวมโลกของ Node กับ ASP.NET Core
ขอขอบคุณผู้มีส่วนร่วมมากมาย!
ตรวจสอบปัญหาที่ง่ายขึ้นของเราที่นี่
ไม่มีอะไรสมบูรณ์แบบ แต่โปรดแจ้งให้เราทราบด้วยการสร้างปัญหา (ตรวจสอบให้แน่ใจว่าไม่มีเรื่องนี้อยู่แล้ว) และเราจะพยายามแก้ไขปัญหา! หากคุณมีความคิดที่ดีหรือต้องการมีส่วนร่วมอย่าลังเลที่จะสร้างปัญหากับข้อเสนอหรือเพียงแค่ทำประชาสัมพันธ์จากส้อมของคุณ
ลิขสิทธิ์ (c) 2016-2019 Mark Pieszak
ตรวจสอบ trilon.io สำหรับข้อมูลเพิ่มเติม! Twitter @trilon_io
ติดต่อเราที่ [email protected] และพูดคุยเกี่ยวกับความต้องการโครงการของคุณ
Twitter: @trilon_io