Shakapacker

repository·main·Indexed 19 days ago

https://github.com/shakacode/shakapacker

A manifest-backed bridge for Ruby on Rails applications to use modern JavaScript bundlers like webpack 5 or Rspack. It provides Rails-native view helpers, installer tasks, and configuration conventions to manage complex frontend asset pipelines. Version 10.3.1 includes managed build paths via shakapacker-webpack and shakapacker-rspack, support for transpilers like SWC, Babel, and esbuild, and a dedicated TypeScript type system exported from shakapacker/types.

Tokens
98.6K
Snippets
319
Records
453
Agent score
66%

What's inside shakapacker

  1. Overview of Shakapacker features and capabilities

    main

    Shakapacker is the successor to rails/webpacker, providing a manifest-backed bridge between Rails and modern bundlers like webpack 5 or Rspack.

    Key Features:

    • Bundler Support: First-class support for Rspack (up to 17x faster than webpack), webpack 5, and managed bundler stacks via shakapacker-webpack or shakapacker-rspack (v10.1+).
    • Transpilation: Supports JavaScript/TypeScript via SWC, Babel, or esbuild.
    • Rails Integration: Native manifest integration and view helpers for bundled assets.
    • Modern Web Dev: Support for Code splitting, HMR (Hot Module Replacement), CDN asset hosts, Subresource Integrity (SRI), and HTTP 103 Early Hints.
    • Package Managers: Compatible with npm, Yarn, pnpm, and Bun.
    • Optional Integrations: Extra packages are available for React, TypeScript, Sass, Less, Stylus, CSS, PostCSS, and CoffeeScript.
  2. Compare Rails JavaScript bundling approaches

    main

    Choosing a JavaScript strategy for Rails depends on your frontend complexity. Use the following comparison to decide which tool fits your application needs:

    ApproachWhat it doesBuild stepRails integration
    importmap-railsServes JS as native ES modules via HTTP/2NoneAsset pipeline (Propshaft/Sprockets)
    jsbundling-railsThin wrapper running esbuild/rollup/webpack via package.json scriptsYes (bring your own)Asset pipeline fingerprints output
    vite-railsIntegrates Vite (ESM dev server + Rollup prod build)Yes (Vite)Vite manifest + view helpers
    ShakapackerManifest-backed bridge to webpack 5 or RspackYes (webpack/Rspack)Native manifest + view helpers
  3. Understand CSS Modules Export Modes (v8 vs v10)

    main

    Shakapacker has two primary modes for handling CSS Modules. Version 10 defaults to Named Exports, while version 8 and earlier used Default Exports.

    Featurev8 (and earlier)v10+ (Current Default)
    Default behaviorDefault export objectNamed exports
    Import syntaximport styles from '...'import { className } from '...'
    Class referencestyles.classNameclassName
    Export conventionasIs (no transformation)camelCaseOnly
    TypeScript warningsMay show warningsNo warnings
    Tree-shakingLimitedOptimized

    When to use Named Exports (v10):

    • To eliminate webpack/TypeScript warnings about missing exports.
    • To enable better tree-shaking (unused CSS class exports can be eliminated).
    • To benefit from explicit dependencies and type safety.

    When to use Default Exports (v8):

    • If you have a large legacy codebase and want to avoid updating all import statements.
    • If you prefer the namespace import pattern where all classes are available under one object.
  4. Triage categories for PR review comments

    main

    When using the Address Review Prompt, the assistant categorizes fetched GitHub comments into three distinct groups to help you manage the review process:

    • MUST-FIX: High-priority items including correctness bugs, regressions, security issues, missing tests that could hide bugs, and clear inconsistencies with adjacent code that would block a merge.
    • DISCUSS: Items that require a decision, such as reasonable scope-expanding suggestions or architectural opinions.
    • SKIPPED: Low-priority or non-actionable items like style preferences, documentation nits, speculative suggestions, or duplicate comments.

    The assistant will present a summary of these counts and wait for your selection before proceeding to any code modifications.

  5. How NODE_ENV default behavior works in v9

    main

    In Shakapacker v9, NODE_ENV now intelligently defaults based on your RAILS_ENV. This ensures the development server correctly loads development configurations and uses the configured port instead of defaulting to 8080.

    Default Mapping:

    • RAILS_ENV=production $\rightarrow$ NODE_ENV defaults to "production"
    • RAILS_ENV=development or RAILS_ENV=test $\rightarrow$ NODE_ENV defaults to "development"
    • RAILS_ENV is unset or custom (e.g., staging) $\rightarrow$ NODE_ENV defaults to "production"

    Cleanup: If you previously used workarounds to force development mode, you can now remove NODE_ENV=development from:

    • .env, .env.development, or .env.local files
    • docker-compose.yml or Dockerfile
    • Custom scripts or bin/dev / Procfile.dev
  6. Configure the package manager via package.json

    main

    Shakapacker v8 uses the packageManager property in your package.json to determine which JavaScript package manager to use. This is powered by the package_json gem.

    If this property is missing, npm will be used by default. To ensure consistent behavior and avoid errors (especially when a lockfile other than package-lock.json is present), explicitly set the packageManager field. For example, if using Yarn, set it to yarn@<version>.

    Note: The rake task check_yarn has been renamed to check_manager.

  7. Understand Early Hints configuration precedence

    main

    When determining which Early Hints to send, Shakapacker applies settings in the following order (later settings override earlier ones):

    1. Global Configuration: Defined in shakapacker.yml.
    2. Controller Class Configuration: Defined via configure_pack_early_hints at the class level.
    3. Manual/Dynamic Configuration: Explicit calls to configure_pack_early_hints within an action or via manual API calls.

    Within a single configuration call, the all: key is applied first, and then specific css: or js: keys will override those values.

  8. Architecture requirements for HTTP 103 Early Hints

    main

    To use HTTP 103 Early Hints in production, you must use a proxy architecture because Puma only supports HTTP/1.1 for Early Hints. The proxy handles HTTP/2 for external clients and translates requests to HTTP/1.1 for Puma.

    Required Components:

    • Puma 5+: Must be started with the --early-hints flag.
    • HTTP/2-capable Proxy: The proxy must support translating 103 responses back to HTTP/2.
      • Supported: Thruster, nginx, Cloudflare.
      • Not Supported: Control Plane, AWS ALB.
    • Rails 5.2+

    Browser Behavior Note: Browsers only process the first HTTP/1.1 103 response. Shakapacker sends a single 103 response containing all combined hints (JS and CSS).

  9. Understand the Shakapacker package split (v11+)

    main

    Starting with v11, Shakapacker has moved from a single package to a three-package architecture to solve the problem of conditional peer dependencies. This prevents bloating installs for users who don't need specific bundlers.

    1. shakapacker (Core)

    This is the base package. It handles:

    • Config loading (shakapacker.yml)
    • Manifest reading and asset lookup
    • Dev server proxy client
    • CLI entry points (shakapacker, shakapacker-dev-server)
    • View helper support for Ruby
    • Shared utilities (webpack-merge, etc.)

    2. shakapacker-webpack (Managed Webpack)

    A supplemental package for the standard Webpack experience. It includes shakapacker and terser-webpack-plugin as direct dependencies and requires a specific 'singleton' stack of Webpack peer dependencies.

    3. shapacker-rspack (Managed Rspack)

    A supplemental package for the Rspack experience. It includes shakapacker as a direct dependency and requires the Rspack singleton stack as peer dependencies.

  10. Compare style-loader vs mini-css-extract-plugin for CSS delivery

    main

    When deciding how to serve CSS in development, consider the following trade-offs:

    style-loader (Default)

    Injects CSS into <style> tags using JavaScript.

    Benefits:

    • No Flash of Unstyled Content (FOUC) on HMR refreshes.
    • Smaller and faster incremental updates during development.

    Drawbacks:

    • Increases JavaScript bundle size.
    • Requires JavaScript execution before CSS is applied.
    • Can cause FOUC on the initial page load.
    • Delivery mechanism differs from production.

    mini-css-extract-plugin

    Serves CSS as a standalone file via <link rel="stylesheet"> tags.

    Benefits:

    • Matches production behavior, reducing the risk of deployment surprises (e.g., forgetting stylesheet_pack_tag).
    • No FOUC on initial page loads.
    • Simplifies configuration by eliminating the need for style-loader.

    Drawbacks:

    • Requires a separate HTTP request.
    • Potential for FOUC during HMR refreshes.
    • More data transferred per refresh (full stylesheet reload instead of incremental patches), though this is typically negligible in local development.
  11. Security constraints for precompile hooks

    main

    To prevent security vulnerabilities, Shakapacker enforces several restrictions on the precompile_hook path:

    • Project Root Restriction: The hook must reference a script located within your project root. Paths like /usr/bin/malicious-script or ../../../etc/passwd are rejected.
    • Symlink Resolution: Shakapacker resolves symlinks to their real paths before validation to ensure they do not point to files outside the project.
    • Path Traversal Protection: Attempts to use .. to escape the project directory are blocked.
    • Boundary Checking: The system uses proper path boundary checking (via File::SEPARATOR) to prevent partial path match exploits.
  12. Use the Shakapacker main module for singleton access

    main

    The Shakapacker module provides singleton-style access to the core functionality of the library, including configuration, compilation, manifest lookup, dev server status, and environment management. Most common tasks can be performed directly through this module.

    # Access configuration
    Shakapacker.config
    
    # Compile assets
    Shakapacker.compile
    
    # Look up assets in manifest
    Shakapacker.manifest.lookup("application.js")
    
    # Check dev server status
    Shakapacker.dev_server.running?
    
    # Manage environment
    Shakapacker.env