Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ลดปริมาณการส่งข้อมูล #2

Merged
merged 3 commits into from
Apr 8, 2017

Conversation

dtinth
Copy link
Contributor

@dtinth dtinth commented Apr 8, 2017

สวัสดีครับ, ขอบคุณครับสำหรับไลบรารี่ดีๆ สำหรับนักพัฒนาเว็บไทย 👍

ใน PR นี้ผมลองทำการ Optimize ต่างๆ เพื่อลดขนาดไฟล์ที่ส่งไปยังเบราเซอร์ครับ โดยถือว่าเซิฟเวอร์ได้บีบอัดข้อมูลด้วยอัลกอริธึม Gzip อยู่แล้ว และปริมาณการถ่ายโอนข้อมูลวัดจาก Chrome DevTools ครับ (ได้ทำการ Disable Cache แล้ว)

ตารางที่ 1: ขนาดไฟล์ก่อนทำการ Optimize

ไฟล์ ขนาดไฟล์ ขนาดเมื่อถูก Gzip
jszip.min.js 99.5 KB 29.7 KB
jszip-utils.min.js 1.7 KB 1.2 KB
JQL.min.js 3.1 KB 1.3 KB
typeahead.bundle.js 43.4 KB 14.6 KB
jquery.Thailand.min.js 2.4 KB 1.2 KB
db.zip 65.3 KB 65.6 KB
รวม 215.4 KB 113.6 KB

เอา JSZIP ออกแล้วใช้ไฟล์ .json ธรรมดา

โดยปกติเว็บเซิฟเวอร์จะ Gzip ไฟล์ JSON อยู่แล้วครับ ดังนั้นจึงไม่จำเป็นต้องอัด ZIP ไฟล์ฐานข้อมูล

หลังจากเอา JSZIP ออกอันนี้คือปริมาณข้อมูลที่ถ่ายโอนครับ:

ตารางที่ 2: ขนาดไฟล์หลังนำ JSZIP ออก

ไฟล์ ขนาดไฟล์ ขนาดเมื่อถูก Gzip
JQL.min.js 3.1 KB 1.3 KB
typeahead.bundle.js 43.4 KB 14.6 KB
jquery.Thailand.min.js 2.3 KB 1.2 KB
db.json 759.0 KB 70.2 KB
รวม 807.8 KB 87.3 KB

ขนาดลดลงจากเดิม: 26.3 KB (23.1%)

บีบอัดฐานข้อมูล

เนื่องจากฐานข้อมูลจังหวัด–อำเภอ–ตำบล–รหัสไปรษณีย์ มีลักษณะเป็น Hierarchical อยู่แล้ว (คือสามารถ Represent ในรูปของ Tree ได้) เมื่อนำมาวางเป็นตารางจึงเกิดความซ้ำซ้อนจนเกินไปครับ

[ { d: 'พระบรมมหาราชวัง', a: 'พระนคร', p: 'กรุงเทพมหานคร', z: 10200 },
  { d: 'ตะพง', a: 'เมืองระยอง', p: 'ระยอง', z: 21000 },
  { d: 'เพ', a: 'เมืองระยอง', p: 'ระยอง', z: 21160 },
  { d: 'แกลง', a: 'เมืองระยอง', p: 'ระยอง', z: 21160 },
  { d: 'บ้านแลง', a: 'เมืองระยอง', p: 'ระยอง', z: 21000 },
  { d: 'นาตาขวัญ', a: 'เมืองระยอง', p: 'ระยอง', z: 21000 },
  { d: 'เนินพระ', a: 'เมืองระยอง', p: 'ระยอง', z: 21000 },
  { d: 'กะเฉด', a: 'เมืองระยอง', p: 'ระยอง', z: 21100 },
  { d: 'ทับมา', a: 'เมืองระยอง', p: 'ระยอง', z: 21000 },
  { d: 'น้ำคอก', a: 'เมืองระยอง', p: 'ระยอง', z: 21000 },
  { d: 'ห้วยโป่ง', a: 'เมืองระยอง', p: 'ระยอง', z: 21150 },
  { d: 'มาบตาพุด', a: 'เมืองระยอง', p: 'ระยอง', z: 21150 },
  

จะเห็นว่า , a: 'เมืองระยอง', p: 'ระยอง', z: ถูกเขียนซ้ำหลายครั้งมาก ทั้งๆ ที่ เมืองระยอง–จังหวัดระยอง มีอยู่แค่ที่เดียว

ดังนั้นผมจึงลองอัพเปลี่ยนรูปแบบฐานข้อมูลให้เป็นรูปแบบ Tree แทนครับ:

[ [ 'กระบี่',
    [ [ 'คลองท่อม',
        [ [ 'คลองท่อมเหนือ', [ 81120 ] ],
          [ 'คลองท่อมใต้', [ 81120 ] ],
          [ 'คลองพน', [ 81170 ] ],
          [ 'ทรายขาว', [ 81170 ] ],
          [ 'พรุดินนา', [ 81120 ] ],
          [ 'ห้วยน้ำขาว', [ 81120 ] ],
          [ 'เพหลา', [ 81120 ] ] ] ],
      [ 'ปลายพระยา',
        [ [ 'คีรีวง', [ 81160 ] ],
          [ 'ปลายพระยา', [ 81160 ] ],
          [ 'เขาต่อ', [ 81160 ] ],
          [ 'เขาเขน', [ 81160 ] ] ] ],
      

หลังจากจัดเรียงข้อมูลแบบนี้แล้วทำให้ฐานข้อมูลขนาดลดลงเหลือ 286 KB ครับ

ตารางที่ 3: ขนาดไฟล์หลังปรับโครงสร้างฐานข้อมูล

ไฟล์ ขนาดไฟล์ ขนาดเมื่อถูก Gzip
JQL.min.js 3.1 KB 1.3 KB
typeahead.bundle.js 43.4 KB 14.6 KB
jquery.Thailand.min.js 2.5 KB 1.2 KB
data.json 286.0 KB 57.4 KB
รวม 335.0 KB 74.5 KB

จาก PR นี้จะทำให้ขนาดไฟล์ที่โหลด ลดลงจาก 113.6 KB เหลือ 74.5 KB ครับ (ลดลง 39.1 KB, 34%)

อันนี้คือโค้ดที่ใช้ในการสร้างไฟล์ data.json ครับ (ภาษา Ruby)

# preprocess.rb
require 'json'

data = JSON
    .parse(File.read('jquery.Thailand.js/db.json'))
    .group_by { |row| row['p'] }.map { |province, list1|
        [ province, list1.group_by { |row| row['a'] }.map { |amphur, list2|
            [ amphur, list2.group_by { |row| row['d'] }.map { |district, list3|
                [ district, list3.map { |row| row['z'] }.uniq.sort ]
            }.sort ]
        }.sort ]
    }.sort

File.write('jquery.Thailand.js/data.json', data.to_json)

หลังจากเอา JSZIP ออก ปริมาณการถ่ายโอนข้อมูล (วัดจาก Chrome DevTools)
ลดลงจาก 113.6 KB เหลือ 87.3 KB (ลดลง 26.3 KB, 23%)
@dtinth dtinth changed the title ลดขนาดการถ่ายโอนข้อมูล ลดปริมาณการถ่ายส่งข้อมูล Apr 8, 2017
@dtinth dtinth changed the title ลดปริมาณการถ่ายส่งข้อมูล ลดปริมาณการส่งข้อมูล Apr 8, 2017
@earthchie
Copy link
Owner

อู้ว นี่มัน PR เมพ เขียนอธิบายละเอียดมากๆ ครับ กราบส์
เดี๋ยวจะเอา PR นี้ไปแปะใน Medium เพิ่มเติม เพื่อเป็นการให้เครดิตด้วย

ขอบคุณครับ

@dtinth
Copy link
Contributor Author

dtinth commented Apr 8, 2017

ขอบคุณครับบ

มี Feedback มาจากพี่ @icez และน้อง @jarindr บอกว่าปกติ Nginx โดย Default configuration มันจะไม่ Gzip ไฟล์ .JSON อัตโตมัติครับ 😭 (ใช้ GitHub Pages กับ Firebase เพลินไปหน่อย มัน Gzip เกือบหมดเลย)

ฉะนั้นคนที่ใช้ Nginx เป็นเว็บเซิฟเวอร์ อาจจะต้องตั้งค่าให้มันอัดไฟล์​ JSON ด้วย (ไม่แน่ใจว่า Apache ทำด้วยไหม)

วิธีแก้ทางนึงที่ไม่ต้องแก้ Config ของเว็บเซิฟเวอร์ คือเปลี่ยนจากไฟล์ .json เป็นไฟล์​ .js แล้วโหลดผ่าน JSONP เอาครับ (ไม่แน่แค่ Rename .json เป็นไฟล์ .js ไปเลยอาจจะเวิร์คเหมือนกัน แต่ดูมีความ Hack มากๆ ครับ 5555)

@icez
Copy link

icez commented Apr 8, 2017

@dtinth IMO ไม่น่าซีเรียสมากขนาดนั้น บอก server admin ให้เพิ่ม compression ให้ application/json น่าจะง่ายกว่า ประโยชน์เยอะกว่า ยิ่ง apache นี่แก้ใส่ .htaccess ได้เลยด้วยซ้ำ

@earthchie
Copy link
Owner

แยก branch เลยละกัน 555

https://github.com/earthchie/jquery.Thailand.js/tree/zipped_version

@fake-or-dead
Copy link

เอมาเยือน

@aaronamm
Copy link

ยอดเยี่ยมมากครับผม

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants