Reduce Angular bundle size by remove unused locale in moment.js (without ng eject)

This is my lab test for remove a moment locale from angular app. This article will show you how to reduce Angular bundled size by remove unused locale in moment.js without ng eject

WARNING: This is my first english article. I’m not good english but i think this should be share to other people.

Prepare a lab data

Just install Angular 7 and moment by this command.

ng new ng7-moment
cd ng7-moment
npm install --save moment

And edit `app.component.ts` to something like this
import { Component, OnInit } from '@angular/core';
import * as moment from 'moment';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  time: string;

  ngOnInit() {
    this.time = moment().format('MMMM Do YYYY, h:mm:ss a');
  }
}

And build a production bundle with stats json. by
npm run build -- --prod --stats-json

Next i see how many size of moment.js that include to bundle by
webpack-bundle-analyzer dist/ng7-moment/stats.json

And this i a result

Angular bundle with a full locale of moment.js

As you can see total size is around 300KB (Gzipped around 70KB).

First try: Import min edition

After I google for solution i found someone suggest that I can import moment.min.js. That file not include any locale data. So i change code to

import { Component, OnInit } from '@angular/core';
import * as moment from 'moment/min/moment.min.js';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  time: string;

  ngOnInit() {
    this.time = moment().format('MMMM Do YYYY, h:mm:ss a');
  }
}

The bundle size after changed is

Bundle size after import min version of moment.js

Now size is reduce to around 51KB (Gzipped around 16KB). WOW! At first time I think it works. But when I import a locale data like this code.

import { Component, OnInit } from '@angular/core';
import * as moment from 'moment/min/moment.min.js';
import 'moment/locale/th';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  time: string;

  ngOnInit() {
    this.time = moment().format('MMMM Do YYYY, h:mm:ss a');
  }
}

And see a bundled size.

bundle size when import min version of moment.js and import localeAs you see we have 2 moment.js and full locale in bundled (one is full version and another one is min version). And if you import another library that use moment.js like chart.js the size will be like that too.

bundle size after import min version of moment.js and import chart.js

Second try: Use webpack plugins

I search in Google again. I see another solution to eject webpack config and add some plugin to remove locale. But for my personal reason i don’t want to eject angular config, So I will skip this solution for now.

Solution: Remove by Replace locale folders.

I found Angular has a feature that can replace environments file up to version that it build. I think I can use this folder to replace locale folder too. So let try

  1. Create a my locale folder and if you use any locale, copy it to this folder.
    mkdir src/locale
    
    # If you want to use any locale copy it to your locale folder
    cp node_modules/moment/locale/th.js src/locale/
  2. Edit angular.json to replace default locale. file fileReplacements section and add this code like this.
                  "fileReplacements": [
                    {
                      "replace": "src/environments/environment.ts",
                      "with": "src/environments/environment.prod.ts"
                    },
                    {
                      "replace": "node_modules/moment/locale/",
                      "with": "src/locale/"
                    }
                  ],
  3. Build and see a results. (You will see a warning message like “node_modules/moment/locale/af.js” does not exist. But it OK don’t worry it)

The result is

bundle size after remove unused locale.As you can see the size is around 55KB (Gzipped around 17KB) and no other locale except locale that in new locale folder. even if you import chart.js it still not include unused locale too. Like this

Bundle size after remove unused locale and import chart.js

I hope this will be useful. Thanks for reading.

สอนใช้ Facebook Comment Moderation Tools เบื้องต้น และการทำ Comment Mirroring

วันนี้เราจะมาสอน Facebook Comment Moderation Tool ถ้าถามว่ามันคืออะไร มันคือเครื่องมือจัดการ Comment ของ Facebook ที่เกิดจาก Facebook Comments Plugin (ถ้ายังไม่รู้จัก มันคือกล่อง Comment Facebook ที่ประกฏบนเว็บต่างๆ เช่นเว็บนี้เป็นต้น ลองเลื่อนไปดูตัวอย่างด้านล่างได้ครับ) โดยเครื่องมือนี้นอกสามารถลบ Comment ต่างๆที่ไม่ต้องการได้แล้ว ยังมีฟีเจอร์บางอันที่หลายๆคนไม่รู้มาแนะนำด้วย ซึ่งมันคือการตั้ง Blacklist คำ และ Mirroring Comment

การตั้งค่าการใช้ Facebook Comment Moderation Tool

  1. ติดตั้ง Facebook Comment Plugins ให้กับหน้าต่างๆ ตามปกติ  (ในบทความขอไม่สอนวิธีการเอา Comment Plugins มาใส่ในนะครับ ถ้าใช้ WordPress จะมี plugins เยอะแยะ)
  2. ตั้งค่า Admin มี 2 วิธีคือ
    1. ไปสร้าง app facebook (ดูวิธีสร้าง app ได้ที่นี่) แล้วใส่คำสั่งนี้ลงใน <head> ของทุกหน้า
      <meta property="fb:app_id" content="{YOUR_APP_ID}" />

       
    2. ใส่เป็น Facebook user id โดยใส่คำสั่งนี้ลงใน <head> เช่นกัน
      <meta property="fb:admins" content="{YOUR_FACEBOOK_USER_ID_1}"/>
      <meta property="fb:admins" content="{YOUR_FACEBOOK_USER_ID_2}"/>

      ถ้ามีคนเดียวก็ใส่บรรทัดเดียว มี 2 คนก็ใส่ 2 บรรทัด มีกี่คนก็ใส่ไปเท่านั้นคน

      โดยส่วนตัวแนะนำวิธีสร้าง App ID มากกว่า ครับ เพราะใช้ Facebook Comment Mirror ได้ และถ้าใช้ WordPress และลง Plugin Yoast SEO สามารถนำ App ID ไปใส่ใน Yoast SEO ได้เลย ในหน้า Social – Yoast SEO ในแทบ Facebook จะมีช่องให้ใส่ Facebook App ID ได้เลยครับ ไม่ต้องแก้ Code ใดๆ

  3. สำหรับคนใช้แบบ App ID ต้องไปเช็คการตั้งค่าใน Facebook For Developer ในส่วนของ App โดยกดเข้าไปใน Facebook App ที่เราผูกกับเว็บไซต์ไว้ (app id ที่เราเอาไปใส่ใน head) ให้เข้าไปที่ Settings > Advanced และให้เปิดตัวเลือก Social Discovery เพื่อให้คนที่ไม่ได้ Login facebook สามารถมองเห็น Comment ได้
    เปิด Social Discovery ใน Settings ของ App

วิธีใช้ Facebook Comment Moderation Tool เบื้องต้น

  1. ให้เข้าไปที่หน้า Facebook Comment Moderation Tool
  2. เมื่อเข้าไปแล้วจะพบหน้าตาดังนี้ (หากมี Comment อยู่)
    หน้าตาของ Facebook Comment Moderation Toolโดยจากภาพส่วนที่แสดงต่างๆมีดังนี้

    1. เอาไว้เปลี่ยน App หรือเว็บกรณีมีมากกว่า 1 เว็บ
    2. เป็นลิงค์เพื่อไปดูบทความหรือหน้าต้นฉบับ ว่าเนื้อหาเป็นอะไร
    3. เป็นส่วนจัดการต่าง โดยไล่จากซ้ายไปขวาคือ
      1. Approve สำหรับยินยอมให้เนื้อหานั้นแสดงผลบนเว็บเรา (หากเปิด Public ไว้จะไม่มีผลใดๆ ไม่ต้องกดก็แสดงอยู่ดี)
      2. Hide คือซ่อนความเห็นนั้นไม่ให้แสดง
      3. Report Spam ตามชื่อ คือบอก Facebook ว่า Comment เป็น Spam
      4. More ในปัจจุบันในเมนูนี้ผมไม่เห็นตัวเลือกอื่นนอกจาก Ban User ให้ไม่สามารถมาโพสในเว็บเราได้อีกต่อไป
    4. Settings เป็นการตั้งค่าต่างซึ่งจะอธิบายในหัวข้อต่อไป
  3. พอดีทำรูปเสร็จเพิ่งเห็นขี้เกียจแก้รูป ขออธิบายตรงนี้นะครับ ข้างล่างหัวข้อ 1 จากภาพด้านบนจะมีแทปต่างๆ ให้เราดู โดยแต่ละอันมีความหมายดังนี้
    1. Review คือรอการตรวจสอบ ถ้าเรากด Approve จะไป Public (แต่ถ้าตั้ง Public ไว้ไม่ต้องกดมันก็แสดงให้คนอื่นเห็น)
    2. Public คือ Comment ที่แสดงบนเว็บแล้ว
    3. Hidden ความเห็นที่ถูกซ่อน
    4. Flagged กับ My Queue ไม่เคยใช้ครับ ใครรู้บอกด้านล่างทีครับ T_T

ค่าต่างๆที่สามารถตั้งได้ในหน้า Settings ของ Facebook Comment Moderation Tool

หน้า Settings

หน้า Settings ของ Facebook Comment moderation tool

ในหน้านี้จะมีให้ปรับดังนี้ (ไล่จากบนลงล่าง)

  1. เรียง Comment ตามอะไร โดย
    – Top คือให้ Facebook เป็นเลือก ว่าอันไหนดีที่สุด
    – Newsest คือจะเห็นใหม่สุดก่อน
    – Oldest คือแสดงเก่าสุดก่อน
  2. Enable Attachments คือการอนุญาติให้ผู้ใช้คอมเม้นเป็นภาพหรือ Sticker ได้
  3. Enable Notifications คือบอกว่าถ้ามีคน Comment บนเว็บเราให้แจ้งเตือนในเฟสเราไหม
  4. Comment Mirroring จะขึ้นเมื่อใช้ Admin เป็นแบบ App เท่านั้น มันคือฟีเจอร์ที่ Facebook ทำไว้ให้ โดยความสามารถของมันคือตามชื่อมันคือการส่ง Comment ที่โพสบนเว็บ ไปแสดงบน Post ที่แชร์ URL นั้นบน Page ที่เราเลือก และหากมีคน Comment บน Post ที่แชร์ URL นั้นบน Page ที่เราเลือก ก็จะไปแสดงบนเว็บของเราด้วยเช่นกันครับ (แต่ใช้ได้เฉพาะหน้าใหม่ๆ ที่ Facebook ไม่เคยเห็น ถ้าเป็นหน้าเก่าที่เคยแชร์แล้วจะไม่มีผล)

หน้า Moderation Rules

หน้า Moderation Rules ของ Facebook Comment moderation tool

ในหน้านี้จะตั้งค่า

  1. ความยาวสูงสุดต่อ Comment อย่างของผมคือ 5000 ตัวอักษร
  2. ตั้งค่าปิดไม่ให้ Comment หลัง Facebook เจอบทความนั้นไปแล้วกี่วัน (การเจอของมันเช่นมีคนไลค์ หรือแชร์)
  3. เปิด Mode Spam Filter แบบ Aggressive อันนี้อธิบายง่ายๆคือเพิ่มระดับ Spam Filter ให้สูงขึ้น ทำให้บางครั้งอาจจะไป Filter เอา Comment จริงๆออกด้วย ไม่แนะนำให้เปิด
  4. ตรวจว่ามีกี่ลิงค์ใน Comment ถ้ามีมากกว่าที่เรากำหนด ให้เราต้องมาตรวจก่อน ถึงจะแสดงได้
  5. ตั้งค่าการตรวจสอบ โดยแต่ละอันหมายถึง
    1. Public = เปิดกว้างคือ Comment ปุปขึ้นเลยไม่มีการตรวจสอบ ถึงมี Blacklist Word ก็แสดงอยู่ดี
    2. Review Blacklisted Comments = แสดงทั้งหมด ยกเว้น Comment ที่มี Blacklist Word ซึ่งเราจะต้องตรวจสอบก่อนแสดง (วิธีตั้ง Blacklist จะสอนในหัวข้อถัดๆไป) แนะนำอันนี้ครับ
    3. Closed = ซ่อนทุกความเห็น Comment ที่ไม่มี Blacklist Word เท่านั้น ถ้ามีจะถูกลบไปเลย ถึงจะแสดงใน Review และต้องกด Approve ทุก Comment ถึงจะแสดง

หน้า Moderators

หน้านี้เอาไว้ตั้งว่าใครบ้างที่สามารถตรวจสอบ Comment ได้

หน้า Blacklist

หน้า Blacklist ของ Facebook Comment moderation tool

หน้านี้เอาไว้ตั้ง Blacklist Word โดยแนะนำว่าการตั้งจะต้องนำหน้าและตามหลังด้วย .* เช่นเราจะห้ามคำว่า มีเวลาว่าง (เอามาจาก “มีเวลาว่าง 2 – 3 ชม ไหม”) ผมต้องใส่ไปว่า .*มีเวลาว่าง.* จากนั้นให้กด Enter 1 ที หากถูกต้องจากขึ้นประมาณนี้ (ของผมมี 3 คำ ใส่ไปเป็นตัวอย่าง)
ตัวอย่างการตั้ง Blacklist Word ใน Facebook Comment moderation tool

หน้า Banned Users

ตามชื่อเลยครับ เป็นหน้าสำหรับตั้งค่าว่าใครถูกแบนไม่ให้ Comment ในเว็บเราบ้าง สามารถใส่ชื่อไปได้เลยครับ

วิธีปิดกล่อง Comment ตรงกล่อง Chat ของ Facebook (Post Tabs)

วันนี้ผมเพิ่งได้อับเดตตัวใหม่จาก Facebook ที่ทำให้เมื่อมีคนคอมเม้นที่โพสที่ผมเกี่ยวข้อง มันจะมาเด้งเปรียบเสมือน chat ตัวหนึ่ง ซึ่งผมไม่ชอบ และจะปิดมัน และผมคิดว่าหลายๆคนก็น่าจะไม่ชอบมันเช่นกัน ดังนั้นเลยนำวิธีมาบอกครับ

ก่อนอื่นสำหรับคนที่ไม่รู้ว่า Facebook Post Tabs หรือไอ้กล่องคอมเม้นที่ช่องแชทคืออะไร ให้ดูภาพนี้ครับ

ตัวอย่าง facebook post tab

กล่องใหญ่ๆด้านซ้ายนั่นแหละครับ มันจะขึ้นมาทุกครั้งที่มีคอมเม้นที่เกี่ยวข้องกับเราขึ้นมา

วิธีปิด Facebook Post Tabs

  1. ให้กดรูปเฟืองตรงมุมขวาล่างในหน้า Facebook(อยู่ในแถบด้านขวา ตรงกล่องค้นหาคนจะคุยด้วย)
  2. กด Turn Off Post Tabs เท่านี้ ก็จะไม่มีคอมเม้นมาแสดงในแถบแชทอีกต่อไปครับ
    กด Turn Off Post Tabs เพื่อปิดกล่องคอมเม้นที่แถบแชท

วิธีซ่อนลิงค์เวลาพิมพ์เว็บเพจออกจากเครื่องปริ้น

หลายคนเวลาต้องการจะปริ้นหน้าเพจของเว็บใดๆ มักจะประสบปัญหาว่าเมื่อสั่งปริ้นออกมาแล้ว ติดลิงค์เว็บและข้อมูลอื่นๆ ที่ไม่ได้ต้องการออกมาด้วย ที่บริเวณหัวและท้ายกระดาษ ดังรูป

ตัวอย่างการปริ้นที่ติดข้อมูลส่วนเกิน เช่นลิงค์เว็บบริเวณหัวและท้ายกระดาษ

ซึ่งสาเหตุที่เกิดเป็นเพราะตัว Internet Browser กำหนดว่าให้ใส่เป็นค่าตั้งต้น เพื่อป้องกันผู้ใช้ลืมว่าปริ้นจากที่ใดวันที่เท่าไหร่ ซึ่งเราสามารถปิดได้ดังนี้ (ตัวอย่างนี้ข้อใช้ Internet Explorer 11 นะครับ เข้าใจว่า 8 9 10 11 12 ใช้เหมือนกัน)

วิธีแก้ปัญหา

  1. บริเวณมุมขวาบนจะมีรูปเฟืองอยู่ ให้กดรูปเฟืองแล้วตามด้วย Print > Page Setup ตามลำดับ (ถ้ามุมขวาไม่มี ให้ไปหาจากเมนู File แทนนะครับ)
    บริเวณมุมขวาบนจะมีรูปเฟืองอยู่ ให้กดรูปเฟืองแล้วตามด้วย Print > Page Setup ตามลำดับ
  2. จะมีหน้าต่างขึ้นมาดังรูป
    ค่าตั้งต้นเมื่อสั่งปริ้นหน้าเว็บให้เราแก้ในส่วนของ Headers and Footers ตามต้องการ โดยจากบนลงล่างหมายถึงตำแน่งที่จะพิมพ์ข้อมูลออกมา ไล่จาก ซ้าย กลาวง ขวา หากไม่ต้องการให้มีข้อความใดๆให้เลือก Empty ดังรูปต่อไปนี้
    รูปแสดงการตั้งค่าให้ไม่แสดงข้อมูลส่่วนเกินในหน้าเพจ
  3. หลังจากนั้นสั่งปริ้นตามปกติได้เลยครับ จะไม่มีหัวและท้ายกระดาษมากวนใจอีกต่อไป
    ผลลัพธ์จากการปรับแต่ง

 

Script สำหรับ Backup ข้อมูล ย้อนหลัง 7 วัน

อันนี้เป็น Script สำหรับ Backup ข้อมูลผ่าน rsync โดย Backup ย้อนหลัง 7 วัน (สามารถปรับได้)

สิ่งที่ต้องเตรียมก่อนใช้

  1. Linux/Unix Only
  2. ติดตั้ง rsync
  3. เครื่อง Backup ต้องสามารถ SSH Without Password เข้าเครื่องเป้าหมายได้ (ลองอ่านอันนี้ หรืออันนี้ดูครับ)
  4. เครื่อง Backup ต้องติดตั้ง PHP (ไม่จำเป็นต้องมี Apache)
  5. เครื่องเป้าหมายควรมี MySQL Tools (พวก mysqldump เป็นต้น) ในกรณ๊ต้องการสำรองข้อมูลจาก MySQL

Script ที่ใช้

<?php
chdir(__DIR__);

$SOURCE_HOST = '[email protected]';
$SOURCE_PATH = '/home/user/';

$MYSQL_USERNAME = "DATABASE_USERNAME";
$MYSQL_PASSWORD = "DATABASE_PASSWORD";

$dateFormat = 'Ymd';

$before = date($dateFormat,strtotime('yesterday'));
$dateKey = date($dateFormat);
$delDate = date($dateFormat,strtotime('-7 days'));

$excludeDirs = [
	'cache1/*',
	'cache2/*',
];

system("ssh {$SOURCE_HOST} \"mysqlcheck --all-databases -u{$MYSQL_USERNAME} -p{$MYSQL_PASSWORD} -r\"");
system("ssh {$SOURCE_HOST} \"mysqldump -u {$MYSQL_USERNAME} -p{$MYSQL_PASSWORD} --lock-tables=false --all-databases  | gzip --rsyncable -f -c - > {$SOURCE_PATH}/backupdb/backup.sql.gz\"");

system("cp -al {$before} {$dateKey}");

$excludeStr = '';
foreach($excludeDirs as $dir){
        $excludeStr .= " --exclude '{$dir}'";
}

system("rsync -a --delete {$excludeStr} {$SOURCE_HOST}:{$SOURCE_PATH} {$dateKey}/");

if(!empty($delDate)){
system("rm -rf ./{$delDate}");
}

echo "COMPLETE";

อธิบายคำสั่ง

บรรทัดที่ 1 – 14 เป็นการตั้งค่าเครื่องเป้าหมาย ว่าจะ backup จาก host ใดและ path ใด ข้อมูลการเข้าถึง Database และจำนวนวันที่ backup ย้อนหลัง โดยสามารถตั้งวันที่ backup สูงสุดได้ในบรรทัดที่ 14

บรรทัดที่ 16-19 เป็นการตั้งค่าว่าจะไม่ backup file ใด้บ้าง เช่นพวก cache เราอาจจะไม่ backup เป็นต้น

บรรทัดที่ 21-22 เป็นการสั่ง backup ฐานข้อมูล ให้ออกมาเป็น file.sql

บรรทัดที่ 24 เป็นการสั่งคัดลอก folder เมื่อวาน แบบ Hardlink มาเป็นโฟลเดอร์วันที่ปัจจุบัน โดยการทำ Hardlink จะช่วยประหยักเนื้อที่ได้มากในกรณีที่ไม่เปลี่ยนแปลง เช่นถ้าเราสั่งคัดลอก a.zip ขนาด 1GB ไปเป็น b.zip แบบ Hardlink ขนาดที่จะถูกใช้บน Harddisk จะถูกใช้แค่ 1GB เท่านั้น ไม่ใช่ 2GB แบบปกติ เพราะไฟล์เก็บที่เดียวกัน (อ่านเพิ่มเติมได้ที่นี่)

บรรทัดที่ 26-29 เป็นการสร้าง exclude parameter หรือก็คือเอา บรรทัด 16-19 มาแปลงให้ rsync เข้าใจได้

บรรทัดที่ 31 เป็นการสั่ง rsync จากต้นฉบับมาโฟลเดอร์ปัจจุบัน โดยจะดึงเฉพาะไฟล์ที่มีการเปลี่ยนแปลงหลังจากเมื่อวานเท่านั้น ทำให้ Backup ได้อย่างรวดเร็ว

บรรทัดที่ 33-35 คือสั่งให้ลบโฟลเดอร์ backup ที่เกิน 7 วันทิ้ง

คำแนะนำอื่นๆ

อย่าใช้ script นี้ผ่าน http เพราะมันจะ timeout ให้ตั้ง cronjob เป็นประมาณ php backup.php

ในกรณที่ MySQL เราใช้แต่ InnoDB และไม่มี MyISAM สามารถเอาบรรทัดที่ 21 ออกได้ (บรรทัด mysqlcheck) เพราะ check ไปก็ทำไรไม่ได้ InnoDB ไม่ Support

ในบรรทัดที่ 22 เราจะเห็นว่ามี –lock-tables=false ซึ่งหมายถึงเราจะไม่ lock table ในการเขียน ซึ่งทำให้เว็บสามารถทำงานได้ปกติตอน dump ข้อมูลออก แต่ข้อมูลที่ได้อาจจะไม่ตรงกัน เช่น table a ถึก dump เสร็จแล้ว ในระหว่างที่ dump table b ออกมา มีการเขียนที่ table a และ c ซึ่ง table c ต้องใช้ข้อมูลจาก table a แบบนี้จตะเกิดปัญหาได้ เพราะ table c ที่ถูก dump มีข้อมูลบางอย่างที่ต้องพึ่ง table a แต่ตอน dump table a ตัว table a ยังไม่มีข้อมูลนั้น ทางแก้มี 2 แบบ

  1. ตั้ง –lock-tables=true
  2. ในกรณีที่มีแต่ InnoDB ให้ใช้ –single-transaction แทน