แก้ปัญหา ข้อผิดพลาด 404 ของการรีเฟรชหน้าด้วย Angular, VueJs, React

เริ่มไงดี 555 ก็คือ deploy angular แล้ว refresh (F5) แล้วมัน 404
ก็ลอง research พบว่าส่วนใหญ่จะแก้ config ที่ nginx กัน
แต่ server ผมไม่ได้ใช้ nginx และผมอยากทำให้มันลองรับหลายๆ server
คำตอบเลยมาจบที่ .htaccess (.htaccess/root directory คืออะไร)

ปัญหาเกิดจาก SPA

หมายถึง ทุกๆ app ที่เป็น SPA ถ้าใช้ route, path ปัญหาข้างบนยังไงก็เกิด
เพราะ SPA จะทำงานแค่ index.html แล้วใช้ javascript change DOM ตาม path

ดังนั้น ถ้าเรากดเว็บไปเรื่อย มันจะไม่ error เพราะ browser มันมองว่ามันอยู่หน้า index.html เหมือนเดิม (อยากรู้ว่า redirect หรือไม่ ลองลง Redirect Path)

แต่ถ้าเมื่อไหร่ที่มีการ F5 มันจะ error เพราะ path ปัจจุบันที่อยู่ ไม่ได้มีอยู่จริงใน directory server เช่น step ดังนี้

เข้า browser แล้วเล่นเปิด 1 -> กด 2 -> กด 3
1. https://app.kreangkrai.com/
2. https://app.kreangkrai.com/paste-bin
3. F5

browser จะ refresh ใหม่และ คิดว่าเรากำลังอยู่หน้า paste-bin
ดังนั้นมันจะไปหา directory paste-bin/index.html แต่ไม่มีไง
มันเลย Error 404 (อ๋ออออออ)

แล้วแก้ยังไงละ?

วิธีแก้คือ ก็ส่งกลับไป index.html นั้นแหละ
ส่งกลับไปด้วย mod_rewrite
สร้าง .htaccess ใน root directory แล้วก็แปะโค้ดนี้

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^(.*) /index.html [NC,L]

ตรง RewriteRule . index.html [L] เนี่ยแหละ จะเป็นตัวส่งกลับไป index.html
ด้วย path /paste-bin ดังนั้น
พอ SPA รับ /paste-bin มา ก็เลย render DOM หน้า /paste-bin ให้

Step จะเป็นแบบนี้

  1. หลังจากด F5
  2. browser ส่งคำขอหน้าเว็บ /paste-bin
  3. .htaccess ดักตีหัว และส่งกลับให้แต่ index.html
  4. browser รับหน้า index.html แต่ยังมี path /paste-bin
  5. ดังนั้น browser จึงเปิดหน้า index.html ที่ SPA เป็น /paste-bin

อ่านมาถึงตรงนี้ ผมก็คงบอกว่า ผมเองก็มั่วมาเยอะ เข้าใจผิดก็เยอะ
step ที่กล่าวข้างบน อาจจะไม่ถูกต้อง แต่ภาพมันจะประมาณนี้แหละ

Command Flag
[R]     Redirect you can add an =301 or =302 to change the type.
[F]    Forces the url to be forbidden. 403 header
[G]    Forces the url to be gone 401 header
[L]    Last rule. (You should use this on all your rules that don’t link together)
[N]    Next round. Rerun the rules again from the start
[C]    Chains a rewrite rule together with the next rule.
[T]    use T=MIME-type to force the file to be a mime type
[NS]    Use if no sub request is requested
[NC]    Makes the rule case INsensitive
[QSA]    Query String Append use to add to an existing query string
[NE]    Turns of normal escapes that are default in the rewriterule
[PT]    Pass through to the handler (together with mod alias)
   Skip the next rule S=3 skips the next 3 rules
[E]    E=var sets an enviromental variable that can be called by other rules