jetpacker 0.1.0 → 0.2.0

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.
Files changed (190) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintignore +4 -0
  3. data/.eslintrc.js +14 -0
  4. data/.gitignore +11 -11
  5. data/.node-version +1 -0
  6. data/.rubocop.yml +125 -0
  7. data/.travis.yml +54 -5
  8. data/CHANGELOG.jetpacker.md +7 -0
  9. data/CHANGELOG.md +1000 -0
  10. data/CONTRIBUTING.md +33 -0
  11. data/Gemfile +9 -3
  12. data/Gemfile.lock +157 -21
  13. data/MIT-LICENSE +20 -0
  14. data/README.md +671 -16
  15. data/Rakefile +8 -3
  16. data/docs/assets.md +119 -0
  17. data/docs/cloud9.md +310 -0
  18. data/docs/css.md +253 -0
  19. data/docs/deployment.md +130 -0
  20. data/docs/docker.md +68 -0
  21. data/docs/engines.md +200 -0
  22. data/docs/env.md +65 -0
  23. data/docs/es6.md +72 -0
  24. data/docs/folder-structure.md +66 -0
  25. data/docs/misc.md +23 -0
  26. data/docs/props.md +223 -0
  27. data/docs/testing.md +137 -0
  28. data/docs/troubleshooting.md +156 -0
  29. data/docs/typescript.md +126 -0
  30. data/docs/v4-upgrade.md +142 -0
  31. data/docs/webpack-dev-server.md +92 -0
  32. data/docs/webpack.md +364 -0
  33. data/docs/yarn.md +23 -0
  34. data/gemfiles/Gemfile-rails-edge +12 -0
  35. data/gemfiles/Gemfile-rails.4.2.x +9 -0
  36. data/gemfiles/Gemfile-rails.5.0.x +9 -0
  37. data/gemfiles/Gemfile-rails.5.1.x +9 -0
  38. data/gemfiles/Gemfile-rails.5.2.x +9 -0
  39. data/gemfiles/Gemfile-rails.6.0.x +9 -0
  40. data/jetpacker.gemspec +28 -22
  41. data/lib/install/angular.rb +23 -0
  42. data/lib/install/bin/webpack +18 -0
  43. data/lib/install/bin/webpack-dev-server +18 -0
  44. data/lib/install/binstubs.rb +4 -0
  45. data/lib/install/coffee.rb +25 -0
  46. data/lib/install/config/.browserslistrc +1 -0
  47. data/lib/install/config/babel.config.js +72 -0
  48. data/lib/install/config/postcss.config.js +12 -0
  49. data/lib/install/config/webpack/development.js +5 -0
  50. data/lib/install/config/webpack/environment.js +3 -0
  51. data/lib/install/config/webpack/production.js +5 -0
  52. data/lib/install/config/webpack/test.js +5 -0
  53. data/lib/install/config/webpacker.yml +96 -0
  54. data/lib/install/elm.rb +39 -0
  55. data/lib/install/erb.rb +25 -0
  56. data/lib/install/examples/angular/hello_angular.js +7 -0
  57. data/lib/install/examples/angular/hello_angular/app/app.component.ts +9 -0
  58. data/lib/install/examples/angular/hello_angular/app/app.module.ts +16 -0
  59. data/lib/install/examples/angular/hello_angular/index.ts +8 -0
  60. data/lib/install/examples/angular/hello_angular/polyfills.ts +73 -0
  61. data/lib/install/examples/coffee/hello_coffee.coffee +4 -0
  62. data/lib/install/examples/elm/Main.elm +55 -0
  63. data/lib/install/examples/elm/hello_elm.js +16 -0
  64. data/lib/install/examples/erb/hello_erb.js.erb +6 -0
  65. data/lib/install/examples/react/babel.config.js +87 -0
  66. data/lib/install/examples/react/hello_react.jsx +26 -0
  67. data/lib/install/examples/react/tsconfig.json +20 -0
  68. data/lib/install/examples/stimulus/application.js +1 -0
  69. data/lib/install/examples/stimulus/controllers/hello_controller.js +18 -0
  70. data/lib/install/examples/stimulus/controllers/index.js +9 -0
  71. data/lib/install/examples/svelte/app.svelte +11 -0
  72. data/lib/install/examples/svelte/hello_svelte.js +20 -0
  73. data/lib/install/examples/typescript/hello_typescript.ts +4 -0
  74. data/lib/install/examples/typescript/tsconfig.json +23 -0
  75. data/lib/install/examples/vue/app.vue +22 -0
  76. data/lib/install/examples/vue/hello_vue.js +72 -0
  77. data/lib/install/javascript/packs/application.js +18 -0
  78. data/lib/install/loaders/coffee.js +6 -0
  79. data/lib/install/loaders/elm.js +25 -0
  80. data/lib/install/loaders/erb.js +11 -0
  81. data/lib/install/loaders/svelte.js +9 -0
  82. data/lib/install/loaders/typescript.js +11 -0
  83. data/lib/install/loaders/vue.js +6 -0
  84. data/lib/install/react.rb +18 -0
  85. data/lib/install/stimulus.rb +12 -0
  86. data/lib/install/svelte.rb +29 -0
  87. data/lib/install/template.rb +55 -0
  88. data/lib/install/typescript.rb +46 -0
  89. data/lib/install/vue.rb +49 -0
  90. data/lib/jetpacker/version.rb +2 -1
  91. data/lib/tasks/installers.rake +37 -0
  92. data/lib/tasks/webpacker.rake +28 -0
  93. data/lib/tasks/webpacker/binstubs.rake +11 -0
  94. data/lib/tasks/webpacker/check_binstubs.rake +12 -0
  95. data/lib/tasks/webpacker/check_node.rake +24 -0
  96. data/lib/tasks/webpacker/check_yarn.rake +24 -0
  97. data/lib/tasks/webpacker/clean.rake +21 -0
  98. data/lib/tasks/webpacker/clobber.rake +16 -0
  99. data/lib/tasks/webpacker/compile.rake +43 -0
  100. data/lib/tasks/webpacker/info.rake +20 -0
  101. data/lib/tasks/webpacker/install.rake +13 -0
  102. data/lib/tasks/webpacker/verify_install.rake +13 -0
  103. data/lib/tasks/webpacker/yarn_install.rake +21 -0
  104. data/lib/webpacker.rb +46 -0
  105. data/lib/webpacker/commands.rb +50 -0
  106. data/lib/webpacker/compiler.rb +107 -0
  107. data/lib/webpacker/configuration.rb +113 -0
  108. data/lib/webpacker/dev_server.rb +66 -0
  109. data/lib/webpacker/dev_server_proxy.rb +31 -0
  110. data/lib/webpacker/dev_server_runner.rb +72 -0
  111. data/lib/webpacker/env.rb +39 -0
  112. data/lib/webpacker/helper.rb +176 -0
  113. data/lib/webpacker/instance.rb +37 -0
  114. data/lib/webpacker/manifest.rb +118 -0
  115. data/lib/webpacker/railtie.rb +98 -0
  116. data/lib/webpacker/rake_tasks.rb +6 -0
  117. data/lib/webpacker/runner.rb +22 -0
  118. data/lib/webpacker/version.rb +4 -0
  119. data/lib/webpacker/webpack_runner.rb +32 -0
  120. data/package.json +82 -0
  121. data/package/__tests__/config.js +55 -0
  122. data/package/__tests__/dev_server.js +43 -0
  123. data/package/__tests__/development.js +30 -0
  124. data/package/__tests__/env.js +46 -0
  125. data/package/__tests__/production.js +29 -0
  126. data/package/__tests__/staging.js +29 -0
  127. data/package/__tests__/test.js +26 -0
  128. data/package/config.js +37 -0
  129. data/package/config_types/__tests__/config_list.js +118 -0
  130. data/package/config_types/__tests__/config_object.js +43 -0
  131. data/package/config_types/config_list.js +75 -0
  132. data/package/config_types/config_object.js +55 -0
  133. data/package/config_types/index.js +7 -0
  134. data/package/dev_server.js +20 -0
  135. data/package/env.js +19 -0
  136. data/package/environments/__tests__/base.js +74 -0
  137. data/package/environments/base.js +166 -0
  138. data/package/environments/development.js +51 -0
  139. data/package/environments/production.js +79 -0
  140. data/package/environments/test.js +3 -0
  141. data/package/index.js +24 -0
  142. data/package/rules/babel.js +21 -0
  143. data/package/rules/css.js +3 -0
  144. data/package/rules/file.js +20 -0
  145. data/package/rules/index.js +20 -0
  146. data/package/rules/module.css.js +3 -0
  147. data/package/rules/module.sass.js +8 -0
  148. data/package/rules/node_modules.js +24 -0
  149. data/package/rules/sass.js +8 -0
  150. data/package/utils/__tests__/deep_assign.js +32 -0
  151. data/package/utils/__tests__/deep_merge.js +10 -0
  152. data/package/utils/__tests__/get_style_rule.js +65 -0
  153. data/package/utils/__tests__/objectify.js +9 -0
  154. data/package/utils/deep_assign.js +22 -0
  155. data/package/utils/deep_merge.js +22 -0
  156. data/package/utils/get_style_rule.js +45 -0
  157. data/package/utils/helpers.js +58 -0
  158. data/package/utils/objectify.js +3 -0
  159. data/test/command_test.rb +33 -0
  160. data/test/compiler_test.rb +75 -0
  161. data/test/configuration_test.rb +108 -0
  162. data/test/dev_server_runner_test.rb +51 -0
  163. data/test/dev_server_test.rb +47 -0
  164. data/test/env_test.rb +23 -0
  165. data/test/helper_test.rb +142 -0
  166. data/test/manifest_test.rb +42 -0
  167. data/test/rake_tasks_test.rb +69 -0
  168. data/test/test_app/Rakefile +3 -0
  169. data/test/test_app/app/javascript/packs/application.js +10 -0
  170. data/test/test_app/bin/webpack +14 -0
  171. data/test/test_app/bin/webpack-dev-server +14 -0
  172. data/test/test_app/config.ru +5 -0
  173. data/test/test_app/config/application.rb +12 -0
  174. data/test/test_app/config/environment.rb +4 -0
  175. data/test/test_app/config/webpack/development.js +0 -0
  176. data/test/test_app/config/webpacker.yml +97 -0
  177. data/test/test_app/config/webpacker_public_root.yml +19 -0
  178. data/test/test_app/package.json +13 -0
  179. data/test/test_app/public/packs/manifest.json +31 -0
  180. data/test/test_app/yarn.lock +11 -0
  181. data/test/test_helper.rb +33 -0
  182. data/test/webpack_runner_test.rb +51 -0
  183. data/test/webpacker_test.rb +13 -0
  184. data/yarn.lock +8321 -0
  185. metadata +267 -29
  186. data/.rspec +0 -3
  187. data/LICENSE.txt +0 -21
  188. data/bin/console +0 -14
  189. data/bin/setup +0 -8
  190. data/lib/jetpacker.rb +0 -6
@@ -0,0 +1,11 @@
1
+ binstubs_template_path = File.expand_path("../../install/binstubs.rb", __dir__).freeze
2
+
3
+ namespace :webpacker do
4
+ desc "Installs Webpacker binstubs in this application"
5
+ task binstubs: [:check_node, :check_yarn] do
6
+ require "rails/generators"
7
+ require "rails/generators/rails/app/app_generator"
8
+ generator = Rails::Generators::AppGenerator.new [Jets.root], {force: ENV['FORCE']}, destination_root: Jets.root
9
+ generator.apply binstubs_template_path, verbose: false
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ namespace :webpacker do
2
+ desc "Verifies that webpack & webpack-dev-server are present."
3
+ task :check_binstubs do
4
+ unless File.exist?("bin/webpack")
5
+ $stderr.puts "webpack binstubs not found.\n"\
6
+ "Have you run rails webpacker:install ?\n"\
7
+ "Make sure the bin directory or binstubs are not included in .gitignore\n"\
8
+ "Exiting!"
9
+ exit!
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,24 @@
1
+ namespace :webpacker do
2
+ desc "Verifies if Node.js is installed"
3
+ task :check_node do
4
+ begin
5
+ node_version = `node -v || nodejs -v`
6
+ raise Errno::ENOENT if node_version.blank?
7
+
8
+ pkg_path = Pathname.new("#{__dir__}/../../../package.json").realpath
9
+ node_requirement = JSON.parse(pkg_path.read)["engines"]["node"]
10
+
11
+ requirement = Gem::Requirement.new(node_requirement)
12
+ version = Gem::Version.new(node_version.strip.tr("v", ""))
13
+
14
+ unless requirement.satisfied_by?(version)
15
+ $stderr.puts "Webpacker requires Node.js #{requirement} and you are using #{version}"
16
+ $stderr.puts "Please upgrade Node.js https://nodejs.org/en/download/"
17
+ $stderr.puts "Exiting!" && exit!
18
+ end
19
+ rescue Errno::ENOENT
20
+ $stderr.puts "Node.js not installed. Please download and install Node.js https://nodejs.org/en/download/"
21
+ $stderr.puts "Exiting!" && exit!
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ namespace :webpacker do
2
+ desc "Verifies if Yarn is installed"
3
+ task :check_yarn do
4
+ begin
5
+ yarn_version = `yarn --version`
6
+ raise Errno::ENOENT if yarn_version.blank?
7
+
8
+ pkg_path = Pathname.new("#{__dir__}/../../../package.json").realpath
9
+ yarn_requirement = JSON.parse(pkg_path.read)["engines"]["yarn"]
10
+
11
+ requirement = Gem::Requirement.new(yarn_requirement)
12
+ version = Gem::Version.new(yarn_version)
13
+
14
+ unless requirement.satisfied_by?(version)
15
+ $stderr.puts "Webpacker requires Yarn #{requirement} and you are using #{version}"
16
+ $stderr.puts "Please upgrade Yarn https://yarnpkg.com/lang/en/docs/install/"
17
+ $stderr.puts "Exiting!" && exit!
18
+ end
19
+ rescue Errno::ENOENT
20
+ $stderr.puts "Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/"
21
+ $stderr.puts "Exiting!" && exit!
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ $stdout.sync = true
2
+
3
+ require "webpacker/configuration"
4
+
5
+ namespace :webpacker do
6
+ desc "Remove old compiled webpacks"
7
+ task :clean, [:keep] => ["webpacker:verify_install", :environment] do |_, args|
8
+ Webpacker.ensure_log_goes_to_stdout do
9
+ Webpacker.clean(Integer(args.keep || 2))
10
+ end
11
+ end
12
+ end
13
+
14
+ # Run clean if the assets:clean is run
15
+ if Rake::Task.task_defined?("assets:clean")
16
+ Rake::Task["assets:clean"].enhance do
17
+ Rake::Task["webpacker:clean"].invoke
18
+ end
19
+ else
20
+ Rake::Task.define_task("assets:clean" => "webpacker:clean")
21
+ end
@@ -0,0 +1,16 @@
1
+ require "webpacker/configuration"
2
+
3
+ namespace :webpacker do
4
+ desc "Remove the webpack compiled output directory"
5
+ task clobber: ["webpacker:verify_install", :environment] do
6
+ Webpacker.clobber
7
+ $stdout.puts "Removed webpack output path directory #{Webpacker.config.public_output_path}"
8
+ end
9
+ end
10
+
11
+ # Run clobber if the assets:clobber is run
12
+ if Rake::Task.task_defined?("assets:clobber")
13
+ Rake::Task["assets:clobber"].enhance do
14
+ Rake::Task["webpacker:clobber"].invoke
15
+ end
16
+ end
@@ -0,0 +1,43 @@
1
+ $stdout.sync = true
2
+
3
+ def yarn_install_available?
4
+ rails_major = Rails::VERSION::MAJOR
5
+ rails_minor = Rails::VERSION::MINOR
6
+
7
+ rails_major > 5 || (rails_major == 5 && rails_minor >= 1)
8
+ end
9
+
10
+ def enhance_assets_precompile
11
+ # yarn:install was added in Rails 5.1
12
+ deps = yarn_install_available? ? [] : ["webpacker:yarn_install"]
13
+ Rake::Task["assets:precompile"].enhance(deps) do
14
+ Rake::Task["webpacker:compile"].invoke
15
+ end
16
+ end
17
+
18
+ namespace :webpacker do
19
+ desc "Compile JavaScript packs using webpack for production with digests"
20
+ task compile: ["webpacker:verify_install", :environment] do
21
+ Webpacker.with_node_env(ENV.fetch("NODE_ENV", "production")) do
22
+ Webpacker.ensure_log_goes_to_stdout do
23
+ if Webpacker.compile
24
+ # Successful compilation!
25
+ else
26
+ # Failed compilation
27
+ exit!
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ # Compile packs after we've compiled all other assets during precompilation
35
+ skip_webpacker_precompile = %w(no false n f).include?(ENV["WEBPACKER_PRECOMPILE"])
36
+
37
+ unless skip_webpacker_precompile
38
+ if Rake::Task.task_defined?("assets:precompile")
39
+ enhance_assets_precompile
40
+ else
41
+ Rake::Task.define_task("assets:precompile" => ["webpacker:yarn_install", "webpacker:compile"])
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ require "webpacker/version"
2
+
3
+ namespace :webpacker do
4
+ desc "Provide information on Webpacker's environment"
5
+ task :info do
6
+ $stdout.puts "Ruby: #{`ruby --version`}"
7
+ $stdout.puts "Jets: #{Jets.version}"
8
+ $stdout.puts "Rails: #{Rails.version}"
9
+ $stdout.puts "Webpacker: #{Webpacker::VERSION}"
10
+ $stdout.puts "Node: #{`node --version`}"
11
+ $stdout.puts "Yarn: #{`yarn --version`}"
12
+
13
+ $stdout.puts "\n"
14
+ $stdout.puts "@rails/webpacker: \n#{`npm list @rails/webpacker version`}"
15
+
16
+ $stdout.puts "Is bin/webpack present?: #{File.exist? 'bin/webpack'}"
17
+ $stdout.puts "Is bin/webpack-dev-server present?: #{File.exist? 'bin/webpack-dev-server'}"
18
+ $stdout.puts "Is bin/yarn present?: #{File.exist? 'bin/yarn'}"
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ install_template_path = File.expand_path("../../install/template.rb", __dir__).freeze
2
+
3
+ namespace :webpacker do
4
+ desc "Install Webpacker in this application"
5
+ task install: [:check_node, :check_yarn] do
6
+ install_template_path = File.expand_path("../../install/template.rb", __dir__)
7
+
8
+ require "rails/generators"
9
+ require "rails/generators/rails/app/app_generator"
10
+ generator = Rails::Generators::AppGenerator.new [Jets.root], {force: ENV['FORCE']}, destination_root: Jets.root
11
+ generator.apply install_template_path, verbose: false
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require "webpacker/configuration"
2
+
3
+ namespace :webpacker do
4
+ desc "Verifies if Webpacker is installed"
5
+ task verify_install: [:check_node, :check_yarn, :check_binstubs] do
6
+ unless Webpacker.config.config_path.exist?
7
+ $stderr.puts "Configuration config/webpacker.yml file not found. \n"\
8
+ "Make sure webpacker:install is run successfully before " \
9
+ "running dependent tasks"
10
+ exit!
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ namespace :webpacker do
2
+ desc "Support for older Rails versions. Install all JavaScript dependencies as specified via Yarn"
3
+ task :yarn_install do
4
+ system "yarn install --no-progress"
5
+
6
+ exit(1) unless $?.success?
7
+ end
8
+ end
9
+
10
+ def enhance_yarn_install
11
+ Rake::Task["yarn:install"].enhance do
12
+ exit(1) unless $?.success?
13
+ end
14
+ end
15
+
16
+ if Rake::Task.task_defined?("yarn:install")
17
+ enhance_yarn_install
18
+ else
19
+ # this is mainly for pre-5.x era
20
+ Rake::Task.define_task("yarn:install" => "webpacker:yarn_install")
21
+ end
@@ -0,0 +1,46 @@
1
+ require "active_support/core_ext/module/attribute_accessors"
2
+ require "active_support/core_ext/string/inquiry"
3
+ require "active_support/logger"
4
+ require "active_support/tagged_logging"
5
+
6
+ module Webpacker
7
+ extend self
8
+
9
+ def instance=(instance)
10
+ @instance = instance
11
+ end
12
+
13
+ def instance
14
+ @instance ||= Webpacker::Instance.new
15
+ end
16
+
17
+ def with_node_env(env)
18
+ original = ENV["NODE_ENV"]
19
+ ENV["NODE_ENV"] = env
20
+ yield
21
+ ensure
22
+ ENV["NODE_ENV"] = original
23
+ end
24
+
25
+ def ensure_log_goes_to_stdout
26
+ old_logger = Webpacker.logger
27
+ Webpacker.logger = ActiveSupport::Logger.new(STDOUT)
28
+ yield
29
+ ensure
30
+ Webpacker.logger = old_logger
31
+ end
32
+
33
+ delegate :logger, :logger=, :env, to: :instance
34
+ delegate :config, :compiler, :manifest, :commands, :dev_server, to: :instance
35
+ delegate :bootstrap, :clean, :clobber, :compile, to: :commands
36
+ end
37
+
38
+ require "webpacker/instance"
39
+ require "webpacker/env"
40
+ require "webpacker/configuration"
41
+ require "webpacker/manifest"
42
+ require "webpacker/compiler"
43
+ require "webpacker/commands"
44
+ require "webpacker/dev_server"
45
+
46
+ # require "webpacker/railtie" if defined?(Rails)
@@ -0,0 +1,50 @@
1
+ class Webpacker::Commands
2
+ delegate :config, :compiler, :manifest, :logger, to: :@webpacker
3
+
4
+ def initialize(webpacker)
5
+ @webpacker = webpacker
6
+ end
7
+
8
+ def clean(count = 2)
9
+ if config.public_output_path.exist? && config.public_manifest_path.exist? && versions.count > count
10
+ versions.drop(count).flat_map(&:last).each do |file|
11
+ File.delete(file) if File.file?(file)
12
+ logger.info "Removed #{file}"
13
+ end
14
+ end
15
+
16
+ true
17
+ end
18
+
19
+ def clobber
20
+ config.public_output_path.rmtree if config.public_output_path.exist?
21
+ config.cache_path.rmtree if config.cache_path.exist?
22
+ end
23
+
24
+ def bootstrap
25
+ manifest.refresh
26
+ end
27
+
28
+ def compile
29
+ compiler.compile.tap do |success|
30
+ manifest.refresh if success
31
+ end
32
+ end
33
+
34
+ private
35
+ def versions
36
+ all_files = Dir.glob("#{config.public_output_path}/**/*")
37
+ manifest_config = Dir.glob("#{config.public_manifest_path}*")
38
+
39
+ packs = all_files - manifest_config - current_version
40
+ packs.group_by { |file| File.mtime(file).utc.to_i }.sort.reverse
41
+ end
42
+
43
+ def current_version
44
+ manifest.refresh.values.map do |value|
45
+ next if value.is_a?(Hash)
46
+
47
+ File.join(config.root_path, "public", value)
48
+ end.compact
49
+ end
50
+ end
@@ -0,0 +1,107 @@
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
+ cattr_accessor(:watched_paths) { [] }
8
+
9
+ # Additional environment variables that the compiler is being run with
10
+ # Webpacker::Compiler.env['FRONTEND_API_KEY'] = 'your_secret_key'
11
+ cattr_accessor(:env) { {} }
12
+
13
+ delegate :config, :logger, to: :webpacker
14
+
15
+ def initialize(webpacker)
16
+ @webpacker = webpacker
17
+ end
18
+
19
+ def compile
20
+ if stale?
21
+ run_webpack.tap do |success|
22
+ # We used to only record the digest on success
23
+ # However, the output file is still written on error, (at least with ts-loader), meaning that the
24
+ # digest should still be updated. If it's not, you can end up in a situation where a recompile doesn't
25
+ # take place when it should.
26
+ # See https://github.com/rails/webpacker/issues/2113
27
+ record_compilation_digest
28
+ end
29
+ else
30
+ logger.info "Everything's up-to-date. Nothing to do"
31
+ true
32
+ end
33
+ end
34
+
35
+ # Returns true if all the compiled packs are up to date with the underlying asset files.
36
+ def fresh?
37
+ watched_files_digest == last_compilation_digest
38
+ end
39
+
40
+ # Returns true if the compiled packs are out of date with the underlying asset files.
41
+ def stale?
42
+ !fresh?
43
+ end
44
+
45
+ private
46
+ attr_reader :webpacker
47
+
48
+ def last_compilation_digest
49
+ compilation_digest_path.read if compilation_digest_path.exist? && config.public_manifest_path.exist?
50
+ rescue Errno::ENOENT, Errno::ENOTDIR
51
+ end
52
+
53
+ def watched_files_digest
54
+ files = Dir[*default_watched_paths, *watched_paths].reject { |f| File.directory?(f) }
55
+ file_ids = files.sort.map { |f| "#{File.basename(f)}/#{Digest::SHA1.file(f).hexdigest}" }
56
+ Digest::SHA1.hexdigest(file_ids.join("/"))
57
+ end
58
+
59
+ def record_compilation_digest
60
+ config.cache_path.mkpath
61
+ compilation_digest_path.write(watched_files_digest)
62
+ end
63
+
64
+ def run_webpack
65
+ logger.info "Compiling..."
66
+
67
+ stdout, stderr, status = Open3.capture3(
68
+ webpack_env,
69
+ "#{RbConfig.ruby} ./bin/webpack",
70
+ chdir: File.expand_path(config.root_path)
71
+ )
72
+
73
+ if status.success?
74
+ logger.info "Compiled all packs in #{config.public_output_path}"
75
+ logger.error "#{stderr}" unless stderr.empty?
76
+
77
+ if config.webpack_compile_output?
78
+ logger.info stdout
79
+ end
80
+ else
81
+ non_empty_streams = [stdout, stderr].delete_if(&:empty?)
82
+ logger.error "Compilation failed:\n#{non_empty_streams.join("\n\n")}"
83
+ end
84
+
85
+ status.success?
86
+ end
87
+
88
+ def default_watched_paths
89
+ [
90
+ *config.resolved_paths_globbed,
91
+ config.source_path_globbed,
92
+ "yarn.lock", "package.json",
93
+ "config/webpack/**/*"
94
+ ].freeze
95
+ end
96
+
97
+ def compilation_digest_path
98
+ config.cache_path.join("last-compilation-digest-#{webpacker.env}")
99
+ end
100
+
101
+ def webpack_env
102
+ return env unless defined?(ActionController::Base)
103
+
104
+ env.merge("WEBPACKER_ASSET_HOST" => ENV.fetch("WEBPACKER_ASSET_HOST", ActionController::Base.helpers.compute_asset_host),
105
+ "WEBPACKER_RELATIVE_URL_ROOT" => ENV.fetch("WEBPACKER_RELATIVE_URL_ROOT", ActionController::Base.relative_url_root))
106
+ end
107
+ end
@@ -0,0 +1,113 @@
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
+ attr_reader :root_path, :config_path, :env
7
+
8
+ def initialize(root_path:, config_path:, env:)
9
+ @root_path = root_path
10
+ @config_path = config_path
11
+ @env = env
12
+ end
13
+
14
+ def dev_server
15
+ fetch(:dev_server)
16
+ end
17
+
18
+ def compile?
19
+ fetch(:compile)
20
+ end
21
+
22
+ def source_path
23
+ root_path.join(fetch(:source_path))
24
+ end
25
+
26
+ def source_path_globbed
27
+ globbed_path_with_extensions(source_path.relative_path_from(root_path))
28
+ end
29
+
30
+ def resolved_paths
31
+ fetch(:resolved_paths)
32
+ end
33
+
34
+ def resolved_paths_globbed
35
+ resolved_paths.map { |p| globbed_path_with_extensions(p) }
36
+ end
37
+
38
+ def source_entry_path
39
+ source_path.join(fetch(:source_entry_path))
40
+ end
41
+
42
+ def public_path
43
+ root_path.join(fetch(:public_root_path))
44
+ end
45
+
46
+ def public_output_path
47
+ public_path.join(fetch(:public_output_path))
48
+ end
49
+
50
+ def public_manifest_path
51
+ public_output_path.join("manifest.json")
52
+ end
53
+
54
+ def cache_manifest?
55
+ fetch(:cache_manifest)
56
+ end
57
+
58
+ def cache_path
59
+ root_path.join(fetch(:cache_path))
60
+ end
61
+
62
+ def extensions
63
+ fetch(:extensions)
64
+ end
65
+
66
+ def check_yarn_integrity=(value)
67
+ data[:check_yarn_integrity] = value
68
+ end
69
+
70
+ def check_yarn_integrity?
71
+ fetch(:check_yarn_integrity)
72
+ end
73
+
74
+ def webpack_compile_output?
75
+ fetch(:webpack_compile_output)
76
+ end
77
+
78
+ def extract_css?
79
+ fetch(:extract_css)
80
+ end
81
+
82
+ private
83
+ def fetch(key)
84
+ data.fetch(key, defaults[key])
85
+ end
86
+
87
+ def data
88
+ @data ||= load
89
+ end
90
+
91
+ def load
92
+ YAML.load(config_path.read)[env].deep_symbolize_keys
93
+
94
+ rescue Errno::ENOENT => e
95
+ raise "Webpacker configuration file not found #{config_path}. " \
96
+ "Please run rails webpacker:install " \
97
+ "Error: #{e.message}"
98
+
99
+ rescue Psych::SyntaxError => e
100
+ raise "YAML syntax error occurred while parsing #{config_path}. " \
101
+ "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
102
+ "Error: #{e.message}"
103
+ end
104
+
105
+ def defaults
106
+ @defaults ||= \
107
+ HashWithIndifferentAccess.new(YAML.load_file(File.expand_path("../../install/config/webpacker.yml", __FILE__))[env])
108
+ end
109
+
110
+ def globbed_path_with_extensions(path)
111
+ "#{path}/**/*{#{extensions.join(',')}}"
112
+ end
113
+ end