Chào mn, e đi thực tập html/css/js thì được 1 a bảo học thêm react để nếu khách hàng yêu cầu thì làm được, cho e hỏi là việc làm bằng react có khác gì truyền thống k, vẫn chỉ tạo ra giao diện hay còn thêm gì nữa ạ, e cảm ơn.
Học reactJS để làm gì?
có xe máy được rồi, mua xe hơi làm chi?
có táo được rồi, mua cam làm chi?
Làm react để tạo ra các web application, mấy cái công việc làm web giao diện bạn làm chỉ đơn giản là làm web site ko có chức năng như 1 app, react giúp tạo ra các web app và là single page application !!
Diễn dịch để hiểu tận gốc, bạn cố gắng đọc nhé.
Bạn là người tạo ra giao diện cho trang web (front-end), sau đó phía dev (back-end) sẽ gắn các chức năng vào cái giao diện đó, để làm thành trang web hoàn chỉnh.
Khi muốn đi từ trang này sang trang khác, thì trên giao diện trang web, chúng ta nhấn vào link, vào nút submit,… để chuyển trang.
Mỗi khi chuyển trang, thì phía back-end sẽ trả về mã HTML cho trang mà bạn đang chuyển hướng đến.
Vì ở mỗi trang, có thể tồn tại khá nhiều các nội dung trùng lặp với nhau (header, footer, sidebar,…), bạn code HTML cũng thấy mà đúng không
Lần nào chuyển trang cũng phải load lại mấy nội dung bị lặp, vừa tốn băng thông mà trang load cũng lâu nữa.
Ứng dụng web dạng này gọi là MPA (Multi Page Application)
Sau này, người ta nghĩ ra SPA (Single Page Application),
sau khi browser gửi request, thay vì nhận về cả 1 file HTML như MPA, SPA sẽ chỉ nhận về 1 file JSON chứa dữ liệu cần thiết.
VD: Ở MPA, sau khi bạn nhấn nút submit thông tin đăng ký, sẽ nhận về cả 1 file HTML dài thiệt dài
<html>
....
Đăng ký thành công
....
</html>
Ở SPA, thì chỉ nhận được mẫu JSON thế này thôi
{ status: 'ok', message: 'Đăng ký thành công' }
Tùy theo dữ liệu nhận được, người dev SPA sẽ hiển thị HTML thích hợp lên browser.
- Question: Chỉ nhận được dữ liệu, không nhận được code HTML, thì làm sao hiện lên browser được?
Answer: Tất cả các file HTML của trang web đều được đóng gói vào một (hoặc nhiều) file javascript, đã được load sẵn khi bạn truy cập lần đầu vào site.
Đó là lý do các ứng dụng SPA khi truy cập trang lần đầu thì có phần chậm hơn MPA (vì phải load tất cả HTML của trang web), tuy nhiên trong quá trình thao tác, sử dụng thì SPA mượt hơn rất nhiều, vì không phải load lại trang.
Mục đích sử dụng reactJS không phải là để tạo ra file giao diện (HTML), mà là để sử dụng file giao diện. (bạn cũng cần tạo ra các file HTML trước, sau đó mới ráp vào reactJS)
Do vậy, người code reactJS cũng thường được gọi là kỹ sư front-end, cần có kiến thức và suy nghĩ logic để lập trình cho các hoạt động ở front-end diễn ra trơn tru, cần kết hợp, thảo luận với kỹ sư back-end để thiết kế API hợp lý, chứ không phải chỉ tạo ra file giao diện (HTML) giống với design là được.
Khái niệm, mục đích của việc sử dụng reactJS như vậy chắc cũng tạm ổn.
Bạn bắt tay vào học thì sẽ hiểu rõ hơn.
@songtotnhe cho mình hỏi trường hợp này với, SPA thì client sẽ download hầu như toàn bộ phần giao diện về browser những lần sau không tải HTML,CSS,JS nữa chỉ gửi request để lấy data (json). Nếu như server update version hoặc server chỉ fix 1 vài chi tiết giao diện nhỏ (button, label, checkbox,…) thì client làm sao biết được giao diện đã bị thay đổi để tải về cập nhật mới lại ? hay là chỉ những lúc user xóa cache, xóa lịch sử thủ công khi truy cập lại URL đó nó mới tải giao diện lại từ đầu ?
Nếu như server update version hoặc server chỉ fix 1 vài chi tiết giao diện nhỏ (button, label, checkbox,…) thì client làm sao biết được giao diện đã bị thay đổi để tải về cập nhật mới lại ? hay là chỉ những lúc user xóa cache, xóa lịch sử thủ công khi truy cập lại URL đó nó mới tải giao diện lại từ đầu ?
Khi bạn gửi request đến server, sẽ nhận về một file HTML ().
Trong file HTML đó có link dẫn đến các file assets (JS, CSS, image), các file assets này chính là những đối tượng thường bị cache lại.
Khi bạn làm SPA, đúng là các chi tiết giao diện sẽ nằm trong file JS luôn, do đó, file JS bị cache, cũng có nghĩa là các chi tiết giao diện đó sẽ bị cache.
Tuy nhiên, cái file HTML mà bạn nhận được đầu tiên khi request đến server () thường không nằm trong danh sách các file bị cache (trừ khi người dev cố tình cài đặt cho nó bị cache).
Do đó, mỗi khi bạn nhấn F5 để load lại trang, bạn sẽ luôn nhận được “khung sườn” HTML mới nhất.
Từ thông tin nhận được trong cái “khung sườn” HTML trên, browser sẽ xác định xem có nên tải lại các file assets được nhắc đến trong HTML đó hay không.
Do vậy, khi làm SPA, mỗi khi thay đổi một chút gì đó trong JS/CSS, bạn cũng phải thay đổi một chút trong cái “khung sườn” HTML để browser biết được rằng phía server có thay đổi, từ đó tải lại assets mới.
Có 2 cách mà mình thấy đang được sử dụng rộng rãi.
1/ Thêm tham số truy vấn vào link tải assets.
Khi có sự thay đổi assets thì thay đổi tham số truy vấn để browser nhận biết được và tải lại.
VD:
Ngày 20/02/2021, lúc 15:30:00, sau khi đã code xong file app.js, mình sẽ thêm tham số vào thẻ script như sau
<script src="/app.js?version=20210220_153000"></script>
Tham số truy vấn này có key là “version”, value là “20210220_153000”, bạn có thể sử dụng bất kỳ key/value nào cũng được.
Ngày 21/02/2021, mình có chỉnh sửa, sau khi xong xuôi thì mình đổi tham số lại như sau
<script src="/app.js?version=20210221_153000"></script>
Khi bạn reload trang, browser nhận được file HTML mới và đọc được link tải này, nó nhận thấy link này đã có sự thay đổi so với link của app.js đang được cache (mặc dù cùng tên file nhưng khác tham số, nói chung là khác URL), do vậy nhiều khả năng nó sẽ quyết định tải lại file app.js.
2/ Thay đổi tên file assets mỗi khi có chỉnh sửa.
Cách này có nghĩa là, mỗi lần thay đổi thì sẽ tạo ra file mới (với tên mới), không dùng tên cũ nữa.
VD:
Ngày 20/02/2021, khi đã code xong file app.js, mình đặt tên file là app_20210220.js
Lúc đó thẻ script sẽ trông giống như sau
<script src="/app_20210220.js"></script>
Ngày 21/02/2021, sau khi chỉnh sửa xong, mình đặt tên mới cho file là app_20210221.js
Đồng thời cũng thay đổi thẻ script trong “khung sườn” HTML thành như sau
<script src="/app_20210221.js"></script>
Lúc này, khi bạn reload trang, vì khác tên file nên chắc chắn browser sẽ tải file app_20210221.js rồi.
Tổng kết
Nguyên lý hoạt động của 2 cách trên tương tự nhau, đều là thay đổi URL của assets so với lần trước để browser nhận biết sự thay đổi và tải lại.
Cách 1 bạn có thể thay đổi value của tham số bằng tay sau mỗi lần cập nhật, hoặc gắn value một cách tự động bằng cách truyền vào last_modified của file assets.
Cách 2 thường thì sẽ cần công cụ để thực hiện đổi tên file tự động, chứ ít ai làm bằng tay
Người ta thường dùng mã hash để đặt tên file, VD: app_f53a57.js,…
Cách 2 thì hiệu quả cao hơn cách 1, nhưng cũng phức tạp hơn, cần cài đặt công cụ để phát sinh tên file tự động.
Cách 1 thỉnh thoảnh reload một lần chưa thấy thay đổi thì reload thêm lần nữa cũng sẽ thấy được sự thay đổi, nói chung cách này dùng ổn, dễ cài đặt.
Tùy theo dự án, công nghệ bạn đang sử dụng mà lựa chọn cách thức phù hợp.
Có phải như này không anh @songtotnhe ?
Ban đầu browser tải về :
<script src="/app.js?version=1.0"></script>
một thời gian sau server cập nhật app.js lên 2.0 nhưng browser vẫn lưu 1.0 nên vẫn tiếp tục gửi request để lấy app.js?version=1.0 nhưng bị 404 nên browser sẽ gửi request lại cho mỗi thẻ <script này thôi. Kết quả sau đó mới ra
<script src="/app.js?version=2.0"></script>
Có phải như này không anh @songtotnhe ?
Ban đầu browser tải về :
<script src="/app.js?version=1.0"></script>
một thời gian sau server cập nhật app.js lên 2.0 nhưng browser vẫn lưu 1.0 nên vẫn tiếp tục gửi request để lấy app.js?version= 1.0 nhưng bị 404 nên browser sẽ gửi request lại cho mỗi thẻ <script này thôi. Kết quả sau đó mới ra
<script src="/app.js?version=2.0"></script>
Không phải bạn ạ.
Trong trường hợp trên, app.js?version=1.0 hay app.js?version=2.0 về bản chất là URL trỏ đến cùng 1 file là app.js, đều sẽ tải được file app.js, nên sẽ không xảy ra trường hợp 404.
Ở lần đầu nhận được file HTML, trong đó có đề cập đến app.js như sau
<script src="/app.js?version=1.0"></script>
Như vậy, browser đã tải về file app.js, với URL đã tải là /app.js?version=1.0
Sau này khi server có cập nhật, app.js được đề cập đến trong file HTML là như sau
<script src="/app.js?version=2.0"></script>
File app.js thì browser đang có cache rồi, nhưng khi nó kiểm tra thì thấy rằng URL của app.js này là /app.js?version=2.0, khác với URL 1.0 mà nó đã tải, vì vậy nó sẽ có khả năng tải lại file app.js theo URL /app.js?version=2.0
Khi đã tải thành công thì app.js?version=2.0 sẽ thay thế cho app.js?version=1.0
@songtotnhe anh ơi cho em hỏi những điều này nó có đúng với Angular, VueJS, … và sau này nếu có một framework hay thư viện JS khác nó vẫn vậy đúng không anh ? vì đây là cấu trúc chung của trang SPA ? thanks a
Bài viết này cũng lâu rồi nên mình bổ sung thêm 1 số thứ liên quan đến việc “liệu có cần load hết source ngay từ lần load đầu tiên hay không?” và câu hỏi về việc update version
Liệu có cần load hết source ngay từ lần load đầu tiên hay không?
Câu trả lời là tùy vào ông dev, nếu project nhỏ thì load hết, còn nếu to thì nên dùng lazy import. Nên xem cách build chunk file và chunk dependencies.
Phân tích 2 case sau
- case 1: Hãy hình dung 1 trang Reactjs sử dụng 30 libs + source main, nếu sau khi build về static site mà dồn hết 30 libs + source main vào 1 file app.js thì việc load là rất lâu và không cần thiết, ví dụ vào sign in page thì không nhất thiết phải load sign up page, tương tự cho các page khác.
Ngoài ra nếu ta chỉ sửa 1 text ở login page mà sau khi build, browser phải load lại cả source của sign up page thì lại quá vô lý. - case 2: vẫn như trên, ta có 30 libs phụ thuộc, trong đó có 1 libs bị lỗi và được author lib fix vào version kế tiếp, ta update version cho lib đó nhưng khi build thì 29 libs còn lại phải chịu chung số phận là bị build lại, và browser sẽ load lại 29 libs giống hệt trước đó và 1 lib đổi version, cái ta muốn là 29 lib kia không thay đổi gì thì browser đã load sẽ không phải load lại, và chỉ load lại lib change version.
cách giải quyết: Vậy nên khi build có 1 vài cách như sau
- Cách 1: Gôm hết lib vào 1 file và main source vào 1 file (vendor.js, main.js)
- Cách này ưu điểm là nếu source main change thì vendor đã load trước đó sẽ k cần phải load lại, chỉ load lại file main.js => nhanh hơn 1 tí, nhưng cách này không giải quyết được cả 2 case đã nêu.
- Cách 2: tách hết lib ra mỗi lib là 1 file js + 1 file main.js, và tên file js của lib sẽ là mã
hash
của nội dung lib đó, tức là khi lib nào change version thì mã hash sẽ change => trình duyệt load lại lib đó và skip 29 libs còn lại.- Cách này giải quyết được
case 2
nhưng không giải quyết đượccase 1
.
- Cách này giải quyết được
- Cách 3: khi code react nên tận dụng lazy import các component cho hợp lý và thực hiện chunk libs như cách 2, khi đó thay vì khi build ra file
main.js
thì sẽ build ra số file tương ứng với số component được lazy import.- Cách này giải quyết được cả 2 case, lib change version và chỉ sửa 1 vài component thì browser chỉ load lại những thứ bị change, không load hết source => nhẹ và load nhanh hơn so với build về 1 file
- đối với cách này thì khi vào 1 component có chứa component import lazy thì browser sẽ load source js về, nên sẽ có loading (fallback) trong quá trình load source về, tuy nhiên nó vẫn nhanh.
Về việc cache file thì nếu chúng ta sử dụng mã hash nội dung của file làm file name cho module/lib thì việc cache khi update version là không đáng lo.
Hy vọng sẽ những ý kiến của mình có thể giúp được ai đó, nếu có bất kì đóng góp nào vui lòng comment bên dưới