This gist will collects all issues we solved with Rails 5.2 and Webpacker
# Last few parameters(--skip-* part) is only my habbit not actully required
$ rails new <project_name> --webpack=stimulus --database=postgresql --skip-coffee --skip-test
$ cd <project_name>
$ rails db:create
$ rails g migration enable_hstore_extension
# db/migrate/<TIMESTAMP>_enable_hstore_extension.rb
class EnableHstoreExtension < ActiveRecord::Migration[5.2]
def change
enable_extension 'hstore'
end
end
$ rails g migration enable_uuid_extension
# db/migrate/<TIMESTAMP>_enable_uuid_extension.rb
class EnableUuidExtension < ActiveRecord::Migration[5.2]
def change
enable_extension 'uuid-ossp'
enable_extension 'pgcrypto'
end
end
# lib/templates/active_record/model/model.rb
<% module_namespacing do -%>
class <%= class_name %> < <%= parent_class_name.classify %>
# scope macros
# Concerns macros
# Constants
# Attributes related macros
<% if attributes.any?(&:password_digest?) -%>
has_secure_password
<% end -%>
# association macros
<% attributes.select(&:reference?).each do |attribute| -%>
belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %>
<% end -%>
# validation macros
# callbacks
# other
private
# callback methods
end
<% end -%>
If you are using some front end framework you may like to integrate stylesheet into components with webpack or you just like to integrate stylesheets with webapck like me. This is a way that we integrate that into webpacker.
NOTE: This is only the convention of our team you can avoid this step and keep stylesheet in assets/.
$ mkdir app/javascript/stylesheets
$ touch app/javascript/stylesheets/application.scss
$ touch app/javascript/stylesheets/_variables.scss
$ touch app/javascript/stylesheets/_base.scss
After create files please write down styles as follow:
app/javascript/stylesheets/application.scss
@import 'variables';
@import 'base';
app/javascript/stylesheets/_variables.scss
$colors: (
major: #00D252,
minor: #2F3B59
);
app/javascript/stylesheets/_base.scss
h1 {
color: map-get($colors, major);
}
On the top of app/javascript/packs/application.js
import 'stylesheets/application'
If you are not use --webpack=stimulus
for create project or install stimulus
in existed project.
$ yarn add stimulus
$ mkdir app/javascript/controllers
# To provide a example for testing stimulus
$ touch app/javascript/controllers/clipboard_controller.js
app/javascript/s/packs/application.js
/* eslint no-console:0 */
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
import 'stylesheets/application'
import { Application } from "stimulus"
import { definitionsFromContext } from "stimulus/webpack-helpers"
const application = Application.start()
// The path you may like to change to under `pack` that path will be `./controllers`
// but convention will be in `/app/javascript/controllers`
const context = require.context("controllers", true, /\.js$/)
application.load(definitionsFromContext(context))
Example of testing stimulus
:
app/javascript/controllers/clipboard_controller.js
import { Controller } from 'stimulus'
export default class extends Controller {
static targets = ['source']
initialize() {
console.log('clipboard initialize')
}
connect() {
console.log('clipboard connect')
if (document.queryCommandSupported('copy')) {
this.element.classList.add('clipboard--supported')
}
}
copy(e) {
e.preventDefault()
this.sourceTarget.select()
document.execCommand('copy')
}
}
$ rails g controller pages example
Add app/views/pages/example.html.erb
<h1>Hello, World</h1>
<hr>
<div data-controller="clipboard members dashboard">
PIN
<input type="text" data-target="clipboard.source" value="1234" readonly>
<button data-action="clipboard#copy" class="clipboard-button">
Copy to Clipboard
</button>
</div>
Open app/views/layout/application.html.erb then add pack tags
to <head>
<%= stylesheet_pack_tag 'application' %>
<%= javascript_pack_tag 'application' %>
config/routes.rb
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'pages#example'
end
Then you can test
$ rails s
Navigate to localhost:3000
should see as follow
Until here you should complete Rails 5.2 using webpacker with stimulus and stylesheets.
For common practical stiuation you may want to use bootstrap v4.x.
# https://getbootstrap.com/docs/4.1/getting-started/webpack/
$ yarn add jquery popper.js bootstrap
In app/javascript/stylesheets/application.scss add bootstrap
@import '~bootstrap/scss/bootstrap';
@import 'variables';
@import 'base';
app/javascript/packs/application.js
import 'bootstrap'
Add configuration to config/webpack/environment.js. If you do not setup this step, the abilities related to Popper.js
such as tooltip
will not working.
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
/**
* Automatically load modules instead of having to import or require them everywhere.
* Support by webpack. To get more information:
*
* https://webpack.js.org/plugins/provide-plugin/
* http://j.mp/2JzG1Dm
*/
environment.plugins.prepend(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
jquery: 'jquery',
'window.jQuery': 'jquery',
Popper: ['popper.js', 'default']
})
)
module.exports = environment
Sometimes you may like to use jQuery in views you should expose jQuery to global
# https://webpack.js.org/loaders/expose-loader/
$ yarn add expose-loader -D
# NOTICE: For some production environment you may ignore `-D`
Add configuration to config/webpack/environment.js
/**
* To use jQuery in views
*/
environment.loaders.append('expose', {
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: '$'
}]
})
$ mkdir -p lib/templates/active_record/model
$ touch lib/templates/active_record/model/model.rb
lib/templates/active_record/model/model.rb
<% module_namespacing do -%>
class <%= class_name %> < <%= parent_class_name.classify %>
# scope macros
# Concerns macros
# Constants
# Attributes related macros
<% if attributes.any?(&:password_digest?) -%>
has_secure_password
<% end -%>
# association macros
<% attributes.select(&:reference?).each do |attribute| -%>
belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %>
<% end -%>
# validation macros
# callbacks
# other
private
# callback methods
end
<% end -%>
@andyyou, this is seriously one of the most incredible things I've found in my journey to wrap my head around Webpack.
Thank you so much. Please keep up the amazing work.
FWIW, you might consider adding a note to the Font Awesome section that paid users need a slightly different path structure:
Two minor differences in my application.js which were ultimately necessary to get everything working:
The bootstrap.bundle.js contains Popper.js, which otherwise was not getting included despite my labours to get it working. It didn't seem to matter how or where I included it, it would report as undefined on the console. Also, I switched back to jquery-ujs because I prefer working with my trusted tool of choice.
I haven't yet attempted to get ActionCable working, but this seems to have the high-level details summarized in one place.
The only other thing I wanted to add is that I renamed my app/javascript to app/webpack because it seems silly to call it that. So far as I can tell, all I needed to change was the default->source_path in webpacker.yml and it appears to work without issue. Can you foresee any potential concerns?