สร้าง LIFF Application ด้วย Next.js 14 Typescript

zantaclaus
9 min readMar 13, 2024

--

สวัสดีครับ บทความนี้จะเป็นการแชร์ประสบการณ์ในการสร้าง Web Application เพื่อใช้งานบน LINE Offical Account (LINE OA) หรือที่เรียกกันว่า LIFF ซึ่งย่อมาจาก LINE Front-end Framework สำหรับใครที่อยากรู้จักกับ LIFF ให้มากขึ้น สามารถอ่านเพิ่มเติมได้ที่ LIFF Offical Page

ในบทความนี้ผมจะใช้ Stack เป็น

Next.js 14 App Router + Typescript + Tailwindcss

โดยนอกจากจะเป็นการแนะแนวแนวทางในการสร้าง LIFF Application และยังเป็นการแชร์วิธีการเขียนโค้ดที่ผมชอบใช้ในช่วงนี้, Folder Structure และการดึงข้อมูลเบื้องต้นของผู้ใช้ออกมาจากไลน์​ ถ้าพร้อมแล้วก็ ไปเริ่มกันเลยครับ 😆 !

Introduction

โดยภาพรวมของบทความนี้ เราจะมาสร้าง Web Application ด้วย Next.js 14 ซึ่งจะเป็นแอปพลิเคชันง่ายๆ ที่จะแสดงข้อมูลของผู้ใช้ด้วยดึงข้อมูลมาจาก LINE โดยจะเน้นในการแชร์วิธีการเขียนที่ผมชอบใช้ Folder Structure และฟีเจอร์เด่นๆที่เราสามารถเล่นกับข้อมูลของผู้ใช้ได้

สามารถดูตัวอย่างสั้น ๆ ของเว็บแอปพลิเคชันที่เราจะทำกันได้ที่ลิ้งด้านบนเลยครับ

Source Code : https://github.com/zantaclaus/LIFF-101

Setup Tools

สำหรับเครื่องมือที่ผมอยากนำเสนอให้รู้จักกันเพิ่มเติม จะมีอยู่ 2 ตัวคือ

1. Ngrok

https://ngrok.com/

เป็นเครื่องมือสำหรับทำ Port Forwarding เพื่อทำให้ localhost ของเรากลายเป็น Public URL หรือพูดง่าย ๆ คือมันจะช่วยให้ URL ของเราจาก http://localhost กลายเป็น HTTPS URL ซึ่งจะช่วยให้เราจะสามารถเข้าใช้งานแอปพลิเคชันที่รันอยู่บนคอมพิวเตอร์ของเรา จากอุปกรณ์อื่น ๆ ได้

โดยสาเหตุที่เราต้องใช้เจ้า Ngrok นี้ เป็นเพราะการจะเชื่อมต่อกับ LIFF App จำเป็นที่จะต้องใช้ URL ที่เป็น HTTPS การใช้งาน Ngrok จึงช่วยให้เราสามารถทดสอบแอปพลิเคชันของพวกเราได้สะดวกยิ่งขึ้น

ดังนั้น หากใครสะดวกที่จะใช้เครื่องมืออื่น ๆ เพื่อทำ Port Forwarding อย่าง Cloudflare Tunnel ก็ไม่มีปัญหาเช่นกัน

ในส่วนของการใช้งาน Ngrok สามารถเข้าไปได้ที่ Ngrok.com ทำการสมัครสมาชิก และลงซอฟต์แวร์ตามระบบปฏิบัติการที่ใช้อยู่ได้เลย

การติดตั้ง Ngrok

2. Line Developers Console

Line Developers Console จะเป็นเว็บไซต์ที่เราจะใช้ในการสร้าง LIFF Application และนำ LIFF Appliaciton ID ที่ได้ มาเชื่อมต่อกับโค้ดที่เรากำลังจะเขียนไปด้วยกัน

โดยขั้นตอนนั้นง่ายมาก เริ่มจากเข้าไปที่เว็บไซต์ Line Developer Console และทำการสมัครสมาชิก

สมัครเข้าใช้งาน Line Devlopers Console

จากนั้นจะเข้ามาสู่หน้าตามรูปด้านล่างนี้ เราจะเริ่มจากการสร้าง Provider กันก่อน ทำการกดที่ปุ่มตามรูปด้านล่าง และตั้งชื่อ Provider ของเรา โดยในบทความนี้จะใช้ชื่อว่า “LIFF 101”

การสร้าง LINE Provider
ตั้งชื่อ LINE Provider

หลังจากที่เราทำการสร้าง LINE Provider เสร็จแล้ว จะเด้งมาที่หน้าตามรูปด้านล่างนี้ จะมีฟีเจอร์ต่าง ๆ ที่ทาง LINE มีให้พวกเราเล่น โดยในส่วนของ LIFF จะอยู่ในส่วนของ “Create a LINE Login channel”

สร้าง Line Login Channel

เมื่อกดเข้ามาแล้ว ก็จะเป็นขั้นตอนในการกรอกข้อมูล เพื่อสร้าง Channel ขึ้นมา โดยในส่วนนี้สามารถกรอกได้เลย ยังไม่ได้มีผลกระทบต่อแอปพลิเคชันของเราในตอนนี้มาก

ตัวอย่างการกรอกข้อมูลเพื่อสร้าง Channel
ตัวอย่างการกรอกข้อมูลเพื่อสร้าง Channel
ตัวอย่างการกรอกข้อมูลเพื่อสร้าง Channel

หลักจากกรอกข้อมูล และทำการกดปุ่ม “Create” เรียบร้อยแล้ว เราก็จะได้ Channel ออกมาตามตัวอย่างในภาพ

ตัวอย่างการสร้าง Channel

จากนั้นให้ทำการกดไปที่ Tab LIFF แล้วกดปุ่ม “Add” เพื่อสร้าง LIFF Application ของพวกเรา

หลังจากนั้นก็ทำการกรอกข้อมูลเพื่อทำการสร้าง LIFF Application ขึ้นมา โดยในหน้านี้จะมีตัวเลือกให้เราสามารถ Custom ได้หลายอย่าง ซึ่งทางผู้พัฒนาช่วยเขียนรายละเอียด Options ต่าง ๆ เอาไว้ได้ค่อนข้างดี สามารถไปอ่านเพิ่มเติมกันได้ที่ Adding LIFF App to channel Document

สำหรับครั้งนี้ ผมจะใช้ Setting ประมาณนี้ครับ

ตัวอย่างการตั้งค่า LIFF Application
ตัวอย่างการตั้งค่า LIFF Application

ในส่วนของ Endpoint URL เราสามารถตั้งอะไรไว้ก่อนก็ได้ครับ ขอแค่ให้เป็น https ซึ่งเดี๋ยวเราจะนำ URL ที่ได้จาก Ngrok มาใส่แทนอีกที

หลังจากที่กดสร้างเสร็จแล้ว เราก็จะได้ LIFF Application ขึ้นมาหนึ่งอัน โดยจะมี LIFF ID ที่เราจะนำไปเชื่อมโค้ดของเรา และ LIFF URL ที่ใช้สำหรับให้ผู้ใช้กดเพื่อเข้าไปสู่ LIFF Application ของเรา

ตัวอย่างเมื่อสร้าง LIFF Application สำเร็จ

Create Next.js Project

ในบทความนี้ผมจะใช้ pnpm เป็น Package Management สำหรับใครที่สะดวกใช้ npm, yarn, bun หรือตัวอื่นๆสามารถใช้งานได้ตามสะดวกเลยครับ

เริ่มจากการสร้างโปรเจกต์ด้วยคำสั่งที่เพื่อน ๆ คุ้นเคยกัน

pnpm create next-app
ตัวอย่างการตั้งค่าโปรเจกต์ Next.js

จากนั้นทำการเปิด Repository ขึ้นมา ก็จะได้ตามตัวอย่างภาพด้านล่างนี้

ตัวอย่าง Next.js App Router Repository

Add LIFF Dependencies

เราจะทำการเพิ่ม Dependency ทั้งหมดสองตัว คือ @line/liff และ react-liff โดยสามารถอ่านเพิ่มเติมจากผู้พัฒนาได้ที่ Github react-liff

เริ่มจากการ Install Dependencies

pnpm add @line/liff react-liff
การลง Dependency @line/liff และ react-liff

Add LIFF_ID to Project

ในการที่เราจะสร้าง LIFF Application กัน เราต้องเพิ่ม LIFF ID ไว้ใน .env กันก่อน

เริ่มจากการสร้างไฟล์ .env เอาไว้ที่นอกสุดของ Directory และนำค่า LIFF ID ที่ได้จาก LINE Developer Console เพิ่มเข้าไป ใส่ตัวแปรชื่อ NEXT_PUBLIC_LIFF_ID

// .env

NEXT_PUBLIC_LIFF_ID=XXXXXXXXXXXXXXX
ตัวอย่างการเพิ่ม LIFF ID ใน .env
ตำแหน่งของ LIFF ID ใน LINE Developer Console

จากนั้นเพิ่มตัวแปรและไฟล์ global-config.ts ไว้ในโฟลเดอร์ src มาเพื่อทำการอ่านค่าในไฟล์ .env

// /src/global-config.ts

export const LIFF_ID = process.env.NEXT_PUBLIC_LIFF_ID;
สร้างไฟล์ global-config และอ่านค่า LIFF ID จาก .env

แค่นี้เราก็สามารถทำ LIFF_ID ไปใช้ที่อื่นใน Project ของเรากันได้แล้ว

Implement LIFF Provider

ต่อมาเราจะทำการสร้าง LIFF Provider แล้วนำมันไปครอบโปรเจกต์ของเราเอาไว้ เพื่อให้เราสามารถใช้งานฟีเจอร์ต่าง ๆ ของ LIFF ได้

เริ่มจากการสร้างไฟล์ liff-provider.tsx ไว้ในโฟลเดอร์ /components/liff

// /src/components/liff/liff-provider.tsx

"use client";

import { PropsWithChildren } from "react";
import { LIFF_ID } from "@/global-config";
import { LiffProvider as ReactLiffProvider } from "react-liff";

const LiffProvider = ({ children }: PropsWithChildren) => {
if (!LIFF_ID) {
return <div>Failed to load LIFF_ID</div>;
}

return <ReactLiffProvider liffId={LIFF_ID}>{children}</ReactLiffProvider>;
};

export default LiffProvider;

Discussion

  • ผมทำการสร้าง LiffProvider ที่รับ props เป็น children ขึ้นมา
  • ทำการตรวจสอบว่า LIFF_ID มีหรือไม่ ถ้าไม่มีให้แสดงผล ERROR แต่ถ้ามีให้นำ LiffProvider จาก “react-liff” มาแสดงผล แต่เนื่องจากชื่อของ Component ซ้ำกัน ผมจึงทำการเปลี่ยนชื่อเป็น ReactLiffProvider
  • ผมทำการส่งค่า LIFF_ID ไปยัง ReactLiffProvider ซึ่งเป็นค่าที่ import มาจาก global-config.ts
  • ผมทำการเปลี่ยน Component นี้ให้เป็น Client Component (สังเกตได้จาก “use client” ที่อยู่ด้านบนสุด) เนื่องจาก ReactLiffProvider ต้องรันบน Browser เท่านั้น ไม่สามรถรันบน Server ได้
  • สำหรับชื่อไฟล์ ผมชอบใช้ Kabab Case (eg. liff-provider) มากกว่า Pascal Case (eg. LiffProvider) เพราะส่วนตัวผมรู้สึกว่ามันอ่านได้ง่ายกว่า ดูสวยกว่า แต่ในส่วนนี้เป็นความเห็นส่วนบุคคล สามารถเลือกใช้งานได้ตามที่ตัวเองถนัดเลยคับบ
การสร้าง Liff Provider ในโฟลเดอร์ /src/components/liff

จากนั้นทำการสร้างไฟล์ index.ts ขึ้นมาในโฟลเดอร์นี้ เพื่อทำการ export component ในไฟล์ liff-provider.tsx

// /src/components/liff/index.tsx

export { default } from "./liff-provider";
สร้างไฟล์ index.ts เพื่อทำการ export components ใน /src/components/liff

เสร็จแล้วเราจะนำ Component ที่เราสร้างขึ้นมานี้ไปใช้งานใน Root ของ component หรือก็คือที่ไฟล์ /src/app/layout.tsx

โค้ดเริ่มต้นของไฟล์ /src/app/layout.tsx

โดยเราจะทำการ import LiffProvider จาก /src/components/liff เข้ามา และนำมาใช้ภายใต้ tag body

// /src/app/layout.tsx

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import LiffProvider from "@/components/liff"; // บรรทัดที่เพิ่มเข้ามา

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>
<LiffProvider>{children}</LiffProvider> {/* บรรทัดที่เพิ่มเข้ามา */}
</body>
</html>
);
}
โค้ดหลังจากเพิ่ม LiffProvider เข้ามาใน /src/app/layout.tsx

Implement LIFF Loading Component

เราจะทำการสร้าง Loading Component กันก่อน เพื่อเอาไว้แสดงผลในเวลาที่ Browser กำลังโหลด LIFF

โดยผมจะทำเป็น Text Loading ง่าย ๆ เพื่อให้บทความนี้ไม่ซับซ้อนจนเกินไป ……. จริง ๆ นะ ผมไม่ได้ขี้เกีขจเลย … จริงๆ 🙂

สำหรับ LIFF Loading Component นี้ ผมจะสร้างไฟล์ชื่อ liff-loading.tsx เอาไว้ใน /src/components/fallback โดยมีแค่คำว่า “Liff Loading…” อยู่กลางหน้าจอ

// /src/components/fallback/liff-loading.tsx

const LiffLoading = () => {
return (
<div className="w-screen h-screen flex justify-center items-center">
<p>LIFF Loading...</p>
</div>
);
};

export default LiffLoading;
สร้าง LIFF Loading Component

Discussion

  • สำหรับไฟล์ liff-loading.tsx นี้เป็นแค่หน้าที่แสดงคำว่า “LIFF Loading…” เอาไว้กลางหน้าจอ
  • เพื่อเอาไว้ใช้ในขณะที่ Browser จะการโหลด LIFF ตอนเริ่มเปิดเว็บไซต์ของเรา

และทำการสร้างไฟล์ index.ts ไว้ใน Directory เดียวกันเพื่อทำการ export ออกมาจาก Directory

// /src/components/fallback/index.ts

export { default as LiffLoading } from "./liff-loading";
สร้างไฟล์ index.ts เพื่อทำการ export components ใน /src/components/fallback

Implement LIFF Store

ในส่วนนี้เราจะทำการสร้าง Store ด้วย zustand เพื่อจะใช้เก็บข้อมูลของผู้ใช้ที่มาจาก LINE

ซึ่งจริง ๆ แล้วหากใครสะดวกที่จะใช้ redux react-context หรือเครื่องมือตัวอื่น ๆ ก็สามารถใช้งานได้ตามที่สะดวกเลยนะครับ แต่ส่วนตัวผมชอบความง่าย และสะดวกของ zustand เลยจะนำมาใช้ในบทความนี้

เร่ิมจากการ install zustand เข้าสู่โปรเจกต์ของเรากันก่อน

pnpm add zustand
Install zustand เข้าสู่โปรเจกต์

ต่อมาทำการสร้าง liff store ใน /src/store โดยผมจะตั้งชื่อว่า liff.ts

// /src/store/liff.ts

import { create } from "zustand";

type Profile = {
userId: string;
displayName: string;
pictureUrl?: string;
};

type LiffStore = {
profile: Profile | null;
setProfile: (profile: Profile) => void;
};

export const useLiffStore = create<LiffStore>()((set) => ({
profile: null,
setProfile: (profile) => set({ profile }),
}));
สร้าง Liff Store สำหรับเก็บข้อมูล Profile ของผู้ใช้ที่ได้มากจาก LIFF

Implement LIFF Init Provider

ต่อไปเราจะทำการดึงข้อมูลของผู้ใช้จาก LIFF กันแล้ว โดยเราจะสร้าง LiffInitProvider ขึ้นมาให้ครอบตัว Root เหมือนเดิม แต่อยู่ภายใต้ LiffProvider ที่เราพึ่งสร้างกันไป (ชื่อมันจะคล้าย ๆ กันนิดนึง แต่คือคนละตัวกันนะครับ)

สำหรับหน้าที่ของ LiffInitProvider นี้ จะมีหน้าที่ดึงข้อมูลผู้ใช้จาก LIFF เมื่อตัว Application เริ่ม Init แล้วทำการเก็บข้อมูลของผู้ใช้ลง Store เพื่อนำไปใช้ในวันหลัง

เริ่มจากการสร้างไฟล์ liff-init-provider.tsx ใน /src/components/liff

// /src/components/liff/liff-init-provider.tsx
// Step 1 สร้างไฟล์ liff-init-provider.tsx

"use client";

import { PropsWithChildren } from "react";

const LiffInitProvider = ({ children }: PropsWithChildren) => {
return children;
};

export default LiffInitProvider;
สร้างไฟล์ liff-init-provider.tsx

ต่อมาเราจะทำการเรียกใช้งาน useLiff ซึ่งเป็น Hook จาก “react-liff” ที่เราพึ่งลง dependency ไป

// /src/components/liff/liff-init-provider.tsx
// Step 2 Import useLiff และทำการแสดงผล LiffLoading

"use client";

import { PropsWithChildren } from "react";
import { useLiff } from "react-liff";
import { LiffLoading } from "../fallback";

const LiffInitProvider = ({ children }: PropsWithChildren) => {
const { isReady, isLoggedIn, liff } = useLiff();

if (!isReady) return <LiffLoading />;

return children;
};

export default LiffInitProvider;
Import useLiff และตรวจสอบความพร้อมใช้งานจากตัวแปร isReady

Discussion

  • เราทำการ Import useLiff จาก “react-liff” เข้ามา
  • จาก useLiff เราสามารถดึงตัวแปร isReady ออกมาได้ เพื่อตรวจสอบว่าตัว liff พร้อมใช้งานรึยัง ถ้ายังไม่พร้อมใช้งาน เราจะให้มันแสดงผล LiffLoading Component ที่เราสร้างเอาไว้

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

// /src/components/liff/liff-init-provider.tsx
// Step 3 สร้างไฟล์ฟังก์ชัน initialize

"use client";

import { PropsWithChildren, useCallback, useEffect } from "react";
import { useLiff } from "react-liff";
import { LiffLoading } from "../fallback";

const LiffInitProvider = ({ children }: PropsWithChildren) => {
const { isReady, isLoggedIn, liff } = useLiff();

const initialize = useCallback(async () => {
// ดึงข้อมูล โปรไฟล์ผู้ใช้ จาก liff
}, []);

useEffect(() => {
if (!isLoggedIn) return;

initialize();
}, [initialize, isLoggedIn]);

if (!isReady) return <LiffLoading />;

return children;
};

export default LiffInitProvider;
สร้างฟังก์ชัน initialize

Discussion

  • ฟังก์ชัน initialize เป็นฟังก์ชันที่ถูกสร้างไว้ เพื่อดึงข้อมูลจาก LIFF
  • นำฟังก์ชัน initialize ไปใช้งานใน useEffect เพื่อให้ถูกเรียกใช้งานเมื่อตัวเว็บไซต์ถูกเปิดขึ้นมา
  • มีการตรวจสอบว่าผู้ใช้ทำการ login สำเร็จแล้วหรือยัง โดยใน process ของการ login นี้ จะถูกทำงานโดยอัตโนมัติ และสามารถตรวจสอบสถานะได้จากตัวแปร isLoggedIn ที่ได้มาจาก useLiff
  • จึงมีการใส่เงื่อนไขเพิ่มเติมว่าถ้าฟังก์ชัน initialize ทำงานก็ต่อเมื่อผู้ใช้ login เรียบร้อยแล้ว (isLoggedIn = true)

ขั้นตอนต่อไป เราจะทำการดึงข้อมูลของผู้ใช้จาก liff ภายในฟังก์ชัน initialize เสร็จแล้วทำการ save profile ของผู้ใช้ใส่ liff store ที่เราได้สร้างกันเอาไว้

// /src/components/liff/liff-init-provider.tsx
// Step 4 ดึงข้อมูลของผู้ใช้ และทำการ save ลง liff-store

"use client";

import { PropsWithChildren, useCallback, useEffect } from "react";
import { useLiff } from "react-liff";
import { LiffLoading } from "../fallback";
import { useLiffStore } from "@/store/liff";

const LiffInitProvider = ({ children }: PropsWithChildren) => {
const { isReady, isLoggedIn, liff } = useLiff();

const setProfile = useLiffStore((state) => state.setProfile);

const initialize = useCallback(async () => {
/* Get user profile */
const profile = await liff.getProfile();

/* Save user profile to liffstore*/
setProfile(profile);
}, [liff, setProfile]);

useEffect(() => {
if (!isLoggedIn) return;

initialize();
}, [initialize, isLoggedIn]);

if (!isReady) return <LiffLoading />;

return children;
};

export default LiffInitProvider;
ดึงข้อมูลโปรไฟล์ของผู้ใช้จาก LIFF และ Save ลง Liff Store

สุดท้ายเราจะนำ Component LiffInitProvider นี้ไปใช้งานที่ /src/app/layout.tsx โดยเราจะในไปไว้ภายใต้ LiffProvider

เรียกใช้งาน LiffInitProvider

เพียงเท่านี้เราก็สามารถดึงข้อมูลผู้ใช้มาจาก LIFF และสามารถเรียกใช้งานผ่าน useLiffStore ได้แล้ว

Implement Home Page

ในส่วนต่อไป เราจะดึงข้อมูลของผู้ใช้ที่เราเก็บเอาไว้ใน Liff Store แล้วเอามาแสดงผลในหน้า Home Page

ก่อนอื่น เราจะทำการเคลียโค้ดเริ่มต้นที่ได้มาตอนที่เราสร้างโปรเจกต์กันก่อน

เริ่มต้นจากไฟล์ /src/app/page.tsx ลบโค้ดที่มีทั้งหมดออก

// /src/app/page/tsx
// ลบโค้ดออกทั้งหมด

export default function Home() {
return <div></div>;
}
ลบโค้ดเริ่มต้นออกจากไฟล์ /src/app/page.tsx

ต่อมาเคลีย styles ที่กำหนดมาในไฟล์ /src/app/global.css

// /src/app/global.css

@tailwind base;
@tailwind components;
@tailwind utilities;
ลบโค้ดเริ่มต้นออกจากไฟล์ /src/app/global.css

สุดท้ายนี้ เราจะดึงข้อมูลของผู้จาก useLiffStore แล้วนำมาแสดงผล

โดยผมจะทำการสร้างไฟล์ใหม่ขึ้นมาที่ /src/users/profile.tsx

// /src/users/profile.tsx

"use client";

import { useLiffStore } from "@/store/liff";
import Image from "next/image";

const Profile = () => {
const profile = useLiffStore((state) => state.profile);

const profilePicture = () => profile?.pictureUrl || "";

if (!profile) return null;

return (
<div className="space-y-4">
<Image
loader={profilePicture}
src="profile.png"
width={100}
height={100}
alt="user profile"
className="rounded-full ransition-transform transform translate-y-0"
/>

<p className="text-center">{profile?.displayName}</p>
</div>
);
};

export default Profile;
สร้าง Profile Component เพื่อแสดงผลข้อมูลของผู้ใช้

Discussion

  • ผมได้ทำการสร้างไฟล์ profile.tsx ขึ้นมาใน /src/components/users
  • โดยในคอมโพแนนท์ได้ทำการดึง profile มาจาก useLiffStore และนำมาแสดงผล
  • โดยมีการตรวจสอบค่าของ profile ก่อนการนำมาแสดงผล หากไม่มี profile ให้ component return null ออกมาแทน

จากนั้นทำการสร้างไฟล์ index.ts เพื่อทำการ export component ใน profile.tsx ออกมาจากโฟลเดอร์ /src/components/users

// /src/components/users

export { default as Profile } from "./profile";
สร้างไฟล์ index.ts เพื่อทำการ export components ใน /src/components/users

สุดท้ายนี้คือการนำ Component Profile ที่เราสร้างขึ้นมาไปแสดงผลใน /src/app/page.tsx

// /src/app/page.tsx

import { Profile } from "@/components/users";

export default function Home() {
return (
<div className="flex flex-col justify-center items-center w-screen h-screen">
<Profile />
</div>
);
}

เรียบร้อยครับ… เพียงเท่านี้เราก็ Implement โค้ดเสร็จทั้งหมดแล้ว เหลือแต่มาดูผลลัพธ์กัน ซึ่งพูดกันตามตรงผมก็อยากให้มีการแสดงผลลัพธ์ในระหว่างการ Implement เช่นกัน แต่มันไม่ได้จริงๆ 🥲

Review the Results

มาถึงในส่วนของการตรวจสอบผลลัพธ์ของพวกเรา โดยปกติเราก็แค่สั่งให้โค้ดของเรารันใน localhost ก็ได้แล้ว แต่เนื่องจากเราต้องทำงานร่วมกับ LIFF ซึ่งต้องนำเว็บไซต์ของเราไปเปิดบน LINE Application ดังนั้น เราจะทำทั้งหมด 3 Steps ครับ

  1. รันเว็บไซต์ของเราบน localhost ที่ port 3000 (หรือ port อื่นก็ได้)

เริ่มจากการรันคำส่ังที่เราคุ้นเคย

pnpm dev

// npm run dev
// yarn dev
// bun dev
ตัวอย่างการรันเว็บไซต์ใน localhost

2. สั่ง ngrok ให้ forward port 3000

ngrok http http://localhost:3000
ตัวอย่างการสั่ง ngrok ให้ forward port 3000
Url ที่ได้มาจากการสั่งให้ ngrok ทำการ forwar port

3. นำ HTTPS URL ที่ได้จาก ngrok ไปใส่ใน LINE Developers Console

แก้ไข Endpoint URL เป็น HTTPS URL ที่ได้มาจาก ngrok

เมื่อเราทำการแก้ไข และกดปุ่ม Update แล้ว เพื่อความสะดวก ให้ทำการปรับโหมดจาก Developing เป็น Published

ปรับโหมดเป็น Published

และสามารถนำ LIFF URL ไปเปิดในแอปพลิเคชัน LINE ได้เลย 🎉🎉🎉

ผลลัพธ์เมื่อเปิดเว็บไซต์จาก LIFF URL

สุดท้ายเพียงแค่เพื่อน ๆ นำ LIFF URL นี้ไปใส่ใน Rich Menu ของ LINE OA ก็จะได้เว็บไซต์เก๋ ๆ ไปอยู่ใน LINE OA ของเพื่อน ๆ กันแล้วครับ 🥳

[แถม] แนะนำ Use Case การใช้งาน

  1. เนื่องจาก LINE เป็น Application ที่แทบจะทุกคนในประเทศไทยมีกัน ทำให้สะดวกในการเข้าถึง ไม่จำเป็นต้องโหลดเป็นแอปพลิเคชัน และยังสามารถเข้าใช้งานได้สะดวกกว่าเว็บไซต์บนเบราเซอร์
  2. LIFF ช่วยให้ทำระบบที่ใช้การ Authen User ด้วย LINE ทำให้ User ไม่จำเป็นต้องสร้าง Account ด้วยตัวเองในระบบของเรา
  3. เราสามารถทำระบบ Authentication ในระบบ Backend ของเราเองก็ได้ โดยใช้ Token ID ที่ได้มาจาก LIFF เป้นตัวยืนยันผู้ใช้ แต่เก็บ Account ของ User ไว้ในระบบของเราเอง ทำให้เพิ่มความยืดหยุ่นในการ Develop และช่วยยืนยันตัวตนของผู้ใช้ไปขั้นนึง
  4. สร้างระบบง่าย ๆ ในการสะสมแต้ม ซึ่งเราจะพบได้บ่อยในช่วงหลายปีมานี้ ที่ร้านค้า ร้านอาหาร มักจะให้เพิ่มเพื่อนกับ LINE Official Account และทำการสมัครสมาชิก เก็บบัตรสะสมแต้ม แลกพ้อยต์กันบน LINE LIFF เพราะสะดวกทั้งการพัฒนา และต่อตัวผู้ใช้งานเอง
  5. นำความสามารถของ LINE LIFF ไปผนวกกับ LINE API ที่มีให้เราได้นำมา สร้างสรรค์ซอฟต์แวร์เจ๋ง ๆ ได้อีกมากมาย

หวังว่าบทความนี้ จะเป็นจุดเริ่มต้นให้เพื่อน ๆ สามารถเริ่มต้นในการสร้าง LIFF Application ได้ง่าย สะดวกและรวดเร็วมากยิ่งขึ้น ทั้งนี้ หากมีคำถาม หรือข้อสงสัยใด ๆ สามารถคอมเม้นต์เอาไว้ได้เลย มาแลกเปลี่ยนความคิดกันน 😀

--

--