{"id":990,"date":"2021-10-20T08:57:48","date_gmt":"2021-10-20T08:57:48","guid":{"rendered":"https:\/\/egany.com\/blogs\/?p=990"},"modified":"2021-10-23T09:16:06","modified_gmt":"2021-10-23T09:16:06","slug":"frontend-du-ky-s2e2-cross-platform-apps-phan-2-sai-1-ly-di-1-6-km","status":"publish","type":"post","link":"https:\/\/egany.com\/blogs\/frontend-du-ky-s2e2-cross-platform-apps-phan-2-sai-1-ly-di-1-6-km\/","title":{"rendered":"Frontend Du K\u00fd S2E2 | Cross-platform Apps (ph\u1ea7n 2): Sai 1 ly, \u0111i 1.6 km"},"content":{"rendered":"<p>Nh\u00e2n d\u1ecbp S\u00e0i G\u00f2n quay tr\u1edf l\u1ea1i sau \u0111\u1ee3t c\u00e1ch ly th\u00ec m\u00ecnh c\u0169ng ra m\u1ed9t b\u00e0i vi\u1ebft m\u1edbi. <strong>Frontend Du K\u00fd<\/strong> k\u00ec n\u00e0y s\u1ebd k\u1ec3 v\u1ec1 qu\u00e1 tr\u00ecnh l\u1ef1a ch\u1ecdn c\u00f4ng ngh\u1ec7 \u0111\u1ec3 ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng Cross-platform Apps.<br \/>\nN\u1ebfu b\u1ea1n ch\u01b0a \u0111\u1ecdc t\u1eadp tr\u01b0\u1edbc, b\u1ea1n c\u00f3 th\u1ec3 \u0111\u1ecdc <a href=\"https:\/\/egany.com\/blogs\/frontend-du-ky-s2e1-cross-platform-apps-phan-1-binh-moi-ruou-cu\/\">t\u1ea1i \u0111\u00e2y<\/a>.<\/p>\n<h2>Gi\u1edbi thi\u1ec7u<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/09\/egany-app.jpg\" alt=\"Cross-platform apps\" \/><\/p>\n<blockquote>\n<p>Cross-platform Apps s\u1ebd \u0111\u01b0\u1ee3c vi\u1ebft t\u1eaft b\u1eb1ng CPA \u0111\u1ec3 thu\u1eadn ti\u1ec7n cho ng\u01b0\u1eddi vi\u1ebft b\u00e0i<\/p>\n<\/blockquote>\n<p>Khi m\u00ecnh c\u00f2n l\u00e0 m\u1ed9t ch\u00e0ng dev tr\u1ebb <del>tr\u00e2u<\/del> trung, n\u0103ng \u0111\u1ed9ng, th\u00edch kh\u00e1m ph\u00e1 v\u00e0 th\u1eed th\u00e1ch, m\u00ecnh \u0111\u01b0\u1ee3c s\u1ebfp tin t\u01b0\u1edfng giao tr\u1ecdng tr\u00e1ch l\u1ef1a ch\u1ecdn c\u00f4ng ngh\u1ec7 \u0111\u1ec3 ph\u00e1t tri\u1ec3n CPA v\u00ec <del>c\u00f4ng ty ai c\u0169ng b\u1eadn<\/del> s\u1ebfp tin t\u01b0\u1edfng v\u00e0o kh\u1ea3 n\u0103ng c\u1ee7a m\u00ecnh. Kh\u00f4ng ph\u1ee5 l\u00f2ng tin c\u1ee7a s\u1ebfp, m\u00ecnh t\u00ecm hi\u1ec3u v\u00e0 l\u1ef1a ch\u1ecdn nh\u1eefng c\u00f4ng ngh\u1ec7 hay nh\u1ea5t, m\u1edbi nh\u1ea5t l\u00fac b\u1ea5y gi\u1edd \u0111\u1ec3 th\u1ef1c hi\u1ec7n.<\/p>\n<p>K\u1ebf ho\u1ea1ch ph\u00e1t tri\u1ec3n bao g\u1ed3m 2 th\u00e0nh ph\u1ea7n ch\u00ednh:<\/p>\n<ul>\n<li><strong>App<\/strong>: \u1ee9ng d\u1ee5ng nh\u00fang ch\u1ea1y tr\u00ean website c\u1ee7a kh\u00e1ch<\/li>\n<li><strong>App Admin<\/strong>: admin d\u00f9ng \u0111\u1ec3 c\u00e0i \u0111\u1eb7t, thi\u1ebft l\u1eadp \u1ee9ng d\u1ee5ng d\u00e0nh cho kh\u00e1ch h\u00e0ng<br \/>\nC\u00f9ng nhau t\u00ecm hi\u1ec3u m\u00ecnh \u0111\u00e3 ch\u1ecdn c\u00f4ng ngh\u1ec7 cho t\u1eebng ph\u1ea7n nh\u01b0 th\u1ebf n\u00e0o nh\u00e9!<\/li>\n<\/ul>\n<h2>C\u00f4ng ngh\u1ec7 App<\/h2>\n<h3>Ng\u00f4n ng\u1eef<\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/02\/javascript-thumb.jpg\" alt=\"JavaScript logo\" \/><\/p>\n<p>Tuy TypeScript \u0111\u00e3 kh\u00e1 th\u1ecbnh h\u00e0nh t\u1ea1i th\u1eddi \u0111i\u1ec3m hi\u1ec7n t\u1ea1i nh\u01b0ng m\u00ecnh v\u1eabn ch\u1ecdn JavaScript \u0111\u1ec3 ph\u00e1t tri\u1ec3n. L\u00fd do khi\u1ebfn m\u00ecnh ch\u1ecdn JavaScript:<\/p>\n<ul>\n<li><strong>Quen thu\u1ed9c<\/strong>. Team ch\u01b0a t\u1eebng l\u00e0m qua ho\u1eb7c ch\u1ec9 bi\u1ebft s\u01a1 qua TypeScript n\u00ean vi\u1ec7c \u00e1p d\u1ee5ng TypeScript ngay v\u00e0o d\u1ef1 \u00e1n s\u1ebd g\u00e2y kh\u00f3 kh\u0103n khi ph\u00e1t tri\u1ec3n<\/li>\n<li><strong>Linh \u0111\u1ed9ng<\/strong>. JavaScript nh\u1edd kh\u00f4ng c\u00f3 ph\u1ea7n type-checking n\u00ean t\u01b0\u01a1ng \u0111\u1ed1i c\u01a1 \u0111\u1ed9ng v\u00e0 d\u1ec5 d\u00e0ng bi\u1ebfn h\u00f3a, r\u1ea5t ph\u00f9 h\u1ee3p cho d\u1ef1 \u00e1n c\u00f3 t\u00ednh thay \u0111\u1ed5i cao v\u00e0 \u0111\u1eb7c bi\u1ec7t ph\u00f9 h\u1ee3p v\u1edbi CPA &#8211; m\u1ed9t d\u1ef1 \u00e1n th\u1eed nghi\u1ec7m<\/li>\n<\/ul>\n<p>D\u0129 nhi\u00ean l\u00e0 JavaScript kh\u00f4ng ph\u1ea3i l\u00e0 l\u1ef1a ch\u1ecdn ho\u00e0n h\u1ea3o. Do kh\u00f4ng c\u00f3 static type-checking n\u00ean khi l\u00e0m vi\u1ec7c v\u1edbi JavaScript, team ph\u1ea3i h\u1ebft s\u1ee9c c\u1ea9n th\u1eadn v\u1edbi vi\u1ec7c qu\u1ea3n l\u00fd d\u1eef li\u1ec7u \u0111\u1ec3 tr\u00e1nh c\u00e1c tr\u01b0\u1eddng h\u1ee3p g\u1ecdi sai t\u00ean ho\u1eb7c g\u00e1n sai ki\u1ec3u (v\u00ed d\u1ee5: g\u00e1n <code>number<\/code> v\u00e0o m\u1ed9t bi\u1ebfn <code>string<\/code>). Ngo\u00e0i ra th\u00ec h\u1ed7 tr\u1ee3 t\u1eeb code editor c\u0169ng b\u1ecb h\u1ea1n ch\u1ebf v\u00e0 kh\u00f4ng m\u1ea1nh b\u1eb1ng vi\u1ec7c s\u1eed d\u1ee5ng TypeScript.<\/p>\n<h3>UI (User Interface)<\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/02\/svelte-thumb.jpg\" alt=\"Svelte logo\" \/><\/p>\n<p>\u0110\u1ec3 \u0111\u00e1p \u1ee9ng \u0111\u01b0\u1ee3c c\u00e1c nhu c\u1ea7u c\u1ee7a b\u1ed9 bundler (\u0111\u1ec1 c\u1eadp \u1edf <a href=\"https:\/\/egany.com\/blogs\/svelte-van-cuoc-thanh-cong\/\" title=\"b\u00e0i vi\u1ebft tr\u01b0\u1edbc\">b\u00e0i vi\u1ebft tr\u01b0\u1edbc<\/a>) th\u00ec m\u00ecnh quy\u1ebft \u0111\u1ecbnh ch\u1ecdn Svelte. L\u00fd do:<\/p>\n<ul>\n<li><strong>Hi\u1ec7u n\u0103ng t\u1ed1t<\/strong>. So v\u1edbi nhu c\u1ea7u c\u1ee7a team th\u00ec hi\u1ec7u n\u0103ng cao ch\u01b0a ph\u1ea3i l\u00e0 m\u1ed9t v\u1ea5n \u0111\u1ec1 qu\u00e1 l\u1edbn \u0111\u1ec3 team ph\u1ea3i c\u00e2n nh\u1eafc. Tuy nhi\u00ean, sau khi xem qua c\u00e1c benchmark c\u1ee7a Svelte th\u00ec m\u00ecnh c\u0169ng kh\u00e1 \u1ea5n t\u01b0\u1ee3ng v\u1edbi hi\u1ec7u n\u0103ng c\u1ee7a n\u00f3 so v\u1edbi c\u00e1c th\u01b0 vi\u1ec7n ho\u1eb7c framework kh\u00e1c<\/li>\n<li><strong>Dung l\u01b0\u1ee3ng bundle nh\u1ecf<\/strong>. \u0110\u00e2y l\u00e0 \u0111i\u1ec3m s\u00e1ng c\u1ee7a Svelte. File build cu\u1ed1i c\u00f9ng c\u1ee7a Svelte kh\u00e1 nh\u1ecf so v\u1edbi React ho\u1eb7c Vue, \u0111\u1ed3ng th\u1eddi h\u1ed7 tr\u1ee3 s\u1eb5n t\u00ednh n\u0103ng \u0111\u00ednh k\u00e8m CSS v\u00e0o file build n\u00ean kh\u00e1 thu\u1eadn ti\u1ec7n v\u1edbi nhu c\u1ea7u c\u1ee7a m\u00ecnh<\/li>\n<li><strong>D\u1ec5 ti\u1ebfp c\u1eadn<\/strong>. M\u00ecnh ch\u1ec9 m\u1ea5t kho\u1ea3ng 1 ng\u00e0y \u0111\u1ec3 l\u00e0m quen v\u00e0 l\u00e0m vi\u1ec7c v\u1edbi Svelte. T\u01b0\u01a1ng \u0111\u1ed1i d\u1ec5 h\u1ecdc, t\u00e0i li\u1ec7u c\u0169ng kh\u00e1 tr\u1ef1c quan n\u00ean vi\u1ec7c ti\u1ebfp c\u1eadn n\u00f3 \u0111\u1ed1i v\u1edbi m\u1ed9t ng\u01b0\u1eddi ch\u01b0a bi\u1ebft g\u00ec kh\u00e1 l\u00e0 d\u1ec5. H\u01a1n n\u1eefa th\u00ec syntax (c\u00fa ph\u00e1p) c\u1ee7a Svelte gi\u1ed1ng ho\u00e0n to\u00e0n v\u1edbi HTML, CSS v\u00e0 JavaScript th\u00f4ng th\u01b0\u1eddng n\u00ean \u00edt g\u1eb7p nh\u1eefng tr\u01b0\u1eddng h\u1ee3p nh\u01b0 nh\u1ea7m <code>class<\/code> v\u00e0 <code>className<\/code> ho\u1eb7c <code>for<\/code> v\u00e0 <code>htmlFor<\/code> \u1edf React<\/li>\n<li><strong>Syntax ti\u1ec7n d\u1ee5ng<\/strong>. M\u00ecnh kh\u00e1 th\u00edch <code>{#await expression}...{:then name}...{:catch name}...{\/await}<\/code> v\u00e0 <code>{#each expression as name}...{:else}...{\/each}<\/code>. So v\u1edbi v\u1edbi c\u00e1c th\u01b0 vi\u1ec7n kh\u00e1c th\u00ec kh\u00e1 ti\u1ec7n d\u1ee5ng, kh\u00f4ng c\u1ea7n ph\u1ea3i t\u1ea1o bi\u1ebfn <code>isLoading<\/code> ho\u1eb7c ki\u1ec3m tra <code>array.length === 0<\/code> b\u1eb1ng tay n\u1eefa<\/li>\n<\/ul>\n<p>Tho\u1ea1t nh\u00ecn th\u00ec Svelte c\u0169ng c\u00f3 v\u1ebb ho\u00e0n h\u1ea3o nh\u01b0ng th\u1ef1c s\u1ef1 th\u00ec v\u1eabn c\u00f3 m\u1ed9t s\u1ed1 \u0111i\u1ec3m c\u1ea7n l\u01b0u \u00fd khi l\u1ef1a ch\u1ecdn Svelte:<\/p>\n<ul>\n<li><strong>M\u1edbi<\/strong>. \u0110\u1ed3 m\u1edbi lu\u00f4n t\u1ed1t h\u01a1n \u0111\u1ed3 c\u0169 l\u00e0 m\u1ed9t nh\u1eadn \u0111\u1ecbnh \u0111\u00fang nh\u01b0ng ch\u01b0a ch\u1eafc \u0111\u00e3 ch\u00ednh x\u00e1c trong ng\u00e0nh c\u00f4ng ngh\u1ec7 th\u00f4ng tin. B\u1ea3n th\u00e2n Svelte l\u00e0 m\u1ed9t th\u01b0 vi\u1ec7n c\u00f2n kh\u00e1 m\u1edbi, h\u01a1n n\u1eefa kh\u00f4ng c\u00f3 t\u1ed5 ch\u1ee9c n\u00e0o l\u1edbn &quot;ch\u1ed1ng l\u01b0ng&quot; n\u00ean c\u0169ng r\u1ea5t d\u1ec5 b\u1ecb b\u1ecf ngang. Vi\u1ec7c c\u00f3 m\u1ed9t \u00f4ng l\u1edbn &quot;ch\u1ed1ng l\u01b0ng&quot; kh\u00f4ng ph\u1ea3i l\u00fac n\u00e0o c\u0169ng l\u00e0 m\u1ed9t \u0111i\u1ec1u t\u1ed1t nh\u01b0ng \u00edt nhi\u1ec1u c\u0169ng s\u1ebd khi\u1ebfn ch\u00fang ta an t\u00e2m h\u01a1n khi l\u1ef1a ch\u1ecdn c\u00f4ng ngh\u1ec7 \u0111\u00f3. Ngo\u00e0i ra th\u00ec do Svelte kh\u00e1 m\u1edbi m\u1ebb, syntax c\u0169ng l\u1ea1 n\u00ean team v\u1eabn s\u1ebd m\u1ea5t th\u1eddi gian ti\u1ebfp c\u1eadn d\u00f9 \u00edt hay nhi\u1ec1u<\/li>\n<li><strong>Global CSS kh\u00e1 b\u1ea5t ti\u1ec7n<\/strong>. Tuy Svelte h\u1ed7 tr\u1ee3 vi\u1ebft CSS tr\u1ef1c ti\u1ebfp trong code nh\u01b0ng m\u1eb7c \u0111\u1ecbnh CSS \u0111\u00f3 s\u1ebd \u0111\u01b0\u1ee3c &quot;scoped&quot; (t\u1ea1m d\u1ecbch l\u00e0 g\u00e1n) cho component \u0111\u00f3. \u0110i\u1ec1u n\u00e0y kh\u00e1 b\u1ea5t ti\u1ec7n n\u1ebfu b\u1ea1n mu\u1ed1n style m\u1ed9t class chung cho t\u1ea5t c\u1ea3 component th\u00ec b\u1ea1n s\u1ebd ph\u1ea3i d\u00f9ng c\u00fa ph\u00e1p \u0111\u1eb7c bi\u1ec7t \u0111\u1ec3 khai b\u00e1o. D\u00f9 kh\u00f4ng \u1ea3nh h\u01b0\u1edfng g\u00ec nhi\u1ec1u nh\u01b0ng m\u00ecnh th\u1ea5y kh\u00e1 b\u1ea5t ti\u1ec7n trong qu\u00e1 tr\u00ecnh code<\/li>\n<\/ul>\n<h3>Th\u01b0 vi\u1ec7n h\u1ed7 tr\u1ee3<\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/10\/lodash.jpg\" alt=\"Lodash logo\" \/> <img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/10\/dayjs.jpg\" alt=\"DayJS logo\" \/> <img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/10\/embla-carousel.jpg\" alt=\"Embla Carousel logo\" \/><\/p>\n<p>Ph\u1ea7n n\u00e0y th\u00ec t\u00f9y thu\u1ed9c \u0111\u1eb7c th\u00f9 app m\u00e0 s\u1ebd thay \u0111\u1ed5i t\u01b0\u01a1ng \u1ee9ng, tuy nhi\u00ean m\u00ecnh c\u0169ng \u0111\u1ec1 c\u1eadp th\u00eam \u0111\u1ec3 c\u00e1c b\u1ea1n c\u00f3 th\u1ec3 tham kh\u1ea3o<\/p>\n<ul>\n<li><strong>Embla Carousel<\/strong>. Do h\u1ea1n ch\u1ebf kh\u00f4ng import tr\u1ef1c ti\u1ebfp \u0111\u01b0\u1ee3c file CSS c\u1ee7a Svelte n\u00ean vi\u1ec7c l\u1ef1a ch\u1ecdn th\u01b0 vi\u1ec7n carousel c\u0169ng t\u01b0\u01a1ng \u0111\u1ed1i kh\u00f3. R\u1ea5t may l\u00e0 Embla \u0111\u00e1p \u1ee9ng \u0111\u01b0\u1ee3c nhu c\u1ea7u n\u00e0y, \u0111\u1ed3ng th\u1eddi hi\u1ec7u n\u0103ng c\u0169ng r\u1ea5t t\u1ed1t n\u00ean m\u00ecnh l\u1ef1a ch\u1ecdn n\u00f3 \u0111\u1ec3 ph\u00e1t tri\u1ec3n ph\u1ea7n carousel<\/li>\n<li><strong>DayJS<\/strong>. Th\u01b0 vi\u1ec7n x\u1eed l\u00fd v\u1ec1 th\u1eddi gian (ng\u00e0y, th\u00e1ng, n\u0103m, gi\u1edd, &#8230;) th\u00ec c\u00f3 r\u1ea5t nhi\u1ec1u v\u00e0 h\u1ea7u h\u1ebft th\u01b0 vi\u1ec7n \u0111\u1ec1u \u0111\u00e1p \u1ee9ng \u0111\u01b0\u1ee3c nhu c\u1ea7u chung c\u1ee7a app. M\u00ecnh l\u1ef1a ch\u1ecdn dayjs v\u00ec k\u00edch th\u01b0\u1edbc th\u01b0 vi\u1ec7n v\u1eeba ph\u1ea3i, t\u00ednh n\u0103ng c\u0169ng v\u1eeba \u0111\u1ee7 nh\u1eefng th\u1ee9 m\u00ecnh c\u1ea7n<\/li>\n<li><strong>Lodash<\/strong>. V\u1ec1 c\u00e1c h\u00e0m utility (get, set, debounce, clone, &#8230;) th\u00ec m\u00ecnh ch\u1ecdn lodash. Underscore v\u00e0 ramda c\u0169ng l\u00e0 nh\u1eefng l\u1ef1a ch\u1ecdn c\u00e1c b\u1ea1n n\u00ean c\u00e2n nh\u1eafc. Team m\u00ecnh s\u1eed d\u1ee5ng lodash quen r\u1ed3i n\u00ean ti\u1ebfp t\u1ee5c s\u1eed d\u1ee5ng th\u00f4i. C\u00e1c b\u1ea1n ch\u1ec9 c\u1ea7n l\u01b0u \u00fd l\u00fac import h\u00e0m \u0111\u1ec3 tr\u00e1nh &quot;b\u01b0ng&quot; c\u1ea3 th\u01b0 vi\u1ec7n thay v\u00ec nh\u1eefng h\u00e0m m\u00ecnh d\u00f9ng l\u00e0 \u1ed5n<\/li>\n<\/ul>\n<p>V\u1eady l\u00e0 xong ph\u1ea7n app. V\u00ec nhu c\u1ea7u ch\u01b0a c\u00f3 g\u00ec nhi\u1ec1u v\u00e0 ph\u1ee9c t\u1ea1p n\u00ean m\u00ecnh ch\u1ec9 l\u1ef1a ch\u1ecdn tr\u01b0\u1edbc c\u00e1c th\u01b0 vi\u1ec7n nh\u01b0 tr\u00ean. Ti\u1ebfp theo m\u00ecnh s\u1ebd n\u00f3i t\u1edbi ph\u1ea7n app admin, n\u01a1i m\u00e0 tinh hoa c\u00f4ng ngh\u1ec7 b\u1eaft \u0111\u1ea7u xu\u1ea5t hi\u1ec7n.<\/p>\n<h2>C\u00f4ng ngh\u1ec7 App Admin<\/h2>\n<h3>Ng\u00f4n ng\u1eef<\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/02\/javascript-thumb.jpg\" alt=\"JavaScript logo\" \/><\/p>\n<p>C\u0169ng gi\u1ed1ng nh\u01b0 c\u00e1c l\u00fd do \u0111\u00e3 \u0111\u1ec1 c\u1eadp ph\u00eda tr\u00ean. M\u00ecnh v\u1eabn \u01b0u ti\u00ean s\u1eed d\u1ee5ng JavaScript \u1edf th\u1eddi \u0111i\u1ec3m hi\u1ec7n t\u1ea1i v\u00ec s\u1ef1 linh \u0111\u1ed9ng c\u1ee7a n\u00f3.<\/p>\n<h3>UI (User Interface)<\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/02\/next-thumb.jpg\" alt=\"NextJS logo\" \/><\/p>\n<p>Team m\u00ecnh ti\u1ebfp t\u1ee5c s\u1eed d\u1ee5ng NextJS \u0111\u1ec3 l\u00e0m UI, c\u1ee5 th\u1ec3 l\u00e0 NextJS 9. Phi\u00ean b\u1ea3n n\u00e0y c\u00f3 c\u00e1c thay \u0111\u1ed5i kh\u00e1 \u0111\u00e1ng gi\u00e1 nh\u01b0:<\/p>\n<ul>\n<li><strong>Dynamic routing theo \u0111\u01b0\u1eddng d\u1eabn file<\/strong>. Vi\u1ec7c h\u1ed7 tr\u1ee3 tr\u1ef1c ti\u1ebfp dynamic routing th\u00f4ng qua c\u00e1ch \u0111\u1eb7t t\u00ean file th\u1ef1c s\u1ef1 r\u1ea5t c\u1ea7n thi\u1ebft. N\u1ebfu nh\u01b0 \u1edf c\u00e1c phi\u00ean b\u1ea3n tr\u01b0\u1edbc, b\u1ea1n s\u1ebd ph\u1ea3i t\u1ea1o custom server \u0111\u1ec3 x\u1eed l\u00fd vi\u1ec7c routing, ph\u1ea3i h\u1ecdc qua ch\u00fat ch\u00fat v\u1ec1 express \u0111\u1ec3 hi\u1ec3u \u0111\u01b0\u1ee3c c\u00fa ph\u00e1p th\u00ec t\u1edbi phi\u00ean b\u1ea3n 9, b\u1ea1n ch\u1ec9 c\u1ea7n \u0111\u1eb7t t\u00ean theo d\u1ea1ng <code>[id].jsx<\/code> l\u00e0 \u0111\u00e3 c\u00f3 th\u1ec3 c\u00f3 \u0111\u01b0\u1ee3c dynamic route r\u1ed3i. \u0110\u00e2y l\u00e0 thay \u0111\u1ed5i \u0111\u00e1ng ch\u00fa \u00fd nh\u1ea5t \u1edf phi\u00ean b\u1ea3n l\u1ea7n n\u00e0y<\/li>\n<li><strong>T\u1ef1 \u0111\u1ed9ng t\u1ed1i \u01b0u h\u00f3a trang<\/strong>. Phi\u00ean b\u1ea3n 9 h\u1ed7 tr\u1ee3 t\u1ef1 \u0111\u1ed9ng export trang t\u0129nh n\u1ebfu trong trang kh\u00f4ng xu\u1ea5t hi\u1ec7n vi\u1ec7c truy xu\u1ea5t d\u1eef li\u1ec7u \u1edf ph\u00eda server. \u0110i\u1ec1u n\u00e0y l\u00e0m t\u0103ng \u0111\u00e1ng k\u1ec3 t\u1ed1c \u0111\u1ed9 t\u1ea3i trang v\u00e0 qua \u0111\u00f3 t\u0103ng tr\u1ea3i nghi\u1ec7m c\u1ee7a ng\u01b0\u1eddi d\u00f9ng l\u00ean nhi\u1ec1u l\u1ea7n<\/li>\n<li><strong>H\u1ed7 tr\u1ee3 TypeScript<\/strong>. N\u1ebfu nh\u01b0 \u1edf c\u00e1c phi\u00ean b\u1ea3n kh\u00e1c b\u1ea1n ph\u1ea3i thi\u1ebft l\u1eadp Babel, Webpack v\u00e0 nhi\u1ec1u th\u1ee9 kh\u00e1c n\u1eefa \u0111\u1ec3 s\u1eed d\u1ee5ng TypeScript th\u00ec b\u00e2y gi\u1edd n\u00f3 \u0111\u00e3 \u0111\u01b0\u1ee3c h\u1ed7 tr\u1ee3 tr\u1ef1c ti\u1ebfp ngay trong NextJS. \u0110\u00e2y c\u0169ng l\u00e0 m\u1ed9t \u0111i\u1ec3m \u0111\u00e1ng ch\u00fa \u00fd \u1edf phi\u00ean b\u1ea3n 9 d\u00f9 team m\u00ecnh ch\u01b0a c\u00f3 \u00fd \u0111\u1ecbnh s\u1eed d\u1ee5ng TypeScript<\/li>\n<\/ul>\n<p>Khi v\u1eeba ra m\u1eaft th\u00ec NextJS 9 xu\u1ea5t hi\u1ec7n l\u1ed7i hot-reload code. M\u00ecnh nh\u1edb l\u00fac \u0111\u00f3 code xong l\u01b0u l\u1ea1i c\u00f3 khi ph\u1ea3i ch\u1edd 1 \u0111\u1ebfn 2 gi\u00e2y m\u1edbi c\u00f3 ph\u1ea3n h\u1ed3i tr\u00ean giao di\u1ec7n. L\u1ed7i n\u00e0y \u0111\u00e3 \u0111\u01b0\u1ee3c kh\u1eafc ph\u1ee5c \u1edf c\u00e1c b\u1ea3n n\u00e2ng c\u1ea5p sau \u0111\u00f3 nh\u01b0ng tr\u1ea3i nghi\u1ec7m ban \u0111\u1ea7u khi s\u1eed d\u1ee5ng kh\u00e1 l\u00e0 kh\u00f3 ch\u1ecbu.<\/p>\n<h3>Deployment<\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/10\/vercel.jpg\" alt=\"Vercel logo\" \/><\/p>\n<p>N\u1ebfu c\u00e1c b\u1ea1n c\u00f3 nh\u1edb th\u00ec team m\u00ecnh tr\u01b0\u1edbc gi\u1edd v\u1eabn deploy b\u1eb1ng tay, t\u1ee9c l\u00e0 s\u1ebd c\u00f3 ng\u01b0\u1eddi \u0111\u1ea3m nh\u1eadn c\u00f4ng vi\u1ec7c merge code, build v\u00e0 push l\u00ean server. Qu\u00e1 tr\u00ecnh n\u00e0y ti\u00eau t\u1ed1n kh\u00e1 nhi\u1ec1u ngu\u1ed3n l\u1ef1c c\u1ee7a team n\u00ean khi ph\u00e1t tri\u1ec3n CPA, team quy\u1ebft \u0111\u1ecbnh s\u1eed d\u1ee5ng lu\u00f4n h\u1ec7 th\u1ed1ng Vercel (tr\u01b0\u1edbc \u0111\u00e2y l\u00e0 Zeit Now) \u0111\u1ec3 t\u1ef1 \u0111\u1ed9ng deploy m\u1ed7i khi code \u0111\u01b0\u1ee3c push l\u00ean GitHub.<\/p>\n<p>NextJS l\u00e0 m\u1ed9t trong nh\u1eefng s\u1ea3n ph\u1ea9m c\u1ee7a Vercel n\u00ean n\u00f3 \u0111\u01b0\u1ee3c h\u1ed7 tr\u1ee3 kh\u00e1 t\u1ed1t, kh\u00f4ng c\u1ea7n tinh ch\u1ec9nh g\u00ec nhi\u1ec1u ngo\u00e0i vi\u1ec7c thi\u1ebft l\u1eadp bi\u1ebfn m\u00f4i tr\u01b0\u1eddng (Environment Variable). Nh\u1edd vi\u1ec7c d\u1ef1 \u00e1n \u0111\u01b0\u1ee3c t\u1ef1 \u0111\u1ed9ng deploy n\u00ean team c\u0169ng c\u00f3 nhi\u1ec1u th\u1eddi gian h\u01a1n \u0111\u1ec3 t\u1eadp trung v\u00e0o vi\u1ec7c ph\u00e1t tri\u1ec3n t\u00ednh n\u0103ng v\u00e0 c\u0169ng kh\u00f4ng c\u00f2n lo s\u1ee3 khi ng\u01b0\u1eddi ph\u1ee5 tr\u00e1ch deploy v\u1eafng m\u1eb7t \u1edf c\u00f4ng ty n\u1eefa.<\/p>\n<h3>Component kit<\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/10\/shopify.jpg\" alt=\"Shopify Polaris logo\" \/><\/p>\n<p>R\u00fat kinh nghi\u1ec7m c\u1ee7a EGANY Apps, l\u1ea7n n\u00e0y team quy\u1ebft \u0111\u1ecbnh s\u1ebd s\u1eed d\u1ee5ng m\u1ed9t b\u1ed9 component c\u00f3 s\u1eb5n \u0111\u1ec3 ti\u1ebft ki\u1ec7m th\u1eddi gian ph\u00e1t tri\u1ec3n. \u0110\u01b0\u1ee3c s\u1ebfp g\u1ee3i \u00fd Shopify Polaris n\u00ean m\u00ecnh c\u0169ng d\u00f9ng th\u1eed. Sau v\u00e0i ng\u00e0y tr\u1ea3i nghi\u1ec7m th\u00ec m\u00ecnh quy\u1ebft \u0111\u1ecbnh ch\u1ecdn Shopify Polaris lu\u00f4n, l\u00fd do:<\/p>\n<ul>\n<li><strong>Design Guidelines t\u1ed1t<\/strong>. Shopify l\u00e0 m\u1ed9t trong nh\u1eefng c\u00f4ng ty e-commerce h\u00e0ng \u0111\u1ea7u hi\u1ec7n nay. V\u00ec v\u1eady, Design Guidelines c\u1ee7a Shopify r\u1ea5t r\u00f5 r\u00e0ng, chi ti\u1ebft v\u00e0 v\u00f4 c\u00f9ng ph\u00f9 h\u1ee3p v\u1edbi c\u00e1c h\u1ec7 th\u1ed1ng e-commerce<\/li>\n<li><strong>G\u1ea7n g\u0169i v\u1edbi ng\u01b0\u1eddi d\u00f9ng<\/strong>. Nhi\u1ec1u n\u1ec1n t\u1ea3ng e-commerce \u0111i theo xu h\u01b0\u1edbng thi\u1ebft k\u1ebf c\u1ee7a Shopify n\u00ean khi s\u1eed d\u1ee5ng Polaris, team s\u1ebd t\u1ea1o \u0111\u01b0\u1ee3c c\u1ea3m gi\u00e1c th\u00e2n thu\u1ed9c cho kh\u00e1ch h\u00e0ng. H\u01a1n n\u1eefa, v\u00ec c\u00e1c component c\u1ee7a Polaris \u0111\u01b0\u1ee3c thi\u1ebft k\u1ebf r\u1ea5t t\u1ed1t n\u00ean x\u00e9t v\u1ec1 UI\/UX th\u00ec team c\u0169ng \u0111\u01b0\u1ee3c &quot;h\u01b0\u1edfng so\u00e1i&quot;<\/li>\n<li><strong>T\u00e0i li\u1ec7u chi ti\u1ebft, r\u00f5 r\u00e0ng<\/strong>. Tuy v\u1eabn c\u00f2n m\u1ed9t s\u1ed1 ch\u1ed7 ch\u01b0a ch\u00ednh x\u00e1c tuy\u1ec7t \u0111\u1ed1i nh\u01b0ng t\u00e0i li\u1ec7u component c\u1ee7a Polaris kh\u00e1 t\u1ed1t, c\u00f3 v\u00ed d\u1ee5 r\u00f5 r\u00e0ng v\u00e0 c\u00f3 h\u1eb3n h\u01b0\u1edbng d\u1eabn s\u1eed d\u1ee5ng bao g\u1ed3m khi n\u00e0o n\u00ean d\u00f9ng, tr\u00ecnh b\u00e0y nh\u01b0 th\u1ebf n\u00e0o cho \u0111\u00fang, &#8230;<\/li>\n<\/ul>\n<p>\u0110i\u1ec3m duy nh\u1ea5t m\u00ecnh kh\u00f4ng th\u00edch \u1edf Polaris l\u00e0 kh\u00f4ng custom \u0111\u01b0\u1ee3c nhi\u1ec1u. C\u0169ng d\u1ec5 hi\u1ec3u v\u00ec Polaris ph\u00e1t tri\u1ec3n t\u1eadp trung cho h\u1ec7 th\u1ed1ng e-commerce c\u1ee7a Shopify. M\u1ecdi th\u1ee9 \u0111\u1ec1u \u0111\u01b0\u1ee3c &quot;\u0111\u00f3ng g\u00f3i&quot; v\u00e0 &quot;ch\u1ed1t \u0111\u01a1n&quot;. D\u0129 nhi\u00ean l\u00e0 b\u1ea1n v\u1eabn c\u00f3 th\u1ec3 custom v\u1ec1 m\u00e0u s\u1eafc (theme) ho\u1eb7c ng\u00f4n ng\u1eef (locale) nh\u01b0ng n\u1ebfu b\u1ea1n mu\u1ed1n thay \u0111\u1ed5i layout th\u00ec qu\u1ea3 th\u1eadt l\u00e0 h\u01a1i kh\u00f3 kh\u0103n.<\/p>\n<h3>Rich-text editor<\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/10\/ckeditor.jpg\" alt=\"CKEditor logo\" \/><\/p>\n<p>\u0110a s\u1ed1 c\u00e1c component kit nh\u01b0 Ant Design, Material Design hay c\u1ee5 th\u1ec3 l\u00e0 Shopify Polaris \u0111\u1ec1u kh\u00f4ng h\u1ed7 tr\u1ee3 rich-text editor n\u00ean m\u00ecnh ph\u1ea3i t\u00ecm th\u01b0 vi\u1ec7n thay th\u1ebf.<\/p>\n<p>\u0110\u1ec3 ti\u1ebft ki\u1ec7m th\u1eddi gian th\u00ec m\u00ecnh s\u1eed d\u1ee5ng l\u1ea1i CKEditor c\u00f3 s\u1eb5n \u1edf EGANY Apps. V\u00ec \u0111a s\u1ed1 c\u00e1c th\u01b0 vi\u1ec7n rich-text editor \u0111\u1ec1u kh\u00f4ng h\u1ed7 tr\u1ee3 ch\u1ebf \u0111\u1ed9 SSR (Server Side Rendering) n\u00ean vi\u1ec7c t\u00edch h\u1ee3p c\u0169ng m\u1ea5t ch\u00fat th\u1eddi gian.<\/p>\n<p>\u0110\u00e1nh gi\u00e1 s\u01a1 b\u1ed9 v\u1ec1 CKEditor:<\/p>\n<ul>\n<li><strong>Nhi\u1ec1u t\u00ednh n\u0103ng<\/strong>. CKEditor c\u00f3 kh\u00e1 nhi\u1ec1u t\u00ednh n\u0103ng, \u0111\u00e2y l\u00e0 m\u1ed9t \u0111i\u1ec3m c\u1ed9ng nh\u01b0ng r\u1ea5t ti\u1ebfc l\u00e0 team ch\u1ec9 d\u00f9ng m\u1ed9t s\u1ed1 \u00edt trong \u0111\u00f3 n\u00ean vi\u1ec7c custom \u0111\u1ec3 \u1ea9n\/t\u1eaft b\u1edbt t\u00ednh n\u0103ng r\u1ea5t m\u1ea5t th\u1eddi gian<\/li>\n<li><strong>Hi\u1ec7u n\u0103ng kh\u00f4ng cao<\/strong>. V\u00ec kh\u00f4ng h\u1ed7 tr\u1ee3 SSR n\u00ean m\u1ecdi th\u1ee9 ph\u1ea3i \u0111\u01b0\u1ee3c load \u1edf ph\u00eda client. Do c\u00f3 nhi\u1ec1u t\u00ednh n\u0103ng n\u00ean vi\u1ec7c kh\u1edfi t\u1ea1o editor m\u1ea5t nhi\u1ec1u th\u1eddi gian, g\u00e2y c\u1ea3m gi\u00e1c b\u1ecb &quot;kh\u1ef1ng&quot; \u1edf giao di\u1ec7n. Tuy \u0111\u00e3 gi\u1ea3i quy\u1ebft b\u1eb1ng vi\u1ec7c load async nh\u01b0ng tr\u1ea3i nghi\u1ec7m ng\u01b0\u1eddi d\u00f9ng \u00edt nhi\u1ec1u v\u1eabn b\u1ecb \u1ea3nh h\u01b0\u1edfng<\/li>\n<li><strong>T\u00e0i li\u1ec7u cho React kh\u00f4ng hi\u1ec7u qu\u1ea3<\/strong>. M\u00ecnh \u0111\u00e1nh gi\u00e1 t\u00e0i li\u1ec7u l\u00fac b\u1ea5y gi\u1edd c\u1ee7a CKEditor cho vi\u1ec7c t\u00edch h\u1ee3p React kh\u00e1 m\u1edd nh\u1ea1t, kh\u00f4ng nhi\u1ec1u v\u00ed d\u1ee5 c\u00f3 \u00edch. \u0110a ph\u1ea7n m\u00ecnh ph\u1ea3i t\u1ef1 \u0111i t\u00ecm gi\u1ea3i ph\u00e1p trong Issues \u1edf GitHub ho\u1eb7c c\u00e1c website h\u1ecfi \u0111\u00e1p kh\u00e1c nh\u01b0 StackOverflow<\/li>\n<\/ul>\n<h3>State management<\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/02\/react-thumb.jpg\" alt=\"React logo\" \/> <img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/02\/swr-thumb.jpg\" alt=\"SWR logo\" \/><\/p>\n<p>C\u00f3 l\u1ebd t\u1eeb kh\u00f3a state management kh\u00f4ng c\u00f2n xa l\u1ea1 v\u1edbi c\u00e1c b\u1ea1n n\u1ebfu c\u00e1c b\u1ea1n t\u1eebng ti\u1ebfp x\u00fac v\u1edbi React, Vue, Svelte ho\u1eb7c c\u00e1c th\u01b0 vi\u1ec7n\/framework h\u1ed7 tr\u1ee3 l\u00e0m Single Page Application.<\/p>\n<p>State management th\u00ec m\u00ecnh s\u1ebd chia l\u00e0m 2 d\u1ea1ng:<\/p>\n<ul>\n<li><strong>Server State Management<\/strong>. Qu\u1ea3n l\u00fd state \u0111\u1ebfn t\u1eeb server, t\u1ee9c l\u00e0 c\u00f3 t\u01b0\u01a1ng t\u00e1c v\u1edbi API \u0111\u1ec3 ki\u1ec3m so\u00e1t state<\/li>\n<li><strong>Client State Management<\/strong>. Qu\u1ea3n l\u00fd state \u1edf client, t\u1ee9c l\u00e0 kh\u00f4ng c\u00f3 ho\u1eb7c \u00edt t\u01b0\u01a1ng t\u00e1c v\u1edbi API. N\u1ebfu c\u00f3 th\u01b0\u1eddng ch\u1ec9 l\u00e0 tr\u1ea1ng th\u00e1i ban \u0111\u1ea7u c\u1ee7a state (initial state)<\/li>\n<\/ul>\n<p>\u1ede client th\u00ec m\u00ecnh c\u00f3 th\u1eed qua Recoil, m\u1ed9t th\u01b0 vi\u1ec7n m\u1edbi ra m\u1eaft c\u1ee7a Facebook. So v\u1edbi Redux v\u00e0 MobX th\u00ec Recoil d\u1ec5 s\u1eed d\u1ee5ng h\u01a1n, \u00edt r\u01b0\u1eddm r\u00e0 h\u01a1n. Tuy nhi\u00ean, do Recoil m\u1edbi ch\u1ec9 \u1edf tr\u1ea1ng th\u00e1i beta v\u00e0 t\u00e0i li\u1ec7u l\u00fac n\u00e0y c\u0169ng ch\u01b0a \u0111\u1ea7y \u0111\u1ee7 n\u00ean m\u00ecnh kh\u00f4ng d\u00f9ng.<\/p>\n<p>Sau khi c\u00e2n \u0111o \u0111ong \u0111\u1ebfm nhu c\u1ea7u c\u1ee7a d\u1ef1 \u00e1n th\u00ec m\u00ecnh quy\u1ebft \u0111\u1ecbnh s\u1eed d\u1ee5ng React Context (s\u1eed d\u1ee5ng <code>useContext<\/code> hook). Th\u1eddi gian \u0111\u1ea7u th\u00ec team kh\u00f4ng g\u1eb7p v\u1ea5n \u0111\u1ec1 g\u00ec khi l\u00e0m vi\u1ec7c v\u1edbi React Context. Tuy nhi\u00ean, sau khi d\u1ef1 \u00e1n ph\u00e1t tri\u1ec3n l\u1edbn h\u01a1n th\u00ec m\u1ed9t s\u1ed1 v\u1ea5n \u0111\u1ec1 li\u00ean quan t\u1edbi hi\u1ec7u n\u0103ng ph\u00e1t sinh, c\u1ee5 th\u1ec3 l\u00e0 v\u1ea5n \u0111\u1ec1 v\u1ec1 vi\u1ec7c render c\u1ee7a component. Chi ti\u1ebft nh\u01b0 th\u1ebf n\u00e0o h\u1eb9n c\u00e1c b\u1ea1n \u1edf b\u00e0i sau nh\u00e9!<\/p>\n<p>Client state management tr\u01b0\u1edbc gi\u1edd l\u00e0m nhi\u1ec1u v\u00e0 c\u0169ng s\u1eed d\u1ee5ng nhi\u1ec1u th\u01b0 vi\u1ec7n r\u1ed3i n\u00ean m\u00ecnh c\u00f3 kinh nghi\u1ec7m. Server State Management th\u00ec th\u1eadt s\u1ef1 m\u00e0 n\u00f3i th\u00ec ngay t\u1ea1i th\u1eddi \u0111i\u1ec3m t\u00ecm hi\u1ec3u c\u00f4ng ngh\u1ec7 th\u00ec m\u00ecnh m\u1edbi bi\u1ebft t\u1edbi t\u1eeb kh\u00f3a n\u00e0y. L\u00fac b\u1ea5y gi\u1edd c\u00f3 React Query v\u00e0 SWR. M\u00ecnh c\u00f3 d\u00f9ng th\u1eed c\u1ea3 hai, v\u1ec1 c\u00f4ng d\u1ee5ng th\u00ec c\u1ea3 hai \u0111\u1ec1u \u0111\u00e1p \u1ee9ng t\u1ed1t, React Query c\u00f3 ph\u1ea7n nh\u1ec9nh h\u01a1n v\u1ec1 t\u00ednh n\u0103ng c\u00f3 v\u1ebb v\u00ec v\u1eady m\u00e0 n\u00f3 h\u01a1i ph\u1ee9c t\u1ea1p. Cu\u1ed1i c\u00f9ng th\u00ec m\u00ecnh ch\u1ecdn SWR, l\u00fd do:<\/p>\n<ul>\n<li><strong>\u0110\u01b0\u1ee3c ph\u00e1t tri\u1ec3n b\u1edfi team Vercel<\/strong>. N\u1ebfu \u0111\u00e3 d\u00f9ng NextJS v\u00e0 Vercel r\u1ed3i th\u00ec m\u00ecnh ngh\u0129 d\u00f9ng lu\u00f4n SWR s\u1ebd c\u00f3 \u0111\u01b0\u1ee3c s\u1ef1 &quot;h\u00f2a h\u1ee3p&quot; cao nh\u1ea5t gi\u1eefa c\u00e1c th\u01b0 vi\u1ec7n v\u00e0 framework. N\u1ebfu c\u00f3 v\u1ea5n \u0111\u1ec1 ph\u00e1t sinh th\u00ec ph\u00eda Vercel c\u0169ng s\u1ebd h\u1ed7 tr\u1ee3 cho c\u1ea3 NextJS v\u00e0 SWR<\/li>\n<li><strong>Ti\u1ebft ki\u1ec7m l\u01b0\u1ee3t request v\u1ec1 backend<\/strong>. V\u00ec request s\u1ebd \u0111\u01b0\u1ee3c cache \u1edf ph\u00eda client n\u00ean khi g\u1ecdi m\u1ed9t request nhi\u1ec1u l\u1ea7n (th\u00f4ng qua SWR) th\u00ec ti\u1ebft ki\u1ec7m \u0111\u01b0\u1ee3c kha kh\u00e1 l\u01b0\u1ee3t request. H\u01a1n n\u1eefa, nh\u1edd k\u1ebft qu\u1ea3 \u0111\u01b0\u1ee3c cache tr\u01b0\u1edbc n\u00ean t\u1ed1c \u0111\u1ed9 t\u1ea3i trang t\u0103ng \u0111\u00e1ng k\u1ec3. Team r\u1ea5t b\u1ea5t ng\u1edd v\u1edbi hi\u1ec7u n\u0103ng m\u00e0 SWR mang l\u1ea1i cho website<\/li>\n<li><strong>Tr\u1ea3i nghi\u1ec7m real-time<\/strong>. SWR h\u1ed7 tr\u1ee3 g\u1ecdi l\u1ea1i API (re-fetch) khi ng\u01b0\u1eddi d\u00f9ng chuy\u1ec3n tab v\u00e0 quay l\u1ea1i \u1ee9ng d\u1ee5ng. \u0110i\u1ec1u n\u00e0y t\u1ea1o ra c\u1ea3m gi\u00e1c &quot;real-time&quot; v\u1ec1 m\u1eb7t d\u1eef li\u1ec7u c\u1ee7a ng\u01b0\u1eddi d\u00f9ng. V\u00ed d\u1ee5:\n<ul>\n<li>Ng\u01b0\u1eddi d\u00f9ng nh\u1ea5n n\u00fat thanh to\u00e1n<\/li>\n<li>\u1ee8ng d\u1ee5ng m\u1edf tab m\u1edbi cho ng\u01b0\u1eddi d\u00f9ng thanh to\u00e1n<\/li>\n<li>Sau khi thanh to\u00e1n xong, ng\u01b0\u1eddi d\u00f9ng quay l\u1ea1i tab \u0111ang m\u1edf \u1ee9ng d\u1ee5ng<\/li>\n<li>\u1ee8ng d\u1ee5ng fetch l\u1ea1i th\u00f4ng tin thanh to\u00e1n v\u00e0 c\u1eadp nh\u1eadt l\u00ean giao di\u1ec7n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>M\u00ecnh th\u1eadt s\u1ef1 h\u00e0i l\u00f2ng v\u1edbi tr\u1ea3i nghi\u1ec7m m\u00e0 SWR mang l\u1ea1i. Ngay ch\u00ednh s\u1ebfp m\u00ecnh khi tr\u1ef1c ti\u1ebfp s\u1eed d\u1ee5ng trong qu\u00e1 tr\u00ecnh \u0111i\u1ec1u ch\u1ec9nh n\u1ed9i dung trang (l\u1ea5y t\u1eeb API \u1edf d\u1ea1ng JSON) c\u0169ng kh\u00e1 b\u1ea5t ng\u1edd v\u1edbi t\u00ednh n\u0103ng &quot;real-time&quot; n\u00e0y. M\u00ecnh nh\u1edb s\u1ebfp c\u00f2n h\u1ecfi: &quot;\u1ee6a em l\u00e0m API n\u1ed9i dung real-time lu\u00f4n \u00e0?&quot;. M\u00ecnh ch\u1ec9 c\u01b0\u1eddi v\u00e0 g\u1eadt \u0111\u1ea7u. #c\u00fa-l\u1eeba<\/p>\n<h3>Th\u01b0 vi\u1ec7n h\u1ed7 tr\u1ee3<\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/10\/lodash.jpg\" alt=\"Lodash logo\" \/> <img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/10\/dayjs.jpg\" alt=\"DayJS logo\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/10\/axios.jpg\" alt=\"Axios logo\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/10\/exceljs.jpg\" alt=\"ExcelJS logo\" \/><\/p>\n<p>Ngo\u00e0i lodash v\u00e0 dayjs th\u00ec m\u00ecnh c\u00f2n s\u1eed d\u1ee5ng th\u00eam c\u00e1c th\u01b0 vi\u1ec7n sau:<\/p>\n<ul>\n<li><strong>ExcelJS<\/strong>. H\u1ed7 tr\u1ee3 x\u1eed l\u00fd file excel, ch\u1ee7 y\u1ebfu ph\u1ee5c v\u1ee5 cho vi\u1ec7c import\/export d\u1eef li\u1ec7u trong \u1ee9ng d\u1ee5ng<\/li>\n<li><strong>Axios<\/strong>. Th\u01b0 vi\u1ec7n h\u1ed7 tr\u1ee3 g\u1ecdi API. C\u00e1 nh\u00e2n m\u00ecnh th\u1ea5y axios x\u1eed l\u00fd kh\u00e1 t\u1ed1t trong vi\u1ec7c g\u1ecdi API, b\u1ed5 sung nhi\u1ec1u t\u00ednh n\u0103ng h\u1eefu \u00edch nh\u01b0 timeout ho\u1eb7c progress khi upload file. \u0110i\u1ec1u m\u00ecnh kh\u00f4ng th\u00edch l\u00e0 object <code>error<\/code> tr\u1ea3 v\u1ec1 c\u1ee7a axios kh\u00e1 r\u01b0\u1eddm r\u00e0. N\u1ebfu x\u1eed l\u00fd chung v\u1edbi c\u00e1c l\u1ed7i th\u00f4ng d\u1ee5ng th\u00ec s\u1ebd ph\u1ea3i qua nhi\u1ec1u b\u01b0\u1edbc ki\u1ec3m tra \u0111\u1ec3 x\u00e1c \u0111\u1ecbnh l\u00e0 l\u1ed7i c\u1ee7a axios hay l\u1ed7i runtime b\u00ecnh th\u01b0\u1eddng<\/li>\n<\/ul>\n<h2>C\u00e2u chuy\u1ec7n license<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/egany.cdn.vccloud.vn\/blogs\/wp-content\/uploads\/2021\/10\/caution-1024x768.jpg\" alt=\"\" \/><\/p>\n<blockquote>\n<p>Ngu\u1ed3n \u1ea3nh: <a href=\"https:\/\/dribbble.com\/shots\/10565800-Black-Caution-Sign\" rel=\"nofollow noopener\" target=\"_blank\">https:\/\/dribbble.com\/shots\/10565800-Black-Caution-Sign<\/a><\/p>\n<\/blockquote>\n<p>M\u1ed9t ng\u00e0y \u0111\u1eb9p tr\u1eddi sau khi ho\u00e0n th\u00e0nh m\u1ecdi t\u00ednh n\u0103ng, trong khi ch\u1edd ph\u1ea3n h\u1ed3i t\u1eeb tester th\u00ec m\u00ecnh c\u00f3 \u0111\u1ecdc qua m\u1ed9t b\u00e0i vi\u1ebft n\u00f3i v\u1ec1 vi\u1ec7c l\u1ef1a ch\u1ecdn license ph\u00f9 h\u1ee3p cho d\u1ef1 \u00e1n c\u1ee7a m\u00ecnh. \u0110\u1ecdc xong th\u1ea5y kh\u00e1 th\u00fa v\u1ecb, t\u00f2 m\u00f2 v\u00e0o \u0111\u1ecdc license c\u1ee7a Shopify Polars th\u00ec m\u1edbi nh\u1eadn ra v\u1ea5n \u0111\u1ec1:<\/p>\n<ul>\n<li>Polaris cho b\u1ea1n to\u00e0n quy\u1ec1n khi ph\u00e1t tri\u1ec3n c\u00e1c \u1ee9ng d\u1ee5ng n\u1eb1m trong h\u1ec7 sinh th\u00e1i c\u1ee7a Shopify<\/li>\n<li>C\u00e1c \u1ee9ng d\u1ee5ng n\u1eb1m ngo\u00e0i h\u1ec7 sinh th\u00e1i c\u1ee7a Shopify n\u1ebfu c\u00f3 s\u1eed d\u1ee5ng Polaris th\u00ec ph\u1ea3i kh\u00e1c bi\u1ec7t (c\u1ea3 v\u1ec1 t\u00ednh n\u0103ng v\u00e0 giao di\u1ec7n) so v\u1edbi c\u00e1c s\u1ea3n ph\u1ea9m ho\u1eb7c d\u1ecbch v\u1ee5 c\u1ee7a Shopify cung c\u1ea5p &#8211; \u0111i\u1ec1u n\u00e0y thu\u1ed9c quy\u1ec1n quy\u1ebft \u0111\u1ecbnh c\u1ee7a Shopify<\/li>\n<\/ul>\n<p>CPA ch\u1eafc ch\u1eafn s\u1ebd kh\u00e1c v\u1ec1 t\u00ednh n\u0103ng nh\u01b0ng r\u1ea5t ti\u1ebfc l\u00e0 ph\u1ea7n admin c\u1ee7a CPA kh\u00e1 gi\u1ed1ng so v\u1edbi ph\u1ea7n admin c\u1ee7a Shopify. Ngo\u00e0i ra th\u00ec team c\u0169ng c\u00f3 \u0111i\u1ec1u ch\u1ec9nh component \u0111\u1ec3 ph\u00f9 h\u1ee3p h\u01a1n v\u1edbi design c\u1ee7a team. \u0110i\u1ec1u n\u00e0y \u0111\u1ed3ng ngh\u0129a v\u1edbi vi\u1ec7c team \u0111ang c\u00f3 nguy c\u01a1  vi ph\u1ea1m license c\u1ee7a ph\u00eda Shopify.<\/p>\n<p>Nh\u1eadn \u0111\u01b0\u1ee3c tin th\u00ec team c\u0169ng c\u00f3 h\u1ecdp l\u1ea1i v\u1edbi nhau v\u00e0 \u0111\u01b0a ra quy\u1ebft \u0111\u1ecbnh l\u00e0 s\u1ebd ti\u1ebfp t\u1ee5c s\u1eed d\u1ee5ng Polaris cho t\u1edbi khi s\u1ea3n ph\u1ea9m ho\u00e0n thi\u1ec7n v\u00e0 \u0111\u1ebfn \u0111\u01b0\u1ee3c tay c\u1ee7a m\u1ed9t s\u1ed1 ng\u01b0\u1eddi d\u00f9ng beta. Sau khi nh\u1eadn \u0111\u01b0\u1ee3c ph\u1ea3n h\u1ed3i c\u1ee7a ng\u01b0\u1eddi d\u00f9ng th\u00ec team s\u1ebd ti\u1ebfn h\u00e0nh chuy\u1ec3n \u0111\u1ed5i qua m\u1ed9t component kit kh\u00e1c, hay n\u00f3i c\u00e1ch kh\u00e1c l\u00e0 \u0111\u1eadp b\u1ecf to\u00e0n b\u1ed9 giao di\u1ec7n hi\u1ec7n t\u1ea1i v\u00e0 thay th\u1ebf b\u1eb1ng m\u1ed9t giao di\u1ec7n kh\u00e1c.<\/p>\n<h2>T\u1ea1m k\u1ebft<\/h2>\n<p>Nh\u01b0 c\u00e1c b\u1ea1n \u0111\u00e3 th\u1ea5y, c\u00f4ng s\u1ee9c v\u00e0i th\u00e1ng tr\u1eddi xem nh\u01b0 c\u00f4ng c\u1ed1c ch\u1ec9 v\u00ec v\u00e0i d\u00f2ng ch\u1eef license. \u0110\u00fang nh\u01b0 l\u1eddi \u00f4ng b\u00e0 ta n\u00f3i: &quot;Sai m\u1ed9t ly, \u0111i m\u1ed9t d\u1eb7m&quot;. \u0110\u00e2y qu\u1ea3 th\u1eadt l\u00e0 m\u1ed9t b\u00e0i h\u1ecdc \u0111\u1eaft gi\u00e1 cho c\u00e1 nh\u00e2n m\u00ecnh c\u0169ng nh\u01b0 c\u00e1c th\u00e0nh vi\u00ean trong team trong vi\u1ec7c l\u1ef1a ch\u1ecdn c\u00f4ng ngh\u1ec7 \u0111\u1ec3 s\u1eed d\u1ee5ng trong d\u1ef1 \u00e1n, \u0111\u1eb7c bi\u1ec7t l\u00e0 nh\u1eefng d\u1ef1 \u00e1n th\u01b0\u01a1ng m\u1ea1i.<\/p>\n<p>Qu\u00e1 tr\u00ecnh chuy\u1ec3n \u0111\u1ed5i di\u1ec5n ra nh\u01b0 th\u1ebf n\u00e0o? C\u00f4ng ngh\u1ec7 n\u00e0o s\u1ebd \u0111\u01b0\u1ee3c s\u1eed d\u1ee5ng cho phi\u00ean b\u1ea3n ti\u1ebfp theo? H\u1eb9n g\u1eb7p c\u00e1c b\u1ea1n \u1edf t\u1eadp ti\u1ebfp theo nh\u00e9.<\/p>\n<blockquote>\n<p>B\u00e0i thu\u1ed9c chuy\u00ean m\u1ee5c Engineering v\u00e0 c\u1ea3 chuy\u00ean m\u1ee5c Culture v\u00ec c\u00f4ng ty m\u00ecnh r\u1ea5t ch\u00fa tr\u1ecdng v\u0103n h\u00f3a chia s\u1ebb v\u00e0 h\u1ecdc h\u1ecfi. C\u00e1c b\u1ea1n c\u00f3 th\u1ec3 \u0111\u1ecdc &quot;s\u01b0\u01a1ng s\u01b0\u01a1ng&quot; <a href=\"https:\/\/egany.com\/blogs\/nhung-dieu-can-biet-truoc-khi-vao-lam-viec-tai-egany\/\" title=\"v\u1ec1 EGANY\">v\u1ec1 EGANY<\/a> \u0111\u1ec3 bi\u1ebft v\u00ec sao.<br \/>\nC\u00f2n c\u00e1c c\u01a1 h\u1ed9i \u0111\u1ec3 l\u00e0m &quot;Bug Contributor&quot; c\u00f9ng m\u00ecnh th\u00ec <a href=\"https:\/\/egany.com\/blogs\/careers\/\" title=\"\u1edf \u0111\u00e2y\">\u1edf \u0111\u00e2y<\/a> \ud83d\ude06. <\/p>\n<\/blockquote>\n<p>C\u00e1m \u01a1n c\u00e1c b\u1ea1n \u0111\u00e3 \u0111\u1ecdc b\u00e0i. Happy hacking! \ud83d\udc4c<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nh\u00e2n d\u1ecbp S\u00e0i G\u00f2n quay tr\u1edf l\u1ea1i sau \u0111\u1ee3t c\u00e1ch ly th\u00ec m\u00ecnh c\u0169ng ra m\u1ed9t b\u00e0i vi\u1ebft m\u1edbi. Frontend Du K\u00fd k\u00ec n\u00e0y s\u1ebd k\u1ec3 v\u1ec1 qu\u00e1 tr\u00ecnh l\u1ef1a ch\u1ecdn c\u00f4ng ngh\u1ec7 \u0111\u1ec3 ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng Cross-platform Apps. N\u1ebfu b\u1ea1n ch\u01b0a \u0111\u1ecdc t\u1eadp tr\u01b0\u1edbc, b\u1ea1n c\u00f3 th\u1ec3 \u0111\u1ecdc t\u1ea1i \u0111\u00e2y. Gi\u1edbi thi\u1ec7u Cross-platform Apps s\u1ebd \u0111\u01b0\u1ee3c vi\u1ebft t\u1eaft b\u1eb1ng CPA \u0111\u1ec3 thu\u1eadn ti\u1ec7n cho ng\u01b0\u1eddi vi\u1ebft b\u00e0i Khi m\u00ecnh c\u00f2n l\u00e0 m\u1ed9t ch\u00e0ng dev tr\u1ebb tr\u00e2u trung, n\u0103ng \u0111\u1ed9ng, th\u00edch kh\u00e1m ph\u00e1 v\u00e0 th\u1eed th\u00e1ch, m\u00ecnh \u0111\u01b0\u1ee3c s\u1ebfp tin t\u01b0\u1edfng giao tr\u1ecdng tr\u00e1ch l\u1ef1a ch\u1ecdn c\u00f4ng ngh\u1ec7 \u0111\u1ec3<\/p>\n","protected":false},"author":2,"featured_media":999,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[27,1],"tags":[120,109,117,112,87,90,116,32,64,115,119,34,114,30,118],"_links":{"self":[{"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/posts\/990"}],"collection":[{"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/comments?post=990"}],"version-history":[{"count":0,"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/posts\/990\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/media\/999"}],"wp:attachment":[{"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/media?parent=990"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/categories?post=990"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/egany.com\/blogs\/wp-json\/wp\/v2\/tags?post=990"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}