Webpacker Documentation

repository·master·Indexed 26 days ago

https://github.com/rails/webpacker

A retired bridge for compiled and bundled JavaScript in Rails using webpack. This documentation covers version 6.0.0-rc.6, including Babel configuration for React, deployment to Heroku and Nginx, Capistrano integration, and troubleshooting guides. It also provides migration paths to jsbundling-rails, importmap-rails, or the community-driven Shakapacker.

Tokens
7.6K
Snippets
25
Records
53
Agent score
90%

What's inside Webpacker

  1. Migrate from Webpacker to jsbundling-rails

    master
    If you are currently using Webpacker, the recommended migration path is to switch to jsbundling-rails using Webpack (or another bundler). You can follow the official switching guide provided by the jsbundling-rails repository to transition your application.
  2. Enable Brotli compression in Nginx

    master

    To serve precompressed Brotli files (.br) in Nginx, you must install the ngx_brotli module. Once installed, load the static module in your nginx.conf file:

    load_module modules/ngx_http_brotli_static_module.so;

    Then, enable it in your site configuration using brotli_static on; within the assets/packs location block.

  3. Deploy Webpacker to Heroku

    master

    To run a Webpacker app on Heroku, you must add both the Node.js and Ruby buildpacks. This ensures that npm or yarn executables are available to compile your assets during the deployment process.

    Follow these steps:

    1. Create your Heroku app.
    2. Add your database (e.g., Heroku Postgres).
    3. Add the heroku/nodejs buildpack.
    4. Add the heroku/ruby buildpack.
    5. Push your code to Heroku.
    heroku create my-webpacker-heroku-app
    heroku addons:create heroku-postgresql:hobby-dev
    heroku buildpacks:add heroku/nodejs
    heroku buildpacks:add heroku/ruby
    git push heroku master
  4. Debug your Webpack configuration

    master

    To debug your Webpack configuration, you can use the following methods:

    1. Read error messages: They typically identify the precise key/value pair that does not match Webpack's expected schema.
    2. Use a debugger: Insert a debugger statement in your Webpack configuration and run bin/webpacker --debug-webpacker. You can use the Chrome debugger by navigating to chrome://inspect or using the NiM extension.
    3. Pass arguments to bin/webpacker: Any arguments passed to bin/webpacker are forwarded to Webpack. For example, use --debug to switch loaders to debug mode.
    4. Debug webpack-dev-server: You can pass additional options to start the dev server with debugging enabled using bin/webpacker --debug-webpacker.
    bin/webpacker --debug-webpacker
  5. Use CDN with Webpacker

    master
    Webpacker supports CDNs out-of-the-box using the standard Rails config.action_controller.asset_host setting. If your Rails application is already configured to use a CDN via this setting, Webpacker will automatically use it without additional configuration.
  6. Configure Nginx to serve Webpacker assets

    master

    Webpacker does not serve files in production; you must configure your web server (like Nginx) to serve files directly from the public/ directory.

    To optimize performance, you can use gzip_static to serve precompressed .gz files and brotli_static to serve .br files. Ensure your Nginx configuration includes a location block for assets and packs that sets appropriate cache headers and enables static compression.

    upstream app {
      # server unix:///path/to/app/tmp/puma.sock;
    }
    
    server {
      listen 80;
      server_name www.example.com;
      root /path/to/app/public;
    
      location @app {
        proxy_pass http://app;
        proxy_redirect off;
    
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
      }
    
      location / {
        try_files $uri @app;
      }
    
      location = /favicon.ico { access_log off; log_not_found off; }
      location = /robots.txt  { access_log off; log_not_found off; }
    
      location ~ /\.(?!well-known).* {
        deny all;
      }
    
      location ~ ^/(assets|packs)/ {
        gzip_static on;
        brotli_static on; # Optional
        expires max;
        add_header Cache-Control public;
      }
    }
  7. Configure Capistrano for Webpacker assets

    master

    To prevent assets from recompiling on every deployment when files haven't changed, add public/packs and node_modules to your :linked_dirs in Capistrano.

    If you add node_modules to :linked_dirs, you must ensure yarn install runs before deploy:assets:precompile by adding a custom task to your deploy.rb.

    # In deploy.rb
    append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/packs", ".bundle", "node_modules"
    
    before "deploy:assets:precompile", "deploy:yarn_install"
    
    namespace :deploy do
      desc "Run rake yarn install"
      task :yarn_install do
        on roles(:web) do
          within release_path do
            execute("cd #{release_path} && yarn install --silent --no-progress --no-audit --no-optional")
          end
        end
      end
    end
  8. Silence Angular critical dependency warnings

    master

    To silence Angular-related critical dependency warnings in Webpack, update your config/webpack/base.js to include a ContextReplacementPlugin.

    const webpack = require('webpack')
    const { resolve } = require('path')
    const { webpackConfig, merge } = require('@rails/webpacker')
    
    module.exports = merge(webpackConfig, {
      plugins: [
        new webpack.ContextReplacementPlugin(
          /angular(\\|\/)core(\\|\/)(@angular|esm5)/,
          resolve(config.source_path)
        )
      ]
    })
  9. Configure Babel for React usage

    master

    To use React with Webpacker, you must install the necessary dependencies and configure babel.config.js to include @babel/preset-react and optional plugins like react-refresh for development.

    1. Install dependencies:
    yarn add react react-dom @babel/preset-react
    yarn add --dev @pmmmwh/react-refresh-webpack-plugin react-refresh
    1. Configure babel.config.js to merge the React preset and development plugins into the Webpacker default config.
    // babel.config.js
    module.exports = function (api) {
      const defaultConfigFunc = require('@rails/webpacker/package/babel/preset.js')
      const resultConfig = defaultConfigFunc(api)
      const isProductionEnv = api.env('production')
    
      const changesOnDefault = {
        presets: [
          [
            '@babel/preset-react',
            {
              development: isDevelopmentEnv || isTestEnv,
              useBuiltIns: true
            } 
          ],
          isProductionEnv && ['babel-plugin-transform-react-remove-prop-types', 
            { 
              removeImport: true 
            }
          ]
        ].filter(Boolean),
        plugins: [
          process.env.WEBPACK_SERVE && 'react-refresh/babel'
        ].filter(Boolean),
      }
    
      resultConfig.presets = [...resultConfig.presets, ...changesOnDefault.presets]
      resultConfig.plugins = [...resultConfig.plugins, ...changesOnDefault.plugins ]
    
      return resultConfig
    }
  10. Use Shakapacker for continued Webpacker-like development

    master
    If you require continued evolution of the Webpacker pattern (including features like hot-module reloading), use Shakapacker. Shakapacker is a community-driven gem based on the unreleased v6 work from this repository and is intended to replace the official Webpacker for active development.
  11. Migrate from Webpacker to Import Maps

    master
    For a more modern Rails 7 approach, you can migrate from Webpacker to importmap-rails. This is the default setup for new Rails 7 applications, though the complexity of the migration depends on your specific JavaScript requirements.
  12. Use Webpack ProvidePlugin for global dependencies

    master

    Instead of manually assigning dependencies to the window object (e.g., window.jQuery = jQuery), use Webpack's ProvidePlugin in config/webpack/base.js. This manages build-time dependencies to global symbols automatically.

    // config/webpack/base.js
    
    const webpack = require('webpack')
    const { webpackConfig, merge } = require('@rails/webpacker')
    
    module.exports = merge(webpackConfig, {
      plugins: [
        new webpack.ProvidePlugin({
          $: 'jquery',
          jQuery: 'jquery',
        })
      ],
    })