shakapacker 6.0.0.rc.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.eslintignore +4 -0
- data/.eslintrc.js +14 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
- data/.github/ISSUE_TEMPLATE/feature-request.md +18 -0
- data/.github/workflows/jest.yml +30 -0
- data/.github/workflows/js-lint.yml +31 -0
- data/.github/workflows/rubocop.yml +39 -0
- data/.github/workflows/ruby.yml +48 -0
- data/.gitignore +13 -0
- data/.node-version +1 -0
- data/.rubocop.yml +229 -0
- data/CHANGELOG.md +32 -0
- data/CONTRIBUTING.md +62 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +183 -0
- data/MIT-LICENSE +20 -0
- data/README.md +666 -0
- data/Rakefile +11 -0
- data/config/README.md +3 -0
- data/config/webpacker.yml +1 -0
- data/docs/customizing_babel_config.md +59 -0
- data/docs/deployment.md +116 -0
- data/docs/developing_webpacker.md +29 -0
- data/docs/troubleshooting.md +212 -0
- data/docs/v6_upgrade.md +158 -0
- data/gemfiles/Gemfile-rails-edge +12 -0
- data/gemfiles/Gemfile-rails.5.2.x +9 -0
- data/gemfiles/Gemfile-rails.6.0.x +9 -0
- data/gemfiles/Gemfile-rails.6.1.x +12 -0
- data/lib/install/application.js +15 -0
- data/lib/install/bin/webpacker +15 -0
- data/lib/install/bin/webpacker-dev-server +18 -0
- data/lib/install/bin/yarn +18 -0
- data/lib/install/binstubs.rb +4 -0
- data/lib/install/config/webpack/webpack.config.js +5 -0
- data/lib/install/config/webpacker.yml +64 -0
- data/lib/install/package.json +15 -0
- data/lib/install/template.rb +100 -0
- data/lib/shakapacker/utils/git_utils.rb +23 -0
- data/lib/shakapacker/utils/version_syntax_converter.rb +24 -0
- data/lib/tasks/webpacker/binstubs.rake +15 -0
- data/lib/tasks/webpacker/check_binstubs.rake +12 -0
- data/lib/tasks/webpacker/check_node.rake +31 -0
- data/lib/tasks/webpacker/check_yarn.rake +33 -0
- data/lib/tasks/webpacker/clean.rake +25 -0
- data/lib/tasks/webpacker/clobber.rake +20 -0
- data/lib/tasks/webpacker/compile.rake +45 -0
- data/lib/tasks/webpacker/info.rake +21 -0
- data/lib/tasks/webpacker/install.rake +17 -0
- data/lib/tasks/webpacker/verify_config.rake +14 -0
- data/lib/tasks/webpacker/verify_install.rake +4 -0
- data/lib/tasks/webpacker/yarn_install.rake +18 -0
- data/lib/tasks/webpacker.rake +19 -0
- data/lib/tasks/yarn.rake +38 -0
- data/lib/webpacker/commands.rb +79 -0
- data/lib/webpacker/compiler.rb +130 -0
- data/lib/webpacker/configuration.rb +111 -0
- data/lib/webpacker/dev_server.rb +72 -0
- data/lib/webpacker/dev_server_proxy.rb +33 -0
- data/lib/webpacker/dev_server_runner.rb +96 -0
- data/lib/webpacker/env.rb +43 -0
- data/lib/webpacker/helper.rb +161 -0
- data/lib/webpacker/instance.rb +41 -0
- data/lib/webpacker/manifest.rb +120 -0
- data/lib/webpacker/railtie.rb +63 -0
- data/lib/webpacker/runner.rb +23 -0
- data/lib/webpacker/version.rb +4 -0
- data/lib/webpacker/webpack_runner.rb +58 -0
- data/lib/webpacker.rb +46 -0
- data/package/__tests__/config.js +34 -0
- data/package/__tests__/dev_server.js +45 -0
- data/package/__tests__/development.js +35 -0
- data/package/__tests__/env.js +58 -0
- data/package/__tests__/index.js +9 -0
- data/package/__tests__/production.js +29 -0
- data/package/__tests__/staging.js +30 -0
- data/package/__tests__/test.js +25 -0
- data/package/babel/preset.js +41 -0
- data/package/config.js +32 -0
- data/package/configPath.js +3 -0
- data/package/dev_server.js +20 -0
- data/package/env.js +27 -0
- data/package/environments/__tests__/base.js +69 -0
- data/package/environments/base.js +116 -0
- data/package/environments/development.js +55 -0
- data/package/environments/production.js +79 -0
- data/package/environments/test.js +3 -0
- data/package/index.js +33 -0
- data/package/inliningCss.js +7 -0
- data/package/rules/babel.js +30 -0
- data/package/rules/coffee.js +6 -0
- data/package/rules/css.js +3 -0
- data/package/rules/erb.js +15 -0
- data/package/rules/file.js +23 -0
- data/package/rules/index.js +18 -0
- data/package/rules/less.js +22 -0
- data/package/rules/raw.js +5 -0
- data/package/rules/sass.js +16 -0
- data/package/rules/stylus.js +26 -0
- data/package/utils/get_style_rule.js +37 -0
- data/package/utils/helpers.js +51 -0
- data/package.json +71 -0
- data/rakelib/release.rake +57 -0
- data/test/command_test.rb +109 -0
- data/test/compiler_test.rb +68 -0
- data/test/configuration_test.rb +78 -0
- data/test/dev_server_runner_test.rb +81 -0
- data/test/dev_server_test.rb +47 -0
- data/test/engine_rake_tasks_test.rb +39 -0
- data/test/env_test.rb +23 -0
- data/test/helper_test.rb +159 -0
- data/test/manifest_test.rb +89 -0
- data/test/mounted_app/Rakefile +4 -0
- data/test/mounted_app/test/dummy/Rakefile +3 -0
- data/test/mounted_app/test/dummy/bin/rails +3 -0
- data/test/mounted_app/test/dummy/bin/rake +3 -0
- data/test/mounted_app/test/dummy/config/application.rb +10 -0
- data/test/mounted_app/test/dummy/config/environment.rb +3 -0
- data/test/mounted_app/test/dummy/config/webpacker.yml +75 -0
- data/test/mounted_app/test/dummy/config.ru +5 -0
- data/test/mounted_app/test/dummy/package.json +7 -0
- data/test/rake_tasks_test.rb +71 -0
- data/test/test_app/Rakefile +3 -0
- data/test/test_app/app/packs/entrypoints/application.js +10 -0
- data/test/test_app/app/packs/entrypoints/multi_entry.css +4 -0
- data/test/test_app/app/packs/entrypoints/multi_entry.js +4 -0
- data/test/test_app/bin/webpacker +14 -0
- data/test/test_app/bin/webpacker-dev-server +14 -0
- data/test/test_app/config/application.rb +11 -0
- data/test/test_app/config/environment.rb +4 -0
- data/test/test_app/config/initializers/inspect_autoload_paths.rb +1 -0
- data/test/test_app/config/webpack/webpack.config.js +0 -0
- data/test/test_app/config/webpacker.yml +77 -0
- data/test/test_app/config/webpacker_other_location.yml +79 -0
- data/test/test_app/config/webpacker_public_root.yml +18 -0
- data/test/test_app/config.ru +5 -0
- data/test/test_app/package.json +13 -0
- data/test/test_app/public/packs/manifest.json +50 -0
- data/test/test_app/some.config.js +0 -0
- data/test/test_app/yarn.lock +11 -0
- data/test/test_helper.rb +33 -0
- data/test/webpack_runner_test.rb +57 -0
- data/test/webpacker_test.rb +34 -0
- data/webpacker.gemspec +31 -0
- data/yarn.lock +4029 -0
- metadata +331 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
class Webpacker::Commands
|
|
2
|
+
delegate :config, :compiler, :manifest, :logger, to: :@webpacker
|
|
3
|
+
|
|
4
|
+
def initialize(webpacker)
|
|
5
|
+
@webpacker = webpacker
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Cleanup old assets in the compile directory. By default it will
|
|
9
|
+
# keep the latest version, 2 backups created within the past hour.
|
|
10
|
+
#
|
|
11
|
+
# Examples
|
|
12
|
+
#
|
|
13
|
+
# To force only 1 backup to be kept, set count=1 and age=0.
|
|
14
|
+
#
|
|
15
|
+
# To only keep files created within the last 10 minutes, set count=0 and
|
|
16
|
+
# age=600.
|
|
17
|
+
#
|
|
18
|
+
def clean(count = 2, age = 3600)
|
|
19
|
+
if config.public_output_path.exist? && config.public_manifest_path.exist?
|
|
20
|
+
packs
|
|
21
|
+
.map do |paths|
|
|
22
|
+
paths.map { |path| [Time.now - File.mtime(path), path] }
|
|
23
|
+
.sort
|
|
24
|
+
.reject.with_index do |(file_age, _), index|
|
|
25
|
+
file_age < age || index < count
|
|
26
|
+
end
|
|
27
|
+
.map { |_, path| path }
|
|
28
|
+
end
|
|
29
|
+
.flatten
|
|
30
|
+
.compact
|
|
31
|
+
.each do |file|
|
|
32
|
+
if File.file?(file)
|
|
33
|
+
File.delete(file)
|
|
34
|
+
logger.info "Removed #{file}"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def clobber
|
|
43
|
+
config.public_output_path.rmtree if config.public_output_path.exist?
|
|
44
|
+
config.cache_path.rmtree if config.cache_path.exist?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def bootstrap
|
|
48
|
+
manifest.refresh
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def compile
|
|
52
|
+
compiler.compile.tap do |success|
|
|
53
|
+
manifest.refresh if success
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
def packs
|
|
59
|
+
all_files = Dir.glob("#{config.public_output_path}/**/*")
|
|
60
|
+
manifest_config = Dir.glob("#{config.public_manifest_path}*")
|
|
61
|
+
|
|
62
|
+
packs = all_files - manifest_config - current_version
|
|
63
|
+
packs.reject { |file| File.directory?(file) }.group_by do |path|
|
|
64
|
+
base, _, ext = File.basename(path).scan(/(.*)(-[\da-f]+)(\.\w+)/).flatten
|
|
65
|
+
"#{File.dirname(path)}/#{base}#{ext}"
|
|
66
|
+
end.values
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def current_version
|
|
70
|
+
packs = manifest.refresh.values.map do |value|
|
|
71
|
+
value = value["src"] if value.is_a?(Hash)
|
|
72
|
+
next unless value.is_a?(String)
|
|
73
|
+
|
|
74
|
+
File.join(config.root_path, "public", "#{value}*")
|
|
75
|
+
end.compact
|
|
76
|
+
|
|
77
|
+
Dir.glob(packs).uniq
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
require "open3"
|
|
2
|
+
require "digest/sha1"
|
|
3
|
+
|
|
4
|
+
class Webpacker::Compiler
|
|
5
|
+
# Additional paths that test compiler needs to watch
|
|
6
|
+
# Webpacker::Compiler.watched_paths << 'bower_components'
|
|
7
|
+
#
|
|
8
|
+
# Deprecated. Use additional_paths in the YAML configuration instead.
|
|
9
|
+
cattr_accessor(:watched_paths) { [] }
|
|
10
|
+
|
|
11
|
+
# Additional environment variables that the compiler is being run with
|
|
12
|
+
# Webpacker::Compiler.env['FRONTEND_API_KEY'] = 'your_secret_key'
|
|
13
|
+
cattr_accessor(:env) { {} }
|
|
14
|
+
|
|
15
|
+
delegate :config, :logger, to: :webpacker
|
|
16
|
+
|
|
17
|
+
def initialize(webpacker)
|
|
18
|
+
@webpacker = webpacker
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def compile
|
|
22
|
+
if stale?
|
|
23
|
+
run_webpack.tap do |success|
|
|
24
|
+
# We used to only record the digest on success
|
|
25
|
+
# However, the output file is still written on error, meaning that the digest should still be updated.
|
|
26
|
+
# If it's not, you can end up in a situation where a recompile doesn't take place when it should.
|
|
27
|
+
# See https://github.com/rails/webpacker/issues/2113
|
|
28
|
+
record_compilation_digest
|
|
29
|
+
end
|
|
30
|
+
else
|
|
31
|
+
logger.debug "Everything's up-to-date. Nothing to do"
|
|
32
|
+
true
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Returns true if all the compiled packs are up to date with the underlying asset files.
|
|
37
|
+
def fresh?
|
|
38
|
+
last_compilation_digest&.== watched_files_digest
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Returns true if the compiled packs are out of date with the underlying asset files.
|
|
42
|
+
def stale?
|
|
43
|
+
!fresh?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
attr_reader :webpacker
|
|
48
|
+
|
|
49
|
+
def last_compilation_digest
|
|
50
|
+
compilation_digest_path.read if compilation_digest_path.exist? && config.public_manifest_path.exist?
|
|
51
|
+
rescue Errno::ENOENT, Errno::ENOTDIR
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def watched_files_digest
|
|
55
|
+
if Rails.env.development?
|
|
56
|
+
warn <<~MSG.strip
|
|
57
|
+
Webpacker::Compiler - Slow setup for development
|
|
58
|
+
|
|
59
|
+
Prepare JS assets with either:
|
|
60
|
+
1. Running `bin/webpack-dev-server`
|
|
61
|
+
2. Set `compile` to false in webpacker.yml and run `bin/webpack -w`
|
|
62
|
+
MSG
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
warn "Webpacker::Compiler.watched_paths has been deprecated. Set additional_paths in webpacker.yml instead." unless watched_paths.empty?
|
|
66
|
+
root_path = Pathname.new(File.expand_path(config.root_path))
|
|
67
|
+
expanded_paths = [*default_watched_paths, *watched_paths].map do |path|
|
|
68
|
+
root_path.join(path)
|
|
69
|
+
end
|
|
70
|
+
files = Dir[*expanded_paths].reject { |f| File.directory?(f) }
|
|
71
|
+
file_ids = files.sort.map { |f| "#{File.basename(f)}/#{Digest::SHA1.file(f).hexdigest}" }
|
|
72
|
+
Digest::SHA1.hexdigest(file_ids.join("/"))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def record_compilation_digest
|
|
76
|
+
config.cache_path.mkpath
|
|
77
|
+
compilation_digest_path.write(watched_files_digest)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def optionalRubyRunner
|
|
81
|
+
bin_webpack_path = config.root_path.join("bin/webpacker")
|
|
82
|
+
first_line = File.readlines(bin_webpack_path).first.chomp
|
|
83
|
+
/ruby/.match?(first_line) ? RbConfig.ruby : ""
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def run_webpack
|
|
87
|
+
logger.info "Compiling..."
|
|
88
|
+
|
|
89
|
+
stdout, stderr, status = Open3.capture3(
|
|
90
|
+
webpack_env,
|
|
91
|
+
"#{optionalRubyRunner} ./bin/webpacker",
|
|
92
|
+
chdir: File.expand_path(config.root_path)
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
if status.success?
|
|
96
|
+
logger.info "Compiled all packs in #{config.public_output_path}"
|
|
97
|
+
logger.error "#{stderr}" unless stderr.empty?
|
|
98
|
+
|
|
99
|
+
if config.webpack_compile_output?
|
|
100
|
+
logger.info stdout
|
|
101
|
+
end
|
|
102
|
+
else
|
|
103
|
+
non_empty_streams = [stdout, stderr].delete_if(&:empty?)
|
|
104
|
+
logger.error "\nCOMPILATION FAILED:\nEXIT STATUS: #{status}\nOUTPUTS:\n#{non_empty_streams.join("\n\n")}"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
status.success?
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def default_watched_paths
|
|
111
|
+
[
|
|
112
|
+
*config.additional_paths,
|
|
113
|
+
"#{config.source_path}/**/*",
|
|
114
|
+
"yarn.lock", "package.json",
|
|
115
|
+
"config/webpack/**/*"
|
|
116
|
+
].freeze
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def compilation_digest_path
|
|
120
|
+
config.cache_path.join("last-compilation-digest-#{webpacker.env}")
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def webpack_env
|
|
124
|
+
return env unless defined?(ActionController::Base)
|
|
125
|
+
|
|
126
|
+
env.merge("WEBPACKER_ASSET_HOST" => ENV.fetch("WEBPACKER_ASSET_HOST", ActionController::Base.helpers.compute_asset_host),
|
|
127
|
+
"WEBPACKER_RELATIVE_URL_ROOT" => ENV.fetch("WEBPACKER_RELATIVE_URL_ROOT", ActionController::Base.relative_url_root),
|
|
128
|
+
"WEBPACKER_CONFIG" => webpacker.config_path.to_s)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
require "yaml"
|
|
2
|
+
require "active_support/core_ext/hash/keys"
|
|
3
|
+
require "active_support/core_ext/hash/indifferent_access"
|
|
4
|
+
|
|
5
|
+
class Webpacker::Configuration
|
|
6
|
+
class << self
|
|
7
|
+
attr_accessor :installing
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
attr_reader :root_path, :config_path, :env
|
|
11
|
+
|
|
12
|
+
def initialize(root_path:, config_path:, env:)
|
|
13
|
+
@root_path = root_path
|
|
14
|
+
@config_path = config_path
|
|
15
|
+
@env = env
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def dev_server
|
|
19
|
+
fetch(:dev_server)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def compile?
|
|
23
|
+
fetch(:compile)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def source_path
|
|
27
|
+
root_path.join(fetch(:source_path))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def additional_paths
|
|
31
|
+
fetch(:additional_paths)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def source_entry_path
|
|
35
|
+
source_path.join(fetch(:source_entry_path))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def public_path
|
|
39
|
+
root_path.join(fetch(:public_root_path))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def public_output_path
|
|
43
|
+
public_path.join(fetch(:public_output_path))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def public_manifest_path
|
|
47
|
+
public_output_path.join("manifest.json")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def cache_manifest?
|
|
51
|
+
fetch(:cache_manifest)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def cache_path
|
|
55
|
+
root_path.join(fetch(:cache_path))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def check_yarn_integrity=(value)
|
|
59
|
+
warn <<~EOS
|
|
60
|
+
Webpacker::Configuration#check_yarn_integrity=(value) is obsolete. The integrity
|
|
61
|
+
check has been removed from Webpacker (https://github.com/rails/webpacker/pull/2518)
|
|
62
|
+
so changing this setting will have no effect.
|
|
63
|
+
EOS
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def webpack_compile_output?
|
|
67
|
+
fetch(:webpack_compile_output)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def fetch(key)
|
|
71
|
+
data.fetch(key, defaults[key])
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
def data
|
|
76
|
+
@data ||= load
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def load
|
|
80
|
+
config = begin
|
|
81
|
+
YAML.load_file(config_path.to_s, aliases: true)
|
|
82
|
+
rescue ArgumentError
|
|
83
|
+
YAML.load_file(config_path.to_s)
|
|
84
|
+
end
|
|
85
|
+
config[env].deep_symbolize_keys
|
|
86
|
+
rescue Errno::ENOENT => e
|
|
87
|
+
if self.class.installing
|
|
88
|
+
{}
|
|
89
|
+
else
|
|
90
|
+
raise "Webpacker configuration file not found #{config_path}. " \
|
|
91
|
+
"Please run rails webpacker:install " \
|
|
92
|
+
"Error: #{e.message}"
|
|
93
|
+
end
|
|
94
|
+
rescue Psych::SyntaxError => e
|
|
95
|
+
raise "YAML syntax error occurred while parsing #{config_path}. " \
|
|
96
|
+
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
|
|
97
|
+
"Error: #{e.message}"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def defaults
|
|
101
|
+
@defaults ||= begin
|
|
102
|
+
path = File.expand_path("../../install/config/webpacker.yml", __FILE__)
|
|
103
|
+
config = begin
|
|
104
|
+
YAML.load_file(path, aliases: true)
|
|
105
|
+
rescue ArgumentError
|
|
106
|
+
YAML.load_file(path)
|
|
107
|
+
end
|
|
108
|
+
HashWithIndifferentAccess.new(config[env])
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
class Webpacker::DevServer
|
|
2
|
+
DEFAULT_ENV_PREFIX = "WEBPACKER_DEV_SERVER".freeze
|
|
3
|
+
|
|
4
|
+
# Configure dev server connection timeout (in seconds), default: 0.01
|
|
5
|
+
# Webpacker.dev_server.connect_timeout = 1
|
|
6
|
+
cattr_accessor(:connect_timeout) { 0.01 }
|
|
7
|
+
|
|
8
|
+
attr_reader :config
|
|
9
|
+
|
|
10
|
+
def initialize(config)
|
|
11
|
+
@config = config
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def running?
|
|
15
|
+
if config.dev_server.present?
|
|
16
|
+
Socket.tcp(host, port, connect_timeout: connect_timeout).close
|
|
17
|
+
true
|
|
18
|
+
else
|
|
19
|
+
false
|
|
20
|
+
end
|
|
21
|
+
rescue
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def host
|
|
26
|
+
fetch(:host)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def port
|
|
30
|
+
fetch(:port)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def https?
|
|
34
|
+
case fetch(:https)
|
|
35
|
+
when true, "true", Hash
|
|
36
|
+
true
|
|
37
|
+
else
|
|
38
|
+
false
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def protocol
|
|
43
|
+
https? ? "https" : "http"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def host_with_port
|
|
47
|
+
"#{host}:#{port}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def pretty?
|
|
51
|
+
fetch(:pretty)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def hmr?
|
|
55
|
+
fetch(:hmr)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def env_prefix
|
|
59
|
+
config.dev_server.fetch(:env_prefix, DEFAULT_ENV_PREFIX)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
def fetch(key)
|
|
64
|
+
return nil unless config.dev_server.present?
|
|
65
|
+
|
|
66
|
+
ENV["#{env_prefix}_#{key.upcase}"] || config.dev_server.fetch(key, defaults[key])
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def defaults
|
|
70
|
+
config.send(:defaults)[:dev_server] || {}
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require "rack/proxy"
|
|
2
|
+
|
|
3
|
+
class Webpacker::DevServerProxy < Rack::Proxy
|
|
4
|
+
delegate :config, :dev_server, to: :@webpacker
|
|
5
|
+
|
|
6
|
+
def initialize(app = nil, opts = {})
|
|
7
|
+
@webpacker = opts.delete(:webpacker) || Webpacker.instance
|
|
8
|
+
opts[:streaming] = false if Rails.env.test? && !opts.key?(:streaming)
|
|
9
|
+
super
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def perform_request(env)
|
|
13
|
+
if env["PATH_INFO"].start_with?("/#{public_output_uri_path}") && dev_server.running?
|
|
14
|
+
env["HTTP_HOST"] = env["HTTP_X_FORWARDED_HOST"] = dev_server.host
|
|
15
|
+
env["HTTP_X_FORWARDED_SERVER"] = dev_server.host_with_port
|
|
16
|
+
env["HTTP_PORT"] = env["HTTP_X_FORWARDED_PORT"] = dev_server.port.to_s
|
|
17
|
+
env["HTTP_X_FORWARDED_PROTO"] = env["HTTP_X_FORWARDED_SCHEME"] = dev_server.protocol
|
|
18
|
+
unless dev_server.https?
|
|
19
|
+
env["HTTPS"] = env["HTTP_X_FORWARDED_SSL"] = "off"
|
|
20
|
+
end
|
|
21
|
+
env["SCRIPT_NAME"] = ""
|
|
22
|
+
|
|
23
|
+
super(env)
|
|
24
|
+
else
|
|
25
|
+
@app.call(env)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
def public_output_uri_path
|
|
31
|
+
config.public_output_path.relative_path_from(config.public_path).to_s + "/"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require "shellwords"
|
|
2
|
+
require "socket"
|
|
3
|
+
require "webpacker/configuration"
|
|
4
|
+
require "webpacker/dev_server"
|
|
5
|
+
require "webpacker/runner"
|
|
6
|
+
|
|
7
|
+
module Webpacker
|
|
8
|
+
class DevServerRunner < Webpacker::Runner
|
|
9
|
+
def run
|
|
10
|
+
load_config
|
|
11
|
+
detect_unsupported_switches!
|
|
12
|
+
detect_port!
|
|
13
|
+
execute_cmd
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def load_config
|
|
19
|
+
app_root = Pathname.new(@app_path)
|
|
20
|
+
|
|
21
|
+
@config = Configuration.new(
|
|
22
|
+
root_path: app_root,
|
|
23
|
+
config_path: Pathname.new(@webpacker_config),
|
|
24
|
+
env: ENV["RAILS_ENV"]
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
dev_server = DevServer.new(@config)
|
|
28
|
+
|
|
29
|
+
@hostname = dev_server.host
|
|
30
|
+
@port = dev_server.port
|
|
31
|
+
@pretty = dev_server.pretty?
|
|
32
|
+
@https = dev_server.https?
|
|
33
|
+
@hot = dev_server.hmr?
|
|
34
|
+
|
|
35
|
+
rescue Errno::ENOENT, NoMethodError
|
|
36
|
+
$stdout.puts "webpack dev_server configuration not found in #{@config.config_path}[#{ENV["RAILS_ENV"]}]."
|
|
37
|
+
$stdout.puts "Please run bundle exec rails webpacker:install to install Webpacker"
|
|
38
|
+
exit!
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
UNSUPPORTED_SWITCHES = %w[--host --port]
|
|
42
|
+
private_constant :UNSUPPORTED_SWITCHES
|
|
43
|
+
def detect_unsupported_switches!
|
|
44
|
+
unsupported_switches = UNSUPPORTED_SWITCHES & @argv
|
|
45
|
+
if unsupported_switches.any?
|
|
46
|
+
$stdout.puts "The following CLI switches are not supported by Webpacker: #{unsupported_switches.join(' ')}. Please edit your command and try again."
|
|
47
|
+
exit!
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if @argv.include?("--https") && !@https
|
|
51
|
+
$stdout.puts "Please set https: true in webpacker.yml to use the --https command line flag."
|
|
52
|
+
exit!
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def detect_port!
|
|
57
|
+
server = TCPServer.new(@hostname, @port)
|
|
58
|
+
server.close
|
|
59
|
+
|
|
60
|
+
rescue Errno::EADDRINUSE
|
|
61
|
+
$stdout.puts "Another program is running on port #{@port}. Set a new port in #{@config.config_path} for dev_server"
|
|
62
|
+
exit!
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def execute_cmd
|
|
66
|
+
env = Webpacker::Compiler.env
|
|
67
|
+
env["WEBPACKER_CONFIG"] = @webpacker_config
|
|
68
|
+
env["WEBPACK_SERVE"] = "true"
|
|
69
|
+
|
|
70
|
+
cmd = if node_modules_bin_exist?
|
|
71
|
+
["#{@node_modules_bin_path}/webpack", "serve"]
|
|
72
|
+
else
|
|
73
|
+
["yarn", "webpack", "serve"]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
if @argv.include?("--debug-webpacker")
|
|
77
|
+
cmd = [ "node", "--inspect-brk", "--trace-warnings" ] + cmd
|
|
78
|
+
@argv.delete "--debug-webpacker"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
cmd += ["--config", @webpack_config]
|
|
82
|
+
cmd += ["--progress", "--color"] if @pretty
|
|
83
|
+
|
|
84
|
+
cmd += ["--hot"] if @hot
|
|
85
|
+
cmd += @argv
|
|
86
|
+
|
|
87
|
+
Dir.chdir(@app_path) do
|
|
88
|
+
Kernel.exec env, *cmd
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def node_modules_bin_exist?
|
|
93
|
+
File.exist?("#{@node_modules_bin_path}/webpack-dev-server")
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
class Webpacker::Env
|
|
2
|
+
DEFAULT = "production".freeze
|
|
3
|
+
|
|
4
|
+
delegate :config_path, :logger, to: :@webpacker
|
|
5
|
+
|
|
6
|
+
def self.inquire(webpacker)
|
|
7
|
+
new(webpacker).inquire
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize(webpacker)
|
|
11
|
+
@webpacker = webpacker
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def inquire
|
|
15
|
+
fallback_env_warning if config_path.exist? && !current
|
|
16
|
+
current || DEFAULT.inquiry
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
def current
|
|
21
|
+
Rails.env.presence_in(available_environments)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def fallback_env_warning
|
|
25
|
+
logger.info "RAILS_ENV=#{Rails.env} environment is not defined in config/webpacker.yml, falling back to #{DEFAULT} environment"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def available_environments
|
|
29
|
+
if config_path.exist?
|
|
30
|
+
begin
|
|
31
|
+
YAML.load_file(config_path.to_s, aliases: true)
|
|
32
|
+
rescue ArgumentError
|
|
33
|
+
YAML.load_file(config_path.to_s)
|
|
34
|
+
end
|
|
35
|
+
else
|
|
36
|
+
[].freeze
|
|
37
|
+
end
|
|
38
|
+
rescue Psych::SyntaxError => e
|
|
39
|
+
raise "YAML syntax error occurred while parsing #{config_path}. " \
|
|
40
|
+
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
|
|
41
|
+
"Error: #{e.message}"
|
|
42
|
+
end
|
|
43
|
+
end
|