+7

Webpacker - Cứu cánh trong việc sử dụng Webpack với Rails

Vài năm trước thì Rails là 1 Web framework có thể đáp ứng đủ hoàn toàn nhu cầu của các web developer trong việc phát triển, nhưng mà với sự thay đổi, tiến bộ vượt bậc của JavaScript trong các năm gần đây, dẫn đến việc sử dụng các Javascript framework (AngularJS, ReactJS, Vue, ...) ngày càng nhiều hơn. Điều này làm anh em developer khá là khó khăn trong việc tích hợp, set up môi trường phát triển bởi vì Rails thiếu 1 công cụ tử tế để bundling Javascript. Nhưng điều này sắp tới sẽ thay đổi trong Rails 5.1 - sắp được phát hành trong năm nay, với Gem Webpacker.

Và trong bài post này thì mình xin giới thiệu các tính năng mà nó hỗ trợ trong alpha version, và tại sao mà Gem này sẽ là cứu cánh trong việc tích hợp React, Vue, Angular trong Rails.

Yêu cầu

Cài đặt

Trước khi bắt đầu thì mọi người phải chắc chắn là ruby, node, và yarn đã được cài đặt.

  1. Dùng terminal để tạo thư mục mới 😄
 mkdir webpacker-example-app
 cd webpacker-example-app
 touch Gemfile
  1. Chỉnh sửa Gemfile với nội dung sau đây:

source 'https://rubygems.org'
ruby '2.2.6'
gem 'rails', '~> 5.1.x'
gem 'sprockets', '~> 4.x'
  1. Sau khi đã có Gemfile thì chúng ta cần chạy câu lệnh bundle để cài đặt các thư viện phụ. Từ thư mục webpacker-example-app thì chúng ta chạy 1 trong các câu lệnh duới đây để cài đặt Webpack:
 bundle exec rails new . --webpack --force
 // hoặc là những những câu dưới đây để install webpack với react, angular, vue
 bundle exec rails new . --webpack=react --force
 bundle exec rails new . --webpack=angular --force
 bundle exec rails new . --webpack=vue --force

Với tiền tố mới là --webpack, thì webpack sẽ được cài đặt với Yarn sau khi khởi tạo 1 Rails 5.1 app. Sau khi mà Gem và node_modules được tạo thành công thì chúng đã sẵn sàng để sử dụng webpack với Rails app mới.
Webpacker cũng hỗ trợ Rails 4.2++ apps trở lên bằng cách thêm gem 'webpacker' vào Gemfile và chạy câu lệnh như sau:

 rails webpacker:install
 rails webpacker:install:[react, angular or vue]

Mọi chi tiết về gem Webpacker mọi người có thể vào xem tại đây : https://github.com/rails/webpacker

Cấu hình

1. Cấu trúc thư mục

Nhìn vào thư mục vừa mới được khởi tạo là app/javascript. Đây là thư mục chưa toàn các JavaScript của app và webpack entry point. Mặc định sẽ là app/javascript/pack.

Và điều tiện lợi ở đây là mọi webpack entry point sẽ được đặt ở trong thư mục app/javacsript/packs và các modules có thể đặt ở thư mục app/javascript 1 cách tự do. Giả sử, chúng ta xây dựng 1 cái app xem lịch chẳng hạn, thì cấu trúc thư mục có thể được đặt như này.

// entry: app/javascript/packs/calendar.js
require('calendar') or import 'calendar'; // in es6 world

// 1. Angular app
// Main index file that loads all dependent code and bootstraps module to DOM if required
require('./components/calendar.js') or import './components/calendar.js';
require('./models/calendar.js') or import './models/calendar.js';
// app/javascript/calendar/index.js

// Modular js much like rails app folder
// app/javascript/calendar/components/calendar.js
// app/javascript/calendar/models/month.js
// app/javascript/calendar/templates/calendar.js
// app/javascript/calendar/services/calendar.js
// app/javascript/calendar/routes/calendar.js

// 1. React app
// Main index file that loads all dependent code and bootstraps module to DOM if required
require('./components/calendar.js') or import './components/calendar.js';
require('./routes/calendar.js') or import './routes/calendar.js';
// app/javascript/calendar/index.js 

// Modular js much like rails app folder
// app/javascript/calendar/components/calendar.jsx
// app/javascript/calendar/routes/calendar.jsx
// app/javascript/calendar/data/calendar.js

2. Cấu hình Webpack

Generators của webpacker sẽ tự động thêm file cấu hình của web cho từng môi trường ở trong thư mục config/webpack. Những file cấu hình này hỗ trợ rất nhiều các tính năng của webpack cho từng môi trường như:

  • code-splitting
  • assets-fingerprinting
  • linking static assets like image and styleshhets

Tất cả các options đều được config ở file config/webpack/paths.yml

3. Xây dưng 1 app demo

1. Setup

Đầu tiên, thêm gem foreman vào Gemfile để quản đa tiến trình trong mồi trường phát triển. Sau đó tạo 2 file Procfile, Procfile.dev ở thư mục gốc.

Procfile

web: bundle exec puma -p $PORT

Procfile.dev

web: bundle exec rails s
# watcher: ./bin/webpack-watcher
hot: ./bin/webpack-dev-server

Tiếp theo tạo 1 file binstub để chạy Procfile.dev, ở thư mục bin/ tạo 1 file tên là server và paste những command sau:

#!/bin/bash -i
bundle install
bundle exec foreman start -f Procfile.dev

Để có thể chạy file này thì có thể chúng ta sẽ cần phải cấp quyền cho nó. Chạy chmod 777 bin/server trong trường hợp này. Sau đó chúng ta chỉ cần chạy ./bin/server và Procfile.dev sẽ được thực thi, webpack và puma cũng thế .

2. Code

Chúng ta sẽ tạo 1 module counter để làm ví dụ. Đầu tiên chúng sẽ tạo folder counter trong app/javascipt dùng để chưa code js cho module này. Tiếp đó chúng ta sẽ thêm 2 file: index.js và counter.js với code sau:

counter.js

// A simple counter example
// The setup will be more complicated in modern apps built using React

const incrementNode = document.getElementById('increment');
const decrementNode = document.getElementById('decrement');
const inputNode = document.getElementById('counter');

const counter = {
  initialize() {
    incrementNode.addEventListener('click', (event) => {
      event.preventDefault();
      const currentValue = inputNode.value;
      inputNode.value = parseInt(currentValue, 0) + 1;
    });

    decrementNode.addEventListener('click', (event) => {
      event.preventDefault();
      const currentValue = inputNode.value;
      if (currentValue > 0) {
        inputNode.value = parseInt(currentValue, 0) - 1;
      }
    });
  }
};

export default counter;

index.js


// Initialize the counter code when DOM is ready
import counter from './counter';

document.addEventListener('DOMContentLoaded', () => {
  counter.initialize();
});

Và ở trong thư mục app/javascript/packs chúng ta cần tạo 1 entry point cho webpack, tạo 1 file tên là counter.js trong đấy và fill vào code sau:

// Require or import the counter module
import '../counter';

3.View

Cuối cùng, chúng ta sẽ thêm counter module này vào phần view của chúng ta. Tạo 1 controller :

bundle exec rails g controller pages index

routes.rb

root 'pages#index'

và cuối cùng ở file pages/index.html.erb:

<div class=”counter-wrapper”>
     <h1>Counter</h1>
     <form class=’counter’>
         <button id=’increment’>Increment</button>
         <input type=”number” name=”counter” id=’counter’ value=’0' />
         <button id=’decrement’>Decrement</button>
     </form>
</div>
<%= javascript_pack_tag 'counter' %>

Ở đây, javascript_pack_tag là 1 helper mới trong rails sẽ, với nhiệm vụ là kéo kéo code javascript đã complied và references nó trong app:

<script src=”http://localhost:8080/counter.js"></script>

4. Chạy chương trình

Mở terminal ra và chạy lệnh:

./bin/server 
# or 
bundle exec foreman start -f Procfile.dev

Giờ app sẽ được chạy ở http://localhost:3000 😄

5. Styling

Giờ chúng ta sẽ thêm 1 chút style cho counter module bằng Sass cho màu mè 😄. Tạo 1 file style.sass ở app/javascript/counter/style.sass:

$grey: #f2f2f2

.counter-wrapper
  max-width: 500px
  margin: 100px auto
  padding: 10px
  border: 1px solid $grey

  form

    input
      display: block
      margin-bottom: 10px

    button
      display: inline-block

và cuối cùng thêm nó vào counter/index.jsview:


// Initialize the counter code when DOM is ready
import './style.sass';
import counter from './counter';

document.addEventListener('DOMContentLoaded', () => {
  counter.initialize();
});
view raw
<%= stylesheet_pack_tag ‘counter’ %>

6. Deployment

Mặc định thì heroku sẽ cài đặt yarn và node nếu như chúng ta deploy app với Webpack (nhớ replace sqlite gem với pg gem ở Gemfile).


heroku create 

heroku addons:create heroku-postgresql:hobby-dev
git push heroku master

Giờ thì mình xin kết thúc bài viết ở đây, bài viết tuy sơ sài nhưng mong là mọi người sẽ nắm bắt được sơ bộ về Gem Webpacker này 😄. Link tham khảo: https://medium.com/statuscode/introducing-webpacker-7136d66cddfb


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí