ฉันใช้รุ่น Angular 2.0.0-alpha.30 เมื่อเปลี่ยนเส้นทางไปยังเส้นทางอื่นแล้วรีเฟรชเบราว์เซอร์โดยแสดงเป็นไม่สามารถรับ / เส้นทาง
คุณสามารถช่วยฉันหาสาเหตุว่าทำไมข้อผิดพลาดนี้เกิดขึ้น
ฉันใช้รุ่น Angular 2.0.0-alpha.30 เมื่อเปลี่ยนเส้นทางไปยังเส้นทางอื่นแล้วรีเฟรชเบราว์เซอร์โดยแสดงเป็นไม่สามารถรับ / เส้นทาง
คุณสามารถช่วยฉันหาสาเหตุว่าทำไมข้อผิดพลาดนี้เกิดขึ้น
คำตอบ:
ข้อผิดพลาดที่คุณเห็นคือเนื่องจากคุณกำลังร้องขอ http: // localhost / route ซึ่งไม่มีอยู่ ตามที่ไซมอน
เมื่อใช้การกำหนดเส้นทาง html5 คุณต้องแมปเส้นทางทั้งหมดในแอปของคุณ (ปัจจุบัน 404) ไปที่ index.htmlในฝั่งเซิร์ฟเวอร์ของคุณ นี่คือตัวเลือกบางอย่างสำหรับคุณ:
ใช้เซิร์ฟเวอร์สด: https://www.npmjs.com/package/live-server
$live-server --entry-file=index.html`
ใช้ nginx: http://nginx.org/en/docs/beginners_guide.html
error_page 404 /index.html
Tomcat - การกำหนดค่าของ web.xml จากความคิดเห็นของKunin
<error-page>
<error-code>404</error-code>
<location>/index.html</location>
</error-page>
pub serve
หรือไม่ ด้วยวิธีนี้ฉันไม่ต้องการpub build
อะไรมากมายในระหว่างการพัฒนา ฉันพยายาม แต่ไม่สามารถทำงานได้เป็นอย่างดีกับproxy_pass
error_page
คำเตือน: การแก้ไขนี้ทำงานร่วมกับ 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 / # / เส้นทางและเมื่อคุณรีเฟรชมันจะโหลดใหม่ในตำแหน่งที่เหมาะสม
หวังว่าจะช่วย!
#
จะเพิ่มโดยอัตโนมัติใน URL มีวิธีใดที่จะลบ # ออกจาก URL โดยใช้สิ่งนี้?
#
จะเหมาะสมที่สุด
PathLocationStrategy
แต่นี่ไม่ได้ผลสำหรับฉัน ฉันใช้วิธีการที่ไม่ถูกต้องหรือฉันไม่รู้วิธีการใช้ PathLocationStrategy
โดยค่าเริ่มต้น 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หมดเปลี่ยนแปลง
update for >= RC.x
(RC.2) ทำงานได้router 3.0.0-alpha.7
แต่มีprovide
คำอธิบายประกอบว่าเลิกใช้แล้วโดยไม่มีข้อมูลเกี่ยวกับฟังก์ชันที่แทนที่
{provide: SomeClass, useClass: OtherClass}
ฉันคิดว่าข้อผิดพลาดที่คุณเห็นนั้นเป็นเพราะคุณกำลังร้องขอhttp: // localhost / routeซึ่งไม่มีอยู่ คุณต้องตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ของคุณจะจับคู่คำขอทั้งหมดไปที่หน้า index.html หลักของคุณ
เนื่องจาก Angular 2 ใช้การกำหนดเส้นทาง html5 เป็นค่าเริ่มต้นแทนที่จะใช้แฮชที่ส่วนท้ายของ URL การรีเฟรชหน้าเว็บดูเหมือนจะเป็นการร้องขอทรัพยากรอื่น
นี่เป็นสถานการณ์ทั่วไปในเราเตอร์ทุกรุ่นหากคุณใช้กลยุทธ์ตำแหน่ง 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 เราเตอร์จะเตะเข้าและทุกอย่างจะทำงานตามที่คาดไว้
ตรวจสอบให้แน่ใจว่าสิ่งนี้อยู่ในองค์ประกอบส่วนหัวของ index.html ของคุณ:
<base href="https://stackoverflow.com/">
ตัวอย่างใน Angular2 สายงานการผลิตและการนำการใช้เอกสารประกอบการใช้รหัสต่อไปนี้ในหัวแทน (พวกเขาอธิบายว่าทำไมในหมายเหตุตัวอย่างสดของเอกสาร):
<script>document.write('<base href="' + document.location + '" />');</script>
เมื่อคุณรีเฟรชหน้าสิ่งนี้จะตั้งค่าฐาน href เป็นเอกสารปัจจุบันของคุณแบบไดนามิก ฉันเห็นสิ่งนี้ทำให้เกิดความสับสนสำหรับคนที่อ่านเอกสารและพยายามทำซ้ำเสียงพลั่ว
หากคุณต้องการที่จะสามารถที่จะป้อน URL ในเบราว์เซอร์โดยไม่ต้องกำหนดค่า AppServer ของคุณเพื่อจัดการคำขอทั้งหมด index.html คุณต้องใช้HashLocationStrategy
วิธีที่ง่ายที่สุดในการกำหนดค่าคือการใช้:
RouterModule.forRoot(routes, { useHash: true })
แทน:
RouterModule.forRoot(routes)
ด้วยHashLocationStrategy URL ของคุณจะเป็นอย่างไร:
http://server:port/#/path
#
จาก url เราจะลบมันได้ไหม
ฉันมีปัญหาเดียวกันกับการใช้ webpack-dev-server ฉันต้องเพิ่มตัวเลือก devServer ใน webpack ของฉัน
// in webpack
devServer: {
historyApiFallback: true,
stats: 'minimal'
}
หากคุณใช้ 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 สิ่งที่ฉันทำเพื่อแก้ไข 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 ของคุณ
การกำหนดค่าเซิร์ฟเวอร์ไม่ใช่วิธีแก้ปัญหาสำหรับ SPA คือสิ่งที่ฉันคิด คุณไม่ต้องการโหลดแองกูลาร์สปาอีกครั้งหากมีเส้นทางที่ผิดมาใช่ไหม? ดังนั้นฉันจะไม่ขึ้นอยู่กับเส้นทางเซิร์ฟเวอร์และเปลี่ยนเส้นทางไปยังเส้นทางอื่น แต่ใช่ฉันจะให้ index.html จัดการคำขอทั้งหมดสำหรับเส้นทางเชิงมุมของเส้นทางแอปเชิงมุม
ลองใช้วิธีนี้แทนเส้นทางอื่นหรือเส้นทางที่ผิด มันใช้งานได้สำหรับฉันไม่แน่ใจ แต่ดูเหมือนว่ากำลังดำเนินการอยู่ สะดุดตัวเองเมื่อเผชิญปัญหา
@RouteConfig([
{ path: '/**', redirectTo: ['MycmpnameCmp'] },
...
}
])
https://github.com/angular/angular/issues/4055
อย่างไรก็ตามอย่าลืมกำหนดค่าโฟลเดอร์เซิร์ฟเวอร์ของคุณและเข้าถึงได้ในกรณีที่คุณมี HTML หรือเว็บสคริปต์ที่ไม่ใช่สปา มิฉะนั้นคุณจะต้องเผชิญกับปัญหา สำหรับฉันเมื่อประสบปัญหาเช่นคุณมันเป็นการผสมผสานของการกำหนดค่าเซิร์ฟเวอร์และด้านบน
สำหรับการแก้ไขด่วนเชิงมุม 5 ให้แก้ไขapp.module.tsและเพิ่ม{useHash:true}
หลังจาก appRoutes
@NgModule(
{
imports:[RouterModule.forRoot(appRoutes,{useHash:true})]
})
แอพเชิงมุมเป็นตัวเลือกที่สมบูรณ์แบบสำหรับการให้บริการด้วยเซิร์ฟเวอร์ 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 พร้อมสำหรับการปรับใช้ในทุกโหมด
คุณสามารถใช้โซลูชันนี้สำหรับแอปพลิเคชันเฉลี่ยฉันใช้ 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
สำหรับพวกเราที่ต้องดิ้นรนตลอดชีวิตใน 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 (ลิงก์ด้านบน)
คุณสามารถลองด้านล่าง มันใช้งานได้สำหรับฉัน!
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
ฉันแค่เพิ่ม. 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 ของคุณในเส้นทางฐานเป็นเส้นทางไดเรกทอรีหลักและตั้งอยู่ในการสร้างโครงการ
ฉันต้องการรักษาเส้นทาง 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>
ฉันตรวจสอบในเมล็ดมุม 2 ว่ามันทำงานอย่างไร
คุณสามารถใช้express-history-api-fallbackเพื่อเปลี่ยนเส้นทางโดยอัตโนมัติเมื่อมีการโหลดหน้าเว็บใหม่
ฉันคิดว่ามันเป็นวิธีที่ยอดเยี่ยมที่สุดในการแก้ไขปัญหา IMO
หากคุณต้องการใช้ PathLocationStrategy:
แอ็พพลิเคชันหน้าเดียวที่มี Java EE / Wildfly: การกำหนดค่าฝั่งเซิร์ฟเวอร์
2017- กรกฎาคม -11: ตั้งแต่นี้มีการเชื่อมโยงจากคำถามที่มีปัญหานี้ แต่ใช้ Angular 2 กับ Electron ฉันจะเพิ่มวิธีแก้ปัญหาของฉันที่นี่
สิ่งที่ฉันต้องทำคือลบออก<base href="./">
จาก index.html ของฉันและอิเลคตรอนเริ่มโหลดหน้านี้อีกครั้งสำเร็จ
เพิ่มการนำเข้า:
import { HashLocationStrategy, LocationStrategy } from '@angular/common';
และในผู้ให้บริการ NgModule ให้เพิ่ม:
providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}]
ใน index.html ไฟล์หลักของแอพเปลี่ยน href ฐานเป็น./index.html
จาก/
แอพเมื่อติดตั้งในเซิร์ฟเวอร์ใด ๆ จะให้ URL จริงสำหรับหน้าซึ่งสามารถเข้าถึงได้จากแอปพลิเคชันภายนอก
เพียงเพิ่ม. 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>
ฉันคิดว่าคุณจะได้รับ 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]
นี่ไม่ใช่คำตอบที่ถูกต้อง แต่เมื่อรีเฟรชคุณสามารถเปลี่ยนเส้นทางการโทรที่ตายแล้วไปยังโฮมเพจโดยเสียสละ 404 หน้ามันเป็นการแฮ็คชั่วคราวเพียงแค่เล่นซ้ำตามด้วยไฟล์ 404.html
<!doctype html>
<html>
<head>
<script type="text/javascript">
window.location.href = "http://" + document.location.host;
</script>
</head>
</html>
ทางออกที่ดีที่สุดในการแก้ปัญหา "เราเตอร์ที่ไม่ทำงานบนรีโหลดเบราว์เซอร์" คือเราควรใช้สปาถอยกลับ หากคุณกำลังใช้แอพพลิเคชั่น 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" });
});
คำตอบนั้นค่อนข้างยุ่งยาก หากคุณใช้ 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 (ซึ่งไม่ดีสำหรับโปรแกรมรวบรวมข้อมูล)นี่ไม่ใช่การแก้ไขปัญหาถาวร แต่เป็นวิธีแก้ปัญหาหรือแฮ็ก
ฉันมีปัญหาเดียวกันนี้เมื่อปรับใช้แอพเชิงมุมของฉันไปที่หน้า 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
ฉันแก้ไขปัญหานี้ (โดยใช้แบ็กเอนด์ 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";
}
}
หากคุณใช้ 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>