skip to Main Content

I work on a Rails project, using Webpack to bundle the assets. Each time I make a change in JS or CSS, I run docker-compose exec web bundle exec rake assets:precompile; to compile all the assets.

After that, I have to restart the docker containers, and run the docker-compose exec web bundle exec npm run dev;

Only after that, I can see the change, and it can take up to 10 minutes. What am I missing? How can I speed up my development process?

My docker-compose.yml:

 version: '2'
services:
  chromedriver:
    image: selenium/standalone-chrome-debug
    volumes:
      # use hosts shared memory to prevent crashes
      # https://github.com/SeleniumHQ/docker-selenium
      - /dev/shm:/dev/shm



  postgres:
    image: postgis/postgis:12-3.0
    volumes:
      - ./bin/docker/postgres/init-test-db.sh:/docker-entrypoint-initdb.d/init-test-db.sh
      - .:/project
    logging:
      driver: "json-file"
      options:
        max-size: "10k"
        max-file: "1"

redis:
        image: redis:5.0.5
        logging:
          driver: "json-file"
          options:
            max-size: "10k"
            max-file: "1"
  worker:
    build: .
    volumes:
      - .:/usr/src/app
      - bundle-cache:/usr/local/bundle
    command: bundle exec sidekiq
    logging:
      driver: "json-file"
      options:
        max-size: "100k"
        max-file: "1"

  web:
    tty: true
    stdin_open: true
    build: .
    volumes:
      - .:/usr/src/app
      - bundle-cache:/usr/local/bundle
    logging:
      driver: "json-file"
      options:
        max-size: "10k"
        max-file: "1"

volumes:
  bundle-cache:

3

Answers


  1. When you are working with a docker-compose, it’s really useful to use volumes to also change files from your computer, and to start your compose with a docker-compose up.

    It looks weird to rebuild assets during a development stage. Is it not possible to bypass this step? I don’t know about Rails, but in python Django it’s possible to "collect the static" only for production.

    Login or Signup to reply.
  2. At the core, there’s an issue that’s unrelated to Docker: If your app is configured correctly, you shouldn’t need to manually compile your assets – ever! And even if you have to, 10 minutes sound like way too much.

    So the first thing you should do is make sure the following things:

    • Is your app running in the development environment (= does Rails.env return development)? If not, try setting RAILS_ENV=development – this can, for instance, be done in the environment setting in your docker-compose.yml (or alternatively in a .env.development file, if you’re using the dotenv-rails gem).
    • Is ad-hoc asset compilation enabled in the development environment? By default, this should be the case, but you might have accidentally/on purpose changed it. Check that config/environments/development.rb doesn’t contain config.assets.compile = false (or, generally, check Rails.application.config.assets.compile and potentially even the whole Rails.application.config.assets setting).
    • Last but not least, as mentioned above, 10 minutes seems like a very long time for asset compilation. I only remember having an asset compilation time this long once – and this was on a Rails 3 app with dozens of gems from rails-assets.org on a free Heroku instance (= super slow in general). So consider checking if you’re loading too much stuff and/or libraries that you don’t really need in the asset compilation step. One very common offender in my experience is the moment.js library which is extremely huge and is often only loaded for a very limited number of features, which can often be replaced by simpler libraries like date-fns or js-joda.

    I’m happy to investigate further and provide more insights, but I think for this you’d have to share more things (e.g. your Gemfile and environment configurations).

    As for Docker, when using the asset pipeline (or newer Rails versions’ webpack integration), I’d suggest to the compiled assets into volumes, so they’re effectively cached. This could be done like so:

    # in the `web` service:
    volumes:
      # for asset pipeline
      - assets:/usr/src/app/public/assets
      # for webpacker
      - packs:/usr/src/app/public/packs
      - packs-test:/usr/src/app/public/packs-test
    
    Login or Signup to reply.
  3. Since you have webpack, why not use webpack to compile?

    bundle exec rails webpacker:compile
    

    Also you can add speed-measure-webpack-plugin for your webpack to see details of time spend on complie

    In your config/webpack/development.js

    process.env.NODE_ENV = process.env.NODE_ENV || 'development'
    
    const environment = require('./environment')
    
    const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
    const smp = new SpeedMeasurePlugin()
    
    module.exports = smp.wrap(environment.toWebpackConfig())
    

    Last in your application.html.erb make sure to use
    <%= javascript_pack_tag 'application' %> to link the webpack compiled js

    Also you should look into webpack dev server with rails, so you don’t need to restart every time you make changes

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search