Memahami Webpack tidak sesulit memahami Wanita (Part II)

Memisahkan konfigurasi Webpack, Integrasi Live Reload dan Loader CSS pada Webpack

I Putu Alfred Crosby
React ID
6 min readJul 24, 2016

--

Pada artikel pertama konfigurasi Webpack sangat sederhana dan hanya ada sebuah file kecil. Namun jika project nantinya semakin berkembang, tentunya konfigurasi ini juga ikut menyesuaikan. Juga akan sangat penting untuk memisahkan konfigurasi sesuai environtment. Kita akan bahas bagaimana splitting the Webpack configuration 😚

Splitting Webpack Configuration

Seperti yang kita ketahui, ada banyak cara untuk manajemen konfigurasi webpack.

  • Bisa dengan membuat beberapa file config berbeda, contohnya: webpack.config.dev.js dan webpack.config.prod.js. Ketika development kita gunakan konfigurasi dev, dan ketika build production kita gunakan konfigurasi prod dengan parameter config seperti dibawah ini.
webpack --config webpack.config.prod.js

Cara pertama banyak digunakan oleh boilerplate-boilerplate react.

  • Bisa dengan sebuah file(atau lebih) lalu webpack config di-merge atau di override sesuai environtment dengan konfigurasi lainnya menggunakan sebuah npm package yaitu webpack-merge.

Cara kedua tidak diharuskan hanya memakai sebuah file, file konfigurasi bisa dipisah juga lalu diekspor per-object.

NOTE: Diatas merupakan beberapa daftar untuk memanajemen konfigurasi sebatas pengetahuan penulis.

Karena saya adalah pelanggan buku SurviveJS, (saya tidak ada afiliasi dengan mereka) saya akan menggunakan cara nomor dua. Yaitu menggunakan webpack-merge. Alasannya, yang jelas bukan karena saya pelanggan SurviveJS 😅, tapi karena saya tidak suka menulis dua kali hal yang persis dan melakukan tujuan yang sama pula. Salah satu contoh: pada entry dan output kita akan memasukkan nilai yang sama pada konfigurasi webpack baik di development maupun di production.

webpack-merge

Koding dari artikel pertama akan dilanjutkan disini. Bagi yang ketinggalan disarankan memulai baca dari artikel pertama.

Install dahulu package webpack-merge dengan menjalankan perintah berikut.

$ npm install webpack-merge --save-dev

Buka file webpack.config.js dan panggil webpack-merge

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const merge = require('webpack-merge');const PATH = {
app: path.join(__dirname, 'app'),
build: path.join(__dirname, 'build')
};
const common = {
entry: {
app: PATH.app
},
output: {
path: PATH.build,
filename: '[name].js'
},
plugins: [
new HtmlWebpackPlugin({
title: 'Belajar Webpack'
})
]
};
let config;switch(process.env.npm_lifecycle_event) {
case 'build':
config = merge(common, {});
break;
default:
config = merge(common, {});
}
module.exports = config;

Nah, jadi idenya common itu akan selalu digunakan baik di dev maupun prod. Nanti config akan di-merge sesuai npm_lifecycle_event.

Apa itu npm_lifecycle_event? Singkatnya, itu adalah perintah-perintah yang kita buat pada key “scripts” di file package.json. Misal teman-teman menjalankan perintah npm run build, jadi npm lifecycle eventnya = build.

webpack-validator

Kita akan integrasikan webpack-validator untuk mem-validasi webpack-config kita, dengan tujuan mengurangi rasa sakit dan frustasi ketika muncul error.

$ npm install webpack-validator --save-dev

Pada baris atas di-require dulu webpack-validatornya, dan di baris terakhir webpack.config.js diubah seperti ini.

...const merge = require('webpack-merge');
const validate = require('webpack-validator');
...module.exports = validate(config);

Sip webpack-config sudah aman, teman-teman bisa coba dulu. Hasilnya akan sama seperti konfigurasi awal.

Live Reload

Cmd + S → Pindah ke browser → Cmd + R

Untuk menggunakan fitur keren ini, kita membutuhkan webpack-dev-server.

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

webpack-dev-server sebenarnya merupakan server kecil berbasis ExpressJS dan mendukung fitur canggih milik webpack yaitu Hot Module Replacement(HMR) yang dapat mem-patch state di browser tanpa full-refresh.

Tambahkan pada file package.json

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

Kalau sudah, coba dijalankan npm start. Jika berhasil maka akan muncul sesuatu di Terminal yang memperlihatkan bahwa proses build berhasil.

Setelah menjalankan npm start

Untuk memastikan kita coba buka browser dengan alamat ini http://localhost:8080

Konfigurasi HMR

Sudah coba ubah teks “Hello world” pada file app/component.js? Ok, HMR belum berjalan karena kita harus konfigurasi dulu. Cara termudah tambahkan flag inline dan hot pada perintah webpack-dev-server. Jadinya seperti ini:

webpack-dev-server --inline --hot

Ok, tapi kita akan gunakan konfigurasi tambahan yang akan kita merge ke webpack-config kita.

Buat file baru dengan nama parts.js di dalam folder libs.

libs/parts.js

const webpack = require('webpack');exports.devServer = function(options) {
return {
devServer: {
historyApiFallback: true,
inline: true,
hot: true,
stats: 'errors-only',
host: options.host,
port: options.port
},
plugins: [
new webpack.HotModuleReplacementPlugin({
multistep: true
})
]
};
}

Kita eksport fungsi diatas dan kita akan panggil di file webpack.config.js kita.

webpack.config.js

...const validate = require('webpack-validator');
const parts = require('./libs/parts');
...switch(process.env.npm_lifecycle_event) {
case 'build':
config = merge(common, {});
break;
default:
config = merge(
common,
parts.devServer({
host: process.env.HOST,
port: process.env.PORT
})

);
}
module.exports = validate(config);

Apa yang kita lakukan disana?

Konfigurasi devServer kita merge dengan common, jadi begitulah ide-nya menggunakan webpack-merge. Kita tidak perlu menulis dua kali untuk hal yang sama. 😃 Jadi skrg mari kita jalankan ulang npm start, kemudian coba tengok browser kalian, dan ubah juga teks “Hello world”. Apakah live reload sudah berjalan?

HMR buat engineer makin ganteng 😎

CSS Loader

Live-reload juga bisa digunakan untuk me-refresh perubahan pada css lho! 😍 Awww, love you webpack! Nah, sekarang kita pasang css-loader dan style-loader dulu ya. Install dulu module-nya:

npm install css-loader style-loader --save-dev

Selanjutnya buka file parts.js dan tambahkan part baru:

libs/parts.js

...exports.cssLoader = function(paths) {
return {
module: {
loaders: [
{
test: /\.css$/,
loaders: ['style', 'css'],
include: paths
}
]
}
};
}

Apa yang kita lakukan?

Konfigurasi di atas akan otomatis memanggil css-loader dan style-loader untuk memproses file dengan ekstensi *.css. Loader dievaluasi dari kanan-ke-kiri. Jadi yang pertama dievaluasi adalah css-loader kemudian style-loader.

NOTE: loaders(jamak) (yang dicetak tebal diatas) digunakan ketika kita akan menggunakan lebih dari satu loader, data berupa array seperti contoh diatas. Jika menggunakan satu loader key harus diubah menjadi loader(tunggal, tanpa ‘s’) dan nilainya berupa string. Contoh: loader: ‘babel’

NOTE: style-loader digunakan untuk mengevaluasi css yang di-import menggunakan require(), sedangkan css-loader digunakan untuk mengevaluasi statement css seperti @import dan url.

Kita akan kembali ke file webpack.config.json untuk menambahkan cssLoader. Update file tersebut pada baris yang sama seperti dibawah ini:

webpack.config.js

...switch(process.env.npm_lifecycle_event) {
case 'build':
config = merge(
common,
parts.cssLoader(PATH.app)
);
break;
default:
config = merge(
common,
parts.cssLoader(PATH.app),
parts.devServer({
host: process.env.HOST,
port: process.env.PORT
})
);
...

Simpan dan sekarang langkah terakhir buat file css pada folder app/

app/main.css

body {
background: #205080;
color: #EEE;
}

Selanjutnya panggil file css tersebut di app/index.js

...require('./main.css')...

Apakah berhasil? Coba diubah file css-nya 🤓

Telusuri lebih dalam apa yang terjadi?

Ketika kita memanggil file css seperti diatas, otomatis webpack ber-asumsi kalau kita menggunakan style-loader. Jadi otomatis webpack akan menulis css kita pada tag <style></style> dan itu berarti css kita menjadi global scope. (Baca: CSS Modules)

Untuk mengubah scope css menjadi local, kita bisa menambahkan query modules pada css-loader. Kita akan pakai cara cepat, buka kembali libs/parts.js

...loaders: ['style', 'css?modules']...

Ubah app/main.css

.blueBgWhiteText {
background: #205080;
color: #EEE;
}

Hapus require(‘./main.css’) dari app/index.js, kemudian kita ubah file app/component.js seperti dibawah ini.

var s = require('./main.css');module.exports = function() {
var element = document.createElement('h1');
element.innerHTML = 'Halo dunia';
element.className = s.blueBgWhiteText;
return element;
}

Jadi css-class dipanggil seperti memanggil object javascript. Apakah berhasil? Ayo coba diubah-ubah cssnya 😍

Kesimpulan

Kita sudah berhasil memisahkan konfigurasi webpack, memasang live-reload dan juga menggunakan loader untuk *.css. Tapi css masih ditulis pada tag <style>. Untuk mengeksport css ke dalam file.css kalian membutuhkan module untuk mengekstrak css ke dalam text yaitu extract-text-webpack-plugin. (akan dibahas di artikel lain)

Source code dapat dilihat disini, (pada branch live-reload)

Di artikel selanjutnya kita akan membahas apa itu source-map.

Jika artikel ini bermanfaat jangan lupa di-share dan klik heart icon-nya.

Artikel Lainnya

Artikel ini merupakan bagian dari Memahami Webpack tidak sesulit memahami Wanita the Series.

Memahami Webpack tidak sesulit memahami Wanita the Series

--

--