記事を書いた経緯
自分自身がお仕事でbootstrap5の導入とesbuildを使ったwebアプリ開発に携わった中で最短で環境構する方法が知りたかったから。
本記事のゴール
bootstrap+esbuildで環境構築して、簡単なrailsのtodoアプリを作成する。アプリ自体はgenerateorでscaffoldを作成した際にできたデフォルトのもの。
esbuildってそもそも何?
esbuild(イーエスビルド)は、javascriptのいわゆるバンドラーと呼ばれる役割のもので、同じような役割をするものにimportmapやrollupがあります。筆者はimportmapとesbuildのみ使ったことがあります。ちなみに、javascriptのバンドラーはrails newの時に指定することができるので現在すでに動いているアプリの環境を移行したいとかでなければnew時に指定することをおすすめします。ちなみに、バンドラーはcss用とjavascript用の2種類あるので両方サポートしているimportmapやwebpackなどを使わない場合にはcssbundling-railsというgemでcssのバンドラーも指定してあげる必要があります。
動作環境の前提
環境構築時には、homebrewをはじめとしたmacOSでのrailsの環境構築がされている前提とします。最低限、anyenv>rbenv>npm>yarn はインストールしておいてください(>の順で環境構築するとうまく行くと思います→念の為パッケージ管理ツールのドキュメントは読んでおくことをおすすめします)。
実際にやってみる
- rails newして新規プロジェクトを立ち上げる(cssをbootstrapで指定する)
rails new Myapp --css bootstrap
create
create README.md
create Rakefile
create .ruby-version
create config.ru
create .gitignore
create .gitattributes
create Gemfile
run git init from "."
Initialized empty Git repository in /Users/kumagaikouhei/Documents/rails_practice/Myapp/.git/
create app
create app/assets/config/manifest.js
create app/assets/stylesheets/application.css
create app/channels/application_cable/channel.rb
create app/channels/application_cable/connection.rb
create app/controllers/application_controller.rb
create app/helpers/application_helper.rb
create app/jobs/application_job.rb
create app/mailers/application_mailer.rb
create app/models/application_record.rb
create app/views/layouts/application.html.erb
create app/views/layouts/mailer.html.erb
create app/views/layouts/mailer.text.erb
create app/assets/images
create app/assets/images/.keep
create app/controllers/concerns/.keep
create app/models/concerns/.keep
create bin
create bin/rails
create bin/rake
create bin/setup
create config
create config/routes.rb
create config/application.rb
create config/environment.rb
create config/cable.yml
create config/puma.rb
create config/storage.yml
create config/environments
create config/environments/development.rb
create config/environments/production.rb
create config/environments/test.rb
create config/initializers
create config/initializers/assets.rb
create config/initializers/content_security_policy.rb
create config/initializers/cors.rb
create config/initializers/filter_parameter_logging.rb
create config/initializers/inflections.rb
create config/initializers/new_framework_defaults_7_0.rb
create config/initializers/permissions_policy.rb
create config/locales
create config/locales/en.yml
create config/master.key
append .gitignore
create config/boot.rb
create config/database.yml
create db
create db/seeds.rb
create lib
create lib/tasks
create lib/tasks/.keep
create lib/assets
create lib/assets/.keep
create log
create log/.keep
create public
create public/404.html
create public/422.html
create public/500.html
create public/apple-touch-icon-precomposed.png
create public/apple-touch-icon.png
create public/favicon.ico
create public/robots.txt
create tmp
create tmp/.keep
create tmp/pids
create tmp/pids/.keep
create tmp/cache
create tmp/cache/assets
create vendor
create vendor/.keep
create test/fixtures/files
create test/fixtures/files/.keep
create test/controllers
create test/controllers/.keep
create test/mailers
create test/mailers/.keep
create test/models
create test/models/.keep
create test/helpers
create test/helpers/.keep
create test/integration
create test/integration/.keep
create test/channels/application_cable/connection_test.rb
create test/test_helper.rb
create test/system
create test/system/.keep
create test/application_system_test_case.rb
create storage
create storage/.keep
create tmp/storage
create tmp/storage/.keep
remove config/initializers/cors.rb
remove config/initializers/new_framework_defaults_7_0.rb
run bundle install
Fetching gem metadata from https://rubygems.org/...........
Resolving dependencies...
Using rake 13.0.6
Fetching concurrent-ruby 1.2.2
Fetching minitest 5.18.0
Using builder 3.2.4
Using erubi 1.12.0
Using websocket-extensions 0.1.5
Fetching rack 2.2.7
Using marcel 1.0.2
Using crass 1.0.6
Fetching nio4r 2.5.9
Fetching timeout 0.3.2
Using mini_mime 1.1.2
Using date 3.3.3
Using racc 1.6.2
Using public_suffix 5.0.1
Using bindex 0.8.1
Using bundler 2.3.14
Fetching regexp_parser 2.8.0
Fetching msgpack 1.7.0
Using matrix 0.4.2
Using method_source 1.0.0
Using thor 1.2.1
Fetching zeitwerk 2.6.7
Installing minitest 5.18.0
Installing concurrent-ruby 1.2.2
Installing nio4r 2.5.9 with native extensions
Installing zeitwerk 2.6.7
Installing msgpack 1.7.0 with native extensions
Installing regexp_parser 2.8.0
Installing rack 2.2.7
Installing timeout 0.3.2
Using io-console 0.6.0
Using rexml 3.2.5
Using rubyzip 2.3.2
Using websocket 1.2.9
Fetching sqlite3 1.6.2 (arm64-darwin)
Using websocket-driver 0.7.5
Fetching nokogiri 1.14.3 (arm64-darwin)
Fetching addressable 2.8.4
Fetching reline 0.3.3
Fetching selenium-webdriver 4.9.0
Installing addressable 2.8.4
Using net-protocol 0.2.1
Fetching rack-test 2.1.0
Using i18n 1.12.0
Using tzinfo 2.0.6
Using sprockets 4.2.0
Using net-imap 0.3.4
Using net-pop 0.1.2
Using net-smtp 0.3.3
Fetching activesupport 7.0.4.3
Installing reline 0.3.3
Fetching mail 2.8.1
Installing rack-test 2.1.0
Fetching irb 1.6.4
Installing sqlite3 1.6.2 (arm64-darwin)
Installing activesupport 7.0.4.3
Installing irb 1.6.4
Fetching debug 1.7.2
Installing nokogiri 1.14.3 (arm64-darwin)
Using globalid 1.1.0
Fetching activemodel 7.0.4.3
Installing debug 1.7.2 with native extensions
Installing activemodel 7.0.4.3
Installing selenium-webdriver 4.9.0
Fetching activejob 7.0.4.3
Installing activejob 7.0.4.3
Installing mail 2.8.1
Fetching activerecord 7.0.4.3
Installing activerecord 7.0.4.3
Using rails-dom-testing 2.0.3
Using xpath 3.2.0
Fetching loofah 2.20.0
Fetching capybara 3.39.0
Fetching webdrivers 5.2.0
Installing loofah 2.20.0
Using rails-html-sanitizer 1.5.0
Fetching actionview 7.0.4.3
Installing webdrivers 5.2.0
Installing capybara 3.39.0
Installing actionview 7.0.4.3
Fetching actionpack 7.0.4.3
Using jbuilder 2.11.5
Fetching puma 5.6.5
Installing actionpack 7.0.4.3
Installing puma 5.6.5 with native extensions
Using sprockets-rails 3.4.2
Fetching actionmailer 7.0.4.3
Fetching actioncable 7.0.4.3
Fetching activestorage 7.0.4.3
Fetching railties 7.0.4.3
Installing actionmailer 7.0.4.3
Installing activestorage 7.0.4.3
Installing actioncable 7.0.4.3
Installing railties 7.0.4.3
Fetching actionmailbox 7.0.4.3
Fetching actiontext 7.0.4.3
Fetching bootsnap 1.16.0
Installing actionmailbox 7.0.4.3
Installing bootsnap 1.16.0 with native extensions
Fetching cssbundling-rails 1.1.2
Fetching stimulus-rails 1.2.1
Fetching turbo-rails 1.4.0
Using web-console 4.2.0
Fetching jsbundling-rails 1.1.1
Installing actiontext 7.0.4.3
Fetching rails 7.0.4.3
Installing cssbundling-rails 1.1.2
Installing stimulus-rails 1.2.1
Installing jsbundling-rails 1.1.1
Installing turbo-rails 1.4.0
Installing rails 7.0.4.3
Bundle complete! 16 Gemfile dependencies, 73 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
run bundle binstubs bundler
rails javascript:install:esbuild
Compile into app/assets/builds
create app/assets/builds
create app/assets/builds/.keep
append app/assets/config/manifest.js
append .gitignore
append .gitignore
Add JavaScript include tag in application layout
insert app/views/layouts/application.html.erb
Create default entrypoint in app/javascript/application.js
create app/javascript
create app/javascript/application.js
Add default package.json
create package.json
Add default Procfile.dev
create Procfile.dev
Ensure foreman is installed
run gem install foreman from "."
Fetching foreman-0.87.2.gem
Successfully installed foreman-0.87.2
1 gem installed
Add bin/dev to start foreman
create bin/dev
Install esbuild
run yarn add esbuild from "."
yarn add v1.22.19
info No lockfile found.
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
success Saved 2 new dependencies.
info Direct dependencies
└─ esbuild@0.17.18
info All dependencies
├─ @esbuild/darwin-arm64@0.17.18
└─ esbuild@0.17.18
✨ Done in 6.57s.
Add build script
run npm pkg set scripts.build="esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=assets" from "."
run yarn build from "."
yarn run v1.22.19
$ esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=assets
app/assets/builds/application.js 62b
app/assets/builds/application.js.map 93b
✨ Done in 0.42s.
rails turbo:install stimulus:install
Import Turbo
append app/javascript/application.js
Install Turbo
run yarn add @hotwired/turbo-rails from "."
yarn add v1.22.19
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
success Saved 3 new dependencies.
info Direct dependencies
└─ @hotwired/turbo-rails@7.3.0
info All dependencies
├─ @hotwired/turbo-rails@7.3.0
├─ @hotwired/turbo@7.3.0
└─ @rails/actioncable@7.0.4
✨ Done in 3.93s.
Run turbo:install:redis to switch on Redis and use it in development for turbo streams
Create controllers directory
create app/javascript/controllers
create app/javascript/controllers/index.js
create app/javascript/controllers/application.js
create app/javascript/controllers/hello_controller.js
Import Stimulus controllers
append app/javascript/application.js
Install Stimulus
run yarn add @hotwired/stimulus from "."
yarn add v1.22.19
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ @hotwired/stimulus@3.2.1
info All dependencies
└─ @hotwired/stimulus@3.2.1
✨ Done in 1.67s.
rails css:install:bootstrap
Build into app/assets/builds
exist app/assets/builds
identical app/assets/builds/.keep
File unchanged! The supplied flag value not found! app/assets/config/manifest.js
Stop linking stylesheets automatically
gsub app/assets/config/manifest.js
File unchanged! The supplied flag value not found! .gitignore
File unchanged! The supplied flag value not found! .gitignore
Remove app/assets/stylesheets/application.css so build output can take over
remove app/assets/stylesheets/application.css
Add stylesheet link tag in application layout
File unchanged! The supplied flag value not found! app/views/layouts/application.html.erb
append Procfile.dev
Add bin/dev to start foreman
identical bin/dev
Install Bootstrap with Bootstrap Icons and Popperjs/core
create app/assets/stylesheets/application.bootstrap.scss
run yarn add sass bootstrap bootstrap-icons @popperjs/core from "."
yarn add v1.22.19
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
success Saved 21 new dependencies.
info Direct dependencies
├─ @popperjs/core@2.11.7
├─ bootstrap-icons@1.10.4
├─ bootstrap@5.2.3
└─ sass@1.62.0
info All dependencies
├─ @popperjs/core@2.11.7
├─ anymatch@3.1.3
├─ binary-extensions@2.2.0
├─ bootstrap-icons@1.10.4
├─ bootstrap@5.2.3
├─ braces@3.0.2
├─ chokidar@3.5.3
├─ fill-range@7.0.1
├─ fsevents@2.3.2
├─ glob-parent@5.1.2
├─ immutable@4.3.0
├─ is-binary-path@2.1.0
├─ is-extglob@2.1.1
├─ is-glob@4.0.3
├─ is-number@7.0.0
├─ normalize-path@3.0.0
├─ picomatch@2.3.1
├─ readdirp@3.6.0
├─ sass@1.62.0
├─ source-map-js@1.0.2
└─ to-regex-range@5.0.1
✨ Done in 2.92s.
insert config/initializers/assets.rb
Appending Bootstrap JavaScript import to default entry point
append app/javascript/application.js
Add build:css script
run npm pkg set scripts.build:css="sass ./app/assets/stylesheets/application.bootstrap.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules" from "."
run yarn build:css from "."
yarn run v1.22.19
$ sass ./app/assets/stylesheets/application.bootstrap.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules
✨ Done in 0.94s.
ちなみに、—css bootstrapと指定すると-jオプションで他に指定しない限り、javascriptのバンドラーがesbuildで設定されてrails newされます。
記事の本旨とはずれますが、—css tailwindを指定するとimportmapがjavascriptバンドラーに設定されるのでそこは注意が必要です。
- rails g scaffoldしてみる
rails generate scaffold todo
invoke active_record
create db/migrate/20230425145754_create_todos.rb
create app/models/todo.rb
invoke test_unit
create test/models/todo_test.rb
create test/fixtures/todos.yml
invoke resource_route
route resources :todos
invoke scaffold_controller
create app/controllers/todos_controller.rb
invoke erb
create app/views/todos
create app/views/todos/index.html.erb
create app/views/todos/edit.html.erb
create app/views/todos/show.html.erb
create app/views/todos/new.html.erb
create app/views/todos/_form.html.erb
create app/views/todos/_todo.html.erb
invoke resource_route
invoke test_unit
create test/controllers/todos_controller_test.rb
create test/system/todos_test.rb
invoke helper
create app/helpers/todos_helper.rb
invoke test_unit
invoke jbuilder
create app/views/todos/index.json.jbuilder
create app/views/todos/show.json.jbuilder
create app/views/todos/_todo.json.jbuilder
-
bootstrap公式ページのsample componentを使ってjsとcssの動作確認をする。
- まずはヘッダーのパーシャルを作成する。
touch app/views/layouts/_header.html.erb
# 以下のコードを追加 https://getbootstrap.jp/docs/5.0/components/navbar/ <nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container-fluid"> <a class="navbar-brand" href="#">Navbar w/ text</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarText"> <ul class="navbar-nav me-auto mb-2 mb-lg-0"> <li class="nav-item"> <a class="nav-link active" aria-current="page" href="#">Home</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Features</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Pricing</a> </li> </ul> <span class="navbar-text"> Navbar text with an inline element </span> </div> </div> </nav>
- application.html.erbにヘッダーを表示するためのrenderメソッドを追加する。
<!DOCTYPE html> <html> <head> <title>Myapp</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %> </head> <body> <%= render 'layouts/header'%> # これを追加 <%= yield %> </body> </html>
- jsとcssをバンドルして(yarnがインストールされている必要があります)ビルドする。
bin/dev # rails serverと同じようなコマンド
-
localhost:3000にアクセスしてヘッダーがうまく表示されているか確認する
ヘッダーにカーソルを当てたりして色が変わればCSSがうまく動いている。
デベロッパーツールでレスポンシブモードを使ってトグルが動くか確認する。
最後に
筆者はあくまで初学者のため、他のもっと初学者の方向けに記事を書いています。間違え等あると思いますので生暖かい目で見ていただけると幸いです。ちなみに間違いがあればお気軽にコメントしてくださると助かります。
参考にした記事
https://qiita.com/jnchito/items/5c41a7031404c313da1f
https://railsguides.jp/working_with_javascript_in_rails.html