rails-erb-loader
A webpack loader that compiles embedded Ruby (.erb) templates into JavaScript for Rails projects.
Repository Health
Technical Analysis
rails-erb-loader is a webpack loader that lets Rails developers write Embedded Ruby (.erb) templates directly inside their JavaScript build pipeline. It spawns a Ruby process (by default bin/rails runner) for each matched file, feeding the source through the ERB, Erubis, or Erubi templating engines and piping the transformed output back into webpack.
This makes it possible to reference Ruby-side constants, model attributes, and other Rails application values from front-end JavaScript and JSX files without duplicating that data in a separate JSON payload or API endpoint, and to declare explicit file dependencies inline so webpack-dev-server rebuilds automatically whenever the referenced Ruby files change.
What You Get
- A webpack loader that matches
.erbfiles and pipes them through a Ruby subprocess for compilation - Support for three templating engines: ERB, Erubis, and Erubi, selected via the
engineoption - Automatic dependency tracking via
rails-erb-loader-dependenciescomments so webpack-dev-server rebuilds on referenced Ruby file changes - A configurable
runnercommand so it works withbin/rails runner, plainruby, or Spring-aware wrapper scripts - Optional
timeoutMsprotection that kills a hanging Ruby subprocess instead of letting builds hang indefinitely
Common Use Cases
- Referencing Rails model constants (e.g.
User::MAX_NAME_LENGTH) directly inside React/JSX form components - Sharing enum values or i18n strings defined in Ruby with front-end validation logic
- Building without a full Rails boot by pointing the
runneroption at plainruby - Auto-reloading webpack-dev-server when a referenced Ruby dependency file changes during development
Under The Hood
Architecture
index.js is the single entry point: it resolves loader options via loader-utils/lodash.defaults, extracts rails-erb-loader-dependencies comments with a regex to register file/directory watchers through webpack’s addDependency/addContextDependency, then spawns a Ruby child process (bin/rails runner by default, or a custom runner) that pipes the source through erb_transformer.rb over stdin/stdout using a unique delimiter string to strip stray output before returning the transformed source through webpack’s async loader callback; the JS and Ruby sides share an implicit contract on that delimiter and the exit-code/signal handling, which is the one piece that has to change in lockstep if the core transform pipeline is ever reworked.
Tech Stack
A CommonJS Node module targeting webpack’s peer-dependency range ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0, using loader-utils for option parsing and lodash.defaults for config merging, with child_process.spawn invoking Ruby and one of the ERB, Erubis, or Erubi gems depending on the engine option; devDependencies show Jest for testing, memory-fs for an in-memory webpack output filesystem in tests, and a neostandard/ESLint flat config for linting, with CI running a matrix across Node 24, Ruby 3.4/4.0, and webpack 2 through 5.
Code Quality
test.js is a comprehensive Jest suite that exercises every documented option (engines, custom runner, env, timeoutMs, dependency comments) end-to-end through real webpack compiles into an in-memory filesystem via compiler.js, backed by fixture files under test/erb and test/dependencies plus a stand-in test/runner script; error handling in index.js is explicit and deliberately distinguishes a normal non-zero exit, a timeout-triggered kill, and termination by signal into separate error messages, and guards against the webpack callback firing twice; there is no TypeScript or type annotations anywhere, and the code intentionally stays on older var-based JS style, but linting (neostandard, eslint-plugin-import-x, eslint-plugin-promise) and the lint step run separately from tests in CI.
What Makes It Unique
The standout ergonomic idea is the in-source /* rails-erb-loader-dependencies ... */ comment convention, which lets a .erb file declare its own file-system dependencies inline so webpack-dev-server hot-reloads correctly without a separate manifest file; combined with pluggable Ruby template engines and a swappable runner command for non-standard boot processes like Spring, it’s a thoughtful, low-friction design for a narrow integration problem rather than a novel technical breakthrough.