We are living as nomad in Cyprus !!
ruby on rails

[Rails] How to use Webpacker

From Rails 6, Webpacker which is a wrapper library for Webpack is packaged by default. Here is how to use Webpacker.

Contents

What is Webpacker

Webpacker is one of the gem package to use Webpack in Ruby on Rails. And Webpack is one of the module in node.js to manage all static files such as JavaScript, CSS and Images by one.

When creating a new Rails application, the following files are related to Webpacker.

Directory structure

app
  /app/javascript
    /channels
      /consumer.js
      /index.js
    /packs
      /application.js
  /bin
    /webpack
    /webpack-dev-server
  /config
    /webpack
      /development.js
      /environment.js
      /production.js
      /test.js
    /webpacker.yml

channels directory is generated by Action Cable component in Rails.

packs directory is generated to manage for webpack.

app/javascript/packs/application.js is included the process to load Active Storage, Action Cable, Turbolinks and Rails-UJS by default.

app/javascript/packs/application.js

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

Check the config/webpacker.yml

webpacker.yml is the webpack equivalent of webpack.config.js.

webpacker.yml

# Note: You must restart bin/webpack-dev-server for changes to take effect

default: &default
  source_path: app/javascript
  source_entry_path: packs
  public_root_path: public
  public_output_path: packs
  cache_path: tmp/cache/webpacker
  check_yarn_integrity: false
  webpack_compile_output: true

  # Additional paths webpack should lookup modules
  # ['app/assets', 'engine/foo/app/assets']
  resolved_paths: []

  # Reload manifest.json on all requests so we reload latest compiled packs
  cache_manifest: false

  # Extract and emit a css file
  extract_css: false

  static_assets_extensions:
    - .jpg
    - .jpeg
    - .png
    - .gif
    - .tiff
    - .ico
    - .svg
    - .eot
    - .otf
    - .ttf
    - .woff
    - .woff2

  extensions:
    - .mjs
    - .js
    - .sass
    - .scss
    - .css
    - .module.sass
    - .module.scss
    - .module.css
    - .png
    - .svg
    - .gif
    - .jpeg
    - .jpg

development:
  <<: *default
  compile: true

  # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
  check_yarn_integrity: true

  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    https: false
    host: localhost
    port: 3035
    public: localhost:3035
    hmr: false
    # Inline should be set to true if using HMR
    inline: true
    overlay: true
    compress: true
    disable_host_check: true
    use_local_ip: false
    quiet: false
    pretty: false
    headers:
      'Access-Control-Allow-Origin': '*'
    watch_options:
      ignored: '**/node_modules/**'


test:
  <<: *default
  compile: true

  # Compile test packs to a separate directory
  public_output_path: packs-test

production:
  <<: *default

  # Production depends on precompilation of packs prior to booting for performance.
  compile: false

  # Extract and emit a css file
  extract_css: true

  # Cache manifest.json for performance
  cache_manifest: true

By default, it seems that you can control the settings separately for 3 types of environment: development, test, production.

Also, the default setting information is read in all environments.

default configuration is as follows:

source_pathThe source root path. (e.g. app/javascript = APP/app/javascript)
source_entry_pathThe entry point path. (e.g. packs = source_path/packs = APP/app/javascript/packs)
public_root_pathCompile output root path. (e.g. public = APP/public)
public_output_pathCompile output path. (e.g. packs = public_root_path/packs = APP/public/packs)
cache_pathcache file path to enhance recompilation times.
check_yarn_integritywebpacker runs a yarn integrity check to ensure that all local JavaScript packages are up-to-date.
webpack_compile_outputEnable to compile output.
resolved_pathsAdditional paths webpack should lookup modules.
cache_manifestReload manifest.json on all requests so we reload latest compiled packs.
extract_cssExtract and emit a css file.
static_assets_extensionswebpack should emit as separate files. it will result in webpack emitting a file of that name instead of loading it in memory as a JavaScript module.
extensionsThe extension list that webpack recognize.

Create a demo page

Create a controller and view for demo.

Terminal

$ rails generate controller Hello index
Running via Spring preloader in process 86718
      create  app/controllers/hello_controller.rb
       route  get 'hello/index'
      invoke  erb
      create    app/views/hello
      create    app/views/hello/index.html.erb
      invoke  test_unit
      create    test/controllers/hello_controller_test.rb
      invoke  helper
      create    app/helpers/hello_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    scss
      create      app/assets/stylesheets/hello.scss

Edit app/views/hello/index.html.erb later.

Set up entry point JS file, custom JS, CSS, Images

At first, create directories for JavaScript, CSS and iamges.

Terminal

$ cd app/javascript/
$ mkdir js css images

Edit the default entry point, packs/application.js file. This is for loading javascript, css and images to all pages.

packs/application.js

...
import '../js/application'
import '../css/application'
const images = require.context('../images', true)
...

This is set up js/application.js and css/application.[s]css and images directory to load.

About Javascript, create a common js for loading to all pages and the specific js for loading the specific view such as hello/index.html.erb.

- js/application.js: Common js for all pages.

- js/hello_world.js: Loaded by js/application.js.

- js/hello.js: Loaded by the specific view hello/index.html.erb.

js/application.js

import hello_world from './hello_world'
hello_world();

js/hello_world.js

export default () => {
    window.onload = () => {
        document.getElementsByTagName("H1")[0].innerText = 'Hello World';
    }
}

js/hello.js

console.log('hello');

About CSS, create a common css / scss for loading to all pages and the specific css / scss for loading the specific view such as hello/index.html.erb.

- css/application.scss: Common css / scss for all pages.

- css/style.css: Loaded by css/application.scss.

- css/hello.css: Loaded by the specific view hello/index.html.erb.

css/application.scss

@import 'style';

css/style.css

h1 {
    color: red;
}

css/hello.css

p {
    color: red;
}

About images, put them under images directory.

The file structure is as follows.

file structure

app/javascript
  /css
    /application.scss
    /hello.css
    /style.css
  /images
    /noknow_logo.png
  /js
    /application.js
    /hello.js
    /hello_world.js
  /packs
    /application.js
    /hello.js

Set up a view

The default layout would be views/layouts/application.html.erb. Set up such as JS, CSS to this file to load to all pages.

views/layouts/application.html.erb

...
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
...

Also, set the hello/index view to read js, css and images for loading only this page.

views/hello/index.html.erb

<%= javascript_pack_tag 'hello', 'data-turbolinks-track': 'reload' %>
<h1>Hello#index</h1>
<p>Find me in app/views/hello/index.html.erb</p>
<%= image_pack_tag 'noknow_logo.png' %>
Search by keywords

Select Language

/

Follow us by