Prerender với puppeteer

NodeJS Dec 07, 2020

Hiện nay các web framework như reactjs, vuejs, angularjs đang ngày càng phổ biến. Trong các Single Page Application (SPA), trình duyệt sẽ chỉ load các file js, css, và html đã được build sẵn, giao diện sẽ được render sau quá trình chạy javascript. Do đó, các thẻ meta tag, title của website sẽ chỉ xuất hiện sau quá trình render, quá trình render các meta tag này còn có thể phụ thuộc vào việc tương tác với api để lấy thông tin. Khi đó, các crawler bot như của google, facebook, twitter sẽ không thể lấy được thông tin của website, và tất nhiên là ứng dụng của bạn sẽ không được xuất hiện trên các công cụ tìm kiếm. Giải pháp được đề ra cho việc này là phải xử lý việc render trang web ở server và trả lại kết quả sau khi render cho client.

Ở bài này, mình sẽ giới thiệu về việc sử dụng puppeteer cho việc prerender. Puppeteer là một headless browser, giúp hỗ trợ chúng ta trong việc request tới page mà ta cần xử lý, đợi cho tới khi page được render xong và lấy ra nội dung html để có thể trả về cho client. Bên cạnh đó, chúng ta cũng cần sử dụng Nginx nhằm mục đích lọc tất cả các request từ crawler bot và chuyển cho ứng dụng chạy puppeteer để xử lý. Ngoài ra, chúng ta có thể sử dụng puppeteer cho việc giả lập tương tác người dùng với trang web, crawler dữ liệu.

Giả sử chúng ta đang có ReactJS app đang chạy ở cổng 3000, và được thiết lập Nginx cho ứng dụng này ở cổng 6666. Khi thử request đến trang này, chúng ta sẽ nhận được response như sau:

Với response trên, rõ ràng là nó không có bất cứ một thông tin nào về website của chúng ta, tất nhiên là không thể tương thích với các search engine.

Thiết lập prerender app với puppeteer, express

$ mkdir prerender-app
$ cd prerender-app
$ npm install express puppeteer
$ touch app.js


Code phần xử lý cho prerender app chạy trên cổng 9000 như sau


Option `networkidle0` sẽ cho puppeteer biết kết thúc việc điều hướng trang khi không còn tồn tại connection nào đang hoạt động, như việc load file, chờ api, …

Thiết lập nginx

server {
  listen 6666;
  listen [::]:6666;
  server_name react_app_server;

  location / {
    # Filter request from crawler bot
    if ($http_user_agent ~* "googlebot|facebookexternalhit|twitterbot) {
      proxy_pass http://localhost:9000;
    }

    proxy_pass http://localhost:3000;
  }
}

Sau khi thiết lập xong thì chúng ta có thể test thử việc request bằng user agent như googlebot.

$ curl -A "googlebot" localhost:6666/features

Như ở trên, chúng ta đã hoàn thành xây dựng một app đơn giản để hỗ trợ prerender ứng dụng ReactJS, VueJS, ... phục vụ cho các crawler bot. Ngoài ra, các bạn có tham khảo Server-Side Rendering ở các link sau:

Tags

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.