Visual Studio Code extension: แชร์ประสบการณ์ในการพัฒนา

บทความนี้ถูก published ที่ Visual Studio Code extension: แชร์ประสบการณ์ในการพัฒนา เมื่อ 15 มีนาคม 2020

สวัสดีครับ 2 อาทิตย์ที่ผ่านมา ผมได้ทำ open source ตัวนึง ซึ่งคิดว่า ขั้นตอน, แนวคิด และตัวงาน อาจจะมีประโยชน์ไม่มากก็น้อยแก่ผู้อ่าน เลยอยากจะมาแชร์ให้ฟังครับ โดยจะเรียงลำดับ ตามนี้ครับ

Code สำหรับ project นี้นะครับ: https://github.com/jojoee/vscode-conda-cheatsheet

1. แรงบัลดาลใจ

ปัจจุบัน editor ที่ผมใช้อยู่เป็นหลักเลยคือ Visual Studio Code (มีใช้ตัวอื่นบ้างก็จะเป็นเครือของ Jetbrains)
ด้วยความที่เป็น Editor ที่เร็ว, มี extension ให้เลือกใช้เยอะและใช้งานได้ดี เลยสนใจและอยากลองทำ extension ขึ้นมาบ้าง
ซึ่งในเนื้อหาถัดๆไปจะขอใช้ตัวอักษร VSCode แทนคำว่า Visual Studio Code นะครับเพื่อความสะดวกในการอ้างถึง

2. กำหนดขอบเขตของงาน

ส่วนนี้จะเป็นการกำหนดที่สิ่งคาดหวังและเวลาที่จะใช้ในการพัฒนา

  1. อยากจะศึกษา ว่าเราจะสามารถทำ VSCode extension ได้อย่างไร
  2. จากข้อ 1) เราก็จะเข้าใจคนออกแบบโปรแกรมมากขึ้น ว่าถ้าเราอยากจะออกแบบโปรแกรมให้มีส่วนต่อขยาย (extension) จะออกแบบอย่างไร หรืออย่างน้อยก็ต้องคำถึงเรื่องอะไรบ้าง
  3. ต้องการใช้เวลาประมาณ 1 อาทิตย์ในการพัฒนา (พอเอาเข้าจริงๆใช้เวลาประมาณ 2 อาทิตย์)
  4. จากข้อ 3) ต้องหา project ที่น่าจะมีประโยชน์และสามารถใช้งานได้จริงภายใน 1 อาทิตย์

3. รายละเอียด project

จากที่ค้นคว้ามาก็เจอ project “cheatsheet” เนี่ยแหละที่คิดว่าจะสามารถทำให้เสร็จทันได้ภายใน 1 อาทิตย์

kubectl: https://github.com/dennyzhang/cheatsheet-kubernetes-A4
VSCode: https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf

cheatsheet เหมือนเป็นพวกสรุปสูตร ตาม domain ต่างๆเช่น VSCode cheatsheet, Docker cheatsheet, Next.js cheatsheet ซึ่งมีได้หลายรูปแบบเช่น website หรือ pdf file ตามตัวอย่างด้านบนครับ ซึ่งใน VSCode marketplace ก็ยังมี extension จำพวกนี้ค่อนข้างน้อยอยู่ดังรูป มีแค่ประมาณ 8 extensions เอง

โดยสรุปแล้ว project ที่จะทำก็จะเป็น Conda cheatsheet โดยมีทั้งหมด 3 features ดังตัวอย่างด้านล่างได้แก่

  1. เปิด Conda cheatsheet เวอร์ชั่น pdf ไฟล์ (เหมือนเปิด pdf file ให้)
  2. เปิด Conda cheatsheet เวอร์ชั่น website (เปิด website ด้วย url ตรงๆ)
  3. เปิด Conda cheatsheet เวอร์ชั่น webview (เราเขียนเนื้อหาด้วย html ขึ้นมาเอง)

(Conda เป็น ตัวจัดการ Python environment management, “คล้ายๆ” nvm ที่เป็น Node Version Manager ของ Javascript)

1. pdf version
2. website version
3. webview version

4. ประสบการณ์ระหว่างการพัฒนา

4.1 เวลาในการพัฒนา

ใช้เวลาในการพัฒนาไปทั้งหมด 2 อาทิตย์ (จากที่วางแผนไว้แค่ 1 อาทิตย์)

  • 1 อาทิตย์แรกใช้เวลาไปกับการอ่าน tutorial แล้วเอา code ของเขามาลองเล่น
  • 1 อาทิตย์ถัดมา ใช้ไปกับการพัฒนาจริงๆ

ตัวอย่าง website สอนการเขียนและตัวอย่าง code

4.2 การพัฒนา

การพัฒนาของ project นี้จะขึ้น project ตั้งต้นด้วยเครื่องมือจากคำแนะนำ VSCode website (จากบทความ Your First Extension) เองเลย ซึ่งเราจะใช้ Yeoman

เราจะต้องลง Yeoman และ generator ซึ่งมันจะ setup ส่วนประกอบต่างๆให้เรา เช่น ทำให้ build tool, unit test, lint tool, etc.

(yo / Yeo / Yeoman เป็นเครื่องมือในการทำ โปรเจคตั้งต้น / boilerplate / starter)

// example command
npm install -g yo generator-code && yo code
Homepage
yo code
Project structure after run “yo code” with “New Extension (TypeScript)”

โดยเมื่อ VSCode generator ทำงานเสร็จเราก็จะได้ structure ตามนี้ ซึ่งไม่เหมือนกันตามรูปแบบของ extension (ในที่นี้ผมเลือก “New Extension (TypeScript)”)

ซึ่งไฟล์หลักๆในการพัฒนาก็จะเป็นไฟล์ “extension.ts” ครับ

4.3 indentation ไม่เหมือนกัน

คำสั่ง “lint:fix”

ปัญหาแรกที่เจอมาคือ indentation ไม่ตรงกับที่ผมใช้

ผมก็เลยเปลี่ยน indentation ทั้งหมดให้เป็น space 2 อัน ด้วย eslint ที่ติดมากับ generator ด้วย คำสั่ง “lint:fix” ใน package.json

4.4 พัฒนา features

ในที่นี้เรากะว่าจะพัฒนากันอยู่ 3 features

  • Conda Cheatsheet: PDF
  • Conda Cheatsheet: Website
  • Conda Cheatsheet: Webview

ถึงแม้จะฟังดูไม่เหมือนกัน แต่เทคนิคที่ใช้นั้นผมตัดสินใจเลือกใช้เทคนิคเดียวกันทั้งหมดคือ webview ครับ

https://github.com/jojoee/vscode-conda-cheatsheet/blob/master/src/extension.ts
  • Conda Cheatsheet: PDF — ใช้ webview embed <img> เข้าไป โดย html
  • Conda Cheatsheet: Website — ใช้ webview embed <iframe>
  • Conda Cheatsheet: Webview — ใช้ webview เหมือนกัน + ทำ html ขึ้นมาเอง

สรุปก็คือทั้ง 3 features เราจะใช้เทคนิคเดียวกันหมดคือทำ webview ขึ้นมาครับ

4.5 พัฒนา features “Conda Cheatsheet: Webview”

โดย feature “Conda Cheatsheet: PDF” และ “Conda Cheatsheet: Website” นั้นค่อนข้างตรงไปตรงมา แต่ feature “Conda Cheatsheet: Webview” เราจำเป็นต้อง เขียน html ขึ้นมาเองใหม่ครับ

Code และ description ซึ่งเป็นสองส่วนหลักๆในการทำ cheatsheet

ซึ่งปกติแล้ว cheatsheet ทั้งหลายจะประกอบด้วย 2 ส่วนหลักๆครับ ซึ่งก็คือ code และ description แสดงผลซ้ำไปซ้ำมา ทำให้เราตัดสินใจใช้ Pug (เป็น template engine) มา render template ให้เราครับ

https://github.com/pugjs/pug

4.6 ทำ webview ให้ support light และ dark theme ของ VSCode

ใน VSCode นั้นปกติจะมี theme อยู่ 2 แบบ light และ dark ซึ่งเราก็ต้องการที่จะทำให้ support ทั้ง 2 themes โดยการเพิ่มตัวแปรใน css file

ทำให้ support ทั้ง 2 themes – ซ้าย: dark theme, ขวา: lighttheme
https://github.com/jojoee/vscode-conda-cheatsheet/blob/master/asset/custom.css

โดยเราจะใช้ตัวแปร “vscode-menu-selectionBackground” และ “vscode-menu-selectionForeground” เพื่อให้ css เราปรับไปตาม VSCode theme ที่เราเลือก (อ้างอิง Theme Color)

4.7 click ที่ code เพื่อที่จะ copy code

ใน feature webview นั้นเราต้องการที่จะทำให้สามารถ copy code หลังจาก click ที่ code นั้นๆได้ด้วย เพื่อนำไปวาง (หรือ paste หรือ ctrl + v) เพื่อใช้งานได้ทันที

Conda Cheatsheet: Webview – screenshot
main.js เป็นตัวส่ง event
extension.ts เป็นตัวรับ event

การทำ feature นี้ต้อง setup ตัวส่ง event (ในไฟล์ html ที่ render) และทำตัวรับ event ดังรูปด้านบนครับ

4.8 compile template on the fly และ pre-compile

ตอนแรกที่ผมพัฒนา “Conda Cheatsheet: Webview” feature ผมตั้งใจให้ เรียก module “pug” ขณะ run-time เพื่อ render “pug” template เป็น html format

ทำให้เวลาผมทำเป็น VSCode extension package (ขึ้น VSCode marketplace) นั้น package ของผมนั้นใหญ่มาก เพราะต้องเอา code ของ “pug” module ขึ้นไปด้วย

ผมเลยต้องเปลี่ยนเป็น จาก “เปลี่ยน .pug เป็น .html ขณะใช้งาน” เป็น “pre-compile เป็น html ก่อนทำเป็น VSCode extension package”

ด้านล่างเป็นการเปรียบเทียบลำดับการทำงานของ “ก่อน” และ “หลัง” ปรับแต่ง

ก่อน (เปลี่ยน .pug เป็น .html ขณะใช้งาน)
- ทำเป็น VSCode extension package เพื่อขึ้น VSCode marketplace
- user เรียกใช้งานคำสั่ง
- VSCode extension เรียกใช้งาน module “pug” เพื่อแปลง .pug เป็น .html
- นำ html ไปใช้งานใน webviewหลัง (pre-compile เป็น html ก่อนทำเป็น VSCode extension package)
- เขียน script ขึ้นมาทำการ แปลง .pug เป็น .html เตรียมไว้เลย
- ทำเป็น VSCode extension package เพื่อขึ้น VSCode marketplace
- user เรียกใช้งานคำสั่ง
- VSCode extension จะเรียกใช้งาน .html (ที่ compile ไว้แล้ว) ไปใช้งานได้เลย

ผลก็คือขนาดของ VSCode extension package ลดลงจาก 3.37MB เป็น 359.68KB (ลดไปประมาณ 98%)

conda-cheatsheet-1.2.2.vsix (3513 files, 3.37MB) - before
conda-cheatsheet-1.2.3.vsix (14 files, 359.68KB) - after

4.9 การทำ gif, screenshot

เพื่อเป็นการสาธิตวิธีการใช้งาน ให้ผู้ใช้เข้าใจได้ง่ายขึ้น ว่า VSCode extension นี้ทำอะไรได้บ้าง, โดยที่ผมใช้หลักๆคือ OSX capture screenshot, GIPHY Capture KeyCastr

4.10 ทำ CI + auto publish ขึ้น VSCode marketplace

ขั้นตอนในการ Publishing Extensions คร่าวๆคือ

  • สมัคร Azure DevOps organization
  • สร้าง Personal Access Token (PAT) เพื่อใช้ในการ publish VSCode extension
  • ใช้ PAT ในการ publish VSCode extension
Travis CI build of jojoee/vscode-conda-cheatsheet

5. สิ่งที่ควรปรับปรุงแก้ไขและศึกษาทำเพิ่ม

สำหรับ project นี้สิ่งที่ยังขาดและสามารถเพิ่มเติมได้ก็คือ การ auomate ครับ เช่น

  • feature “Conda Cheatsheet: PDF” — ด้วยความที่เราต้อง download และเปลี่ยนเป็นรูปภาพ ทำให้เรายังต้องทำแบบ manual, ถ้าให้ดีก็น่าจะเขียน script มาทำงานแทนเรา (download + แปลง pdf เป็น image ไฟล์)
  • feature “Conda Cheatsheet: Webview” — script สำหรับการ pre-compile จาก .pug เป็น .html นั้นดีแล้ว — แต่ในระหว่างการพัฒนาถ้ามีการเปลี่ยนแปลง .pug, เราไม่ได้เขียน watch task ให้มัน auto compile เมื่อ .pug เมื่อมีการแก้ไข
  • ยังไม่ได้เขียน test ใดๆ

6. ส่งท้าย

ขอบคุณผู้อ่านที่เสียสละเข้ามาเยี่ยมชมนะครับ ผิดพลาดอย่างไร หรือเพิ่มเติมส่วนไหน คอมเม้นด้านล่างได้เลยนะครับ หวังว่าจะเป็นประโยชน์แก่ผู้อ่านไม่มากก็น้อยนะครับ — ลิ้งไปตัว project ครับ https://github.com/jojoee/vscode-conda-cheatsheet

Conda Cheatsheet – extension preview inside VSCode editor