เราเตอร์เชิงมุม 2.0 ไม่ทำงานในการโหลดเบราว์เซอร์ใหม่


190

ฉันใช้รุ่น Angular 2.0.0-alpha.30 เมื่อเปลี่ยนเส้นทางไปยังเส้นทางอื่นแล้วรีเฟรชเบราว์เซอร์โดยแสดงเป็นไม่สามารถรับ / เส้นทาง

คุณสามารถช่วยฉันหาสาเหตุว่าทำไมข้อผิดพลาดนี้เกิดขึ้น


1
ฉันเดาว่ามันคือstackoverflow.com/questions/16569841
GünterZöchbauer

ขอบคุณสำหรับการตอบกลับ แต่สิ่งนั้นมีไว้สำหรับเชิงมุม 1.x ฉันกำลังเผชิญปัญหาในเชิงมุม 2.0
Vinz และ Tonz

1
คำถามที่เชื่อมโยงเป็นปัญหาทั่วไปเกี่ยวกับ pushState ไม่ใช่เฉพาะเชิงมุม คำถามของคุณไม่ได้ให้ข้อมูลเพียงพอที่จะรู้ว่าเกี่ยวข้องหรือไม่
GünterZöchbauer

5
Angular 2.0 ใช้เราเตอร์ใหม่ที่สมบูรณ์ดังนั้นโพสต์ที่เชื่อมโยงจึงไม่มีประโยชน์ตั้งแต่เราเตอร์เก่า
Vinz and Tonz

อย่างที่บอกไปแล้วว่ามันเป็นปัญหาของ pushState ไม่ใช่เฉพาะ Angular และไม่สามารถแก้ไขได้โดย Angular แต่จำเป็นต้องแก้ไขบนเซิร์ฟเวอร์แทน
GünterZöchbauer

คำตอบ:


141

ข้อผิดพลาดที่คุณเห็นคือเนื่องจากคุณกำลังร้องขอ http: // localhost / route ซึ่งไม่มีอยู่ ตามที่ไซมอน

เมื่อใช้การกำหนดเส้นทาง html5 คุณต้องแมปเส้นทางทั้งหมดในแอปของคุณ (ปัจจุบัน 404) ไปที่ index.htmlในฝั่งเซิร์ฟเวอร์ของคุณ นี่คือตัวเลือกบางอย่างสำหรับคุณ:

  1. ใช้เซิร์ฟเวอร์สด: https://www.npmjs.com/package/live-server

    $live-server --entry-file=index.html`
    
  2. ใช้ nginx: http://nginx.org/en/docs/beginners_guide.html

    error_page 404 /index.html
    
  3. Tomcat - การกำหนดค่าของ web.xml จากความคิดเห็นของKunin

    <error-page>
          <error-code>404</error-code>
          <location>/index.html</location>
    </error-page>
    

1
เนื่องจากต้องการการสนับสนุนด้านเซิร์ฟเวอร์สำหรับการกำหนดเส้นทาง html5 จึงทำงานได้อย่างสมบูรณ์แบบ Thanx
Prabhat

ฉันสามารถใช้ nginx เป็นพร็อกซีได้pub serveหรือไม่ ด้วยวิธีนี้ฉันไม่ต้องการpub buildอะไรมากมายในระหว่างการพัฒนา ฉันพยายาม แต่ไม่สามารถทำงานได้เป็นอย่างดีกับproxy_pass error_page
Franklin Yu

@ FranklinYu ฉันยังไม่เคยทำมาก่อน คุณได้รับการแก้ไขหรือไม่
Quy Tang

1
ใช้ nginx , error_page 404 / ดัชนี. html ในตำแหน่งของแอพที่ใช้งานได้สำหรับฉัน ขอบคุณ.
Richard K. Campion

2
Tomcat - การกำหนดค่าของ web.xml <error-page> <error-code> 404 </error-code> <location> /index.html </location> </error-page>
Kunin

65

คำเตือน: การแก้ไขนี้ทำงานร่วมกับ Alpha44

ฉันมีปัญหาเดียวกันและแก้ไขได้โดยใช้HashLocationStrategy ที่ระบุไว้ใน Angular.io API Preview

https://angular.io/docs/ts/latest/api/common/index/HashLocationStrategy-class.html

เริ่มต้นด้วยการนำเข้าคำสั่งที่จำเป็น

import {provide} from 'angular2/angular2';
import {
  ROUTER_PROVIDERS,
  LocationStrategy,
  HashLocationStrategy
} from 'angular2/router';

และในที่สุด bootstrap มันเข้าด้วยกันอย่างนั้น

bootstrap(AppCmp, [
  ROUTER_PROVIDERS,
  provide(LocationStrategy, {useClass: HashLocationStrategy})
]);

เส้นทางของคุณจะปรากฏเป็นhttp: // localhost / # / เส้นทางและเมื่อคุณรีเฟรชมันจะโหลดใหม่ในตำแหน่งที่เหมาะสม

หวังว่าจะช่วย!


1
รหัสนี้จะทำงานได้ดี แต่มีปัญหาบางอย่างในเทคนิคนี้โดยใช้สิ่งนี้#จะเพิ่มโดยอัตโนมัติใน URL มีวิธีใดที่จะลบ # ออกจาก URL โดยใช้สิ่งนี้?
Pardeep Jain

ตกลงฉันลองใช้ "PathLocationStrategy" ที่ระบุไว้ที่นี่แต่ไม่สามารถใช้งานได้ URL ที่ไม่มีค่า#จะเหมาะสมที่สุด
SimonHawesome

ใช่ฉันก็ลองเหมือนกันPathLocationStrategyแต่นี่ไม่ได้ผลสำหรับฉัน ฉันใช้วิธีการที่ไม่ถูกต้องหรือฉันไม่รู้วิธีการใช้ PathLocationStrategy
Pardeep Jain

1
สิ่งนี้ไม่ได้ผลสำหรับฉันใน RC1 การนำเข้า LocationStrategy, HashLocationStrategy จาก '@ angular / router' ล้มเหลว
infojolt

1
ขออภัยที่กลับมาที่คำถามนี้นานกว่า 1 ปี :) แต่ HashLocationStrategy ช่วยให้อยู่บนเส้นทางเราเตอร์เดียวกันได้หรือไม่ ในกรณีของฉันเมื่อฉันรีเฟรชมันจะพาฉันไปที่localhost / # / <default route> นั่นคือเส้นทางเริ่มต้นสำหรับหน้าแรก ฉันจะไปยังเส้นทางปัจจุบันที่ฉันเปิดอยู่เมื่อฉัน 'รีเฟรช' ได้อย่างไร
rajugaadu

47

โดยค่าเริ่มต้น Angular ใช้ HTML5 pushstate ( PathLocationStrategyใน Angular Slang)
คุณต้องการเซิร์ฟเวอร์ที่ประมวลผลคำขอทั้งหมดเหมือนที่ร้องขอindex.htmlหรือคุณเปลี่ยนเป็นHashLocationStrategy(ด้วย # ใน URL สำหรับเส้นทาง) https://angular.io/docs/ts/latest/api/common/index/HashLocationStrategy-class HTML

ดูเพิ่มเติมที่https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/

เพื่อสลับไปHashLocationStrategyใช้

อัปเดตสำหรับ> = RC.5 และ 2.0.0 สุดท้าย

import {HashLocationStrategy, LocationStrategy} from '@angular/common';

@NgModule({
  declarations: [AppCmp], 
  bootstrap: [AppCmp],
  imports: [BrowserModule, routes],
  providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}]
]);

หรือสั้นกว่าด้วย useHash

imports: [RouterModule.forRoot(ROUTER_CONFIG, {useHash: true}), ...

ให้แน่ใจว่าคุณมีการนำเข้าที่จำเป็นทั้งหมด

สำหรับเราเตอร์ (RC.3) ใหม่

<base href="."> 

อาจทำให้เกิด 404 เช่นกัน

มันต้องการแทน

<base href="/">

อัปเดตสำหรับ> = RC.x

bootstrap(AppCmp, [
  ROUTER_PROVIDERS,
  provide(LocationStrategy, {useClass: HashLocationStrategy})
  // or since RC.2
  {provide: LocationStrategy, useClass: HashLocationStrategy} 
]);

import {provide} from '@angular/core';
import {  
  PlatformLocation,  
  Location,  
  LocationStrategy,  
  HashLocationStrategy,  
  PathLocationStrategy,  
  APP_BASE_HREF}  
from '@angular/common';  

อัปเดตสำหรับ> = beta.16การนำเข้ามีการเปลี่ยนแปลง

import {BrowserPlatformLocation} from '@angular/platform-browser';

import {provide} from 'angular2/core';
import {
  // PlatformLocation,
  // Location,
  LocationStrategy,
  HashLocationStrategy,
  // PathLocationStrategy,
  APP_BASE_HREF}
from 'angular2/router';
import {BrowserPlatformLocation} from 'angular2/src/router/location/browser_platform_location';

<beta.16

import {provide} from 'angular2/core';
import {
  HashLocationStrategy
  LocationStrategy,
  ROUTER_PROVIDERS,
} from 'angular2/router';

ดูเพิ่มเติมhttps://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta16-2016-04-26หมดเปลี่ยนแปลง


1
ขอบคุณ! ให้ดูเหมือนว่าจะมีการย้ายภายใต้เชิงมุม / แกน: นำเข้า {ให้} จาก 'angular2 / แกน'
StrangeLoop

1
เพื่อทราบ: update for >= RC.x(RC.2) ทำงานได้router 3.0.0-alpha.7แต่มีprovideคำอธิบายประกอบว่าเลิกใช้แล้วโดยไม่มีข้อมูลเกี่ยวกับฟังก์ชันที่แทนที่
Mrusful

ใช้{provide: SomeClass, useClass: OtherClass}
GünterZöchbauer

2
คำตอบล่าสุด สำหรับเวอร์ชันล่าสุดของเชิงมุม 2.4.1 ฉันมี <base href = "./"> เปลี่ยนเป็น <base href = "/"> แก้ไขปัญหาที่ฉันมี อาจเป็นประโยชน์สำหรับใครบางคน
Saiyaff Farouk

28

ฉันคิดว่าข้อผิดพลาดที่คุณเห็นนั้นเป็นเพราะคุณกำลังร้องขอhttp: // localhost / routeซึ่งไม่มีอยู่ คุณต้องตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ของคุณจะจับคู่คำขอทั้งหมดไปที่หน้า index.html หลักของคุณ

เนื่องจาก Angular 2 ใช้การกำหนดเส้นทาง html5 เป็นค่าเริ่มต้นแทนที่จะใช้แฮชที่ส่วนท้ายของ URL การรีเฟรชหน้าเว็บดูเหมือนจะเป็นการร้องขอทรัพยากรอื่น


7
ดังนั้นเราจะแก้ไขได้อย่างไร เราจะแมปคำขอทั้งหมดกับดัชนีหลักโดยค่าเริ่มต้นได้อย่างไร มันพึ่งพาเซิร์ฟเวอร์หรือไม่
Ayyash

1
ใช่คุณจะทำสิ่งนี้บนเซิร์ฟเวอร์โดยใช้กรอบงานเว็บใดก็ตามที่คุณใช้ ทางเลือกคือการใช้ HashLocationStrategy ดังที่อธิบายไว้ด้านล่าง
Simon

คุณจะทำการโหลดแองกูลาร์สปาในทุกเส้นทางที่ไม่มีในปัจจุบัน มันควรจัดการอย่างไร?
Gary

จะรีโหลดเฉพาะเมื่อผู้ใช้คลิกรีเฟรชในเบราว์เซอร์ไม่ใช่เมื่อผู้ใช้เปลี่ยนเส้นทางผ่าน UI ไม่ใช่วิธีการรีโหลดเมื่อผู้ใช้รีเฟรช
Wallace Howery

19

นี่เป็นสถานการณ์ทั่วไปในเราเตอร์ทุกรุ่นหากคุณใช้กลยุทธ์ตำแหน่ง HTML เริ่มต้น

จะเกิดอะไรขึ้นคือ URL บนแถบเบราว์เซอร์นั้นเป็น URL HTML แบบเต็มปกติเช่น: http://localhost/routeเต็มรูปแบบเช่นตัวอย่างเช่น:

ดังนั้นเมื่อเรากด Enter ในแถบเบราว์เซอร์ที่มีการร้องขอ HTTP routeที่เกิดขึ้นจริงส่งไปยังเซิร์ฟเวอร์ที่จะได้รับไฟล์ชื่อ

เซิร์ฟเวอร์ไม่มีไฟล์ดังกล่าวและไม่มีการกำหนดค่าใด ๆ เช่น express บนเซิร์ฟเวอร์เพื่อจัดการคำขอและให้การตอบสนองดังนั้นเซิร์ฟเวอร์ส่งคืน 404 ไม่พบเนื่องจากไม่พบrouteไฟล์

สิ่งที่เราต้องการให้เซิร์ฟเวอร์ส่งคืนindex.htmlไฟล์ที่มีแอปพลิเคชันหน้าเดียว จากนั้นเราเตอร์ควรเตะเข้าและดำเนินการ/route URL และแสดงส่วนประกอบที่แมปกับมัน

ดังนั้นเพื่อแก้ไขปัญหาที่เราต้องกำหนดค่าเซิร์ฟเวอร์เพื่อกลับ index.html (สมมติว่าเป็นชื่อของไฟล์แอปพลิเคชันหน้าเดียวของคุณ) ในกรณีที่คำขอไม่สามารถจัดการได้ซึ่งตรงข้ามกับ 404 ไม่พบ

วิธีการทำเช่นนี้จะขึ้นอยู่กับเทคโนโลยีด้านเซิร์ฟเวอร์ที่ใช้ หาก Java เป็นตัวอย่างคุณอาจต้องเขียน servlet ใน Rails มันจะแตกต่างกันเป็นต้น

ในการให้ตัวอย่างที่เป็นรูปธรรมหากเช่นคุณกำลังใช้ NodeJs คุณจะต้องเขียนมิดเดิลแวร์ดังนี้:

function sendSpaFileIfUnmatched(req,res) {
    res.sendFile("index.html", { root: '.' });
}

จากนั้นลงทะเบียนที่ส่วนท้ายสุดของมิดเดิลแวร์เชน:

app.use(sendSpaFileIfUnmatched);

สิ่งนี้จะทำหน้าที่index.htmlแทนการส่งคืน 404 เราเตอร์จะเตะเข้าและทุกอย่างจะทำงานตามที่คาดไว้


นี่เป็นปัญหาของฉันอย่างแน่นอน หากคุณใช้ NGINX คำตอบนี้จะช่วยแก้ปัญหาได้: stackoverflow.com/questions/7027636/…
นาธาน

มีการสอนเกี่ยวกับวิธีการทำเช่นนี้สำหรับ java? ขอบคุณ
0000000000000000000000000

13

ตรวจสอบให้แน่ใจว่าสิ่งนี้อยู่ในองค์ประกอบส่วนหัวของ index.html ของคุณ:

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

ตัวอย่างใน Angular2 สายงานการผลิตและการนำการใช้เอกสารประกอบการใช้รหัสต่อไปนี้ในหัวแทน (พวกเขาอธิบายว่าทำไมในหมายเหตุตัวอย่างสดของเอกสาร):

<script>document.write('<base href="' + document.location + '" />');</script>

เมื่อคุณรีเฟรชหน้าสิ่งนี้จะตั้งค่าฐาน href เป็นเอกสารปัจจุบันของคุณแบบไดนามิก ฉันเห็นสิ่งนี้ทำให้เกิดความสับสนสำหรับคนที่อ่านเอกสารและพยายามทำซ้ำเสียงพลั่ว


ขอบคุณที่แบ่งปันสิ่งนี้ ชัดเจนกว่านี้มันใช้ได้กับฉันเมื่อฉันใส่ <base href = "/"> โดยตรงหลังจากโหลด css ทั้งหมดใน <head> และก่อนที่จะโหลดไฟล์ใด ๆ ของ Js ฉันหวังว่ามันจะช่วยให้ทุกคน
wmehanna

ฉันมี <base href = "./"> ใน index.html จากนั้นนำออก '.' จาก href และใช้งานได้ ..
Saurabh Solanki

10

หากคุณต้องการที่จะสามารถที่จะป้อน URL ในเบราว์เซอร์โดยไม่ต้องกำหนดค่า AppServer ของคุณเพื่อจัดการคำขอทั้งหมด index.html คุณต้องใช้HashLocationStrategy

วิธีที่ง่ายที่สุดในการกำหนดค่าคือการใช้:

RouterModule.forRoot(routes, { useHash: true })

แทน:

RouterModule.forRoot(routes)

ด้วยHashLocationStrategy URL ของคุณจะเป็นอย่างไร:

http://server:port/#/path

ขอบคุณ! สิ่งนี้ช่วยได้ แต่ฉันไม่ต้องการ#จาก url เราจะลบมันได้ไหม
Hidayt Rahman

7

ฉันมีปัญหาเดียวกันกับการใช้ webpack-dev-server ฉันต้องเพิ่มตัวเลือก devServer ใน webpack ของฉัน

สารละลาย:

// in webpack
devServer: {
    historyApiFallback: true,
    stats: 'minimal'
}

ชนิดของเวทมนตร์วูดู: p สำหรับข้อมูลเพิ่มเติมดู: webpack.github.io/docs/ ......
Jissay

7

หากคุณใช้ Apache หรือ Nginx เป็นเซิร์ฟเวอร์คุณต้องสร้าง.htaccess(หากไม่ได้สร้างไว้ก่อนหน้านี้) และ "เปิด" RewriteEngine

RewriteEngine On  
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ /index.html

ไม่ได้รับคำถามของคุณวิธีนี้ทดสอบในเซิร์ฟเวอร์Apache และ Nginx ( nginx.com )
Rakesh Roy

1
นี่สำหรับ Apache เท่านั้น; รูปแบบการกำหนดค่า Nginx แตกต่างอย่างสิ้นเชิง
แฟรงคลินหยู

5

เซิร์ฟเวอร์ของฉันคือ Apache สิ่งที่ฉันทำเพื่อแก้ไข 404 เมื่อการรีเฟรชหรือการลิงก์ลึกนั้นง่ายมาก เพียงเพิ่มหนึ่งบรรทัดใน apache vhost config:

ErrorDocument 404 /index.html

ดังนั้นข้อผิดพลาด 404 จะถูกเปลี่ยนเส้นทางไปยัง index.html ซึ่งเป็นสิ่งที่การกำหนดเส้นทาง angular2 ต้องการ

ตัวอย่างไฟล์ vhost ทั้งหมด:

<VirtualHost *:80>
  ServerName fenz.niwa.local
  DirectoryIndex index.html
  ErrorDocument 404 /index.html

  DocumentRoot "/Users/zhoum/Documents/workspace/fire/fire_service/dist"
  ErrorLog /Users/zhoum/Documents/workspace/fire/fire_service/logs/fenz.error.log
  CustomLog /Users/zhoum/Documents/workspace/fire/fire_service/logs/fenz.access.log combined

  <Directory "/Users/zhoum/Documents/workspace/fire/fire_service/dist">
    AllowOverride All
    Options Indexes FollowSymLinks
    #Order allow,deny
    #Allow from All
    Require all granted
  </Directory>

  Header set Access-Control-Allow-Origin "*"
  Header set Access-Control-Allow-Methods "GET, POST"
  Header set Access-Control-Allow-Credentials "true"
  Header set Access-Control-Allow-Headers "Accept-Encoding"
</VirtualHost>

ไม่ว่าคุณจะใช้เซิร์ฟเวอร์ใดฉันคิดว่าประเด็นทั้งหมดคือการค้นหาวิธีกำหนดค่าเซิร์ฟเวอร์เพื่อเปลี่ยนเส้นทาง 404 ไปยัง index.html ของคุณ


4

การกำหนดค่าเซิร์ฟเวอร์ไม่ใช่วิธีแก้ปัญหาสำหรับ SPA คือสิ่งที่ฉันคิด คุณไม่ต้องการโหลดแองกูลาร์สปาอีกครั้งหากมีเส้นทางที่ผิดมาใช่ไหม? ดังนั้นฉันจะไม่ขึ้นอยู่กับเส้นทางเซิร์ฟเวอร์และเปลี่ยนเส้นทางไปยังเส้นทางอื่น แต่ใช่ฉันจะให้ index.html จัดการคำขอทั้งหมดสำหรับเส้นทางเชิงมุมของเส้นทางแอปเชิงมุม

ลองใช้วิธีนี้แทนเส้นทางอื่นหรือเส้นทางที่ผิด มันใช้งานได้สำหรับฉันไม่แน่ใจ แต่ดูเหมือนว่ากำลังดำเนินการอยู่ สะดุดตัวเองเมื่อเผชิญปัญหา

@RouteConfig([
  { path: '/**', redirectTo: ['MycmpnameCmp'] }, 
   ...
  }
])

https://github.com/angular/angular/issues/4055

อย่างไรก็ตามอย่าลืมกำหนดค่าโฟลเดอร์เซิร์ฟเวอร์ของคุณและเข้าถึงได้ในกรณีที่คุณมี HTML หรือเว็บสคริปต์ที่ไม่ใช่สปา มิฉะนั้นคุณจะต้องเผชิญกับปัญหา สำหรับฉันเมื่อประสบปัญหาเช่นคุณมันเป็นการผสมผสานของการกำหนดค่าเซิร์ฟเวอร์และด้านบน


4

สำหรับการแก้ไขด่วนเชิงมุม 5 ให้แก้ไขapp.module.tsและเพิ่ม{useHash:true}หลังจาก appRoutes

@NgModule(
{
  imports:[RouterModule.forRoot(appRoutes,{useHash:true})]
})

3

แอพเชิงมุมเป็นตัวเลือกที่สมบูรณ์แบบสำหรับการให้บริการด้วยเซิร์ฟเวอร์ HTML แบบคงที่ คุณไม่ต้องการเอ็นจิ้นฝั่งเซิร์ฟเวอร์ในการเขียนหน้าแอปพลิเคชันแบบไดนามิกเนื่องจาก Angular ทำเช่นนั้นในฝั่งไคลเอ็นต์

หากแอปใช้เราเตอร์แบบเชิงมุมคุณต้องกำหนดค่าเซิร์ฟเวอร์เพื่อส่งคืนหน้าโฮสต์ของแอปพลิเคชัน (index.html) เมื่อมีการขอไฟล์ที่ไม่มี

แอปพลิเคชันที่กำหนดเส้นทางควรสนับสนุน "ลิงก์ลึก" ลิงก์ลึกคือ URL ที่ระบุพา ธ ไปยังส่วนประกอบภายในแอป ตัวอย่างเช่นhttp://www.example.com/heroes/42เป็นลิงก์ลึกไปยังหน้ารายละเอียดฮีโร่ที่แสดงฮีโร่ที่มี id: 42

ไม่มีปัญหาเมื่อผู้ใช้นำทางไปยัง URL นั้นจากภายในไคลเอนต์ที่ทำงานอยู่ เราเตอร์เชิงมุมตีความ URL และเส้นทางไปยังหน้าและฮีโร่นั้น

แต่การคลิกลิงก์ในอีเมลเข้ามาในแถบที่อยู่ของเบราว์เซอร์หรือเพียงรีเฟรชเบราว์เซอร์ขณะที่อยู่ในหน้ารายละเอียดฮีโร่ - การกระทำทั้งหมดเหล่านี้ได้รับการจัดการโดยเบราว์เซอร์นอกแอปพลิเคชันที่ทำงานอยู่ เบราว์เซอร์ทำการร้องขอโดยตรงไปยังเซิร์ฟเวอร์สำหรับ URL นั้นผ่านเราเตอร์

เซิร์ฟเวอร์แบบคงที่ผลตอบแทนประจำ index.html เมื่อได้รับการร้องขอสำหรับhttp://www.example.com/ แต่จะปฏิเสธhttp://www.example.com/heroes/42และส่งคืนข้อผิดพลาด 404 - ไม่พบเว้นแต่จะได้รับการกำหนดค่าให้ส่งคืน index.html แทน

หากปัญหานี้เกิดขึ้นในการผลิตให้ทำตามขั้นตอนด้านล่าง

1) เพิ่มไฟล์ Web.Config ในโฟลเดอร์ src ของแอปพลิเคชันเชิงมุมของคุณ วางรหัสด้านล่างไว้

<configuration>
<system.webServer>
<rewrite>
    <rules>
    <rule name="Angular Routes" 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>
</configuration>

2) เพิ่มการอ้างอิงถึงมันใน angular-cli.json ใน angular-cli.json ใส่ Web.config ในบล็อคสินทรัพย์ดังที่แสดงด้านล่าง

"assets": [
    "assets",
    "favicon.ico",
    "Web.config"
  ],

3) ตอนนี้คุณสามารถสร้างโซลูชันสำหรับการผลิตโดยใช้

ng build --prod

นี่จะเป็นการสร้างโฟลเดอร์ dist ไฟล์ภายในโฟลเดอร์ dist พร้อมสำหรับการปรับใช้ในทุกโหมด


ทางออกที่ดีที่สุดสามารถหารายละเอียดจากเชิงมุม: angular.io/guide/deployment#fallbackในขณะที่สร้างไฟล์ web.config อย่าลืมเพิ่มแท็ก <configuration> </configuration> ขอบคุณสำหรับคำตอบ Malatesh
Palash Roy

3

คุณสามารถใช้โซลูชันนี้สำหรับแอปพลิเคชันเฉลี่ยฉันใช้ ejs เป็นเครื่องมือดู:

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile);
app.use(function (req, res, next) {
    return res.render('index.html');
});

และยังตั้งอยู่ใน angular-cli.json

"apps": [
    {
      "root": "src",
      "outDir": "views",

มันจะทำงานได้ดีแทน

app.get('*', function (req, res, next) {
    res.sendFile('dist/index.html', { root: __dirname });
 });

ปัญหาการสร้างด้วยการรับ db db และการคืน index.html


1
สิ่งนี้ทำงานได้อย่างสมบูรณ์ในเดือนตุลาคม 2017 สำหรับการสมัคร MEAN สแต็ก
ทีม Mindsect

2

สำหรับพวกเราที่ต้องดิ้นรนตลอดชีวิตใน IIS: ใช้รหัส PowerShell ต่อไปนี้เพื่อแก้ไขปัญหานี้ตามเอกสาร Angular 2 อย่างเป็นทางการ (มีคนโพสต์ในกระทู้นี้หรือไม่? http://blog.angular-university.io/angular2-router/ )

Import-WebAdministration
# Grab the 404 handler and update it to redirect to index.html.
$redirect = Get-WebConfiguration -filter "/system.WebServer/httperrors/error[@statusCode='404']" -PSPath IIS:\Sites\LIS 
$redirect.path = "/index.html"
$redirect.responseMode = 1
# shove the updated config back into IIS
Set-WebConfiguration -filter "/system.WebServer/httperrors/error[@statusCode='404']" -PSPath IIS:\Sites\LIS -value $redirect

สิ่งนี้จะเปลี่ยนเส้นทาง 404 ไปยังไฟล์ /index.html ตามคำแนะนำในเอกสาร Angular 2 (ลิงก์ด้านบน)


2

คุณสามารถลองด้านล่าง มันใช้งานได้สำหรับฉัน!

main.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

...
export class MainComponent implements OnInit {
    constructor(private router: Router) {
        let path: string = window.location.hash;
        if (path && path.length > 0) {
            this.router.navigate([path.substr(2)]);
        }
    }

    public ngOnInit() { }
}

คุณสามารถปรับปรุง path.substr (2) เพิ่มเติมเพื่อแบ่งเป็นพารามิเตอร์เราเตอร์ ฉันใช้มุมฉาก 2.4.9


สิ่งนี้มีประโยชน์มากสำหรับการจัดการรีเฟรชเบราว์เซอร์! สำหรับเชิงมุม 5 ฉันต้องแก้ไขมันเล็กน้อยเพื่อใช้ window.location.pathname และเปรียบเทียบค่านั้นกับเส้นทางที่คาดหวัง
Wallace Howery

2

ฉันแค่เพิ่ม. htaccess ในรูท

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
    RewriteRule ^ - [L]
    RewriteRule ^ ./index.html
</IfModule>

ที่นี่ฉันเพิ่งเพิ่มจุด '.' (ไดเรกทอรีหลัก) ใน /index.html ไปที่. / index.html
ตรวจสอบให้แน่ใจว่าไฟล์ index.html ของคุณในเส้นทางฐานเป็นเส้นทางไดเรกทอรีหลักและตั้งอยู่ในการสร้างโครงการ


1

ฉันต้องการรักษาเส้นทาง URL ของหน้าย่อยในโหมด HTML5 โดยไม่เปลี่ยนเส้นทางกลับไปที่ดัชนีและไม่มีวิธีแก้ปัญหาที่นั่นบอกวิธีการทำเช่นนี้ดังนั้นนี่คือวิธีที่ฉันทำสำเร็จ:

สร้างไดเรกทอรีเสมือนง่าย ๆ ใน IIS สำหรับทุกเส้นทางของคุณและชี้ไปที่รูทแอป

ล้อมรอบ system.webServer ของคุณใน Web.config.xml ด้วยแท็กตำแหน่งนี้มิฉะนั้นคุณจะได้รับข้อผิดพลาดซ้ำ ๆ จากการโหลด Web.config เป็นครั้งที่สองด้วยไดเรกทอรีเสมือน:

<configuration>
    <location path="." inheritInChildApplications="false">
    <system.webServer>
        <defaultDocument enabled="true">
            <files>
                <add value="index.html" />
            </files>
        </defaultDocument>
    </system.webServer>
  </location>
</configuration>

1

ฉันตรวจสอบในเมล็ดมุม 2 ว่ามันทำงานอย่างไร

คุณสามารถใช้express-history-api-fallbackเพื่อเปลี่ยนเส้นทางโดยอัตโนมัติเมื่อมีการโหลดหน้าเว็บใหม่

ฉันคิดว่ามันเป็นวิธีที่ยอดเยี่ยมที่สุดในการแก้ไขปัญหา IMO


1

หากคุณต้องการใช้ PathLocationStrategy:

  • การกำหนดค่า Wildfly:
    • สร้างไฟล์ undertow-handers.conf เพื่อวางไว้ใน WEB-INF
    • เนื้อหา: (ไม่รวมจุดสิ้นสุดที่เหลือของคุณ!)
      • regex ['(. / ภาพรวม / ?. ? $)'] และไม่ใช่ regex ['(. / endpoints. )'] -> เขียนใหม่ ['/ index.html']
      • regex ['(. / deployments / ?. ? $)'] และไม่ใช่ regex ['(. / endpoints. )'] -> เขียนใหม่ ['/ index.html']

แอ็พพลิเคชันหน้าเดียวที่มี Java EE / Wildfly: การกำหนดค่าฝั่งเซิร์ฟเวอร์


1

2017- กรกฎาคม -11: ตั้งแต่นี้มีการเชื่อมโยงจากคำถามที่มีปัญหานี้ แต่ใช้ Angular 2 กับ Electron ฉันจะเพิ่มวิธีแก้ปัญหาของฉันที่นี่

สิ่งที่ฉันต้องทำคือลบออก<base href="./">จาก index.html ของฉันและอิเลคตรอนเริ่มโหลดหน้านี้อีกครั้งสำเร็จ


1

เพิ่มการนำเข้า:

import { HashLocationStrategy, LocationStrategy } from '@angular/common';

และในผู้ให้บริการ NgModule ให้เพิ่ม:

providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}]

ใน index.html ไฟล์หลักของแอพเปลี่ยน href ฐานเป็น./index.htmlจาก/

แอพเมื่อติดตั้งในเซิร์ฟเวอร์ใด ๆ จะให้ URL จริงสำหรับหน้าซึ่งสามารถเข้าถึงได้จากแอปพลิเคชันภายนอก


1

เพียงเพิ่ม. htaccessในรูทที่ได้รับการแก้ไข 404 ในขณะที่รีเฟรชหน้าเพจในมุมฉาก apache2 4

<IfModule mod_rewrite.c>
    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]
</IfModule>

1

ฉันคิดว่าคุณจะได้รับ 404 เพราะคุณกำลังร้องขอhttp: // localhost / routeซึ่งไม่มีอยู่ในเซิร์ฟเวอร์ Tomcat เนื่องจาก Angular 2 ใช้การกำหนดเส้นทาง html 5 โดยค่าเริ่มต้นแทนที่จะใช้แฮชที่ส่วนท้ายของ URL การรีเฟรชหน้าเว็บดูเหมือนจะเป็นการร้องขอทรัพยากรอื่น

เมื่อใช้การกำหนดเส้นทางเชิงมุมบน Tomcat คุณต้องตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ของคุณจะจับคู่เส้นทางทั้งหมดในแอปของคุณกับ index.html หลักของคุณในขณะรีเฟรชหน้า มีหลายวิธีในการแก้ไขปัญหานี้ ไม่ว่าอย่างใดอย่างหนึ่งที่เหมาะกับคุณคุณสามารถไปที่

1) ใส่รหัสด้านล่างใน web.xml ของโฟลเดอร์การปรับใช้ของคุณ:

<error-page>
     <error-code>404</error-code>
     <location>/index.html</location>
</error-page>

2) คุณสามารถลองใช้ HashLocationStrategy กับ # ใน URL สำหรับเส้นทาง:

ลองใช้:

RouterModule.forRoot (เส้นทาง {useHash: true})

แทน:

RouterModule.forRoot (เส้นทาง)

ด้วย HashLocationStrategy URL ของคุณจะเป็นอย่างไร:

http: // localhost / # / เส้นทาง

3) Tomcat URL Rewrite Valve: เขียน url ใหม่โดยใช้การกำหนดค่าระดับเซิร์ฟเวอร์เพื่อเปลี่ยนเส้นทางไปยัง index.html หากไม่พบทรัพยากร

3.1) ภายในโฟลเดอร์ META-INF สร้างไฟล์ context.xml และคัดลอกบริบทด้านล่างภายใน

<? xml version='1.0' encoding='utf-8'?>
<Context>
  <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
</Context>

3.2) ภายใน WEB-INF ให้สร้างไฟล์ rewrite.config (ไฟล์นี้มีกฎสำหรับการเขียน URL ใหม่และใช้โดย Tomcat สำหรับการเขียน URL ใหม่) ภายใน rewrite.config ให้คัดลอกเนื้อหาด้านล่าง:

  RewriteCond %{SERVLET_PATH} !-f
  RewriteRule ^/(.*)$ /index.html [L]

0

นี่ไม่ใช่คำตอบที่ถูกต้อง แต่เมื่อรีเฟรชคุณสามารถเปลี่ยนเส้นทางการโทรที่ตายแล้วไปยังโฮมเพจโดยเสียสละ 404 หน้ามันเป็นการแฮ็คชั่วคราวเพียงแค่เล่นซ้ำตามด้วยไฟล์ 404.html

<!doctype html>
<html>
    <head>
        <script type="text/javascript">
            window.location.href = "http://" + document.location.host;
        </script>
    </head>
</html>

0

ทางออกที่ดีที่สุดในการแก้ปัญหา "เราเตอร์ที่ไม่ทำงานบนรีโหลดเบราว์เซอร์" คือเราควรใช้สปาถอยกลับ หากคุณกำลังใช้แอพพลิเคชั่น angular2 กับแกน asp.net เราจำเป็นต้องกำหนดมันในหน้า "StartUp.cs" ภายใต้เส้นทาง MVC ฉันกำลังแนบรหัส

 app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
            routes.MapSpaFallbackRoute("spa-fallback", new { controller = "Home", action = "Index" });
        });

0

คำตอบนั้นค่อนข้างยุ่งยาก หากคุณใช้ Apache Server ธรรมดา (หรือ IIS) คุณจะได้รับปัญหาเนื่องจากเพจ Angular ไม่มีอยู่จริง พวกเขา "คำนวณ" จากเส้นทางเชิงมุม

มีหลายวิธีในการแก้ไขปัญหา หนึ่งคือการใช้HashLocationStrategy ที่เสนอโดย Angular แต่จะมีการเพิ่มเครื่องหมายที่คมชัดใน URL นี่คือส่วนใหญ่สำหรับความเข้ากันได้กับ Angular 1 (ฉันถือว่า) ข้อเท็จจริงคือส่วนหลังของชาร์ปไม่ได้เป็นส่วนหนึ่งของ URL (จากนั้นเซิร์ฟเวอร์จะแก้ไขส่วนก่อนเครื่องหมาย "#") ที่สามารถสมบูรณ์แบบ

นี่คือวิธีการปรับปรุง (ตาม 404 เคล็ดลับ) ฉันถือว่าคุณมีแอปพลิเคชันเชิงมุมของคุณในเวอร์ชัน "กระจาย"ng build --prodถ้าคุณใช้ Angular-CLI) และคุณเข้าถึงหน้าเว็บโดยตรงด้วยเซิร์ฟเวอร์ของคุณและเปิดใช้งาน PHP

หากเว็บไซต์ของคุณอ้างอิงจากหน้าเว็บ (เช่น Wordpress) และคุณมีโฟลเดอร์เพียงโฟลเดอร์เดียวสำหรับ Angular (ชื่อ "dist" ในตัวอย่างของฉัน) คุณสามารถทำอะไรแปลก ๆ แต่ท้ายที่สุดง่าย ฉันถือว่าคุณได้เก็บหน้าแองกูลาร์ไว้ใน "/ dist" (ตามด้วย<BASE HREF="/dist/"> ) ตอนนี้ใช้การเปลี่ยนเส้นทาง 404 และความช่วยเหลือของ PHP

ในการกำหนดค่า Apache ของคุณ (หรือใน.htaccessไฟล์ไดเรกทอรีแอปพลิเคชันเชิงมุมของคุณ) คุณต้องเพิ่มErrorDocument 404 /404.php

404.php จะเริ่มต้นด้วยรหัสต่อไปนี้:

<?php
$angular='/dist/';
if( substr($_SERVER['REQUEST_URI'], 0, strlen($angular)) == $angular ){
    $index = $_SERVER['DOCUMENT_ROOT'] . $angular . "index.html";
    http_response_code(200);
    include $index;
    die;
}

// NOT ANGULAR...
echo "<h1>Not found.</h1>"

ที่$angularเป็นค่าที่เก็บไว้ใน HREF ของเชิงมุมของคุณindex.htmlของเชิงมุมของคุณ

หลักการนั้นค่อนข้างง่ายหาก Apache ไม่พบหน้านั้นการเปลี่ยนเส้นทาง 404 ถูกสร้างขึ้นมากับสคริปต์ PHP เราเพียงตรวจสอบว่าหน้านั้นอยู่ในไดเรกทอรีแอปพลิเคชันเชิงมุม หากเป็นกรณีนี้เราเพียงโหลด index.html โดยตรง (โดยไม่เปลี่ยนเส้นทาง): นี่เป็นสิ่งจำเป็นเพื่อไม่ให้ URL เปลี่ยนแปลง นอกจากนี้เรายังเปลี่ยนรหัส HTTP จาก 404 เป็น 200 (ดีกว่าสำหรับโปรแกรมรวบรวมข้อมูล)

จะทำอย่างไรถ้าไม่มีหน้าอยู่ในแอปพลิเคชันเชิงมุม เราใช้ "catch all" ของเราเตอร์เชิงมุม (ดูเอกสารประกอบของเราเตอร์เชิงมุม)

วิธีนี้ใช้ได้กับแอปพลิเคชัน Angular ที่ฝังอยู่ภายในเว็บไซต์พื้นฐาน (ฉันคิดว่ามันจะเป็นกรณีนี้ในอนาคต)

หมายเหตุ:

  • พยายามทำเช่นเดียวกันกับ mod_redirect (โดยการเขียน URL ใหม่) ไม่ใช่วิธีแก้ปัญหาที่ดีเพราะไฟล์ (เช่นสินทรัพย์) ต้องโหลดจริง ๆ แล้วมีความเสี่ยงมากกว่าการใช้โซลูชัน "ไม่พบ"
  • เพียงแค่เปลี่ยนเส้นทางโดยใช้ErrorDocument 404 /dist/index.htmlงาน แต่ Apache ยังคงตอบกลับด้วยรหัสข้อผิดพลาด 404 (ซึ่งไม่ดีสำหรับโปรแกรมรวบรวมข้อมูล)

0

นี่ไม่ใช่การแก้ไขปัญหาถาวร แต่เป็นวิธีแก้ปัญหาหรือแฮ็ก

ฉันมีปัญหาเดียวกันนี้เมื่อปรับใช้แอพเชิงมุมของฉันไปที่หน้า gh ก่อนอื่นฉันได้รับการต้อนรับด้วย 404 ข้อความเมื่อรีเฟรชหน้าเว็บของฉันใน gh-pages

จากนั้นสิ่งที่ @ gunter ชี้ให้เห็นฉันเริ่มใช้HashLocationStrategyซึ่งให้มาพร้อมกับ Angular 2

แต่ที่มาพร้อมกับชุดของตัวเองของปัญหา#ใน url มันก็ไม่ดีจริงๆทำให้แปลก URL https://rahulrsingh09.github.io/AngularConcepts/#/faqลักษณะเช่นนี้

ฉันเริ่มค้นคว้าเกี่ยวกับปัญหานี้และเจอบล็อก ฉันลองยิงมันแล้วก็ใช้งานได้

นี่คือสิ่งที่ฉันทำตามที่ระบุไว้ในบล็อกนั้น

คุณจะต้องเริ่มต้นด้วยการเพิ่มไฟล์ 404.html ลงใน repo gh-pages ของคุณที่มีเอกสาร HTML เปล่าอยู่ข้างใน แต่เอกสารของคุณจะต้องมีทั้งหมดมากกว่า 512 ไบต์ (อธิบายไว้ด้านล่าง) ถัดไปใส่มาร์กอัพต่อไปนี้ในองค์ประกอบส่วนหัวของหน้า 404.html ของคุณ:

<script>
  sessionStorage.redirect = location.href;
</script>
<meta http-equiv="refresh" content="0;URL='/REPO_NAME_HERE'"></meta>

รหัสนี้ตั้งค่า URL การพยายามเข้าสู่ตัวแปรในวัตถุ sessionStorage มาตรฐานและเปลี่ยนเส้นทางทันทีไปยังหน้า index.html ของโครงการของคุณโดยใช้เมตารีเฟรชเมตาแท็ก หากคุณกำลังทำไซต์ Github อย่าใส่ชื่อ repo ลงในข้อความ replacer ของ attribute นั้นให้ทำดังนี้: content = "0; URL = '/'"

ในการจับภาพและคืนค่า URL ที่ผู้ใช้นำทางในตอนแรกคุณจะต้องเพิ่มแท็กสคริปต์ต่อไปนี้ในส่วนหัวของหน้า index.html ของคุณก่อนที่ JavaScript อื่นจะทำงานกับสถานะปัจจุบันของหน้า:

<script>
  (function(){
    var redirect = sessionStorage.redirect;
    delete sessionStorage.redirect;
    if (redirect && redirect != location.href) {
      history.replaceState(null, null, redirect);
    }
  })();
</script>

JavaScript บิตนี้จะดึง URL ที่เราเก็บไว้ใน sessionStorage ในหน้า 404.html และแทนที่รายการประวัติปัจจุบันด้วย

backalleycoderอ้างอิงขอบคุณ@Danielสำหรับวิธีแก้ปัญหานี้

ตอนนี้ URL ข้างต้นจะเปลี่ยนเป็นhttps://rahulrsingh09.github.io/AngularConcepts/faq


0

ฉันแก้ไขปัญหานี้ (โดยใช้แบ็กเอนด์ Java / Spring) โดยเพิ่มตัวจัดการที่ตรงกับทุกอย่างที่กำหนดในเส้นทางแองกูลาร์ของฉันที่ส่งกลับ index.html แทนที่จะเป็น 404 จากนั้นบูตใหม่นี้จะมีประสิทธิภาพ ฉันมีตัวจัดการ 404 สำหรับสิ่งที่ไม่ได้ถูกจับ

@Controller         ////don't use RestController or it will just send back the string "index.html"
public class Redirect {

    private static final Logger logger = LoggerFactory.getLogger(Redirect.class);

    @RequestMapping(value = {"comma", "sep", "list", "of", "routes"})
    public String redirectToIndex(HttpServletRequest request) {
        logger.warn("Redirect api called for URL {}. Sending index.html back instead. This will happen on a page refresh or reload when the page is on an Angular route", request.getRequestURL());
        return "/index.html";
    }
}

0

หากคุณใช้ Apache หรือ Nginx เป็นเซิร์ฟเวอร์คุณจะต้องสร้าง. htaccess

<IfModule mime_module>
      AddHandler application/x-httpd-ea-php72 .php .php7 .phtml
    </IfModule>
    # php -- END cPanel-generated handler, do not edit

    <IfModule mod_rewrite.c>
        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]
    </IfModule>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.