Migrate to Webpacker a Decidim module
Decidim modules are included to Decidim apps as gems. Since the introduction of Webpacker to manage and compile assets in Decidim, there are some changes required to make modules compatible with Decidim
Overview
The recommended way to import assets from a gem in a Rails app using Webpacker is to publish a package in npmjs.org and include it in the package.json via npm install
. Then the assets are available to Webpack via node_modules/ folder
Once created, you should update the instructions to install the module and add the step to add the assets with npm.
Folder migration
It is recommend to migrate to the new folders structure:
app/packs:
├── entrypoints
└── src
└── stylesheets
└── images
Update Rails helpers
javascript_include_tag
and stylesheet_link_tag
have been replaced by javascript_pack_tag
and stylesheet_pack_tag
For images, if they are in app/packs/images
you could use image_pack_tag
.
Asset compilation
As all assets are now compiled using Webpacker without ever loading the Rails or Decidim environment, there are some new conventions how to tell Webpacker about the Decidim module’s assets.
To begin with, create a new file named config/assets.rb
inside your Decidim module.
After this, add the following contents in that file, depending what kind of assets your module provides:
# frozen_string_literal: true
# This file is located at `config/assets.rb` of your module.
# Define the base path of your module. Please note that `Rails.root` may not be
# used because we are not inside the Rails environment when this file is loaded.
base_path = File.expand_path("..", __dir__)
# Register an additional load path for webpack. All the assets within these
# directories will be available for inclusion within the Decidim assets. For
# example, if you have `app/packs/src/decidim/foo.js`, you can include that file
# in your JavaScript entrypoints (or other JavaScript files within Decidim)
# using `import "src/decidim/foo"` after you have registered the additional path
# as follows.
Decidim::Webpacker.register_path("#{base_path}/app/packs")
# Register the entrypoints for your module. These entrypoints can be included
# within your application using `javascript_pack_tag` and if you include any
# SCSS files within the entrypoints, they become available for inclusion using
# `stylesheet_pack_tag`.
Decidim::Webpacker.register_entrypoints(
decidim_foo: "#{base_path}/app/packs/entrypoints/decidim_foo.js",
decidim_foo_admin: "#{base_path}/app/packs/entrypoints/decidim_foo_admin.js"
)
# If you want to import some extra SCSS files in the Decidim main SCSS file
# without adding any extra stylesheet inclusion tags, you can use the following
# method to register the stylesheet import for the main application.
Decidim::Webpacker.register_stylesheet_import("stylesheets/decidim/foo/app")
# If you want to do the same but include the SCSS file for the admin panel's
# main SCSS file, you can use the following method.
Decidim::Webpacker.register_stylesheet_import("stylesheets/decidim/foo/admin", group: :admin)
# If you want to override some SCSS variables/settings for Foundation from the
# module, you can add the following registered import.
Decidim::Webpacker.register_stylesheet_import("stylesheets/decidim/foo/settings", type: :settings)
# If you want to do the same but override the SCSS variables of the admin
# panel's styles, you can use the following method.
Decidim::Webpacker.register_stylesheet_import("stylesheets/decidim/foo/admin_settings", type: :settings, group: :admin)
Component stylesheet migration
In older Decidim versions your components could define their own stylesheet as follows:
Decidim.register_component(:your_component) do |component|
component.engine = Decidim::YourComponent::Engine
component.stylesheet = "decidim/your_component/your_component"
component.admin_stylesheet = "decidim/your_component/your_component_admin"
end
These were automatically included in the main application’s stylesheet file and also in the admin panel’s stylesheet file. These no longer work with Webpacker as the Decidim environment is not loaded when Webpacker compiles the assets.
What you should do instead is to follow the asset compilation migration guide above and migrate these definitions into your module’s config/assets.rb
file as follows:
# frozen_string_literal: true
# This file is located at `config/assets.rb` of your module.
base_path = File.expand_path("..", __dir__)
# Register the additional path for Webpacker in order to make the module's
# stylesheets available for inclusion.
Decidim::Webpacker.register_path("#{base_path}/app/packs")
# Register the main application's stylesheet include statement:
Decidim::Webpacker.register_stylesheet_import("stylesheets/decidim/your_component/your_component")
# Register the admin panel's stylesheet include statement:
Decidim::Webpacker.register_stylesheet_import("stylesheets/decidim/your_component/your_component_admin", group: :admin)
Help Decidim to know the module’s assets folder
To prevent Zeitwerk issues trying to autoload the non-ruby module folders, modify the lib/[module_name]/engine.rb
file to include the following:
---
initializer "[module_name].webpacker.assets_path" do
Decidim.register_assets_path File.expand_path("app/packs", root)
end
---