### Bundle 在使用 React 時是一定會使用到 Webpack 等等工具來把 JSX、CSS、IMAGES... 等等進行打包。如果你的 APP 已經建立得非常大時,產生的 Bundle 檔案也會非常巨大。使用者在下載時就會花上很多時間了喔 ! ### 解決方法 我們可以通過使用 React 內建的 Lazy loading 來解決一次過下載巨大 Bundle 檔案的問題。它的原理是把單一的 Bundle 檔案依不同的 package 來分割開,然後在使用者實際使用時才動態載入。 ### 內裏是 Promise 我們有以下的 module ,作用把兩個傳入的數字相加。 ```js // math.js export default sum(a, b) => a + b; ``` 在傳統的使用方法,我們是以下這樣 : ```js import sum from './math.js'; console.log(sum(1, 2)); // 3 ``` 使用 Lazy Loading 的話,載入的 object 就會變成了 Promise 物件: ```js import('./math.js') .then(sum => console.log(sum(1, 2))); // 3 ``` ### 實際使用 在實際使用上,我們可以通過使用 `React.lazy` 方法來簡單化整個載入的流程。 ```js // 載入 SomeComponent const SomeComponent = React.lazy(() => import('./SomeComponent.jsx')); ``` 然可以作為一般的 Component 來使用,但是需要放在 React.Suspense 元件內。 ```js <React.Suspense fallback={<div>Loading...</div>}> <SomeComponent /> </React.Suspense> ``` React.Suspense 是處理其子 Component 如果有 Lazy Loading 動作時,就會劃出 fallback 的元件出來,等待 Lazy Load 完成後,就會顯示元件。 ### 筆者推介使用方法 因為在 React 內得多元件都可以重用,但是如果有使用 React Router 的話,不同 URL 之間的元件是一定不會重用的,所以我們可以簡單把 React.Suspense 包住整個 Router。然後把不同 Route 內的 Component 都轉成使用 Lazy Load,這樣就已經可以簡單快速地分割出合適的 Bundle 檔案了。 ### 官方文件 官方文件 : https://zh-hant.reactjs.org/docs/code-splitting.html
### Image slider / Carousels 在網站上很多時都會使用流水式的 Banner 來告訴使用者最近的事情。  ### 選擇現成的 Library 初時筆者找到了 `react-alice-carousel` 這個套件,好像很簡單易用,所以後快速的試了一下。不過發現有個問題到現時最新的 Version 都好像還沒有修正好,就是在圖片滑動的中途,如果整個 Component 出現 unmount 的情況,就會出現 Error : Updated on unmounted component。 雖然在它們的 github 上好像沒有人 report 過這樣的 issue。不過筆者確實是遇到了,所以還是選擇另家的好了。 ### nuka-carousel 這是另一家大神寫出來的 Image slider,使用上也是非常之簡單。 Github: https://github.com/FormidableLabs/nuka-carousel 下面會簡單記錄一下使用的方法。 ### 安裝 可以使用 npm 來安裝。 ```sh $ npm install nuka-carousel ``` ### 使用 使用上也是十分之簡單,只要用 Carousel 包住想要用來 Slide 的內容就可以了,高度是自動的,內容可以用 Array 填入就可以。配上 Div 使用 background 來使用就非常得心應手。 ```js import React from 'react'; import Carousel from 'nuka-carousel'; export default class extends React.Component { render() { return ( <Carousel> <img src="https://via.placeholder.com/400/ffffff/c0392b/&text=slide1" /> <img src="https://via.placeholder.com/400/ffffff/c0392b/&text=slide2" /> <img src="https://via.placeholder.com/400/ffffff/c0392b/&text=slide3" /> <img src="https://via.placeholder.com/400/ffffff/c0392b/&text=slide4" /> <img src="https://via.placeholder.com/400/ffffff/c0392b/&text=slide5" /> <img src="https://via.placeholder.com/400/ffffff/c0392b/&text=slide6" /> </Carousel> ); } } ``` 送上 div 顯示圖片的咒語: ```js <div style={{ background: '#FFFFFF url(https://via.placeholder.com/400/ffffff/c0392b/&text=slide1) center center / cover no-repeat', height: '0px', paddingBottom: '30%' }} /> ``` 以下是筆者使用的 Config: ```js <Carousel autoplay={ true } autoplayInterval={ 4000 } withoutControls={ false } wrapAround={ true } speed={ 1000 } renderCenterLeftControls={ () => {} } renderCenterRightControls={ () => {} } > {items} </Carousel> ```
### 設定 Nginx 要在 nginx 上取得 proxy 的 client address,需要事先在設定 nginx 時就要加入下 `--with-http_realip_module` 的設定。如果安裝的 nginx 是由 apt 上下載的,就可以使用以下指令來查看你的 nginx 有沒有設定 `--with-http_realip_module` 模組。 ```sh $ nginx -V nginx version: nginx/1.18.0 (Ubuntu) built with OpenSSL 1.1.1f 31 Mar 2020 TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-5J5hor/nginx-1.18.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-compat --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module ``` 如果在輸出的結看看到了模組的名稱,就代表已經設定好了。 ### 設定來自 Cloudflare 的 IP address 然後需要把來自 Cloudflare 的 IP address 設定到 nginx.conf 檔案內。 參考 Cloudflare 的網站 : https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs-Logging-visitor-IP-addresses-with-mod-cloudflare- ```txt set_real_ip_from 103.21.244.0/22; set_real_ip_from 103.22.200.0/22; set_real_ip_from 103.31.4.0/22; set_real_ip_from 104.16.0.0/12; set_real_ip_from 108.162.192.0/18; set_real_ip_from 131.0.72.0/22; set_real_ip_from 141.101.64.0/18; set_real_ip_from 162.158.0.0/15; set_real_ip_from 172.64.0.0/13; set_real_ip_from 173.245.48.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 190.93.240.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17; set_real_ip_from 2400:cb00::/32; set_real_ip_from 2606:4700::/32; set_real_ip_from 2803:f800::/32; set_real_ip_from 2405:b500::/32; set_real_ip_from 2405:8100::/32; set_real_ip_from 2c0f:f248::/32; set_real_ip_from 2a06:98c0::/29; ``` 再設定 Cloudflare 的 IP 寫入 header 欄位名稱。 ```txt real_ip_header CF-Connecting-IP; #real_ip_header X-Forwarded-For; ``` 設定好後,在 Nginx 的 Virtual Host Config 檔案內使用變數 $remote_addr 時,就可以取得 Cloudflare 傳入的真正地址了。 下面是 Virtual Host Config 檔案使用 Reverse proxy 的例子 : ```txt location / { proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Host $http_host; proxy_pass https://localhost:81; } ```
由於不同之間的 browser 都有差異,所以如果要保險起見,需要以多種的語法來最最得 scroll top 值來確保安全。而已經有大神寫好了這個簡單的語法 ! ```js window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0 ```