简体   繁体   中英

Rails 7 and importmaps: What will happen on production with my javascript that is split into many files?

I'm in the process of upgrading a heroku hosted website from Rails 5 to Rails 7. I was using webpacker, but since it's deprecated, I decided to switch to using importmaps. My site has a lot of javascript, mainly for a bunch of games/toys/experiments. The javascript is very object oriented. Each game/toy/experiment uses a lot of classes, many of them quite small, and every class is in its own file, using es6 style imports: "import Something from './something'".

Before the upgrade, some combination of shims, transpiling, and asset precompiling would turn these many files into just a few files, on both production and development servers. I definitely don't remember which tools were doing what, and hopefully I won't have to, but here is my Gemfile before the upgrade:

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.6'

gem 'rails', '~> 5.2.2'
# Use Puma as the app server
gem 'puma', '~> 4.3' #'~> 3.11'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'mini_racer', platforms: :ruby

# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
gem 'redis', '~> 4.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '>= 3.0.5', '< 3.2'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of chromedriver to run system tests with Chrome
  gem 'chromedriver-helper'
end



### Added manually


## Interface

# Style Defaults - Makes everything look good by default.
# Structure - Makes it easier to do almost everything you're going to do with the interface.
gem 'bootstrap'

# Templates - Makes templates easier to read and write.
gem 'haml'

# Forms - Makes forms not almost completely infuriating.
gem 'simple_form'

# Email
gem 'mailgun-ruby', '~>1.1.6'


## Database

# Postgres, which is good for text searching
gem 'pg'

# Bulk database insert
gem 'bulk_insert'

# Search (postgres specific)
gem 'textacular', '~> 5.0'


## Storage

# AWS S3 - For storage and retrieval of a lot of data cheaply.
gem 'aws-sdk-rails'
gem 'aws-sdk-s3'


## Javascript

# ES6 - Turns ES6 it into something that will work with all browsers.
gem "babel-transpiler"

# DOM - Makes the DOM much easier to deal with.
gem "jquery-rails"

# Modules - Allows use of separate files as modules and other things I can't remember
gem 'webpacker'


## Payments
# Stripe: Makes payments possible.
gem 'stripe', :git => 'https://github.com/stripe/stripe-ruby'


## Accounts
# Third Party Sign-In
gem 'omniauth-google-oauth2'
gem 'omniauth-facebook'

And here are the few changes to it after upgrading:

# CHANGED: Upgraded from 2.6.6 to 3.1.2 to upgrade from heroku-18 to heroku-22.
ruby '3.1.2'

# CHANGED: Upgraded from 5.2.2 to 7.0.4 to upgrade from heroku-18 to heroku-22.
gem 'rails', '~> 7.0.4'

# removed these:
# gem 'mini_racer', platforms: :ruby
# gem 'bcrypt', '~> 3.1.7'
# gem 'mini_magick', '~> 4.8'
# gem 'capistrano-rails', group: development

...

gem 'bootstrap', '~> 5.2.1' # added version

Now I understand the following:

  • importmaps will load up all the libraries that aren't mine from CDN's, and it will load them separately, and it seems like it will do this fine. I know this because I actually upgraded another website before this (but it had less of it's own javascript).

  • It will load my javascript somehow. Most of it will probably work if I deploy it right now, but...

In development, something unexpected is happening, which is that every single little javascript file that I have for each of these classes is getting loaded separately, and it's annoyingly slow. I knew that it would load the "top-level" sort of entry point modules separately, but I thought that the modules imported by modules would end up wrapped up somehow. So now I have two questions:

  1. Will all these files load separately on production? (Or will they somehow load separately but in a way that is fast?) On the page that I'm currently looking at there are over 30 of my javascript files loading.

  2. (bonus-ish) Can I make the loading process better on development? It's tolerable for now, and I really need to get the upgrade done for production more than I need to make development more pleasant to deal with, but it would be nice to make development load faster as well. One nice thing about it is that if it loads fast on development I can at least be a little more confident that it will be ok on production.

  1. Will all these files load separately on production?

Yes, the idea is to use importmaps together with HTTP2 / HTTP3 / QUIC that have pipelining which removes penalty of creating connections for every file – multiple files is not an issue anymore for HTTP2+ – vice-versa – compiled big files and image sprites are bad now.

  1. Can I make the loading process better on development?

In development files are loading through HTTP1.1, unfortunately, I don't know solutions for this for now. Although there is one cool thing if Stimulus is used – lazy controllers loading , you can make so that if you are viewing page of one of your game/toy/experiment then javascript files for that particular experiment are loaded but not for others.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM