เริ่มต้นทำโปรเจ็กท์ Javascript ES6 ด้วย Webpack4 , Babel7 และ ESLint กัน

สวัสดีครับ บทความนี้ผมกำลังจะลองทำ library เป็นของตัวเองดู เลยได้คำแนะนำให้ใช้ Webpack ซึ่งเป็น Module Bundler ตัวหนึ่ง

โดยประโยชน์ของ Module Bundler จะคอยแปลงไฟล์ของเราเป็นก้อนเดียวพร้อมใช้งาน และมีขนาดเล็ก นอกจากนี้ยังช่วยโปรเจ็กท์ของเราเขียนอยู่ในรูปแบบ ES6 รวมถึงความสามารถในการ Import , Export ด้วย

โดยมี Babel ร่วมด้วย จะทำให้ ES6 ของเราจะกลับไปอยู่ในรูปแบบ ES5 เพื่อให้สามารถใช้กับ Browser ส่วนใหญ่ได้อย่างไม่มีปัญหา

และปิดท้ายด้วย ESLint ทำหน้าที่คอยตรวจทาน Syntax ของเราให้เขียนอยู่ในรูปแบบ ES6 และตรวจเช็คตัวแปรที่ไม่ได้ใช้ หรือฟังก์ชั่นที่ไม่เหมาะสมอีกด้วย

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

มารู้จัก Module bundler

จากที่เกริ่นไป Module Bundler จะคอยทำให้ไฟล์โปรเจ็กท์เรารวมกันเป็นก้อนเดียวพร้อมใช้งาน พร้อมทำให้โปรเจ็กท์เราเขียนในรูปแบบ ES6 รวมถึงมีความสามารถในการ Import , Export และคอยทำ Minify ให้โปรเจ็กท์ของเราให้มีขนาดเล็กและสามารถดูโค๊ดได้ยากเวลาเอาไปใช้จริงอีกด้วย

จากที่ศึกษาในตลาดมี Module Bundler ให้เล่นหลักๆอยู่ 3 ตัว

  1. Webpack เป็น module Bundler ที่เหมาะสำหรับทำแอป
  2. Rollup เป็น module bundler ที่เหมาะสำหรับทำ Library
  3. Parcel เป็น module bundler ที่มีความสามารถคือใช้ได้เลย

แต่จริงๆแล้ว module bundler แต่ละตัวไม่ได้ต่างกันมาก สามารถพอใช้แทนกันได้

ในครั้งนี้ผมจะเริ่มทำด้วย Webpack ก่อน เนื่องจากมีคนเคยใช้คอยให้คำแนะนำได้ และหากมีโอกาสจะเขียนบทความที่ทำด้วย Rollup อีกทีดูครับ

ต่อไปเราจะมาเริ่มต้นทำโปรเจ็กท์ด้วย Webpack กันเลย

เตรียม NPM Package

ณ จุดนี้เราจะใช้ NPM เป็นตัว Install Package ต่างๆ โดยเราจะต้องเซ็ตโปรเจ็กท์ให้พร้อมใช้ NPM ก่อน โดยการสร้าง package.json

โดย NPM เป็นความสามารถของ NodeJS ดังนั้น เครื่องเราจะต้องมี NodeJS ก่อน แต่ผมขอข้ามวิธีการลง NodeJS เพื่อไม่ให้เป็นการเสียเวลานะครับ

อันดับแรก สร้าง package.json ด้วยคำสั่ง

$ npm init

และจะมี setting ขึ้นมาให้เราตั้ง หากใช้ของที่มีอยู่แล้วให้กด Enter รัวๆ โดย ข้างล่างเป็นตัวอย่างที่ผมตั้งค่าไว้

package name: (demo-webpack-starter)
version: (1.0.0)
description: test webpack starter
entry point: (index.js) ./src/index.js
test command:
git repository:
(https://github.com/pagongamedev/demo-webpack-starter.git)
keywords: demo webpack starter
author: pagongamedev
license: (ISC)

หรือ

หากใครอยากเร็ว ก็ลองใช้คำสั่ง — yes ตามหลังแทน ทุกอย่างจะเป็นค่าพื้นฐานแทน ทำให้เราไม่ต้องตั้งค่าอะไรเลย

$ npm init --yes 

หากใครใช้ git อย่าลืมเพิ่ม .gitignore ตามข้างล่างนี้

node_modules/

เตรียม Webpack4

โดยผมจะใช้ webpack เวอร์ชั่น 4 นะครับ หากเอาไปใช้แล้วรันไม่ได้ ให้ดูเวอร์ชั่นอีกทีเพราะ webpack แต่ละเวอร์ชั่นชอบเปลี่ยนคำสั่งบ่อย

หรือดูเพิ่มเติมที่ https://webpack.js.org/guides/getting-started/

อันดับแรกทำการติดตั้ง Package Webpack และ Webpack-cli

$ npm install --save-dev webpack webpack-cli

และทำการสร้างไฟล์ webpack.config.js ดังนี้

const path = require("path");module.exports = {
entry: "./src/index.js",
mode: "production",
output: {
path: path.resolve(__dirname, "./build/"),
filename: "bundle.js"
}
};

จากนั้นให้เพิ่มคำสั่งข้างล่างใน scripts ในไฟล์ package.json

{
...
"scripts": {
... ,
"webpack": "node_modules/.bin/webpack",
"webpack:dev": "node_modules/.bin/webpack --mode=development"
},
...
}

เมื่อเซ็ตเรียบร้อยแล้ว

เราสามารถสร้างไฟล์ที่สามารถนำไปใช้จริง ที่ทำการย่อขนาดด้วย Minify ออกมาเรียบร้อยแล้วด้วยคำสั่ง

$ npm run webpack

หรือ

ใช้คำสั่งข้างล่าง สำหรับต้องการได้ไฟล์เต็ม โดยไม่ทำการย่อขนาด เพื่อดูข้อมูลข้างใน สำหรับตอนกำลังพัฒนา

$ npm run webpack:dev

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

เตรียมโปรเจ็กท์ตัวอย่างสำหรับ Webpack

เมื่อเราใช้ Webpack จะทำให้เราสามารเขียนโปรเจ็กท์เป็น ES6 และมีความสามรถในการ Import Export ได้เลย

โดยโปรเจ็กท์ตัวอย่างผมจะมีไฟล์ดังนี้ โดยทุกอย่างใน src จะถูกสร้างให้ออกมาเป็นไฟล์ bundle.js ไฟล์เดียวให้ index.htm ได้ใช้งาน

index.htm
src
├─ HelloWorld.js
├─ Triangle.js
└─ index.js

ไฟล์ HelloWorld.js จะมีฟังก์ชั่นในการแสดงผลคำว่า HelloWorld

const callHelloWorld = () => {
console.log("Hello World");
};
export default callHelloWorld;

ไฟล์ Triangle.js จะมีฟังก์ชั่นในการคำนวนพื้นที่สามเหลี่ยม

const calTriangle = (width, height) => {
return 0.5 * width * height;
};
export default calTriangle;

ไฟล์ index.js จะมีหน้าที่รวมไฟล์ และ สร้างตัวแปรแบบ Global

import callHelloWorld from "./HelloWorld";
import calTriangle from "./Triangle";
window.callHelloWorld = callHelloWorld;
window.calTriangle = calTriangle;

ไฟล์ index.htm จะลองนำฟังก์ชั่นในไฟล์ที่สร้างออกมามาใช้งาน

<html>
<head>
<title>demo webpack starter</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="../build/bundle.js"></script>
<script>
callHelloWorld();
console.log("Triangle width 5 and height 10 area is "
,calTriangle(5,10));
</script>
</body>
</html>

ลองทดสอบด้วยคำสั่ง npm run webpack จะได้ไฟล์ build/bundle.js ขึ้นมา

$ npm run webpack

พอได้แล้ว ลองทดสอบ index.htm ดู เป็นอันเรียบร้อยดังข้างล่าง

Hello World
Triangle width 5 and height 10 area is 25

เมื่อ Webpack ใช้งานได้แต่เรา จะต้องพัฒนาโปรเจ็กท์ต่อ แต่ไม่อยากลอง Build บ่อยๆ สามารถทำ Auto Build Webpackทุกครั้งที่เซฟในตัวอย่างต่อไป

ทำ Auto Build Webpack ทุกครั้งที่เซฟ

โดยเราจะใช้ Webpack Dev Server เข้ามาช่วย Auto Build ทุกครั้งที่เซฟ แต่ไฟล์ที่ Build จะอยู่ใน RAM ดังนั้นจะใช้เฉพาะตอนกำลังพัฒนา หากใช้จริงให้ Build ดัวยคำสั่งปกติอีกที

โดยสามารถดูข้อมูลเพิ่มเติมได้ ที่นี่

เริ่มต้นให้ติดตั้ง Webpack Dev Server ด้วยคำสั่ง

$ npm install --save-dev webpack-dev-server

และทำการเพิ่มคำสั่งข้างล่างใน scripts ในไฟล์ package.json

{
...
"scripts": {
... ,
"start:dev": "webpack-dev-server"
},
...
}

หากเราจะใช้ให้รันคำสั่งข้างล่างนี้ได้เลย

$ npm run start:dev

เตรียม Babel 7 สำหรับแปลง ES6 เป็น ES5

เนื่องจาก ES6 เป็นมาตรฐานที่เกิดขึ้นมาใหม่ ดังนั้นไม่ใช่ทุก Web Browser สามารถรัน ES6 ได้ โดยเฉพาะ Web Browser เก่าๆ

ดังนั้น Babel7 จะทำหน้าที่คอยแปลง ES6 ของเราให้อยู่ ในรูป ES5 หรือในรูปแบบที่ Browser ส่วนใหญ่รองรับ ทำให้โปรเจ็กท์ที่เราสร้างขึ้นมาสามารถใช้กับ Browser ส่วนใหญ่ได้อย่างไม่มีปัญหา

สำหรับ Webpack จะใช้ Babel ได้นั้น จะต้องใช้สิ่งที่เรียกว่า Babel Loader โดย Babel Loader จะมีเวอร์ชั่นสูงกว่า Babel อยู่ 1 เวอร์ชั่นเสมอ ดังนั้น Babel7 จะใช้คู่กับ Babel Loader 8

สามารถดูเพิ่มเติมได้ที่ https://github.com/babel/babel-loader

ทำการติดตั้ง babel-loader

$ npm install --save-dev babel-loader @babel/core @babel/preset-env

โดย babel-loader ทำหน้าที่เชื่อมกับ Webpack
@babel/core คือตัว Babel 7
@babel/preset-env เป็นตัวแปลง ES6 ให้อยู่ในรูปแบบ Web Browser ส่วนใหญ่รองรับ

จากนั้นทำการติดตั้ง babel/plugin-proposal-class-properties เพื่อให้โปรเจ็กท์ ES6 สามารถเขียน Class ได้เหมือน Class จริงๆ

$ npm install --save-dev @babel/plugin-proposal-class-properties

จากนั้นให้เพิ่มคำสั่ง Module ต่อจาก Output ใน webpack.config.js

{
output: {
..
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loaders: [{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
plugins: ["@babel/plugin-proposal-class-properties"]
}
}]
}]
}
};

จากนั้นให้ทดสอบด้วยการรัน Webpack อีกครั้งถ้าได้ถือว่าสำเร็จ

$ npm run webpack

ต่อไปก็เหลืออย่างสุดท้ายคือ การเช็ค Syntax ES6 ด้วย Eslint ไปดูวิธีทำกัน

กัน Syntax ES6 พลาด ด้วย ESLint

แม้ว่าเราจะใช้ Webpack ทำให้โปรเจ็กท์เราเขียนในรูปแบบ ES6 ได้ก็จริง แต่ก็ใช่ว่าจะยังเขียนในรูปแบบ ES5 ในโปรเจ็กท์ได้อยู่

ดังนั้นเราควรจะล็อก Syntax ที่ใช้ให้อยู่ในรูปแบบ ES6 ไปเลย ดังนั้นเราจะใช้ ESLint มาช่วยดูแล นอกจากนั้น ESLint จะคอยช่วยดูพวกตัวแปรที่ไม่ได้ใช้ หรือ คำสั่งที่ไม่ควรใช้อีกด้วย

แน่นอนว่าหากใช้กับ webpack ก็ต้องมีตัวเชื่อมกับ ESLint นั่นก็คือ ESLint Loader เข้ามาด้วย

สามารถดูเพิ่มเติมได้ที่นี่ https://github.com/webpack-contrib/eslint-loader

เริ่มต้นทำการติดตั้ง ESLint Loader

$ npm install --save-dev eslint-loader

และทำการติดตั้ง ESLint

$ npm install --save-dev eslint

ติดตั้งส่วนเสริม ESLint สำหรับ Plugin

$ npm install --save-dev eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard

ติดตั้งส่วนเสริม ESLint สำหรับ Config

npm install --save-dev eslint-config-standard eslint-config-prettier

แน่นอนว่า ESLint ก็ต้องเชื่อมกับ Babel ด้วย โดยจะใช้การติดตั้ง babel-eslint

$ npm install --save-dev babel-eslint

และเมื่อติดตั้งทั้งหมดเสร็จ ทำการสร้างไฟล์ .eslintrc สำหรับตั้งค่า ESLint

{
"extends": [
"standard",
"prettier"
],
"parser": "babel-eslint"
}

จากนั้นให้เพิ่ม Loader ต่อจาก Babel Loader ใน webpack.config.js

{
... ,
loaders: [{
loader: "babel-loader",
...
},{
loader: "eslint-loader",
options: {
// eslint options (if necessary)
}
}]
}

ลองรัน Webpack อีกครั้ง

$ npm run webpack

หาก Syntax ไม่ถูกต้อง ESLint จะคอยมาเตือนทุกครั้งเวลาที่ทำการ Build ไฟล์

หากเปิดด้วย VSCode และขึ้น Error ว่าหา babel-eslint ไม่เจอให้ทำการปิดเปิด VSCode ใหม่อีกที

สรุป

การใช้ Webpack จะช่วยให้เราสามารถเขียนโปรเจ็กท์ในรูปแบบ ES6 แต่ก็ยังสามารถนำไปรันกับเวปไซต์ทั่วไปได้ เพราะมี babel มาคอยช่วยแปลงกลับเป็น ES5

แต่มีการติดตั้งค่อนข้างเยอะ สำหรับท่านใดที่ตามไม่ทัน หรือไม่เข้าใจ สามารถเข้าไปดู Source Code เพิ่มเติมใน Github ได้เลยครับ

ทั้งนี้ผมก็พึ่งหัดใช้ Webpack เป็นครั้งแรก อาจจะมีผิดพลาด หรือ ตกหล่น ต้องขออภัย มา ณ ที่นี้ด้วย และ จะแก้ไขให้เร็วที่สุด

หวังว่าบทความนี้จะเป็นประโยชน์สำหรับทุกๆท่าน และขอขอบคุณทุกท่านที่คอยติดตาม แล้วพบกันใหม่ในบทความหน้าครับ

--

--

Pagon GameDev
บริษัทต่างโลก อินเตอร์แอคทีฟ จำกัด

Interactive Developer ผู้สนใจการทำเกม และ Interactive XR VR MR AR มากว่า 10 ปี ปัจจุบันเป็น Co-Founder บริษัท ต่างโลก อินเตอร์แอคทีฟ จำกัด