Làm thế nào để định cấu hình đúng Apache trên một ứng dụng SPA React nằm trên một thư mục con sử dụng các URL lồng nhau được xây dựng từ React Router?

Jul 04 2020

Tôi có trang web của mình được lưu trữ trên một thư mục con, chẳng hạn như http: // mywebsite / admin, trong đó / admin là thư mục con

Tôi đã tải ứng dụng phản ứng của mình (tạo bản dựng ứng dụng tạo phản ứng) lên thư mục con / admin. Tôi cũng đang sử dụng react-router v4 BrowserRouter để thực hiện một số định tuyến phía máy khách đơn giản. Dưới đây là một số đoạn trích liên quan trên ứng dụng phản ứng của tôi:

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import { BrowserRouter } from 'react-router-dom';

import './css/custom.css';

ReactDOM.render(<BrowserRouter basename="/admin"><App /></BrowserRouter>, document.getElementById("root"));

bên trong hàm kết xuất App.jsx

<Route
    path='/students'
    render={(props) =>
        <Students
            {...props}
        />
    }
/>

<Route
    path='/teachers'
    render={(props) =>
        <Teachers
            {...props}
        />
    }
/>

Tất cả đều tốt và hoạt động tốt khi điều hướng trang web bao gồm các url lồng nhau, như bạn đã thấy trên các đoạn trích, /admin/students& /admin/teachers.

Vấn đề chính: khi tôi đang trên /admin/teacherstuyến đường và tôi làm mới trang , trang không tải bất kỳ thứ gì. Làm mới chỉ hoạt động khi tôi đang trên /admintuyến đường. Nhưng không phải khi nó /admin/teacherscũng không /admin/students.

Đây không phải là lần đầu tiên tôi xây dựng một SPA sử dụng react-router v4 được lưu trữ trên máy chủ Apache. Tôi đã sử dụng lại .htaccess mà tôi có trong dự án trước đây của mình. .Htaccess này cũng nằm trong /adminthư mục con. Dưới đây là .htaccess:

.htaccess

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.html?path=$1 [NC,L,QSA]

Điều này định tuyến tất cả các yêu cầu tới index.html được tạo bởi phiên bản sản xuất ứng dụng tạo-phản ứng. Tuy nhiên, theo điều tra của tôi, loại cấu hình này chỉ hoạt động trên một dự án không nằm trên thư mục con và không sử dụng các URL lồng nhau.

Lưu ý, .htaccessbây giờ tôi có 2 cái . Một trên /adminthư mục gốc và một trong thư mục con. Cả hai đều chứa các .htaccessmã giống nhau . Lý do cho điều này là, tôi có một SPA khác đang chạy tại thư mục gốc.

Tôi đang thiếu gì?

Làm thế nào để định cấu hình Apache đúng cách trên một ứng dụng SPA React nằm trên một thư mục con sử dụng các URL lồng nhau được xây dựng từ React Router?

Trả lời

2 MrWhite Jul 17 2020 at 00:05

Chủ yếu giải quyết câu trả lời của OP , cộng với một số lưu ý khác ...

Đây là nơi tôi đã mắc lỗi:

Lưu ý rằng tôi có 2 .htaccess bây giờ. Một trên thư mục gốc và một ở thư mục con / admin. Cả hai đều chứa các mã .htaccess giống nhau. Lý do cho điều này là, tôi có một SPA khác đang chạy tại thư mục gốc.

Đây không nhất thiết là một "sai lầm" - bạn chỉ cần đảm bảo rằng bạn đang sử dụng các lệnh chính xác. Trên thực tế, giữ hai .htaccesstệp riêng biệt có thể thích hợp hơn nếu chúng được dự định là các SPA hoàn toàn riêng biệt.

Để có hai .htaccesstệp riêng biệt - giống hệt nhau - những điểm quan trọng là:

  • Làm cho chuỗi thay thế tương đối , tức là. không có tiền tố gạch chéo.
  • Không bao gồm một RewriteBasechỉ thị. (Điều này sẽ ghi đè tiền tố thư mục.)

Khi chuỗi RewriteRule thay thế là một đường dẫn tương đối thì tiền tố thư mục (tức là vị trí của .htaccesstệp) được thêm trở lại vào cuối quá trình viết lại.

Vì vậy, cả hai /.htaccess/admin/.htaccesssẽ chứa các lệnh giống hệt nhau:

RewriteEngine on
RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.+) index.html?path=$1 [L,QSA]

TUY NHIÊN, một sự khác biệt nhỏ giữa giải pháp này và giải pháp của OP là admin/một phần của đường dẫn URL không được chuyển đến paththam số URL. Bạn có thể mã hóa cứng này nếu cần. ví dụ. index.html?path=admin/$1. Hoặc giải thích điều này trong kịch bản của bạn.

Đầu tiên RewriteRulechỉ là một tối ưu hóa nhỏ ngăn chặn việc kiểm tra thêm hệ thống tệp sau khi yêu cầu đã được ghi lại thành index.html.

Lưu ý rằng tôi đã thay đổi (.*)(0 hoặc nhiều hơn) thành (.+)(1 hoặc nhiều hơn). Điều này tránh kiểm tra thư mục bổ sung khi yêu cầu thư mục gốc. I E. example.com/example.com/admin/. Bạn không viết lại các yêu cầu này, nhưng thay vào đó, phụ thuộc vào DirectoryIndex index.htmlviệc được đặt một cách thích hợp - đây là cài đặt mặc định trong cấu hình máy chủ.

Vì chuỗi thay thế ( index.php?page=$1) là tương đối, khi ở trong tài liệu gốc, nó sẽ ghi lại một cách hiệu quả /index.phpvà khi nào ở trong /admin/.htaccessđó sẽ viết lại thành một cách hiệu quả /admin/index.php.

Lưu ý rằng các chỉ thị mod_rewrite /admin/.htaccessghi đè hoàn toàn các chỉ thị mod_rewrite trong .htaccesstệp mẹ vì các chỉ thị mod_rewrite không được kế thừa theo mặc định (không giống như các mô-đun khác).


Ngoài ra, để tránh lặp lại, trong khi vẫn duy trì hai .htaccesstệp riêng biệt, bạn có thể bật kế thừa mod_rewrite trong /admin/.htaccesstệp. Ví dụ...

Trong /.htaccesstệp gốc :

RewriteEngine on
RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.+) index.html?path=$1 [L,QSA]

Sau đó, thay vào đó, /admin/.htaccessbạn sẽ có những thứ sau:

RewriteEngine On
RewriteOptions Inherit

Điều này kế thừa các chỉ thị mod_rewrite mẹ như thể chúng được sao chép tại chỗ theo đúng nghĩa đen trong /admin/.htaccesstệp.

Tuy nhiên, điều này làm tăng thêm một lớp phức tạp. Ngoài việc SPA /adminhiện đang phụ thuộc vào .htaccesstệp gốc , bây giờ bạn phải cẩn thận rằng bạn không thêm bất kỳ chỉ thị vi phạm nào vào .htaccesstệp gốc .


Qua một bên:

RewriteCond %{REQUEST_URI} admin
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) admin/index.html?path=$1 [QSA,L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.*) index.html?path=$1 [QSA,L]

Điều kiện đầu tiên để kiểm tra "quản trị viên" trong đường dẫn URL (ngẫu nhiên, điều này kiểm tra "quản trị viên" ở bất kỳ đâu trong đường dẫn URL - điều này không hoàn toàn chính xác) là không bắt buộc - việc kiểm tra có thể được thực hiện tối ưu hơn trong RewriteRulechỉ thị chính nó. Ví dụ:

RewriteRule ^(admin/.*) admin/index.html?path=$1 [QSA,L]

Hai quy tắc này có thể được kết hợp thành một nếu muốn, có thể có sự rõ ràng. Ví dụ:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(admin/)?.* $1index.html?path=$0 [QSA,L]

Sau $1đó, backreference chứa tiền tố đường dẫn tùy chọn, admin/hoặc không có gì . Và $0chứa các trận đấu đầy đủ.

2 eric Jul 14 2020 at 06:35

Đây là nơi tôi đã mắc lỗi:

Lưu ý rằng tôi có 2 .htaccess bây giờ. Một trên thư mục gốc và một ở thư mục con / admin. Cả hai đều chứa các mã .htaccess giống nhau. Lý do cho điều này là, tôi có một SPA khác đang chạy tại thư mục gốc.

Đơn giản chỉ cần điều chỉnh gốc của tôi .htaccess và xóa các .htaccessđó là bên trong các vấn đề chính / admin subdirectory cố định được mô tả trên câu hỏi của tôi.

Root .htaccess :

RewriteCond %{REQUEST_URI} admin
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) admin/index.html?path=$1 [QSA,L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.*) index.html?path=$1 [QSA,L]
1 DanieleRicci Jul 09 2020 at 05:46

Tôi thực sự không biết câu trả lời cho vấn đề của bạn, nhưng tôi có thể đề nghị bạn chơi với Locationchỉ thị; cái gì đó như

<Location "/admin">
  RewriteEngine on
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ /admin/index.html?path=$1 [NC,L,QSA]
</Location>

Hi vọng điêu nay co ich.