เขียน UI ครั้งเดียว รันเป็นแอป iOS และ Android
CKN UI Native นำหน้าจอที่เขียนด้วย CKN UI สำหรับเว็บ ไปแสดงเป็น native view จริงบน iOS และ Android โดยไม่ต้องเขียนหน้าจอใหม่แยกอีกชุด ทีมเดียวดูแลทั้งเว็บและมือถือ ลดต้นทุนการพัฒนาและทำให้ฟีเจอร์ออกพร้อมกันทุกช่องทาง
หน้ารายการ บนสามแพลตฟอร์ม
โค้ดหน้าจอชุดเดียว วาดเป็น view ของ iOS, Android และ macOS จริง
ฟอร์มแก้ไข พร้อมโหมด offline
ช่องกรอก ปุ่ม และตัวเลือก ใช้ control ของแต่ละระบบ ทำงานต่อได้แม้ไม่มีเครือข่าย






สิ่งที่ CKN UI Native ทำได้
หน้าจอเดียว ใช้ได้ทั้งเว็บและมือถือ
component และ template เดิมของ CKN UI แสดงผลเป็น view ของ iOS และ Android โดยตรง ไม่มีโค้ดเฉพาะแพลตฟอร์มในหน้าจอ มีเพียงไฟล์ entry ของแอปที่รู้ว่ากำลังรันบน native
- รัน component class ชุดเดียวกับเว็บ
- template แบบ declarative เดิม ไม่ต้องเรียนภาษาใหม่
- ตัวตรวจในขั้นตอน check บอกทันทีว่าโค้ดส่วนไหนใช้บน native ไม่ได้
ใช้ engine ของระบบปฏิบัติการ
แอปและ component รันใน JavaScriptCore บน Apple และ WebView engine แบบไม่มีหน้าจอบน Android ไม่ต้องฝัง JavaScript runtime ของบุคคลที่สามมาด้วย
- ไม่มี Swift package, CocoaPod หรือ Gradle library เพิ่ม
- รองรับ iOS 17+ และ Android 10+
- มี runtime พื้นฐานให้ครบ: timer, fetch, WebSocket, URL, crypto
ระบบ layout ของ CKN เอง
ใช้ layout แบบ flexbox ของ CKN UI คำนวณตำแหน่งในตัว engine ฝั่ง Swift และ Kotlin แค่สร้าง view วางตามกรอบที่ได้รับ และส่ง event กลับ
- ส่งข้อมูลระหว่าง engine กับ native เป็น batch เดียวต่อ frame
- layout ตรงกับ Chrome ภายใน 1 px ในชุดทดสอบ
- โปรโตคอลมีเอกสารกำกับ ตรวจสอบและขยายต่อได้
Component มาตรฐานและธีมของ CKN
component ที่ผูกกับ browser API เช่น modal, select, table, grid, kanban มีเวอร์ชัน native ของตัวเองใช้ชื่อ tag เดิม ธีม innobiz และ ckn ถูกสร้างจากกฎกลางของแพลตฟอร์ม จึงหน้าตาตรงกับเว็บ
- overlay เป็น bottom sheet, list sheet และ picker ของระบบ
- ตารางข้อมูล, grid และ kanban (ลากด้วยการกดค้าง)
- ธีม innobiz และ ckn พร้อมใช้
ทำงานออฟไลน์ได้
เก็บข้อมูลคิวงานออฟไลน์ใน SQLite ของเครื่อง ใช้ระบบ outbox และ sync ตัวเดียวกับเว็บ การนำทาง คลิปบอร์ด และสถานะเครือข่ายก็เชื่อมกับระบบของเครื่องผ่าน port
- outbox และ offline sync บน SQLite
- stack การนำทางและปุ่ม back ของระบบ
- รู้สถานะออนไลน์ และคัดลอกข้อมูลตารางไปคลิปบอร์ด
อัปเดต UI ผ่านเซิร์ฟเวอร์พร้อมระบบย้อนกลับ
แอปดาวน์โหลด UI bundle ใหม่จากเซิร์ฟเวอร์ ตรวจ hash ทุกไฟล์ แล้วเปลี่ยนใช้ตอนเปิดแอปครั้งถัดไป ถ้า bundle ใหม่เปิดไม่ขึ้น ระบบย้อนกลับเป็นเวอร์ชันก่อนหน้าให้เอง
- ตรวจ hash และขนาดไฟล์ก่อนใช้ทุกครั้ง
- bundle ที่ผิดหรือ manifest ไม่ตรงจะถูกปฏิเสธ
- ปล่อยการแก้ UI ผ่านการ deploy เซิร์ฟเวอร์ ไม่ต้องรอ store เมื่อ host ไม่เปลี่ยน
ตัวเลขที่วัดจริง
ตัวเลขชุดนี้วัดบนเครื่อง Mac ที่มี simulator ของ iPhone และ emulator ของ Android ไม่ใช่โทรศัพท์จริง ใช้เป็นฐานเปรียบเทียบระหว่างเวอร์ชัน ส่วนตัวเลขบนเครื่องจริงยังอยู่ระหว่างการวัด
ตัวเลขจากชุดทดสอบและ benchmark ภายในของ CKN ผลจริงขึ้นกับเครื่องและปริมาณข้อมูลของแต่ละระบบ
ธุรกิจของคุณได้อะไร
ลดต้นทุนและเวลา
หน้าจอชุดเดียวใช้ทั้งเว็บ iOS และ Android ไม่ต้องจ้างทีมแยกต่อแพลตฟอร์ม และฟีเจอร์ใหม่ออกพร้อมกันทุกช่องทาง
ปล่อยการแก้ไขได้เร็วและเสี่ยงน้อย
การแก้ UI ส่งผ่านเซิร์ฟเวอร์ของคุณ มีการตรวจ hash และย้อนกลับอัตโนมัติ ต้องผ่าน store เฉพาะเมื่อตัวแอป host เปลี่ยน
เป็นเจ้าของ stack ทั้งหมด
ไม่มีไลบรารีของบุคคลที่สามใน JavaScript, Swift และ Kotlin ลดความเสี่ยงเรื่องลิขสิทธิ์ ช่องโหว่จากต้นทาง และการเลิกพัฒนาของโครงการภายนอก
จุดเริ่มต้นของแอป native
ใช้งานอยู่ในส่วนต่าง ๆ ของ CKN stack
- แอปมือถือของแอปพลิเคชันที่สร้างด้วย CKN UI โดยใช้หน้าจอเดิมจากเว็บ
- ชุดเครื่องมือ ckn CLI สร้าง host project สำหรับ iOS และ Android ให้อัตโนมัติ
- เซิร์ฟเวอร์ CKN ส่ง UI bundle ผ่าน middleware สำหรับการอัปเดตแบบ over-the-air
class HelloScreen extends Component { // the same class the web build renders
static template = /*html*/`<section class="flex flex-col gap-2 p-4">
<span class="text-sm font-semibold">Hello, {{this.name}}</span>
<ckn-button label="Wave" click()="{{this.wave()}}"></ckn-button></section>`;
name = "CKN"; wave() { this.name = "native"; }
}
Component.register(HelloScreen, "hello-screen");
async function main() {
installNativeRuntime(); // setTimeout, fetch, WebSocket, URL ... over the bridge
const host = createNativeHost({ theme: createNativeTheme("innobiz") });
setDefaultEngine("ir"); setDefaultHost(host);
registerStandardComponents(); registerNativeOverrides();
await mountOnHost(host, HelloScreen);
} void main();
