การใช้ Laravel Mix สำหรับคอมไพล์ CSS และ JavaScript ใน WordPress และโปรเจ็กท์ standalone

เราเข้าสู่ทศวรรษที่ 20s แล้ว เรามีเครื่องมือช่วยอำนวยความสะดวกในการทำเว็บเยอะแยะมากมาย หนึ่งในนั้นคือบรรดา CSS Preprocessor ทั้งหลายไม่ว่าจะเป็น SASS, LESS, หรือ Stylus รวมไปถึงฟีเจอร์ใหม่ๆ ใน JavaScript ที่เพิ่มเข้ามาใหม่อย่างรวดเร็วจนเบราเซอร์ตามกันไม่ค่อยทัน

กำแพงสำคัญอย่างหนึ่งที่ทำให้หลายคนยังไม่ก้าวไปใช้เครื่องมือเหล่านี้สักทีนั่นคือความยุ่งยากในการตั้งค่าเครื่องมือในการคอมไพล์ (หรือทรานสไพล์) ภาษาเหล่านี้ให้เป็นโค้ดที่เบราเซอร์ส่วนใหญ่ในตลาดสามารถเอาไปใช้งานได้

เออ พูดถึงแกนั่นแหละนัง Webpack

ทางออกหนึ่งคือไปใช้ starter theme ที่ตั้งค่าพวกนี้มาให้แล้วอย่างเช่น Sage 9

Laravel Mix

วันนี้จะพามารู้จัก Laravel Mix ซึ่งเป็น wrapper ของ Webpack ที่ช่วยให้เราสามารถคอมไพล์ CSS Preprocessor และ ESNext รวมไปถึงบันเดิลไฟล์จากหลายๆ แพ็คเกจออกมาเป็นไฟล์เดียว ที่เราสามารถใช้งานมันได้ง่ายๆ แบบแทบไม่ต้องตั้งค่าอะไรให้ยุ่งยากเลย

จริงๆ Laravel Mix นี่มันเป็นเครื่องมือของเฟรมเวิร์ก Laravel นั่นแหละ แต่ว่ามันสามารถเอาออกมาใช้แบบ standalone กับโปรเจ็กท์อื่นๆ รวมไปถึงธีมของ WordPress ได้ด้วย

ก่อนที่เราจะติดตั้ง Laravel Mix ก่อนอื่นเครื่องเราต้องนิดตั้ง Node.js และ package manager สักตัวเช่น npm (มากับ Node.js เอง) หรือ Yarn

แนะนำว่าต้องมีพื้นฐานการใช้งาน Command prompt หรือ Terminal เล็กน้อยนะครับ อย่างน้อยคือใช้คำสั่ง cd เป็น และใช้ npm หรือ yarn เป็น

ติดตั้ง Laravel Mix

เปิด cmd หรือ Terminal ขึ้นมาแล้วเปิดไปยังไดเรคทอรี่ธีมของเรา แล้วสั่งติดตั้งแพ็คเกจ laravel-mix และ cross-env ให้เรียบร้อย

// สำหรับคนที่ใช้ npm
$ npm install laravel-mix cross-env --save-dev

// สำหรับคนที่ใช้ Yarn
$ yarn add laravel-mix cross-env --dev

cross-env เป็นแพ็คเกจสำหรับช่วยเรื่อง environment variable ที่บน Windows และ Unix-like นั้นมีวิธีใช้ต่างกัน ซึ่งเราจำเป็นจะต้องใช้ env นี้ในขั้นตอนการคอมไพล์ assets

ใครที่ใช้ Node.js เวอร์ชัน 8 ต้องติดตั้งแพ็คเกจ [email protected] แทน เพราะเวอร์ชันล่าสุดนั้นต้องการ Node.js เวอร์ชัน 10 ขึ้นไป

โดยส่วนตัวผมเจอปัญหาคอมไพล์ไม่ผ่านจาก node-sass ตัว global ไม่ตรงเวอร์ชัน ถึงจะสั่งติดตั้งใหม่แล้วก็ไม่สามารถใช้ได้ กรณีแบบนี้เราสามารถแก้ได้ง่ายๆ ด้วยการติดตั้งแพ็คเกจ node-sass เพิ่มลงไปอีกแพ็คเกจหนึ่ง

จากนั้นคัดลอกไฟล์ node_modules/laravel-mix/setup/webpack.mix.js ออกมาวางไว้ที่ root directory ของธีมเรา

$ cp node_modules/laravel-mix/setup/webpack.mix.js ./

จากนั้นเปิดไฟล์ package.json ขึ้นมา แล้วก็อปคอนฟิก scripts นี้ไปใส่ไว้ก่อนปิดปีกกาสุดท้าย (หรือถ้ามีคอนฟิก scripts อยู่แล้ว ก็ก็อปข้างในใส่เพิ่มเข้าไป)

"scripts": {
    "build": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "build:production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
}

คอนฟิกทั้งสองค่าข้างบนจะเพิ่มคำสั่ง build และ build:production ให้กับ npm หรือ yarn สำหรับใช้บิลด์ assets สำหรับ dev (เว็บที่กำลังทำอยู่) และ production (ตัวเว็บที่เปิดใช้จริง) ตามลำดับ (มันเป็นช็อตคัทสำหรับคำสั่งยาวๆ ข้างหลัง ใครจะไปอยากจำ จริงมั้ย) เราสามารถรันคำสั่งนี้ผ่าน terminal ได้แบบนี้

// สำหรับคนใช้ npm
$ npm run build
$ npm run build:production

// สำหรับคนใช้ Yarn
$ yarn build
$ yarn build:production

ความต่างของการ build ธรรมดาสำหรับตอน dev และการ build:production สำหรับใช้บน production คือในเวอร์ชัน dev นั้น ไฟล์ JS และ CSS จะมี sourcemap บอกอยู่ว่าโค้ดส่วนนั้นมาจากไฟล์ไหน แพ็คเกจไหน บรรทัดเท่าไหร่ เมื่อเราเปิดด้วย dev tool ดูแล้วมันจะมีบอกให้เราได้เห็นในพาเนล style เราจะได้ตามไปแก้ได้ถูกไฟล์

ส่วนการบิลด์สำหรับ production นั้นจะเอา sourcemap ออกไป และทำการ minify ไฟล์ให้ด้วยเพื่อลดขนาดไฟล์ให้เล็กลง

build ธรรมดา มีบอกว่าโค้ดส่วนนั้นมาจากไฟล์ไหนผ่าน sourcemap
build ธรรมดา มีบอกว่าโค้ดส่วนนั้นมาจากไฟล์ไหนผ่าน sourcemap
build:production โค้ดถูก minified และเอา sourcemap ออก
build:production โค้ดถูก minified และเอา sourcemap ออก

จริงๆ ถึงตรงนี้ Laravel Mix ก็พร้อมใช้งานในขั้นต้นแล้ว แต่เดี๋ยวเราจะไปปรับแต่ง Laravel Mix เพิ่มเติมอีกเล็กน้อย รวมถึงจัดการโครงสร้างไฟล์เพื่อให้เหมาะกับธีมเรามากขึ้น

อ้อ ถ้าสมมุติว่าเราไม่อยากมาสั่งคอมไพล์ไฟล์เองทุกครั้ง เราสามารถสั่งให้ Webpack คอยดูการเปลี่ยนแปลงของไฟล์ และคอมไพล์ใหม่อัตโนมัติได้ด้วย

// สำหรับคนใช้ npm
$ npm run build -- --watch

// สำหรับคนใช้ Yarn
$ yarn build --watch
Webpack คอยตรวจไฟล์และคอมไพล์ใหม่อัตโนมัติ

กำหนดโครงสร้างไฟล์

ค่าเริ่มต้นของ Laravel Mix นั้นจะกำหนด entry point สำหรับ CSS และ JS เอาไว้ในไดเรคทอรี่ src/ ในไดเรคทอรี่ธีมของเรา คือ

  • src/app.js สำหรับไฟล์จาวาสคริปท์
  • src/app.scss สำหรับไฟล์ SCSS

และจะคอมไพล์ assets ออกมาเก็บไว้ในไดเรคทอรี่ dist/

  • dist/app.js สำหรับไฟล์จาจาสคริปท์
  • dist/app.css สำหรับไฟล์ SCSS ที่ถูกคอมไพล์ออกมาเป็น CSS แล้ว

ในตัวอย่างนี้เราจะสมมุติว่าเราจะเปลี่ยนที่เก็บไฟล์ไปเป็นไดเรคทอรี่ assets/scripts/main.js และ assets/styles/main.scss และให้คอมไพล์ออกมาที่ dist/scripts/main.js และ dist/styles/main.css ตามลำดับ

เอาล่ะ เปิดไฟล์ webpack.mix.js ที่เราก็อปออกมาเมื่อสักครู่นี้ขึ้นมา เราจะเห็นไฟล์ยาวเหยียด แต่ส่วนมากถูกคอมเมนต์ทิ้งเอาไว้ สาระสำคัญตอนนี้มีอยู่แค่สองบรรทัด คือ

let mix = require('laravel-mix');

mix.js('src/app.js', 'dist/').sass('src/app.scss', 'dist/');

เนี่ยแหละ คอนฟิกเริ่มต้นทั้งหมดของมัน ไม่มีแล้วความปวดหัว!

อธิบายโค้ดคือบรรทัดแรกให้ require แพ็คเกจ laravel-mix เข้ามาไว้ในตัวแปร mix จากนั้นในบรรทัดที่สอง จะเรียกใช้เมท็อด .js() เพื่อกำหนดการคอมไพล์จาวาสคริปท์จากไฟล์ src/app.js ไปไว้ที่ไดเรคทอรี่ dist/ และใช้เมท็อด .sass() สำหรับคอมไพล์ไฟล์ src/app.scss ไปเก็บไว้ในไดเรทอรี่ dist/ ด้วยอีกไฟล์

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

let mix = require('laravel-mix');

mix
  .js('assets/scripts/main.js', 'dist/scripts/')
  .sass('assets/styles/main.scss', 'dist/styles/');

จากนั้นสั่ง npm run build ก็จะได้ไฟล์ที่คอมไพล์แล้วไปโผล่อยู่ในไดเรคทอรี่ dist/scripts/ และ dist/styles/ ตามลำดับ

ขั้นตอนต่อไปคือบอกให้เวิร์ดเพรส enqueue ไฟล์พวกนี้เข้ามา ให้เราเปิดไฟล์ functions.php ของธีมขึ้นมา แล้ว enqueue มันเข้าไปให้เรียบร้อย

<?php
add_action('wp_enqueue_scripts', function () {
  wp_enqueue_style('main-style', get_stylesheet_directory_uri() . "/dist/styles/main.css", false, null);
  wp_enqueue_script('main-js', get_stylesheet_directory_uri() . "/dist/scripts/main.js", ['jquery'], null, true);
}, 100);

และอย่าลืมไปเพิ่มไดเรคทอรี่ dist/ ลงในไฟล์ .gitignore ด้วย

ถ้าลองดูการตั้งค่าอื่นๆ ในไฟล์ที่ถูกคอมเมนต์เอาไว้ จะพบว่า Laravel Mix ยังรองรับการคอมไพล์อย่างอื่นอีกเพียบ ไม่ว่าจะเป็น LESS, Stylus, PostCSS, หรือแม้แต่ TypeScript และ React.js

เรียกใช้ jQuery ของ WordPress ใน Laravel Mix

jQuery ยังถือเป็นหนึ่ง library คู่บุญของชาว WordPress ทั้งนี้ถ้าเราจะเอามาใช้ใน Laravel Mix โดยปกติแล้วเราต้องติดตั้ง jQuery เพิ่มเข้าไปเอง ซึ่งจะกลายเป็นว่าเว็บเรามี jQuery สองตัว คือตัวหนึ่งของ WordPress เอง และอีกตัวคือที่เราติดตั้งไว้บน Webpack

เราสามารถแก้ให้ Laravel Mix เรียกใช้ jQuery ของ WordPress ได้ง่ายๆ ด้วยการใส่ตั้งค่าให้ jQuery ถูกเรียกผ่าน external plugin โดยให้เพิ่มการตั้งค่านี้ลงในไฟล์ webpack.mix.js

mix.webpackConfig({
  externals: {
    jquery: 'jQuery'
  }
});

เท่านี้แหละ พร้อมใช้แล้ว

ใช้ Bootstrap ผ่าน npm

อันนี้เป็น use case ประหลาดๆ อันนึงที่เจอบ่อยๆ นั่นคือหลายคนติดตั้งแพ็คเกจ Bootstrap ผ่าน npm แล้วเวลาดีพลอยก็อัปโหลดไดเรคทอรี่หลุมดำอย่าง node_modules ขึ้นไปทั้งก้อน ซึ่งแน่นอนมันใหญ่มาก

ขั้นแรกให้ติดตั้งแพ็คเกจ bootstrap และ popper.js ลงไปให้เรียบร้อย (เราไม่จำเป็นต้องติดตั้ง jQuery เพราะเราสามารถใช้ของ WordPress ได้เลย)

// สำหรับคนใช้ npm
$ npm install bootstrap popper.js

// สำหรับคนใช้ Yarn
$ yarn add bootstrap popper.js

ขั้นต่อไปให้เปิดไฟล์ assets/styles/main.scss ขึ้นมา แล้วอิมพอร์ต scss ของ Bootstrap เข้ามาด้วยคำสั่ง @import

@import "~bootstrap/scss/bootstrap";

เราสามารถแก้ไขการตั้งค่าของ Bootstrap เพิ่มเติมเช่นเปลี่ยนค่าสีเริ่มต้น ผ่านการตั้งตัวแปร SCSS ซึ่งอันนี้ขอติดไว้ก่อน มันยาวพอจะแยกเป็นอีกเรื่องได้เลย

จากนั้นให้เปิดไฟล์ assets/scripts/main.js ขึ้นมา แล้วอิมพอร์ต jquery และ bootstrap เข้ามา

import 'jquery';
import 'bootstrap';

เท่านี้ก็เรียบร้อย เราสามารถเขียน CSS และ JS ใช้งานต่อตามปกติได้เลย

Optimize ไฟล์ภาพอัตโนมัติด้วย Imagemin

นอกจากฟีเจอร์ built-in ทั้งหลายแล้ว เรายังเพิ่มความสามารถให้ Laravel Mix ผ่านส่วนเสริมได้อีกด้วย (ดูส่วนเสริมทั้งหมดได้ในนี้) ในตัวอย่างนี้เราจะพาไปดูการใช้ laravel-mix-imagemin ในการ optimize ไฟล์ภาพอัตโนมัติกัน

อย่างแรกให้ติดตั้งส่วนเสริม laravel-mix-imagemin ก่อน

// สำหรับคนใช้ npm
$ npm install laravel-mix-imagemin --save-dev

// สำหรับคนใช้ Yarn
$ yarn add laravel-mix-imagemin --dev

จากนั้นเปิดไฟล์ webpack.mix.js ขึ้นมา แล้ว require ส่วนเสริมและเพิ่มคอนฟิกของ imagemin ดังนี้

let mix = require('laravel-mix');
require('laravel-mix-imagemin');

mix.webpackConfig({
  externals: {
     jquery: 'jQuery'
  }
});

mix
  .js('src/app.js', 'dist/')
  .sass('src/app.scss', 'dist/')
  .imagemin([
    {
      from: 'assets/images/',
      to: 'dist/images/'
    }
  ]);

สังเกตุว่าที่ออพเจ็กท์ mix เราเรียกใช้เมท็อด .imagemin() เพิ่มเข้ามา จากคอนฟิกตัวอย่างจะเป็นการคัดลอกไฟล์ภาพจากไดเรคทอรี่ assets/image/ เอาไปเก็บไว้ที่ dist/images/ แล้วทำการ optimize ไฟล์เหล่านั้น

เวลาเราเรียกใช้ไฟล์ในธีมก็ให้อ้างอิงไฟล์จากไดเรคทอรี่ dist/images ได้เลย หรือถ้าเป็นการเรียกใช้จาก CSS ก็เรียกเอาผ่าน relative path เช่น

body {
  background-image: url("../images/background.svg");
}

ปิดตัวเลือก Process CSS URLs

โดยปกติแล้วเมื่อ Laravel Mix เจอว่าไฟล์ SCSS ของเรามีการเรียกใช้ assets อื่น เช่นรูปภาพหรือฟอนต์ Laravel Mix จะสแกนหาไฟล์ที่เรียกใช้แล้วคัดลอกออกมาที่ public directory พร้อมกับเปลี่ยน URL ในไฟล์ CSS ที่คอมไพล์แล้วให้อัตโนมัติ

ฟังดูสะดวกดี แต่เอาเข้าจริงในบางกรณี Laravel Mix จะไม่สามารถหาไฟล์นั้นเจอได้ และทำให้คอมไพล์ไม่ผ่านในที่สุด รวมกับเราใช้วิธีก็อปไฟล์ออกมายัง dist/ เองแล้ว (ทั้งจาก imagemin และ copy-watched) ทำให้เราสามารถปิดฟีเจอร์นี้ได้ ด้วยการเรียกใช้เมท็อด option ดังนี้

mix.options({
  processCssUrls: false,
});

ดีพลอยเว็บจริง

เมื่อเราติดตั้งแพ็คเกจต่างๆ ด้วย npm หรือ yarn เราจะได้ไดเรคทอรี่ node_modules/ มาอันหนึ่ง ที่ในนั้นจะประกอบด้วยแพ็คเกจย่อยๆ มากมายมหาศาล และถ้าหากใครที่ยังใช้วิธีดีพลอยเว็บผ่าน FTP อยู่ น่าจะเข้าใจความเจ็บปวดในการอัปโหลดไฟล์มากมายมหาศาลเหล่านี้ได้เป็นอย่างดี

ข่าวดีก็คือเมื่อเราจัดการรวมไฟล์ทั้งหมดออกมาเป็นไฟล์เดียวแล้ว เราก็ไม่จำเป็นต้องใช้ node_modules/ อีกต่อไป รวมไปถึงไดเรคทอรี่ assets/ ที่ใชเก็บไฟล์ดิบก่อนการคอมไพล์อีกด้วย

ดังนั้นในขั้นตอนการดีพลอย เราสามารถข้ามสองไดเรคทอรี่นี้ไปได้เลย เพียงแค่อัปโหลดไดเรคทอรี่ dist/ อันเดียวก็เพียงพอแล้ว


Posted

in

by

Comments

One response to “การใช้ Laravel Mix สำหรับคอมไพล์ CSS และ JavaScript ใน WordPress และโปรเจ็กท์ standalone”

  1. someone like me Avatar
    someone like me

    ขอบใจนะ ได้ประโยชน์มาก

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.