Các url của bộ định tuyến phản ứng không hoạt động khi làm mới hoặc viết thủ công

761
DavidDev 2015-01-14 07:51.

Tôi đang sử dụng React-router và nó hoạt động tốt khi tôi nhấp vào các nút liên kết, nhưng khi tôi làm mới trang web của mình, nó không tải những gì tôi muốn.

Ví dụ, tôi đang ở localhost/joblistvà mọi thứ đều ổn vì tôi đã đến đây bằng cách nhấn vào một liên kết. Nhưng nếu tôi làm mới trang web, tôi nhận được:

Cannot GET /joblist

Theo mặc định, nó không hoạt động như thế này. Ban đầu tôi đã URL của tôi là localhost/#/localhost/#/joblistvà họ làm việc hoàn toàn tốt đẹp. Nhưng tôi không thích loại URL này, vì vậy cố gắng xóa nó đi #, tôi đã viết:

Router.run(routes, Router.HistoryLocation, function (Handler) {
 React.render(<Handler/>, document.body);
});

Vấn đề này không xảy ra với localhost/, điều này luôn trả về những gì tôi muốn.

CHỈNH SỬA: Ứng dụng này là một trang, vì vậy /joblistkhông cần phải hỏi bất kỳ máy chủ nào.

EDIT2: Toàn bộ bộ định tuyến của tôi.

var routes = (
    <Route name="app" path="/" handler={App}>
        <Route name="joblist" path="/joblist" handler={JobList}/>
        <DefaultRoute handler={Dashboard}/>
        <NotFoundRoute handler={NotFound}/>
    </Route>
);

Router.run(routes, Router.HistoryLocation, function (Handler) {
  React.render(<Handler/>, document.body);
});

30 answers

1224
Stijn de Witt 2016-04-15 02:27.

Nhìn vào các nhận xét về câu trả lời được chấp nhận và bản chất chung của câu hỏi này ('không hoạt động'), tôi nghĩ đây có thể là một nơi tốt cho một số giải thích chung về các vấn đề liên quan ở đây. Vì vậy, câu trả lời này nhằm mục đích làm thông tin cơ bản / chi tiết về trường hợp sử dụng cụ thể của OP. Xin vui lòng chịu với tôi.

Phía máy chủ so với phía Máy khách

Điều quan trọng đầu tiên cần hiểu về điều này là hiện tại có 2 nơi URL được diễn giải, trong khi trước đây chỉ có 1 trong 'ngày xưa'. Trước đây, khi cuộc sống còn đơn giản, một số người dùng đã gửi yêu cầu http://example.com/abouttới máy chủ, máy chủ sẽ kiểm tra phần đường dẫn của URL, xác định người dùng đang yêu cầu trang giới thiệu và sau đó gửi lại trang đó.

Với định tuyến phía máy khách, vốn là thứ mà React-Router cung cấp, mọi thứ ít đơn giản hơn. Lúc đầu, máy khách chưa tải bất kỳ mã JS nào. Vì vậy, yêu cầu đầu tiên sẽ luôn là máy chủ. Sau đó, nó sẽ trả về một trang có chứa các thẻ script cần thiết để tải React và React Router, v.v. Chỉ khi những script đó đã được tải xong thì giai đoạn 2 mới bắt đầu. Trong giai đoạn 2, khi người dùng nhấp vào liên kết điều hướng 'Giới thiệu về chúng tôi' chẳng hạn, URL chỉ được thay đổi cục bộ thành http://example.com/about(có thể thực hiện bởi API Lịch sử ), nhưng không có yêu cầu nào đối với máy chủ được thực hiện . Thay vào đó, React Router thực hiện công việc của nó ở phía máy khách, xác định xem React nào sẽ hiển thị và hiển thị nó. Giả sử trang giới thiệu của bạn không cần thực hiện bất kỳ lệnh gọi REST nào, nó đã được thực hiện. Bạn đã chuyển đổi từ Trang chủ sang Giới thiệu mà không có bất kỳ yêu cầu máy chủ nào được kích hoạt.

Vì vậy, về cơ bản khi bạn nhấp vào một liên kết, một số Javascript chạy thao tác với URL trong thanh địa chỉ mà không gây ra làm mới trang , do đó khiến React Router thực hiện chuyển đổi trang ở phía máy khách .

Nhưng bây giờ hãy xem xét điều gì sẽ xảy ra nếu bạn sao chép và dán URL vào thanh địa chỉ và gửi email cho bạn bè. Bạn của bạn chưa tải trang web của bạn. Nói cách khác, cô ấy vẫn đang trong giai đoạn 1 . Không có Bộ định tuyến phản ứng nào đang chạy trên máy của cô ấy. Vì vậy, trình duyệt của mình sẽ làm cho một yêu cầu máy chủ để http://example.com/about.

Và đây là nơi mà rắc rối của bạn bắt đầu. Cho đến bây giờ, bạn có thể thoát khỏi chỉ cần đặt một HTML tĩnh tại webroot của máy chủ của bạn. Nhưng điều đó sẽ gây ra 404lỗi cho tất cả các URL khác khi được yêu cầu từ máy chủ . Các URL tương tự đó hoạt động tốt ở phía máy khách , vì ở đó Bộ định tuyến React đang thực hiện định tuyến cho bạn, nhưng chúng không thành công ở phía máy chủ trừ khi bạn làm cho máy chủ của mình hiểu chúng.

Kết hợp định tuyến phía máy chủ và phía máy khách

Nếu bạn muốn http://example.com/aboutURL hoạt động trên cả máy chủ và phía máy khách, bạn cần thiết lập các tuyến cho nó trên cả phía máy chủ và máy khách. Có lý phải không?

Và đây là nơi bắt đầu lựa chọn của bạn. Các giải pháp bao gồm từ việc vượt qua hoàn toàn vấn đề, thông qua một tuyến bắt tất cả trả về HTML bootstrap, đến cách tiếp cận đẳng hình đầy đủ trong đó cả máy chủ và máy khách chạy cùng một mã JS.

.

Vượt qua vấn đề hoàn toàn: Lịch sử băm

Với Lịch sử băm thay vì Lịch sử trình duyệt , URL của trang giới thiệu sẽ trông giống như sau: http://example.com/#/about Phần sau #biểu tượng băm ( ) không được gửi đến máy chủ. Vì vậy máy chủ chỉ nhìn thấy http://example.com/và gửi trang chỉ mục như mong đợi. React-Router sẽ chọn #/aboutmột phần và hiển thị trang chính xác.

Nhược điểm :

  • URL 'xấu xí'
  • Phương pháp này không thể kết xuất phía máy chủ. Liên quan đến Tối ưu hóa Công cụ Tìm kiếm (SEO), trang web của bạn bao gồm một trang duy nhất hầu như không có bất kỳ nội dung nào trên đó.

.

Bắt hết

Với cách tiếp cận này, bạn sử dụng Lịch sử trình duyệt, nhưng chỉ cần thiết lập một bản tóm tắt trên máy chủ gửi /*đến index.html, mang lại hiệu quả cho bạn tình huống tương tự như với Lịch sử băm. Tuy nhiên, bạn có các URL rõ ràng và bạn có thể cải thiện chương trình này sau đó mà không phải làm mất hiệu lực tất cả các mục yêu thích của người dùng.

Nhược điểm :

  • Phức tạp hơn để thiết lập
  • Vẫn không có SEO tốt

.

Hỗn hợp

Trong cách tiếp cận kết hợp, bạn mở rộng theo kịch bản tổng hợp bằng cách thêm các tập lệnh cụ thể cho các tuyến đường cụ thể. Bạn có thể tạo một số tập lệnh PHP đơn giản để trả về các trang quan trọng nhất trên trang web của mình với nội dung được bao gồm, vì vậy, Googlebot ít nhất có thể xem nội dung trên trang của bạn.

Nhược điểm :

  • Thậm chí phức tạp hơn để thiết lập
  • Chỉ SEO tốt cho những tuyến đường mà bạn đưa ra liệu pháp đặc biệt
  • Mã trùng lặp để hiển thị nội dung trên máy chủ và máy khách

.

Isomorphic

Điều gì sẽ xảy ra nếu chúng ta sử dụng Node JS làm máy chủ của mình để chúng ta có thể chạy cùng một mã JS ở cả hai đầu? Bây giờ, chúng tôi đã xác định tất cả các tuyến đường của mình trong một cấu hình bộ định tuyến phản ứng duy nhất và chúng tôi không cần phải sao chép mã hiển thị của mình. Có thể nói đây là 'chén thánh'. Máy chủ gửi đánh dấu giống hệt như chúng tôi sẽ gửi nếu quá trình chuyển đổi trang xảy ra trên máy khách. Giải pháp này là tối ưu về mặt SEO.

Nhược điểm :

  • Máy chủ phải (có thể) chạy JS. Tôi đã thử nghiệm với Java icw Nashorn nhưng nó không hoạt động với tôi. Trong thực tế, điều đó chủ yếu có nghĩa là bạn phải sử dụng máy chủ dựa trên Node JS.
  • Nhiều vấn đề môi trường phức tạp (sử dụng windowtrên phía máy chủ, v.v.)
  • Đường cong học tập sâu sắc

.

Tôi nên sử dụng cái nào?

Chọn cái mà bạn có thể bỏ đi. Cá nhân tôi nghĩ rằng tóm tắt là đủ đơn giản để thiết lập, vì vậy đó sẽ là mức tối thiểu của tôi. Thiết lập này cho phép bạn cải thiện mọi thứ theo thời gian. Nếu bạn đang sử dụng Node JS làm nền tảng máy chủ của mình, tôi chắc chắn sẽ điều tra việc thực hiện một ứng dụng isomorphic. Vâng, lúc đầu thì khó, nhưng khi bạn hiểu rõ thì đó thực sự là một giải pháp rất hữu ích cho vấn đề.

Vì vậy, về cơ bản, đối với tôi, đó sẽ là yếu tố quyết định. Nếu máy chủ của tôi chạy trên Node JS, tôi sẽ đi isomorphic; nếu không, tôi sẽ sử dụng giải pháp Catch-all và chỉ mở rộng trên nó (Giải pháp kết hợp) khi thời gian tiến triển và các yêu cầu SEO đòi hỏi nó.

Nếu bạn muốn tìm hiểu thêm về kết xuất isomorphic (còn gọi là 'phổ quát') với React, có một số hướng dẫn tốt về chủ đề này:

Ngoài ra, để giúp bạn bắt đầu, tôi khuyên bạn nên xem một số bộ dụng cụ khởi động. Chọn một cái phù hợp với lựa chọn của bạn cho hệ thống công nghệ (hãy nhớ rằng React chỉ là chữ V trong MVC, bạn cần nhiều thứ hơn để xây dựng một ứng dụng đầy đủ). Bắt đầu với việc xem xét một công cụ do chính Facebook xuất bản:

Hoặc chọn một trong số nhiều người của cộng đồng. Có một trang web tốt hiện đang cố gắng lập chỉ mục tất cả chúng:

Tôi bắt đầu với những điều này:

Hiện tại, tôi đang sử dụng phiên bản kết xuất phổ quát tại nhà được lấy cảm hứng từ hai bộ dụng cụ bắt đầu ở trên, nhưng chúng đã lỗi thời.

Chúc may mắn với tìm kiếm của bạn!

123
jmancherje 2016-05-26 14:26.

Tất cả các câu trả lời ở đây đều cực kỳ hữu ích, những gì phù hợp với tôi là cấu hình máy chủ Webpack của tôi để mong đợi các tuyến đường.

devServer: {
   historyApiFallback: true,
   contentBase: './',
   hot: true
},

HistoryApiFallback là thứ đã khắc phục sự cố này cho tôi. Giờ đây, định tuyến hoạt động chính xác và tôi có thể làm mới trang hoặc nhập trực tiếp URL. Không cần phải lo lắng về các giải pháp thay thế trên máy chủ nút của bạn. Câu trả lời này rõ ràng chỉ hoạt động nếu bạn đang sử dụng webpack.

CHỈNH SỬA: xem câu trả lời của tôi ở đây để biết lý do chi tiết hơn tại sao điều này là cần thiết: https://stackoverflow.com/a/37622953/5217568

100
BrahimS 2016-11-15 05:10.

Bạn có thể thay đổi .htaccesstệp của mình và chèn cái này:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]
</IfModule>

Tôi đang sử dụng react: "^16.12.0"react-router: "^5.1.2" Phương pháp này là Bắt tất cả và có lẽ là cách dễ nhất để bạn bắt đầu.

70
user2875289 2017-04-19 01:16.

Đối với người dùng React Router V4 :

Nếu bạn cố gắng giải quyết vấn đề này bằng kỹ thuật Hash History được đề cập trong các câu trả lời khác, hãy lưu ý rằng

<Router history={hashHistory} >

không hoạt động trong V4, vui lòng sử dụng HashRouterthay thế:

import { HashRouter } from 'react-router-dom'

<HashRouter>
  <App/>
</HashRouter>

Tham khảo: HashRouter

39
Aidin 2017-09-05 00:43.

Tôi vừa mới sử dụng create-react-app để tạo một trang web và gặp vấn đề tương tự được trình bày ở đây. Tôi sử dụng BrowserRoutingtừ react-router-domgói. Tôi đang chạy trên máy chủ Nginx và điều đã giải quyết được vấn đề đó cho tôi là thêm phần sau vào/etc/nginx/yourconfig.conf

location / {
  if (!-e $request_filename){
    rewrite ^(.*)$ /index.html break;
  }
}

Điều này tương ứng với việc thêm phần sau .htaccessvào trường hợp bạn đang chạy Appache

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

Đây dường như cũng là giải pháp do chính Facebook đề xuất và bạn có thể tham khảo tại đây

31
Efe Ariaroo 2018-04-02 04:26.

Trong index.html của bạn head, hãy thêm thông tin sau:

<base href="/">
<!-- This must come before the css and javascripts -->

Sau đó, khi chạy với máy chủ webpack dev, hãy sử dụng lệnh này.

webpack-dev-server --mode development --hot --inline --content-base=dist --history-api-fallback

--history-api-fallback là phần quan trọng

30
Todd 2015-01-22 10:37.

Bộ định tuyến có thể được gọi theo hai cách khác nhau, tùy thuộc vào việc điều hướng xảy ra trên máy khách hay trên máy chủ. Bạn đã định cấu hình nó cho hoạt động phía máy khách. Tham số chính là tham số thứ hai cho phương thức chạy , vị trí.

Khi bạn sử dụng thành phần React Router Link, nó sẽ chặn điều hướng trình duyệt và gọi chuyển đổi Để thực hiện điều hướng phía máy khách. Bạn đang sử dụng HistoryLocation, vì vậy nó sử dụng API lịch sử HTML5 để hoàn thành ảo tưởng điều hướng bằng cách mô phỏng URL mới trong thanh địa chỉ. Nếu bạn đang sử dụng các trình duyệt cũ hơn, điều này sẽ không hoạt động. Bạn sẽ cần sử dụng thành phần HashLocation.

Khi bạn nhấn làm mới, bạn sẽ bỏ qua tất cả mã React và React Router. Máy chủ nhận được yêu cầu /joblistvà nó phải trả lại một cái gì đó. Trên máy chủ, bạn cần chuyển đường dẫn được yêu cầu đến runphương thức để nó hiển thị đúng dạng xem. Bạn có thể sử dụng cùng một bản đồ tuyến đường, nhưng có thể bạn sẽ cần một cuộc gọi khác tới Router.run. Như Charles đã chỉ ra, bạn có thể sử dụng tính năng viết lại URL để xử lý việc này. Một tùy chọn khác là sử dụng máy chủ node.js để xử lý tất cả các yêu cầu và chuyển giá trị đường dẫn làm đối số vị trí.

Ví dụ: trong express, nó có thể trông như thế này:

var app = express();

app.get('*', function (req, res) { // This wildcard method handles all requests

    Router.run(routes, req.path, function (Handler, state) {
        var element = React.createElement(Handler);
        var html = React.renderToString(element);
        res.render('main', { content: html });
    });
});

Lưu ý rằng đường dẫn yêu cầu đang được chuyển đến run. Để làm điều này, bạn sẽ cần phải có một công cụ xem phía máy chủ mà bạn có thể chuyển HTML được hiển thị sang. Có một số cân nhắc khác khi sử dụng renderToStringvà chạy React trên máy chủ. Sau khi trang được hiển thị trên máy chủ, khi ứng dụng của bạn tải trong máy khách, nó sẽ hiển thị lại, cập nhật HTML được hiển thị phía máy chủ nếu cần.

24
th3morg 2017-11-23 17:10.

Nếu bạn đang lưu trữ một ứng dụng phản ứng thông qua AWS Static S3 Hosting & CloudFront

Vấn đề này do CloudFront phản hồi với thông báo 403 Access Denied vì nó mong đợi / some / other / path tồn tại trong thư mục S3 của tôi, nhưng đường dẫn đó chỉ tồn tại nội bộ trong định tuyến của React với react-router.

Giải pháp là thiết lập quy tắc Trang lỗi phân phối. Đi tới cài đặt CloudFront và chọn bản phân phối của bạn. Tiếp theo, chuyển đến tab "Trang Lỗi". Nhấp vào "Tạo phản hồi lỗi tùy chỉnh" và thêm mục nhập cho 403 vì đó là mã trạng thái lỗi mà chúng tôi nhận được. Đặt Đường dẫn Trang Phản hồi thành /index.html và mã trạng thái thành 200. Kết quả cuối cùng khiến tôi kinh ngạc vì sự đơn giản của nó. Trang chỉ mục được cung cấp, nhưng URL được giữ nguyên trong trình duyệt, vì vậy khi ứng dụng phản ứng tải, nó sẽ phát hiện đường dẫn URL và điều hướng đến tuyến đường mong muốn.

Quy tắc trang lỗi 403

19
Venkatesh Somu 2017-02-08 05:55.

Điều này có thể giải quyết vấn đề của bạn

Tôi cũng gặp phải vấn đề tương tự trong ứng dụng ReactJS ở chế độ Sản xuất. Đây là 2 giải pháp cho vấn đề.

1. Thay đổi lịch sử định tuyến thành "hashHistory" thay vì browserHistory thay cho

<Router history={hashHistory} >
   <Route path="/home" component={Home} />
   <Route path="/aboutus" component={AboutUs} />
</Router>

Bây giờ, hãy xây dựng ứng dụng bằng lệnh

sudo npm run build

Sau đó, đặt thư mục xây dựng vào thư mục var / www / của bạn, Bây giờ ứng dụng đang hoạt động tốt với việc bổ sung thẻ # trong mỗi URL. giống

localhost / # / home localhost / # / aboutus

Giải pháp 2: Không có thẻ # bằng trình duyệtHistory,

Đặt history = {browserHistory} trong Bộ định tuyến của bạn, Bây giờ xây dựng nó bằng cách sử dụng sudo npm run build.

Bạn cần tạo tệp "conf" để giải quyết trang 404 không tìm thấy, tệp conf phải như thế này.

mở thiết bị đầu cuối của bạn gõ các lệnh dưới đây

cd / etc / apache2 / sites-available ls nano sample.conf Thêm nội dung bên dưới vào đó.

<VirtualHost *:80>
    ServerAdmin [email protected]
    ServerName 0.0.0.0
    ServerAlias 0.0.0.0
    DocumentRoot /var/www/html/

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    <Directory "/var/www/html/">
            Options Indexes FollowSymLinks
            AllowOverride all
            Require all granted
    </Directory>
</VirtualHost>

Bây giờ bạn cần kích hoạt tệp sample.conf bằng cách sử dụng lệnh sau

cd /etc/apache2/sites-available
sudo a2ensite sample.conf

sau đó nó sẽ yêu cầu bạn tải lại máy chủ apache, sử dụng dịch vụ sudo tải lại apache2 hoặc khởi động lại

sau đó mở thư mục localhost / build của bạn và thêm tệp .htaccess với nội dung bên dưới.

   RewriteEngine On
   RewriteBase /
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_FILENAME} !-l
   RewriteRule ^.*$ / [L,QSA]

Bây giờ ứng dụng đang hoạt động bình thường.

Lưu ý: thay đổi IP 0.0.0.0 thành địa chỉ IP cục bộ của bạn.

Nếu có bất kỳ nghi ngờ nào liên quan đến điều này, hãy đưa ra bình luận.

Tôi hy vọng nó là hữu ích cho những người khác.

16
Chtiwi Malek 2017-10-19 00:47.

Nếu bạn đang lưu trữ ứng dụng phản ứng của mình trên IIS, chỉ cần thêm tệp web.config chứa:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" path="/" responseMode="ExecuteURL" />
    </httpErrors>
  </system.webServer>
</configuration>

Điều này sẽ yêu cầu máy chủ IIS trả lại trang chính cho máy khách thay vì lỗi 404 và không cần sử dụng lịch sử băm.

16
sree 2016-09-10 13:18.

Máy chủ Webpack Dev có một tùy chọn để kích hoạt điều này. Mở ra package.jsonvà thêm --history-api-fallback. Giải pháp này đã làm việc cho tôi.

react-router-tutorial

14
Colton Hicks 2017-06-10 12:01.

Nếu bạn đang sử dụng Create React App:

Có một bước đi tuyệt vời về vấn đề này với các giải pháp cho nhiều nền tảng lưu trữ lớn mà bạn có thể tìm thấy TẠI ĐÂY trên trang Tạo ứng dụng React. Ví dụ: tôi sử dụng React Router v4 và Netlify cho mã giao diện người dùng của mình. Tất cả những gì cần làm là thêm 1 tệp vào thư mục chung của tôi ("_redirects") và một dòng mã trong tệp đó:

/*  /index.html  200

Giờ đây, trang web của tôi hiển thị đúng các đường dẫn như mysite.com/pricing khi được nhập vào trình duyệt hoặc khi ai đó nhấn vào làm mới.

14
suraj 2017-09-12 01:51.

Thêm cái này vào webpack.config.js:

devServer: {
    historyApiFallback: true
}
13
Isaac Pak 2017-08-10 07:46.

Ngăn xếp sản xuất: React, React Router v4, BrowswerRouter, Express, Nginx

1) Trình duyệt Người dùngRouter cho các url đẹp

// app.js

import { BrowserRouter as Router } from 'react-router-dom'

const App = () {
  render() {
    return (
        <Router>
           // your routes here
        </Router>
    )
  }
}

2) Thêm index.html vào tất cả các yêu cầu không xác định bằng cách sử dụng /*

// server.js

app.get('/*', function(req, res) {   
  res.sendFile(path.join(__dirname, 'path/to/your/index.html'), function(err) {
    if (err) {
      res.status(500).send(err)
    }
  })
})

3) gói webpack với webpack -p

4) chạy nodemon server.jshoặcnode server.js

CHỈNH SỬA: Bạn có thể muốn để nginx xử lý điều này trong khối máy chủ và bỏ qua bước 2:

location / {
    try_files $uri /index.html;
}
7
Kiran Joshi 2018-06-29 20:26.

Hãy thử thêm tệp ".htaccess" vào bên trong thư mục chung với mã bên dưới.

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

RewriteRule ^ /index.html [L]  
6
Matt Goo 2016-05-03 14:11.

Nếu bạn có dự phòng cho index.html của mình, hãy đảm bảo rằng trong tệp index.html của bạn, bạn có cái này:

<script>
  System.config({ baseURL: '/' });
</script>

Điều này có thể khác nhau giữa các dự án.

4
Joshua Dyck 2018-07-24 16:46.

Nếu bạn đang sử dụng firebase, tất cả những gì bạn phải làm là đảm bảo rằng bạn có thuộc tính ghi lại trong tệp firebase.json trong thư mục gốc của ứng dụng (trong phần lưu trữ).

Ví dụ:

{ 
  "hosting": {
    "rewrites": [{
      "source":"**",
      "destination": "/index.html"
    }]    
  }
}

Hy vọng điều này sẽ tiết kiệm cho người khác một kho sự thất vọng và thời gian lãng phí.

Chúc bạn viết mã vui vẻ ...

Đọc thêm về chủ đề:

https://firebase.google.com/docs/hosting/full-config#rewrites

Firebase CLI: “Định cấu hình dưới dạng ứng dụng một trang (viết lại tất cả các url thành /index.html)”

4
Sasha Ignashevich 2019-01-21 12:41.

Tôi đã tìm thấy giải pháp cho SPA của mình với bộ định tuyến phản ứng (Apache). Chỉ cần thêm .htaccess

<IfModule mod_rewrite.c>

  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]

</IfModule>

nguồn: https://gist.github.com/alexsasharegan/173878f9d67055bfef63449fa7136042

3
Paul Whipp 2016-09-12 20:28.

Tôi chưa sử dụng kết xuất phía máy chủ nhưng tôi gặp phải vấn đề tương tự như OP trong đó Liên kết dường như hoạt động tốt hầu hết thời gian nhưng không thành công khi tôi có một tham số. Tôi sẽ ghi lại giải pháp của mình ở đây để xem nó có giúp được ai không.

Jsx chính của tôi chứa cái này:

<Route onEnter={requireLogin} path="detail/:id" component={ModelDetail} />

Điều này hoạt động tốt cho liên kết phù hợp đầu tiên nhưng khi: id thay đổi trong các <Link>biểu thức được lồng trên trang chi tiết của mô hình đó, url sẽ thay đổi trong thanh trình duyệt nhưng nội dung của trang ban đầu không thay đổi để phản ánh mô hình được liên kết.

Rắc rối là tôi đã sử dụng props.params.idđể thiết lập mô hình componentDidMount. Thành phần chỉ được gắn kết một lần nên điều này có nghĩa là mô hình đầu tiên là mô hình bám trên trang và các Liên kết tiếp theo sẽ thay đổi các đạo cụ nhưng giữ nguyên giao diện trang.

Đặt mô hình ở trạng thái thành phần ở cả componentDidMountvà trong componentWillReceiveProps(nơi nó dựa trên các đạo cụ tiếp theo) giải quyết vấn đề và nội dung trang thay đổi để phản ánh mô hình mong muốn.

3
zappee 2017-01-16 04:01.

Chủ đề này hơi cũ và đã được giải quyết nhưng tôi muốn gợi ý cho bạn một giải pháp đơn giản, rõ ràng và tốt hơn. Nó hoạt động nếu bạn sử dụng máy chủ web.

Mỗi máy chủ web có khả năng chuyển hướng người dùng đến một trang lỗi trong trường hợp là http 404. Để giải quyết vấn đề này, bạn cần chuyển hướng người dùng đến trang chỉ mục.

Nếu bạn sử dụng máy chủ cơ sở Java (tomcat hoặc bất kỳ máy chủ ứng dụng java nào), giải pháp có thể như sau:

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- WELCOME FILE LIST -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <!-- ERROR PAGES DEFINITION -->
    <error-page>
        <error-code>404</error-code>
        <location>/index.jsp</location>
    </error-page>

</web-app>

Thí dụ:

  • TẢI http://example.com/about
  • Máy chủ web ném http 404 vì trang này không tồn tại ở phía máy chủ
  • cấu hình trang lỗi thông báo cho máy chủ gửi lại trang index.jsp cho người dùng
  • thì JS sẽ thực hiện phần còn lại của công việc ở phía clien vì url ở phía máy khách vẫn là http://example.com/about .

Thế là xong, không cần ảo thuật nữa :)

3
Martin Lloyd Jose 2018-05-29 21:29.

Đối với những người đang sử dụng IIS 10, đây là điều bạn nên làm để điều này trở nên đúng đắn. Hãy chắc chắn rằng bạn đang sử dụng browserHistory với cái này. Để tham khảo, tôi sẽ cung cấp mã cho định tuyến, nhưng đây không phải là điều quan trọng, điều quan trọng là bước tiếp theo sau mã thành phần bên dưới:

class App extends Component {
    render() {
        return (
            <Router history={browserHistory}>
                <div>
                    <Root>
                        <Switch>
                            <Route exact path={"/"} component={Home} />    
                            <Route path={"/home"} component={Home} />
                            <Route path={"/createnewproject"} component={CreateNewProject} />
                            <Route path={"/projects"} component={Projects} />
                            <Route path="*" component={NotFoundRoute} />
                        </Switch>
                    </Root>
                </div>
            </Router>
        )
    }
}
render (<App />, window.document.getElementById("app"));

Vì vấn đề là IIS nhận được yêu cầu từ trình duyệt máy khách, nó sẽ diễn giải URL như thể nó đang yêu cầu một trang, sau đó trả về trang 404 vì không có trang nào khả dụng. Làm như sau:

  1. Mở IIS
  2. Mở rộng Máy chủ rồi mở Thư mục Trang web
  3. Nhấp vào trang web / ứng dụng
  4. Chuyển đến các trang lỗi
  5. Mở mục trạng thái lỗi 404 trong danh sách
  6. Thay vì tùy chọn "Chèn nội dung từ tệp tĩnh vào phản hồi lỗi", hãy thay đổi tùy chọn thành "Thực thi URL trên trang web này" và thêm giá trị gạch chéo "/" vào URL.

Và bây giờ nó sẽ hoạt động tốt.

Tôi hy vọng nó sẽ giúp. :-)

3
user2849063 2018-03-09 19:53.

Nếu bạn đang sử dụng Express hoặc một số khung công tác khác trong phần phụ trợ, bạn có thể thêm cấu hình tương tự như bên dưới và kiểm tra đường dẫn công khai của Webpack trong cấu hình, nó sẽ hoạt động tốt ngay cả khi tải lại nếu bạn đang sử dụng BrowserRouter

expressApp.get('/*', (request, response) => {
    response.sendFile(path.join(__dirname, '../public/index.html'));
});
3
Lalit Tyagi 2018-12-20 05:53.

Sửa lỗi "không thể GET / URL" khi làm mới hoặc khi gọi URL trực tiếp.

Định cấu hình webpack.config.js của bạn để mong đợi liên kết đã cho có các tuyến như thế này.

module.exports = {
  entry: './app/index.js',
  output: {
       path: path.join(__dirname, '/bundle'),
       filename: 'index_bundle.js',
       publicPath: '/'
  },
2
Elnoor 2019-03-11 18:41.

Khi tôi đang sử dụng .Net Core MVC, một cái gì đó như thế này đã giúp tôi:

    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            var url = Request.Path + Request.QueryString;
            return App(url);
        }

        [Route("App")]
        public IActionResult App(string url)
        {
            return View("/wwwroot/app/build/index.html");
        }
   }

Về cơ bản ở phía MVC, tất cả các tuyến không khớp sẽ rơi vào Home/Indexnhư nó được chỉ định trong startup.cs. Bên trong Indexnó có thể lấy url yêu cầu ban đầu và chuyển nó bất cứ khi nào cần thiết.

startup.cs

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

            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });
        });
2
Barny 2017-04-26 22:32.

Nếu bạn đang lưu trữ trong IIS; Thêm cái này vào webconfig của tôi đã giải quyết được vấn đề của tôi

<httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL">
    <remove statusCode="500" subStatusCode="100" />
    <remove statusCode="500" subStatusCode="-1" />
    <remove statusCode="404" subStatusCode="-1" />
    <error statusCode="404" path="/" responseMode="ExecuteURL" />
    <error statusCode="500" prefixLanguageFilePath="" path="/error_500.asp" responseMode="ExecuteURL" />
    <error statusCode="500" subStatusCode="100" path="/error_500.asp" responseMode="ExecuteURL" />
</httpErrors>

Bạn có thể tạo cấu hình tương tự cho bất kỳ máy chủ nào khác

2
Rishabh Jain 2019-10-14 18:19.

bạn có thể thử đọc tất cả những thứ này mặc dù nó không phải của tôi:

https://www.andreasreiterer.at/fix-browserrouter-on-apache/

Sửa lỗi định tuyến của ứng dụng Bây giờ đây là cách cuối cùng để sửa lỗi định tuyến. Để yêu cầu Apache chuyển hướng các yêu cầu đến index.html nơi ứng dụng của chúng tôi hoạt động, chúng tôi phải sửa đổi tệp .htaccess. Nếu chưa có tệp nào như vậy trong thư mục ứng dụng của bạn, chỉ cần tạo tệp đó.

Sau đó, hãy chắc chắn rằng bạn đặt 4 dòng đó sẽ làm cho việc định tuyến của bạn hoạt động một cách kỳ diệu.

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

Sau khi chúng tôi đặt tệp .htaccess đó vào cùng thư mục với index.html, Apache sẽ chuyển hướng trực tiếp từng yêu cầu mới đến ứng dụng của bạn.

Phần thưởng: Triển khai ứng dụng React vào một thư mục con

Nếu bạn đang triển khai ứng dụng của mình vào một thư mục con, vì vậy nó có thể truy cập được, ví dụ như qua https://myapp.com/the-app , bạn sẽ sớm nhận thấy rằng có một vấn đề khác. Mỗi lần nhấp vào một tuyến mới sẽ biến đổi URL thành một cái gì đó giống như https://myapp.com/route-abc - URL này sẽ bị hỏng một lần nữa sau khi tải lại. Nhưng có một cách khắc phục đơn giản cho điều đó:

BrowserRouter có một phần mềm hỗ trợ được gọi là basename, nơi bạn có thể chỉ định đường dẫn thư mục con của mình:

Từ bây giờ, mỗi lượt thích / liên hệ của Tuyến đường sẽ dẫn đến một URL như http://myapp.com/the-app/contacts .

2
Alireza 2020-03-25 04:09.

Sử dụng HashRouterlàm việc cho tôi với Redux cũng có, chỉ đơn giản là thay thế:

import {
  Router //replace Router
} from "react-router-dom";

ReactDOM.render(
    <LocaleProvider locale={enUS}>
    <Provider store={Store}>
        <Router history={history}> //replace here saying Router
            <Layout/>
        </Router>
    </Provider>
</LocaleProvider>, document.getElementById("app"));
registerServiceWorker();

đến:

import {
  HashRouter //replaced with HashRouter
} from "react-router-dom";

ReactDOM.render(
    <LocaleProvider locale={enUS}>
    <Provider store={Store}>
        <HashRouter history={history}> //replaced with HashRouter
            <Layout/>
        </HashRouter>
    </Provider>
</LocaleProvider>, document.getElementById("app"));
registerServiceWorker();
1
Koushik Das 2017-11-14 17:23.

Trong trường hợp, bất kỳ ai ở đây đang tìm kiếm giải pháp trên React JS SPA với Laravel. Câu trả lời được chấp nhận là lời giải thích tốt nhất về lý do tại sao những vấn đề như vậy xảy ra. Như đã giải thích, bạn phải cấu hình cả phía máy khách và phía máy chủ. Trong mẫu lưỡi dao của bạn, hãy bao gồm tệp đi kèm js, hãy đảm bảo sử dụng URL facadenhư thế này

<script src="{{ URL::to('js/user/spa.js') }}"></script>

Trong các tuyến của bạn, hãy đảm bảo thêm điều này vào điểm cuối chính nơi chứa mẫu lưỡi dao. Ví dụ,

Route::get('/setting-alerts', function () {
   return view('user.set-alerts');
});

Trên đây là điểm cuối chính cho mẫu phiến. Bây giờ, hãy thêm một tuyến đường tùy chọn,

Route::get('/setting-alerts/{spa?}', function () {
  return view('user.set-alerts');
});

Vấn đề xảy ra là đầu tiên mẫu phiến được tải, sau đó là bộ định tuyến phản ứng. Vì vậy, khi bạn đang tải '/setting-alerts', nó sẽ tải html và js. Nhưng khi bạn tải '/setting-alerts/about', trước tiên nó sẽ tải ở phía máy chủ. Vì ở phía máy chủ, không có gì trên vị trí này, nó trả về không tìm thấy. Khi bạn có bộ định tuyến tùy chọn đó, nó sẽ tải trang đó và bộ định tuyến phản ứng cũng được tải, sau đó bộ tải phản ứng quyết định thành phần nào sẽ hiển thị. Hi vọng điêu nay co ich.

1
Vishal Singh 2019-02-20 02:02.

Tôi đang sử dụng WebPack, tôi gặp sự cố tương tự Giải pháp => Trong tệp server.js của bạn

const express = require('express');
const app = express();

app.use(express.static(path.resolve(__dirname, '../dist')));
  app.get('*', function (req, res) {
    res.sendFile(path.resolve(__dirname, '../dist/index.html'));
    // res.end();
  });

Tại sao ứng dụng của tôi không hiển thị sau khi làm mới?

0
J. Parrish 2017-05-06 05:39.

Tôi đã gặp vấn đề tương tự và giải pháp Thêm URL cơ sở vào ứng dụng bằng Redux-Router + React-Router đã hiệu quả với chúng tôi ..

Lý lịch:

Chúng tôi đang lưu trữ nhiều ứng dụng trên cùng một máy chủ. Khi chúng tôi làm mới máy chủ sẽ không hiểu tìm chỉ mục của chúng tôi ở đâu trong thư mục dist cho ứng dụng cụ thể đó. Liên kết trên sẽ đưa bạn đến những gì hiệu quả với chúng tôi ... Hy vọng điều này sẽ hữu ích, vì chúng tôi đã dành khá nhiều giờ để tìm ra giải pháp cho nhu cầu của mình.

Chúng tôi đang sử dụng:

package.json

"dependencies": {
"babel-polyfill": "^6.23.0",
"ejs": "^2.5.6",
"express": "^4.15.2",
"prop-types": "^15.5.6",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-redux": "^5.0.4",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.8",
"redux": "^3.6.0",
"redux-persist": "^4.6.0",
"redux-thunk": "^2.2.0",
"webpack": "^2.4.1"
}

webpack.config.js của tôi

webpack.config.js

/* eslint-disable */
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const babelPolyfill = require('babel-polyfill');
const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
  template: __dirname + '/app/views/index.html',
  filename: 'index.html',
  inject: 'body'
});

module.exports = {
  entry: [
    'babel-polyfill', './app/index.js'
  ],
  output: {
    path: __dirname + '/dist/your_app_name_here',
    filename: 'index_bundle.js'
  },
  module: {
    rules: [{
      test: /\.js$/,
      loader: 'babel-loader',
      query : {
          presets : ["env", "react", "stage-1"]
      },
      exclude: /node_modules/
    }]
  },
  plugins: [HTMLWebpackPluginConfig]
}

index.js của tôi

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import Routes from './Routes'
import { Provider } from 'react-redux'
import { createHistory } from 'history'
import { useRouterHistory } from 'react-router'
import configureStore from './store/configureStore'
import { syncHistoryWithStore } from 'react-router-redux'
import { persistStore } from 'redux-persist'

const store = configureStore();

const browserHistory = useRouterHistory(createHistory) ({
  basename: '/your_app_name_here'
})
const history = syncHistoryWithStore(browserHistory, store)

persistStore(store, {blacklist: ['routing']}, () => {
  console.log('rehydration complete')
})
// persistStore(store).purge()


ReactDOM.render(
    <Provider store={store}>
      <div>
        <Routes history={history} />
      </div>
    </Provider>,
  document.getElementById('mount')
)

app.js của tôi

var express = require('express');
var app = express();

app.use(express.static(__dirname + '/dist'));
// app.use(express.static(__dirname + '/app/assets'));
app.set('views', __dirname + '/dist/your_app_name_here');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');

app.get('/*', function (req, res) {
    res.render('index');
});

app.listen(8081, function () {
  console.log('MD listening on port 8081!');
});

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Trong Saturday Night Live, The Bachelor is Bland và Tina Fey trở lại với vai 'Crazy' Sarah Palin

Trong Saturday Night Live, The Bachelor is Bland và Tina Fey trở lại với vai 'Crazy' Sarah Palin

Sau khi Sarah Palin tán thành Donald Trump vào đầu tuần này, gần như không thể tránh khỏi việc Tina Fey sẽ trở lại Saturday Night Live để thăm lại ấn tượng Palin cổ điển của cô. Và Fey chắc chắn đã không làm thất vọng, cô ấy đã đưa ra một lời khen ngợi không hề nhẹ về bài phát biểu chứng thực Iowa quanh co và khó hiểu của Palin trong khi Trump của Darrell Hammond đưa ra bình luận xuyên suốt.

Đây có phải là sự khởi đầu cho sự kết thúc của việc giam giữ Brittney Griner?

Đây có phải là sự khởi đầu cho sự kết thúc của việc giam giữ Brittney Griner?

Brittney Griner (r.) Ngay từ đầu, thân phận của Brittney Griner đã là tình huống con tin Mỹ độc nhất trong lịch sử hiện đại.

Tom Brady là bộ tứ vệ đầu tiên cuối cùng có thể giúp Julio Jones có hơn 10 lần chạm bóng trong một mùa giải

Tom Brady là bộ tứ vệ đầu tiên cuối cùng có thể giúp Julio Jones có hơn 10 lần chạm bóng trong một mùa giải

Chúng ta có thể thấy nhiều hơn nữa về một Julio Jones khỏe mạnh trong khu vực cuối năm nay. John Parker Wilson, Greg McElroy, A.

Đó phải là Đức

Đó phải là Đức

Đối với đội tuyển Anh, không có kẻ thủ ác nào lớn hơn Hầu hết các cổ động viên Anh, nếu không muốn nói là tất cả, hẳn sẽ phải gật gù khi tiếng còi mãn cuộc của trận bán kết lượt về W Euro 2022 vang lên. Bởi vì nó báo hiệu rằng Đức sẽ chờ đợi ở Wembley trong trận chung kết với Anh và là điều duy nhất giữa Anh và chiếc cúp lớn đầu tiên của đội tuyển nữ.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Language