Skip to content

Commit f05e2f5

Browse files
committed
Support React on Rails by merging Webpacker Lite
See #594 From a long discussion on #464, this issue will summarize. I'll soon be posting proposed changes to the README.md. Summary of changes * Move base url out from manifest.json to manifest.rb * Assign env variables to dev server settings so it can be overridden at runtime. * The keys for dev_server should use same format as of now as documented in Paths on the README.md. Note that * hot is a new setting to indicate that the dev_server is used with hot reloading, which means that CSS should be inlined to be hot loaded. The presence of dev_server means that the webpack-dev-server is used for the given env. development: // put the created files to the /public/webpack/development directory public_output_path: webpack/development //# if dev_server is not provided, then dev_server is not used dev_server: hot: true # This is a new setting static: false host: localhost https: false
1 parent 265a54d commit f05e2f5

18 files changed

+392
-54
lines changed

Gemfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,14 @@ gem "rubocop", ">= 0.47", require: false
99
group :test do
1010
gem "minitest", "~> 5.0"
1111
end
12+
13+
14+
if ENV["USE_PRY"]
15+
gem "awesome_print"
16+
gem "pry"
17+
gem "pry-byebug"
18+
gem "pry-doc"
19+
gem "pry-rails"
20+
gem "pry-rescue"
21+
gem "pry-stack_explorer"
22+
end

Gemfile.lock

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,19 @@ GEM
4848
tzinfo (~> 1.1)
4949
arel (7.1.4)
5050
ast (2.3.0)
51+
awesome_print (1.8.0)
52+
binding_of_caller (0.7.2)
53+
debug_inspector (>= 0.0.1)
5154
builder (3.2.3)
55+
byebug (9.0.6)
56+
coderay (1.1.1)
5257
concurrent-ruby (1.0.5)
58+
debug_inspector (0.0.3)
5359
erubis (2.7.0)
5460
globalid (0.3.7)
5561
activesupport (>= 4.1.0)
5662
i18n (0.8.1)
63+
interception (0.5)
5764
loofah (2.0.3)
5865
nokogiri (>= 1.5.9)
5966
mail (2.6.4)
@@ -71,6 +78,24 @@ GEM
7178
parser (2.4.0.0)
7279
ast (~> 2.2)
7380
powerpack (0.1.1)
81+
pry (0.10.4)
82+
coderay (~> 1.1.0)
83+
method_source (~> 0.8.1)
84+
slop (~> 3.4)
85+
pry-byebug (3.4.2)
86+
byebug (~> 9.0)
87+
pry (~> 0.10)
88+
pry-doc (0.10.0)
89+
pry (~> 0.9)
90+
yard (~> 0.9)
91+
pry-rails (0.3.6)
92+
pry (>= 0.10.4)
93+
pry-rescue (1.4.5)
94+
interception (>= 0.5)
95+
pry
96+
pry-stack_explorer (0.4.9.2)
97+
binding_of_caller (>= 0.7)
98+
pry (>= 0.9.11)
7499
rack (2.0.1)
75100
rack-test (0.6.3)
76101
rack (>= 1.0)
@@ -106,6 +131,7 @@ GEM
106131
ruby-progressbar (~> 1.7)
107132
unicode-display_width (~> 1.0, >= 1.0.1)
108133
ruby-progressbar (1.8.1)
134+
slop (3.6.0)
109135
sprockets (3.7.1)
110136
concurrent-ruby (~> 1.0)
111137
rack (> 1, < 3)
@@ -121,17 +147,25 @@ GEM
121147
websocket-driver (0.6.5)
122148
websocket-extensions (>= 0.1.0)
123149
websocket-extensions (0.1.2)
150+
yard (0.9.9)
124151

125152
PLATFORMS
126153
ruby
127154

128155
DEPENDENCIES
156+
awesome_print
129157
bundler (~> 1.12)
130158
minitest (~> 5.0)
159+
pry
160+
pry-byebug
161+
pry-doc
162+
pry-rails
163+
pry-rescue
164+
pry-stack_explorer
131165
rails
132166
rake (>= 11.1)
133167
rubocop (>= 0.47)
134168
webpacker!
135169

136170
BUNDLED WITH
137-
1.14.6
171+
1.15.3

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,8 @@ git push heroku master
11031103
Webpacker lazily compiles assets in test env so you can write your tests without any extra
11041104
setup and everything will just work out of the box.
11051105

1106+
Note, [React on Rails] users should set configuration value `compile` to false, as React on Rails
1107+
handle compilation for test and production environments.
11061108

11071109
Here is a sample system test case with hello_react example component:
11081110

lib/install/config/webpack/shared.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ module.exports = {
2828
output: {
2929
filename: '[name].js',
3030
path: output.path,
31-
publicPath: output.publicPath
3231
},
3332

3433
module: {
@@ -39,7 +38,6 @@ module.exports = {
3938
new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
4039
new ExtractTextPlugin(env.NODE_ENV === 'production' ? '[name]-[hash].css' : '[name].css'),
4140
new ManifestPlugin({
42-
publicPath: output.publicPath,
4341
writeToFileEmit: true
4442
})
4543
],

lib/install/config/webpacker.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ development:
3434
host: localhost
3535
port: 8080
3636
https: false
37+
hot: false
3738

3839
test:
3940
<<: *default

lib/webpacker.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ module Webpacker
22
extend self
33

44
def bootstrap
5-
Webpacker::Env.load
6-
Webpacker::Configuration.load
7-
Webpacker::Manifest.load
5+
Webpacker::Env.load_instance
6+
Webpacker::Configuration.load_instance
7+
Webpacker::DevServer.load_instance
8+
Webpacker::Manifest.load_instance
89
end
910

1011
def compile
1112
Webpacker::Compiler.compile
12-
Webpacker::Manifest.load
13+
Webpacker::Manifest.load_instance
1314
end
1415

1516
def env
@@ -19,6 +20,7 @@ def env
1920

2021
require "webpacker/env"
2122
require "webpacker/configuration"
23+
require "webpacker/dev_server"
2224
require "webpacker/manifest"
2325
require "webpacker/compiler"
2426
require "webpacker/railtie" if defined?(Rails)

lib/webpacker/configuration.rb

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,21 @@
44

55
class Webpacker::Configuration < Webpacker::FileLoader
66
class << self
7+
def reset
8+
@defaults = nil
9+
super
10+
end
11+
712
def entry_path
813
source_path.join(fetch(:source_entry_path))
914
end
1015

16+
def public_output_path
17+
fetch(:public_output_path)
18+
end
19+
1120
def output_path
12-
public_path.join(fetch(:public_output_path))
21+
public_path.join(public_output_path)
1322
end
1423

1524
def manifest_path
@@ -45,19 +54,30 @@ def fetch(key)
4554
end
4655

4756
def data
48-
load if Webpacker.env.development?
49-
raise Webpacker::FileLoader::FileLoaderError.new("Webpacker::Configuration.load must be called first") unless instance
57+
load_instance if Webpacker.env.development?
58+
raise Webpacker::FileLoader::FileLoaderError.new("Webpacker::Configuration.load_data must be called first") unless instance
5059
instance.data
5160
end
5261

5362
def defaults
5463
@defaults ||= HashWithIndifferentAccess.new(YAML.load(default_file_path.read)[Webpacker.env])
5564
end
65+
66+
# Uses the webpack dev server host if appropriate
67+
def output_path_or_url
68+
if Webpacker::DevServer.dev_server?
69+
Webpacker::DevServer.base_url
70+
else
71+
# Ensure we start with a slash so that the asset helpers don't prepend the default asset
72+
# pipeline locations.
73+
public_output_path.starts_with?("/") ? public_output_path : "/#{public_output_path}"
74+
end
75+
end
5676
end
5777

5878
private
59-
def load
60-
return super unless File.exist?(@path)
79+
def load_data
80+
return Webpacker::Configuration.defaults unless File.exist?(@path)
6181
HashWithIndifferentAccess.new(YAML.load(File.read(@path))[Webpacker.env])
6282
end
6383
end

lib/webpacker/dev_server.rb

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Same convention as manifest/configuration.rb
2+
3+
# Loads webpacker configuration from config/webpacker.yml
4+
5+
require "webpacker/configuration"
6+
7+
8+
class Webpacker::DevServer < Webpacker::FileLoader
9+
class << self
10+
def dev_server?
11+
!dev_server_values.nil?
12+
end
13+
14+
# read settings for dev_server
15+
def hot?
16+
return false unless dev_server?
17+
if ENV['WEBPACKER_HMR'].present?
18+
val = ENV['WEBPACKER_HMR'].downcase
19+
return true if val == "true"
20+
return false if val == "false"
21+
raise new ArgumentError("WEBPACKER_HMR value is #{ENV['WEBPACKER_HMR']}. Set to TRUE|FALSE")
22+
end
23+
fetch(:hot)
24+
end
25+
26+
def host
27+
fetch(:host)
28+
end
29+
30+
def port
31+
fetch(:port)
32+
end
33+
34+
def https?
35+
fetch(:https)
36+
end
37+
38+
def protocol
39+
https? ? "https" : "http"
40+
end
41+
42+
def file_path
43+
Webpacker::Configuration.file_path
44+
end
45+
46+
# Uses the hot_reloading_host if appropriate
47+
def base_url
48+
"#{protocol}://#{host}:#{port}"
49+
end
50+
51+
private
52+
53+
def dev_server_values
54+
data.fetch(:dev_server, nil)
55+
end
56+
57+
def fetch(key)
58+
return nil unless dev_server?
59+
dev_server_values.fetch(key, dev_server_defaults[key])
60+
end
61+
62+
def data
63+
load_instance if Webpacker.env.development?
64+
unless instance
65+
raise Webpacker::FileLoader::FileLoaderError.new("Webpacker::DevServer.load_data must be called first")
66+
end
67+
instance.data
68+
end
69+
70+
def dev_server_defaults
71+
@defaults ||= Webpacker::Configuration.defaults[:dev_server]
72+
end
73+
end
74+
75+
private
76+
def load_data
77+
Webpacker::Configuration.instance.data
78+
end
79+
end

lib/webpacker/env.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def file_path
1414
end
1515

1616
private
17-
def load
17+
def load_data
1818
environments = File.exist?(@path) ? YAML.load(File.read(@path)).keys : [].freeze
1919
return ENV["NODE_ENV"] if environments.include?(ENV["NODE_ENV"])
2020
return Rails.env if environments.include?(Rails.env)

lib/webpacker/file_loader.rb

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,44 @@ class NotFoundError < StandardError; end
44
class FileLoaderError < StandardError; end
55

66
class_attribute :instance
7-
attr_accessor :data
7+
attr_accessor :data, :mtime
88

99
class << self
10-
def load(path = file_path)
10+
def load_instance(path = file_path)
11+
# Assume production is 100% cached and don't reload if file's mtime not changed
12+
cached = self.instance && # if we have a singleton
13+
(env == "production" || # skip if production bc always cached
14+
(File.exist?(path) && self.instance.mtime == File.mtime(path))) # skip if mtime not changed
15+
16+
return if cached
1117
self.instance = new(path)
1218
end
19+
20+
def file_path
21+
raise FileLoaderError.new("Subclass of Webpacker::FileLoader should override this method")
22+
end
23+
24+
def reset
25+
self.instance = nil
26+
load_instance
27+
end
28+
29+
private
30+
31+
# Prefer the NODE_ENV to the rails env.
32+
def env
33+
ENV["NODE_ENV"].presence || Rails.env
34+
end
1335
end
1436

1537
private
1638
def initialize(path)
1739
@path = path
18-
@data = load
40+
@mtime = File.exist?(path) ? File.mtime(path) : nil
41+
@data = load_data
1942
end
2043

21-
def load
44+
def load_data
2245
{}.freeze
2346
end
2447
end

0 commit comments

Comments
 (0)