# Asset Bundling (Webpacker)
Introduction
Webpacker is a Rails wrapper around the webpack build system that provides a standard webpack configuration and reasonable defaults.
The goal of webpack, or any front-end build system, is to allow you to write your front-end code in a way that is convenient for developers and then package that code in a way that is convenient for browsers. With webpack, you can manage JavaScript, CSS, and static assets like images or fonts. Webpack will allow you to write your code, reference other code in your application, transform your code, and combine your code into easily downloadable packs.
Installation
Webpacker is available out-of-the-box in the newest version of Rails. Before creating a new project, ensure that the Node version is greater or equal to 10.17.0 as the
webpacker:install
command will be automatically invoked with rails new command.Webpacker File Structure
After the install command is executed, the following files are created:
config/webpacker.yml
— the main configuration file that contains the default configuration and configs for specific environmentsconfig/webpacker/
— the directory where the JavaScript configuration files for particular environments are createdbin/webpack
— an executable file that invokes webpack to create bundlesbin/webpack-dev-server
— an executable file that starts the development server, which reloads webpack every time you make a change inside the JavaScript files included in the bundle
The Anatomy of the Configuration File
The main configuration file for Webpacker is located under the config directory, and it’s named
webpacker.yml
. Unlike Webpacker, configuration for Webpack is stored separately for each environment under the **config/webpack
**directory.Webpacker
By default, the configuration file contains many entries — default ones, and sections for each environment where you can overwrite specific settings. Let’s take a look at the most important settings:
source_path
— the primary source of javascript files in your application. It’s set toapp/javascript
by default, and usually, there's no need to change this value.source_entry_path
— the name of the directory under the source_path where you keep the pack files, aka entry points. By default, this setting is set to the packs’ directory.public_root_path
— path to the directory in your application that is accessible from a browser. In a typical Rails application, it’s a public directorypublic_output_path
— when Webpacker compiles your files, it will put all compiled files in this directory under thepublic_root_path
. By default, the directory is named packs, but you can call it whatever you want.webpack_compile_output
— if the flag is set to true, then output messages are displayed when files are compiled. It’s useful when compilation fails, as you'll be aware of that and can take action.
It is worth mentioning that the development section also contains configuration for the dev server that is used to compile files in the development environment without the need for restarting the server.
If you would like to access the configuration from the rails console or code level, you can call
Webpacker.manifest.config
, which will return the configuration class instance.Webpack
Each environment has its configuration file, but in every file, the main environment file is imported:
config/webpack/environment.js
. In the environment configuration file, there is a place for loading custom plugins that will modify the default behavior of Webpack. We can also add custom rules for compiling our files.The Anatomy of the Pack File
Packs are located under the **
app/javascript/packs
**directory. Each pack file is treated by Webpacker as an entry point when the compilation process starts.The Default Pack File
When you generate a new Rails project, a default pack file named application.js is created with the following content:
import Rails from "@rails/ujs"; import Turbolinks from "turbolinks"; import * as ActiveStorage from "@rails/activestorage"; import "channels"; Rails.start(); Turbolinks.start(); ActiveStorage.start();
1
2
3
4
5
6
7
8As you can see, the first step is to import the given library and then call its initialization method when it’s needed. When you call import, the system searches for a given node module or a local library. With the standard approach, you don’t have to explicitly initialize the library as it’s initialized when you include it in the page source with the script tag.
Including Pack Files in the Application
Pack files are not automatically included in the website’s source. Just like in the asset pipeline case, we have to use a special tag inside our views:
<%= javascript_packs_with_chunks_tag 'application' %>
1How does this method work? Under the hood, it calls the Webpacker configuration that holds the data you put in the **
config/webpacker.yml
**file. It looks for an application.js file inside the entry points directory, which, in our case, isapp/javascript/packs
. You can verify it by calling the following code:Webpacker.manifest.config.source_entry_path
1When entries are found, Webpacker calls **
javascript_include_tag
**method, a helper from theActionView
library available by default in Rails. The method accepts one or more sources and returns script tags that you can apply straight to your view.The Development Server
Webpacker development server’s entry point is the executable file placed inside the
bin
folder and namedwebpack-dev-server
. The process of running the server consists of five steps:- Setting environment — the environment name for Node and Rails is set. When the environment is not specified, the program assumes that the server will be executed in the development environment.
- Loading configuration — the file
config/webpacker.yml
is loaded with settings for the environment set in the previous step. - Validating command options — the program checks if we passed appropriate options to the server command. For example, it will throw an error when the
-https
option is given, but we didn’t specify it in theconfig/webpacker.yml
file. - Verifying port’s availability — the program checks if the given port is available to use. If another program is already using it, it will throw an error letting you know that you have to update the webpack server configuration inside the
config/webpacker.yml
file. - Executing webpack serve command — when the node modules directory exists, the program executes the command within the directory, otherwise, it executes it with yarn. The program passes the configuration option to the command that points to one of the files placed inside the
config/webpack/
directory.
The server is now running, and it compiles your code on the fly, so you don’t have to restart the server to see the changes and check if webpack was able to create the bundle with the new code.
The development server’s code is quite simple. It only loads the config from the configuration file in YAML format and passes the proper config in JavaScript format directly to the
webpack serve
command. You can also run it by hand, but you don’t have to take care of proper command arguments with the built-in command.Compiling Files for the Production Environment
Suppose you want to deploy the application that's using webpacker. In that case, you can simply invoke the
assets:precompile
task as Webpacker automatically hooks up the taskwebpacker:compile
to it.How does the
webpacker:compile
task work under the hood? Let’s dig into it and see. It does the following things:- It wraps the main call into two blocks ensuring that the **
NODE
**environment is set and Webpacker logs are output to the standard out. - It calls Webpack and then parses its logs to determine if the action was successful or not.
You can now visit the
public/packs/js
directory to see the compiled files. They should be deployed to the server.- It wraps the main call into two blocks ensuring that the **