เมื่อดูความคิดเห็นเกี่ยวกับคำตอบที่ยอมรับและลักษณะทั่วไปของคำถามนี้ ('ไม่ทำงาน') ฉันคิดว่านี่อาจเป็นสถานที่ที่ดีสำหรับคำอธิบายทั่วไปเกี่ยวกับปัญหาที่เกี่ยวข้องที่นี่ ดังนั้นคำตอบนี้มีวัตถุประสงค์เพื่อเป็นข้อมูลพื้นหลัง / รายละเอียดเกี่ยวกับกรณีการใช้งานเฉพาะของ OP กรุณาอดทนกับฉัน
ฝั่งเซิร์ฟเวอร์กับฝั่งไคลเอ็นต์
สิ่งใหญ่แรกที่ต้องทำความเข้าใจเกี่ยวกับเรื่องนี้คือตอนนี้มี 2 แห่งที่ตีความ URL ในขณะที่เคยมีเพียง 1 ใน 'วันเก่า' ในอดีตเมื่อชีวิตเรียบง่ายผู้ใช้บางคนส่งคำขอhttp://example.com/about
ไปยังเซิร์ฟเวอร์ซึ่งตรวจสอบส่วนเส้นทางของ URL กำหนดว่าผู้ใช้ร้องขอหน้าเกี่ยวกับแล้วส่งกลับหน้านั้น
ด้วยการกำหนดเส้นทางฝั่งไคลเอ็นต์ซึ่งเป็นสิ่งที่ React-Router จัดให้มีสิ่งต่าง ๆ เรียบง่ายน้อยลง ตอนแรกลูกค้ายังไม่ได้โหลดรหัส JS ใด ๆ ดังนั้นการร้องขอแรกจะไปที่เซิร์ฟเวอร์เสมอ จากนั้นจะส่งคืนหน้าที่มีแท็กสคริปต์ที่จำเป็นในการโหลด React และ React Router เป็นต้นเฉพาะเมื่อสคริปต์เหล่านั้นโหลดแล้วจะเริ่มเฟส 2 ในเฟส 2 เมื่อผู้ใช้คลิกที่ลิงก์การนำทาง 'เกี่ยวกับเรา' URL จะถูกเปลี่ยนเฉพาะภายในเป็นhttp://example.com/about
(ทำโดยAPI ประวัติ ) ที่เป็นไปได้แต่ไม่มีการร้องขอไปยังเซิร์ฟเวอร์. แต่เราท์เตอร์ React จะทำสิ่งนั้นในฝั่งไคลเอ็นต์พิจารณาว่ามุมมอง React ใดที่จะเรนเดอร์และแสดงผล สมมติว่าหน้าเกี่ยวกับของคุณไม่จำเป็นต้องทำการเรียกใช้ REST ใด ๆ ก็เสร็จสิ้นแล้ว คุณได้เปลี่ยนจากหน้าแรกเป็นเกี่ยวกับเราโดยไม่มีการร้องขอจากเซิร์ฟเวอร์
ดังนั้นโดยทั่วไปเมื่อคุณคลิกลิงค์บาง Javascript วิ่งปรุงแต่งว่า URL ในแถบที่อยู่ที่ไม่ก่อให้เกิดการฟื้นฟูหน้าซึ่งจะทำให้เกิดการตอบสนอง Router เพื่อดำเนินการเปลี่ยนแปลงหน้าบนฝั่งไคลเอ็นต์
แต่ตอนนี้ให้พิจารณาว่าจะเกิดอะไรขึ้นหากคุณคัดลอกวาง URL ในแถบที่อยู่และส่งอีเมลถึงเพื่อน เพื่อนของคุณยังไม่ได้โหลดเว็บไซต์ของคุณ ในคำอื่น ๆ ที่เธอยังอยู่ในขั้นตอนที่ 1 ยังไม่มีเราเตอร์ที่ทำงานอยู่ในเครื่องของเธอ ดังนั้นเบราว์เซอร์ของเธอจะทำให้คำขอเซิร์ฟเวอร์http://example.com/about
ไป
และนี่คือที่ที่ปัญหาของคุณเริ่มต้นขึ้น จนถึงตอนนี้คุณสามารถหลีกเลี่ยงได้ด้วยการวาง HTML คงที่ไว้ที่ webroot ของเซิร์ฟเวอร์ของคุณ แต่ที่จะให้404
ข้อผิดพลาดสำหรับ URL อื่น ๆ ทั้งหมดเมื่อมีการร้องขอจากเซิร์ฟเวอร์ URL เดียวกันเหล่านั้นทำงานได้ดีในฝั่งไคลเอ็นต์เนื่องจากมี React Router กำลังทำการกำหนดเส้นทางให้คุณ แต่URL นั้นล้มเหลวที่ฝั่งเซิร์ฟเวอร์เว้นแต่คุณจะทำให้เซิร์ฟเวอร์ของคุณเข้าใจ
รวมการกำหนดเส้นทางเซิร์ฟเวอร์และฝั่งไคลเอ็นต์
หากคุณต้องการให้http://example.com/about
URL ทำงานได้ทั้งบนเซิร์ฟเวอร์และฝั่งไคลเอ็นต์คุณต้องตั้งค่าเส้นทางสำหรับทั้งบนฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์ เหมาะสมหรือไม่
และนี่คือที่ตัวเลือกของคุณเริ่มต้น โซลูชันมีตั้งแต่การข้ามปัญหาไปพร้อมกันผ่านเส้นทาง catch-all ที่ส่งคืน bootstrap HTML ไปยังวิธี isomorphic แบบเต็มซึ่งเซิร์ฟเวอร์และไคลเอนต์ใช้รหัส JS เดียวกัน
.
การข้ามปัญหาไปพร้อมกัน: ประวัติแฮช
ด้วยHash Historyแทนที่จะเป็นBrowser History URL ของคุณสำหรับหน้าเกี่ยวกับจะมีลักษณะดังนี้:
http://example.com/#/about
ส่วนหลัง#
สัญลักษณ์hash ( ) จะไม่ถูกส่งไปยังเซิร์ฟเวอร์ ดังนั้นเซิร์ฟเวอร์จะเห็นhttp://example.com/
และส่งหน้าดัชนีตามที่คาดไว้เท่านั้น React-Router จะหยิบชิ้น#/about
ส่วนขึ้นมาและแสดงหน้าที่ถูกต้อง
ข้อเสีย :
- URL 'น่าเกลียด'
- การแสดงภาพฝั่งเซิร์ฟเวอร์ไม่สามารถทำได้ด้วยวิธีการนี้ เท่าที่เกี่ยวข้องกับ Search Engine Optimization (SEO) เว็บไซต์ของคุณประกอบด้วยหน้าเดียวที่แทบไม่มีเนื้อหาใด ๆ
.
จับทั้งหมด
ด้วยวิธีการนี้คุณจะใช้ประวัติเบราว์เซอร์ แต่เพียงตั้งค่า catch-all บนเซิร์ฟเวอร์ที่ส่ง/*
ไปindex.html
ให้คุณได้อย่างมีประสิทธิภาพเหมือนกับสถานการณ์ประวัติแฮช อย่างไรก็ตามคุณมี URL ที่สะอาดและคุณสามารถปรับปรุงรูปแบบนี้ได้ในภายหลังโดยไม่ต้องทำให้รายการโปรดของผู้ใช้ทั้งหมดไม่ถูกต้อง
ข้อเสีย :
- การตั้งค่าที่ซับซ้อนมากขึ้น
- ยังไม่มี SEO ที่ดี
.
เป็นลูกผสม
ในวิธีไฮบริดคุณขยายตามสถานการณ์ catch-all โดยการเพิ่มสคริปต์เฉพาะสำหรับเส้นทางที่เฉพาะเจาะจง คุณสามารถสร้างสคริปต์ PHP แบบง่าย ๆ เพื่อส่งคืนหน้าที่สำคัญที่สุดของไซต์ของคุณด้วยเนื้อหาที่รวมอยู่ดังนั้น Googlebot สามารถดูว่ามีอะไรอยู่บนหน้าของคุณ
ข้อเสีย :
- ซับซ้อนยิ่งขึ้นในการตั้งค่า
- SEO ที่ดีสำหรับเส้นทางเหล่านั้นที่คุณให้การดูแลเป็นพิเศษ
- รหัสซ้ำสำหรับการแสดงผลเนื้อหาบนเซิร์ฟเวอร์และไคลเอนต์
.
ซึ่งมีรูปร่างสัณฐานเหมือนกัน
เกิดอะไรขึ้นถ้าเราใช้โหนด JS เป็นเซิร์ฟเวอร์ของเราเพื่อให้เราสามารถทำงานเดียวกันรหัส JS ที่ปลายทั้งสอง? ตอนนี้เรามีเส้นทางทั้งหมดที่กำหนดไว้ในการกำหนดค่า react-router เดียวและเราไม่จำเป็นต้องทำซ้ำรหัสการเรนเดอร์ของเรา นี่คือ 'จอกศักดิ์สิทธิ์' เพื่อที่จะพูด เซิร์ฟเวอร์ส่งมาร์กอัปเดียวกันกับที่เราจะได้รับหากการเปลี่ยนหน้าเกิดขึ้นกับลูกค้า โซลูชันนี้เหมาะสมที่สุดในแง่ของ SEO
ข้อเสีย :
- เซิร์ฟเวอร์ต้อง (สามารถ) เรียกใช้ JS ฉันทดลองกับ Java icw Nashorn แต่มันไม่ได้ผลสำหรับฉัน ในทางปฏิบัติมันส่วนใหญ่หมายความว่าคุณต้องใช้เซิร์ฟเวอร์ที่ใช้ Node JS
- ปัญหาสิ่งแวดล้อมที่ยุ่งยากมากมาย (ใช้
window
กับฝั่งเซิร์ฟเวอร์ ฯลฯ )
- โค้งการเรียนรู้ที่สูงชัน
.
ฉันควรใช้แบบไหน
เลือกหนึ่งที่คุณสามารถไปด้วย โดยส่วนตัวแล้วฉันคิดว่า catch-all นั้นง่ายพอที่จะตั้งค่าได้ การตั้งค่านี้ช่วยให้คุณสามารถปรับปรุงสิ่งต่าง ๆ ในช่วงเวลา หากคุณใช้ Node JS เป็นแพลตฟอร์มเซิร์ฟเวอร์อยู่แล้วฉันจะตรวจสอบการทำแอป isomorphic อย่างแน่นอน ใช่มันยากในตอนแรก แต่เมื่อคุณได้รับการแขวนมันจริง ๆ แล้วมันเป็นทางออกที่ดีมากสำหรับปัญหา
โดยพื้นฐานแล้วสำหรับฉันนั่นจะเป็นปัจจัยในการตัดสินใจ ถ้าเซิร์ฟเวอร์ของฉันทำงานบน Node JS ฉันจะใช้ isomorphic ไม่เช่นนั้นฉันจะเลือกใช้โซลูชัน Catch-all และขยายให้มากขึ้น (โซลูชัน Hybrid) เมื่อเวลาผ่านไปและความต้องการ SEO ต้องการ
หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการแสดงผล isomorphic (หรือที่เรียกว่า 'สากล') ด้วย React มีบทช่วยสอนที่ดีในหัวข้อ:
นอกจากนี้เพื่อให้คุณเริ่มต้นฉันขอแนะนำให้ดูชุดเริ่มต้นบางอย่าง เลือกอันที่ตรงกับตัวเลือกของคุณสำหรับสแต็คเทคโนโลยี (โปรดจำไว้ว่า React เป็นเพียง V ใน MVC คุณต้องการสิ่งเพิ่มเติมเพื่อสร้างแอปแบบเต็ม) เริ่มต้นด้วยการดูที่เผยแพร่โดย Facebook เอง:
หรือเลือกหนึ่งในหลาย ๆ แห่งโดยชุมชน มีเว็บไซต์ที่ดีในขณะนี้ที่พยายามจัดทำดัชนีทั้งหมด:
ฉันเริ่มต้นด้วยสิ่งเหล่านี้:
ขณะนี้ฉันกำลังใช้การเรนเดอร์สากลที่ให้แรงบันดาลใจจากชุดเลขหมายสองชุดด้านบน แต่ตอนนี้มันล้าสมัยแล้ว
ขอให้โชคดีกับภารกิจของคุณ!