From af16f6896104d1ffdee8a179e0ad6a6bbcc46f30 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 11 Aug 2017 14:34:49 -0500 Subject: [PATCH 1/8] Make debugging easier --- Gemfile | 1 + Gemfile.lock | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Gemfile b/Gemfile index 08ce6864c..32d7ff145 100644 --- a/Gemfile +++ b/Gemfile @@ -8,4 +8,5 @@ gem "rubocop", ">= 0.49", require: false group :test do gem "minitest", "~> 5.0" + gem "byebug" end diff --git a/Gemfile.lock b/Gemfile.lock index 4b8a5ac12..32e6f8e5f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -48,6 +48,7 @@ GEM arel (7.1.4) ast (2.3.0) builder (3.2.3) + byebug (9.0.6) concurrent-ruby (1.0.5) erubis (2.7.0) globalid (0.3.7) @@ -128,6 +129,7 @@ PLATFORMS DEPENDENCIES bundler (~> 1.12) + byebug minitest (~> 5.0) rails rake (>= 11.1) From 9251b0bf748fce9e4468aed90af62a4b0b324c05 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 11 Aug 2017 15:26:27 -0500 Subject: [PATCH 2/8] Move to a single singleton --- lib/install/angular.rb | 4 +- lib/install/elm.rb | 13 ++- lib/install/react.rb | 4 +- lib/install/template.rb | 2 +- lib/install/vue.rb | 8 +- lib/tasks/webpacker/clobber.rake | 5 +- lib/tasks/webpacker/compile.rake | 12 ++- lib/tasks/webpacker/verify_install.rake | 2 +- lib/webpacker.rb | 28 +++--- lib/webpacker/commands.rb | 22 +++++ lib/webpacker/compiler.rb | 65 +++++++------- lib/webpacker/configuration.rb | 87 ++++++++----------- lib/webpacker/env.rb | 26 ------ lib/webpacker/file_loader.rb | 29 ------- lib/webpacker/helper.rb | 4 +- lib/webpacker/instance.rb | 41 +++++++++ lib/webpacker/logger.rb | 17 ---- lib/webpacker/manifest.rb | 64 ++++++++------ test/compiler_test.rb | 20 ++--- test/configuration_test.rb | 41 ++++----- test/env_test.rb | 16 ---- test/helper_test.rb | 26 +++--- test/manifest_test.rb | 26 ++---- ...acker_test.rb => webpacker_test_helper.rb} | 7 ++ 24 files changed, 262 insertions(+), 307 deletions(-) create mode 100644 lib/webpacker/commands.rb delete mode 100644 lib/webpacker/env.rb delete mode 100644 lib/webpacker/file_loader.rb create mode 100644 lib/webpacker/instance.rb delete mode 100644 lib/webpacker/logger.rb delete mode 100644 test/env_test.rb rename test/{webpacker_test.rb => webpacker_test_helper.rb} (53%) diff --git a/lib/install/angular.rb b/lib/install/angular.rb index 09112d028..10f1df401 100644 --- a/lib/install/angular.rb +++ b/lib/install/angular.rb @@ -3,8 +3,8 @@ puts "Copying angular loader to config/webpack/loaders" copy_file "#{__dir__}/config/loaders/installers/angular.js", "config/webpack/loaders/angular.js" -puts "Copying angular example entry file to #{Webpacker::Configuration.entry_path}" -copy_file "#{__dir__}/examples/angular/hello_angular.js", "#{Webpacker::Configuration.entry_path}/hello_angular.js" +puts "Copying angular example entry file to #{Webpacker::Configuration.source_entry_path}" +copy_file "#{__dir__}/examples/angular/hello_angular.js", "#{Webpacker::Configuration.source_entry_path}/hello_angular.js" puts "Copying hello_angular app to #{Webpacker::Configuration.source_path}" directory "#{__dir__}/examples/angular/hello_angular", "#{Webpacker::Configuration.source_path}/hello_angular" diff --git a/lib/install/elm.rb b/lib/install/elm.rb index 033254436..d002e2bf9 100644 --- a/lib/install/elm.rb +++ b/lib/install/elm.rb @@ -4,12 +4,12 @@ copy_file "#{__dir__}/config/loaders/installers/elm.js", "config/webpack/loaders/elm.js" -puts "Copying elm example entry file to #{Webpacker::Configuration.entry_path}" -copy_file "#{__dir__}/examples/elm/Main.elm", "#{Webpacker::Configuration.entry_path}/Main.elm" +puts "Copying elm example entry file to #{Webpacker::Configuration.source_entry_path}" +copy_file "#{__dir__}/examples/elm/Main.elm", "#{Webpacker::Configuration.source_entry_path}/Main.elm" -puts "Copying elm app file to #{Webpacker::Configuration.entry_path}" +puts "Copying elm app file to #{Webpacker::Configuration.source_entry_path}" copy_file "#{__dir__}/examples/elm/hello_elm.js", - "#{Webpacker::Configuration.entry_path}/hello_elm.js" + "#{Webpacker::Configuration.source_entry_path}/hello_elm.js" puts "Installing all elm dependencies" run "yarn add elm elm-webpack-loader" @@ -17,11 +17,10 @@ run "yarn run elm package install -- --yes" puts "Updating Webpack paths to include Elm file extension" -insert_into_file Webpacker::Configuration.file_path, " - .elm\n", after: /extensions:\n/ +insert_into_file Webpacker::Configuration.config_path, " - .elm\n", after: /extensions:\n/ puts "Updating elm source location" -source_path = File.join(Webpacker::Configuration.source, Webpacker::Configuration.fetch(:source_entry_path)) -gsub_file "elm-package.json", /\"\.\"\n/, %("#{source_path}"\n) +gsub_file "elm-package.json", /\"\.\"\n/, %("#{Webpacker::Configuration.source_entry_path}"\n) puts "Updating .gitignore to include elm-stuff folder" insert_into_file ".gitignore", "/elm-stuff\n", before: "/node_modules\n" diff --git a/lib/install/react.rb b/lib/install/react.rb index 9e16414de..fc837cbf7 100644 --- a/lib/install/react.rb +++ b/lib/install/react.rb @@ -22,8 +22,8 @@ puts "Copying react loader to config/webpack/loaders" copy_file "#{__dir__}/config/loaders/installers/react.js", "config/webpack/loaders/react.js" -puts "Copying react example entry file to #{Webpacker::Configuration.entry_path}" -copy_file "#{__dir__}/examples/react/hello_react.jsx", "#{Webpacker::Configuration.entry_path}/hello_react.jsx" +puts "Copying react example entry file to #{Webpacker::Configuration.source_entry_path}" +copy_file "#{__dir__}/examples/react/hello_react.jsx", "#{Webpacker::Configuration.source_entry_path}/hello_react.jsx" puts "Installing all react dependencies" run "yarn add react react-dom babel-preset-react prop-types" diff --git a/lib/install/template.rb b/lib/install/template.rb index 9960facfc..888958a8e 100644 --- a/lib/install/template.rb +++ b/lib/install/template.rb @@ -12,7 +12,7 @@ copy_file "#{__dir__}/config/.babelrc", ".babelrc" puts "Creating javascript app source directory" -directory "#{__dir__}/javascript", "#{Webpacker::Configuration.source}" +directory "#{__dir__}/javascript", "app/javascript" puts "Copying binstubs" directory "#{__dir__}/bin", "bin" diff --git a/lib/install/vue.rb b/lib/install/vue.rb index 24f3c7ef7..9a9f8009d 100644 --- a/lib/install/vue.rb +++ b/lib/install/vue.rb @@ -3,11 +3,11 @@ puts "Copying vue loader to config/webpack/loaders" copy_file "#{__dir__}/config/loaders/installers/vue.js", "config/webpack/loaders/vue.js" -puts "Copying the example entry file to #{Webpacker::Configuration.entry_path}" -copy_file "#{__dir__}/examples/vue/hello_vue.js", "#{Webpacker::Configuration.entry_path}/hello_vue.js" +puts "Copying the example entry file to #{Webpacker::Configuration.source_entry_path}" +copy_file "#{__dir__}/examples/vue/hello_vue.js", "#{Webpacker::Configuration.source_entry_path}/hello_vue.js" -puts "Copying vue app file to #{Webpacker::Configuration.entry_path}" -copy_file "#{__dir__}/examples/vue/app.vue", "#{Webpacker::Configuration.entry_path}/app.vue" +puts "Copying vue app file to #{Webpacker::Configuration.source_entry_path}" +copy_file "#{__dir__}/examples/vue/app.vue", "#{Webpacker::Configuration.source_entry_path}/app.vue" puts "Installing all vue dependencies" run "yarn add vue vue-loader vue-template-compiler" diff --git a/lib/tasks/webpacker/clobber.rake b/lib/tasks/webpacker/clobber.rake index ec5d3962e..748ccd178 100644 --- a/lib/tasks/webpacker/clobber.rake +++ b/lib/tasks/webpacker/clobber.rake @@ -3,9 +3,8 @@ require "webpacker/configuration" namespace :webpacker do desc "Remove the webpack compiled output directory" task clobber: ["webpacker:verify_install", :environment] do - output_path = Webpacker::Configuration.output_path - FileUtils.rm_r(output_path) if File.exist?(output_path) - $stdout.puts "Removed webpack output path directory #{output_path}" + Webpacker.clobber + $stdout.puts "Removed webpack output path directory #{Webpacker.config.public_output_path}" end end diff --git a/lib/tasks/webpacker/compile.rake b/lib/tasks/webpacker/compile.rake index bb3f35c9c..877b89b81 100644 --- a/lib/tasks/webpacker/compile.rake +++ b/lib/tasks/webpacker/compile.rake @@ -1,10 +1,18 @@ $stdout.sync = true +def ensure_log_goes_to_stdout + old_logger = Webpacker.logger + Webpacker.logger = ActiveSupport::Logger.new(STDOUT) + yield +ensure + Webpacker.logger = old_logger +end + namespace :webpacker do desc "Compile javascript packs using webpack for production with digests" task compile: ["webpacker:verify_install", :environment] do - Webpacker.ensure_log_goes_to_stdout do - if Webpacker::Compiler.compile + ensure_log_goes_to_stdout do + if Webpacker.compile # Successful compilation! else # Failed compilation diff --git a/lib/tasks/webpacker/verify_install.rake b/lib/tasks/webpacker/verify_install.rake index ca20906d6..73f2adca8 100644 --- a/lib/tasks/webpacker/verify_install.rake +++ b/lib/tasks/webpacker/verify_install.rake @@ -3,7 +3,7 @@ require "webpacker/configuration" namespace :webpacker do desc "Verifies if webpacker is installed" task verify_install: [:check_node, :check_yarn, :check_binstubs] do - if File.exist?(Webpacker::Configuration.file_path) + if Webpacker.config.config_path.exist? $stdout.puts "Webpacker is installed 🎉 🍰" $stdout.puts "Using #{Webpacker::Configuration.file_path} file for setting up webpack paths" else diff --git a/lib/webpacker.rb b/lib/webpacker.rb index 958eff25d..893a73728 100644 --- a/lib/webpacker.rb +++ b/lib/webpacker.rb @@ -1,25 +1,27 @@ +require "active_support/core_ext/module/attribute_accessors" +require "active_support/logger" +require "active_support/tagged_logging" + module Webpacker extend self - - def bootstrap - Webpacker::Env.load - Webpacker::Configuration.load - Webpacker::Manifest.load + + def instance=(instance) + @instance = instance end - def compile - Webpacker::Compiler.compile - Webpacker::Manifest.load + def instance + @instance ||= Webpacker::Instance.new end - def env - Webpacker::Env.current - end + delegate :logger, :logger=, :env, to: :instance + delegate :config, :compiler, :manifest, :commands, to: :instance + delegate :bootstrap, :clobber, :compile, to: :commands end -require "webpacker/logger" -require "webpacker/env" +require "webpacker/instance" require "webpacker/configuration" require "webpacker/manifest" require "webpacker/compiler" +require "webpacker/commands" + require "webpacker/railtie" if defined?(Rails) diff --git a/lib/webpacker/commands.rb b/lib/webpacker/commands.rb new file mode 100644 index 000000000..69617ef77 --- /dev/null +++ b/lib/webpacker/commands.rb @@ -0,0 +1,22 @@ +class Webpacker::Commands + delegate :config, :compiler, :manifest, to: :@webpacker + + def initialize(webpacker) + @webpacker = webpacker + end + + def clobber + config.public_output_path.rmtree if config.public_output_path.exist? + config.cache_path.rmtree if config.cache_path.exist? + end + + def bootstrap + config.refresh + manifest.refresh + end + + def compile + compiler.compile + manifest.refresh + end +end diff --git a/lib/webpacker/compiler.rb b/lib/webpacker/compiler.rb index d85775e61..949f16b9e 100644 --- a/lib/webpacker/compiler.rb +++ b/lib/webpacker/compiler.rb @@ -1,20 +1,19 @@ require "open3" -require "webpacker/env" -require "webpacker/configuration" - -module Webpacker::Compiler - extend self - - delegate :cache_path, :output_path, :source, to: Webpacker::Configuration - delegate :logger, to: Webpacker +class Webpacker::Compiler # Additional paths that test compiler needs to watch # Webpacker::Compiler.watched_paths << 'bower_components' mattr_accessor(:watched_paths) { [] } + delegate :config, :logger, :env, to: :@webpacker + + def initialize(webpacker) + @webpacker = webpacker + end + def compile if stale? - cache_source_timestamp + record_compilation_timestamp run_webpack else logger.debug "No compiling needed as everything is fresh" @@ -23,11 +22,7 @@ def compile # Returns true if all the compiled packs are up to date with the underlying asset files. def fresh? - if cached_timestamp_path.exist? && output_path.exist? - cached_timestamp_path.read == current_source_timestamp - else - false - end + source_last_changed_at == source_compiled_from_last_change_at end # Returns true if the compiled packs are out of date with the underlying asset files. @@ -35,26 +30,19 @@ def stale? !fresh? end - # FIXME: Deprecate properly - alias_method :compile?, :fresh? - - def default_watched_paths - ["#{source}/**/*", "yarn.lock", "package.json", "config/webpack/**/*"].freeze - end - private - def current_source_timestamp - files = Dir[*default_watched_paths, *watched_paths].reject { |f| File.directory?(f) } - files.map { |f| File.mtime(f).utc.to_i }.max.to_s + def source_compiled_from_last_change_at + compilation_timestamp_path.read if compilation_timestamp_path.exist? && config.public_manifest_path.exist? end - def cache_source_timestamp - cache_path.mkpath - cached_timestamp_path.write(current_source_timestamp) + def source_last_changed_at + files = Dir[*default_watched_paths, *watched_paths].reject { |f| File.directory?(f) } + files.map { |f| File.mtime(f).utc.to_i }.max.to_s end - def cached_timestamp_path - cache_path.join(".compiler-timestamp") + def record_compilation_timestamp + config.cache_path.mkpath + compilation_timestamp_path.write(source_last_changed_at) end def run_webpack @@ -63,15 +51,24 @@ def run_webpack sterr, stdout, status = Open3.capture3(webpack_env, "#{RbConfig.ruby} ./bin/webpack") if status.success? - logger.info "Compiled all packs in #{Webpacker::Configuration.entry_path}" - true + logger.info "Compiled all packs in #{config.source_entry_path}" else - logger.error "Compilation Failed:\n#{sterr}\n#{stdout}" - false + logger.error "Compilation failed:\n#{sterr}\n#{stdout}" end + + status.success? + end + + + def default_watched_paths + ["#{config.source_path}/**/*", "yarn.lock", "package.json", "config/webpack/**/*"].freeze + end + + def compilation_timestamp_path + config.cache_path.join(".compiled-from-last-change-at") end def webpack_env - { "NODE_ENV" => Webpacker.env, "ASSET_HOST" => ActionController::Base.helpers.compute_asset_host } + { "NODE_ENV" => env, "ASSET_HOST" => ActionController::Base.helpers.compute_asset_host } end end diff --git a/lib/webpacker/configuration.rb b/lib/webpacker/configuration.rb index c04ce8bdd..b3eb77ee4 100644 --- a/lib/webpacker/configuration.rb +++ b/lib/webpacker/configuration.rb @@ -1,67 +1,52 @@ -# Loads webpacker configuration from config/webpacker.yml +class Webpacker::Configuration + delegate :root_path, :config_path, :env, to: :@webpacker -require "webpacker/file_loader" - -class Webpacker::Configuration < Webpacker::FileLoader - class << self - def entry_path - source_path.join(fetch(:source_entry_path)) - end - - def output_path - public_path.join(fetch(:public_output_path)) - end - - def manifest_path - output_path.join("manifest.json") - end + def initialize(webpacker) + @webpacker = webpacker + end - def source_path - Rails.root.join(source) - end + def refresh + @data = load + end - def public_path - Rails.root.join("public") - end + def source_path + root_path.join(data[:source_path]) + end - def file_path(root: Rails.root) - root.join("config/webpacker.yml") - end + def source_entry_path + source_path.join(data[:source_entry_path]) + end - def default_file_path - file_path(root: Pathname.new(__dir__).join("../install")) - end + def public_path + root_path.join("public") + end - def cache_path - Rails.root.join(fetch(:cache_path)) - end + def public_output_path + public_path.join(data[:public_output_path]) + end - def source - fetch(:source_path) - end + def public_manifest_path + public_output_path.join("manifest.json") + end - def compile? - fetch(:compile) - end + def cache_path + root_path.join(data[:cache_path]) + end - def fetch(key) - data.fetch(key, defaults[key]) - end + def compile? + data[:compile] + end + private def data - load if Webpacker.env.development? - ensure_loaded_instance(self) - instance.data + if env.development? + refresh + else + @data ||= load + end end - def defaults - @defaults ||= HashWithIndifferentAccess.new(YAML.load(default_file_path.read)[Webpacker.env]) - end - end - - private def load - return super unless File.exist?(@path) - HashWithIndifferentAccess.new(YAML.load(File.read(@path))[Webpacker.env]) + YAML.load(config_path.read)[env].deep_symbolize_keys end end diff --git a/lib/webpacker/env.rb b/lib/webpacker/env.rb deleted file mode 100644 index 32cc2220e..000000000 --- a/lib/webpacker/env.rb +++ /dev/null @@ -1,26 +0,0 @@ -# Singleton registry for determining NODE_ENV from config/webpacker.yml -require "webpacker/file_loader" - -class Webpacker::Env < Webpacker::FileLoader - DEFAULT = "production" - - class << self - def current - ensure_loaded_instance(self) - instance.data.inquiry - end - - def file_path - Rails.root.join("config", "webpacker.yml") - end - end - - private - def load - ENV["NODE_ENV"].presence_in(available_environments) || Rails.env.presence_in(available_environments) || DEFAULT - end - - def available_environments - File.exist?(@path) ? YAML.load(File.read(@path)).keys : [].freeze - end -end diff --git a/lib/webpacker/file_loader.rb b/lib/webpacker/file_loader.rb deleted file mode 100644 index 42eca50a0..000000000 --- a/lib/webpacker/file_loader.rb +++ /dev/null @@ -1,29 +0,0 @@ -# Provides a base singleton-configuration pattern for loading a file, given a path -class Webpacker::FileLoader - class NotFoundError < StandardError; end - class FileLoaderError < StandardError; end - - class_attribute :instance - attr_accessor :data - - class << self - def load(path = file_path) - self.instance = new(path) - end - - protected - def ensure_loaded_instance(klass) - raise Webpacker::FileLoader::FileLoaderError.new("#{klass.name}#load must be called first") unless instance - end - end - - private - def initialize(path) - @path = path - @data = load - end - - def load - {}.freeze - end -end diff --git a/lib/webpacker/helper.rb b/lib/webpacker/helper.rb index 0034ed099..191ad4adc 100644 --- a/lib/webpacker/helper.rb +++ b/lib/webpacker/helper.rb @@ -9,7 +9,7 @@ module Webpacker::Helper # In production mode: # <%= asset_pack_path 'calendar.css' %> # => "/packs/calendar-1016838bab065ae1e122.css" def asset_pack_path(name, **options) - asset_path(Webpacker::Manifest.lookup(name), **options) + asset_path(Webpacker.manifest.lookup(name), **options) end # Creates a script tag that references the named pack file, as compiled by Webpack per the entries list # in config/webpack/shared.js. By default, this list is auto-generated to match everything in @@ -47,7 +47,7 @@ def stylesheet_pack_tag(*names, **options) private def sources_from_pack_manifest(names, type:) - names.map { |name| Webpacker::Manifest.lookup(pack_name_with_extension(name, type: type)) } + names.map { |name| Webpacker.manifest.lookup(pack_name_with_extension(name, type: type)) } end def pack_name_with_extension(name, type:) diff --git a/lib/webpacker/instance.rb b/lib/webpacker/instance.rb new file mode 100644 index 000000000..d87d4ea72 --- /dev/null +++ b/lib/webpacker/instance.rb @@ -0,0 +1,41 @@ +class Webpacker::Instance + cattr_accessor(:logger) { ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT)) } + + attr_reader :root_path, :config_path + + def initialize(root_path: Rails.root, config_path: Rails.root.join("config/webpacker.yml")) + @root_path, @config_path = root_path, config_path + end + + def env + (ENV["NODE_ENV"].presence_in(available_environments) || + Rails.env.presence_in(available_environments) || + "production".freeze).inquiry + end + + def config + @config ||= Webpacker::Configuration.new self + end + + def compiler + @compiler ||= Webpacker::Compiler.new self + end + + def manifest + @manifest ||= Webpacker::Manifest.new self + end + + def commands + @commands ||= Webpacker::Commands.new self + end + + + private + def available_environments + if config_path.exist? + YAML.load(config_path.read).keys + else + [].freeze + end + end +end \ No newline at end of file diff --git a/lib/webpacker/logger.rb b/lib/webpacker/logger.rb deleted file mode 100644 index 61648afe4..000000000 --- a/lib/webpacker/logger.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "active_support/core_ext/module/attribute_accessors" -require "active_support/logger" -require "active_support/tagged_logging" - -module Webpacker::Logger - mattr_accessor(:logger) { ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT)) } - - def ensure_log_goes_to_stdout - old_logger = logger - self.logger = ActiveSupport::Logger.new(STDOUT) - yield - ensure - self.logger = old_logger - end -end - -Webpacker.extend Webpacker::Logger diff --git a/lib/webpacker/manifest.rb b/lib/webpacker/manifest.rb index 015b65f7f..8063fe4d0 100644 --- a/lib/webpacker/manifest.rb +++ b/lib/webpacker/manifest.rb @@ -1,5 +1,3 @@ -require "webpacker/file_loader" - # Singleton registry for accessing the packs path using a generated manifest. # This allows javascript_pack_tag, stylesheet_pack_tag, asset_pack_path to take a reference to, # say, "calendar.js" or "calendar.css" and turn it into "/packs/calendar.js" or @@ -11,40 +9,52 @@ # # When the configuration is set to on-demand compilation, with the `compile: true` option in # the webpacker.yml file, any lookups will be preceeded by a compilation if one is needed. -class Webpacker::Manifest < Webpacker::FileLoader - class << self - def file_path - Webpacker::Configuration.manifest_path +class Webpacker::Manifest + class MissingEntryError < StandardError; end + + delegate :config, :compiler, :env, to: :@webpacker + + def initialize(webpacker) + @webpacker = webpacker + end + + def refresh + @data = load + end + + def lookup(name) + compile + find name + end + + private + def compile + Webpacker.logger.tagged("Webpacker") { compiler.compile } if config.compile? end - def lookup(name) - if Webpacker::Configuration.compile? - compile_and_find!(name) - else - find!(name) - end + def find(name) + data[name.to_s] || handle_missing_entry(name) end - def lookup_path(name) - Rails.root.join(File.join(Webpacker::Configuration.public_path, lookup(name))) + def handle_missing_entry(name) + raise Webpacker::Manifest::MissingEntryError, + "Can't find #{name} in #{config.public_manifest_path}. Is webpack still compiling?" end - private - def find!(name) - ensure_loaded_instance(self) - instance.data[name.to_s] || - raise(Webpacker::FileLoader::NotFoundError.new("Can't find #{name} in #{file_path}. Is webpack still compiling?")) - end - def compile_and_find!(name) - Webpacker.logger.tagged("Webpacker") { Webpacker.compile } - find!(name) + def data + if env.development? + refresh + else + @data ||= load end - end + end - private def load - return super unless File.exist?(@path) - JSON.parse(File.read(@path)) + if config.public_manifest_path.exist? + JSON.parse config.public_manifest_path.read + else + {} + end end end diff --git a/test/compiler_test.rb b/test/compiler_test.rb index 3059ae6ac..e356b7594 100644 --- a/test/compiler_test.rb +++ b/test/compiler_test.rb @@ -1,22 +1,12 @@ -require "webpacker_test" +require "webpacker_test_helper" class CompilerTest < Minitest::Test - def test_default_watched_paths - assert_equal Webpacker::Compiler.default_watched_paths, ["app/javascript/**/*", "yarn.lock", "package.json", "config/webpack/**/*"] - end - - def test_empty_watched_paths - assert_equal Webpacker::Compiler.watched_paths, [] - end - - def test_watched_paths - Webpacker::Compiler.stub :watched_paths, ["Gemfile"] do - assert_equal Webpacker::Compiler.watched_paths, ["Gemfile"] - end + def setup + Webpacker.compiler.send(:compilation_timestamp_path).delete end def test_freshness - assert Webpacker::Compiler.stale? - assert !Webpacker::Compiler.fresh? + assert Webpacker.compiler.stale? + assert !Webpacker.compiler.fresh? end end diff --git a/test/configuration_test.rb b/test/configuration_test.rb index dc1d96f6c..4fdfa4d55 100644 --- a/test/configuration_test.rb +++ b/test/configuration_test.rb @@ -1,41 +1,32 @@ -require "webpacker_test" +require "webpacker_test_helper" class ConfigurationTest < Minitest::Test - def test_entry_path - entry_path = File.join(File.dirname(__FILE__), "test_app/app/javascript", "packs").to_s - assert_equal Webpacker::Configuration.entry_path.to_s, entry_path - end - - def test_file_path - file_path = File.join(File.dirname(__FILE__), "test_app/config", "webpacker.yml").to_s - assert_equal Webpacker::Configuration.file_path.to_s, file_path - end - - def test_manifest_path - manifest_path = File.join(File.dirname(__FILE__), "test_app/public/packs", "manifest.json").to_s - assert_equal Webpacker::Configuration.manifest_path.to_s, manifest_path + def test_source_path + source_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/app/javascript").to_s + assert_equal source_path, Webpacker.config.source_path.to_s end - def test_output_path - output_path = File.join(File.dirname(__FILE__), "test_app/public/packs").to_s - assert_equal Webpacker::Configuration.output_path.to_s, output_path + def test_source_entry_path + source_entry_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/app/javascript", "packs").to_s + assert_equal Webpacker.config.source_entry_path.to_s, source_entry_path end - def test_source - assert_equal Webpacker::Configuration.source.to_s, "app/javascript" + def test_public_output_path + public_output_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/public/packs").to_s + assert_equal Webpacker.config.public_output_path.to_s, public_output_path end - def test_source_path - source_path = File.join(File.dirname(__FILE__), "test_app/app/javascript").to_s - assert_equal Webpacker::Configuration.source_path.to_s, source_path + def test_public_manifest_path + public_manifest_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/public/packs", "manifest.json").to_s + assert_equal Webpacker.config.public_manifest_path.to_s, public_manifest_path end def test_cache_path - cache_path = File.join(File.dirname(__FILE__), "test_app/tmp/cache/webpacker").to_s - assert_equal Webpacker::Configuration.cache_path.to_s, cache_path + cache_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/tmp/cache/webpacker").to_s + assert_equal Webpacker.config.cache_path.to_s, cache_path end def test_compile? - refute Webpacker::Configuration.compile? + assert Webpacker.config.compile? end end diff --git a/test/env_test.rb b/test/env_test.rb deleted file mode 100644 index cab5acce9..000000000 --- a/test/env_test.rb +++ /dev/null @@ -1,16 +0,0 @@ -require "webpacker_test" - -class EnvTest < Minitest::Test - def test_current_env - assert_equal Webpacker::Env.current, "production" - assert_equal Webpacker.env, "production" - - assert Webpacker::Env.current.production? - assert Webpacker.env.production? - end - - def test_file_path - correct_path = File.join(File.dirname(__FILE__), "test_app/config", "webpacker.yml").to_s - assert_equal Webpacker::Env.file_path.to_s, correct_path - end -end diff --git a/test/helper_test.rb b/test/helper_test.rb index 527968b24..82c52c452 100644 --- a/test/helper_test.rb +++ b/test/helper_test.rb @@ -1,4 +1,4 @@ -require "webpacker_test" +require "webpacker_test_helper" class HelperTest < ActionView::TestCase def setup @@ -12,24 +12,28 @@ def test_asset_pack_path end def test_javascript_pack_tag - script = %() - assert_equal @view.javascript_pack_tag("bootstrap.js"), script + assert_equal \ + %(), + @view.javascript_pack_tag("bootstrap.js") end def test_javascript_pack_tag_splat - script = %(\n) + - %() - assert_equal @view.javascript_pack_tag("bootstrap.js", "application.js", defer: true), script + assert_equal \ + %(\n) + + %(), + @view.javascript_pack_tag("bootstrap.js", "application.js", defer: true) end def test_stylesheet_pack_tag - style = %() - assert_equal @view.stylesheet_pack_tag("bootstrap.css"), style + assert_equal \ + %(), + @view.stylesheet_pack_tag("bootstrap.css") end def test_stylesheet_pack_tag_splat - style = %(\n) + - %() - assert_equal @view.stylesheet_pack_tag("bootstrap.css", "application.css", media: "all"), style + assert_equal \ + %(\n) + + %(), + @view.stylesheet_pack_tag("bootstrap.css", "application.css", media: "all") end end diff --git a/test/manifest_test.rb b/test/manifest_test.rb index 528064800..c62a8df3a 100644 --- a/test/manifest_test.rb +++ b/test/manifest_test.rb @@ -1,32 +1,20 @@ -require "webpacker_test" +require "webpacker_test_helper" class ManifestTest < Minitest::Test - def test_file_path - file_path = File.join(File.dirname(__FILE__), "test_app/public/packs", "manifest.json").to_s - assert_equal Webpacker::Manifest.file_path.to_s, file_path - end - def test_lookup_exception - manifest_path = File.join(File.dirname(__FILE__), "test_app/public/packs", "manifest.json").to_s + manifest_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/public/packs", "manifest.json").to_s asset_file = "calendar.js" - Webpacker::Configuration.stub :compile?, false do - error = assert_raises Webpacker::FileLoader::NotFoundError do - Webpacker::Manifest.lookup(asset_file) + Webpacker.config.stub :compile?, false do + error = assert_raises Webpacker::Manifest::MissingEntryError do + Webpacker.manifest.lookup(asset_file) end - assert_equal error.message, "Can't find #{asset_file} in #{manifest_path}. Is webpack still compiling?" + assert_equal "Can't find #{asset_file} in #{manifest_path}. Is webpack still compiling?", error.message end end def test_lookup_success - asset_file = "bootstrap.js" - assert_equal Webpacker::Manifest.lookup(asset_file), "/packs/bootstrap-300631c4f0e0f9c865bc.js" - end - - def test_lookup_path - file_path = File.join(File.dirname(__FILE__), "test_app/public/packs", "bootstrap-300631c4f0e0f9c865bc.js").to_s - asset_file = "bootstrap.js" - assert_equal Webpacker::Manifest.lookup_path(asset_file).to_s, file_path + assert_equal Webpacker.manifest.lookup("bootstrap.js"), "/packs/bootstrap-300631c4f0e0f9c865bc.js" end end diff --git a/test/webpacker_test.rb b/test/webpacker_test_helper.rb similarity index 53% rename from test/webpacker_test.rb rename to test/webpacker_test_helper.rb index f05871147..07dc2596a 100644 --- a/test/webpacker_test.rb +++ b/test/webpacker_test_helper.rb @@ -3,8 +3,14 @@ require "minitest/autorun" require "rails" require "rails/test_help" +require "byebug" + require "webpacker" +Webpacker.instance = Webpacker::Instance.new \ + root_path: Pathname.new(File.expand_path("../test_app", __FILE__)), + config_path: Pathname.new(File.expand_path("../../lib/install/config/webpacker.yml", __FILE__)) + module TestApp class Application < ::Rails::Application config.root = File.join(File.dirname(__FILE__), "test_app") @@ -12,4 +18,5 @@ class Application < ::Rails::Application end end +Rails.backtrace_cleaner.remove_silencers! TestApp::Application.initialize! From ab6ed5401999aa73f2ef6357b37df110595770e9 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 11 Aug 2017 15:26:35 -0500 Subject: [PATCH 3/8] Missing space --- lib/tasks/webpacker/yarn_install.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/webpacker/yarn_install.rake b/lib/tasks/webpacker/yarn_install.rake index 40d632d07..c60978f68 100644 --- a/lib/tasks/webpacker/yarn_install.rake +++ b/lib/tasks/webpacker/yarn_install.rake @@ -1,5 +1,5 @@ namespace :webpacker do - desc "Support for older Rails versions.Install all JavaScript dependencies as specified via Yarn" + desc "Support for older Rails versions. Install all JavaScript dependencies as specified via Yarn" task :yarn_install, [:arg1, :arg2] do |task, args| system "yarn #{args[:arg1]} #{args[:arg2]}" end From 01653cc6468343118aa66b1bf5f92569be6025df Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 11 Aug 2017 15:27:16 -0500 Subject: [PATCH 4/8] Correct reference --- lib/tasks/webpacker/verify_install.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/webpacker/verify_install.rake b/lib/tasks/webpacker/verify_install.rake index 73f2adca8..902b2af39 100644 --- a/lib/tasks/webpacker/verify_install.rake +++ b/lib/tasks/webpacker/verify_install.rake @@ -5,7 +5,7 @@ namespace :webpacker do task verify_install: [:check_node, :check_yarn, :check_binstubs] do if Webpacker.config.config_path.exist? $stdout.puts "Webpacker is installed 🎉 🍰" - $stdout.puts "Using #{Webpacker::Configuration.file_path} file for setting up webpack paths" + $stdout.puts "Using #{Webpacker.config.config_path} file for setting up webpack paths" else $stderr.puts "Configuration config/webpacker.yml file not found. \n"\ "Make sure webpacker:install is run successfully before " \ From 67a97a1b5569b71b0f5e7c1ccc5709c065207ff6 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 11 Aug 2017 15:32:48 -0500 Subject: [PATCH 5/8] Ignore the temporary --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 207100846..f53d152a2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ /pkg /test/test_app/log node_modules +.byebug_history +/test/test_app/tmp From 1c68f2d845082e236774af3cf36664fb7f9b13c4 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 11 Aug 2017 15:38:00 -0500 Subject: [PATCH 6/8] Update references in the installers --- lib/install/angular.rb | 8 ++++---- lib/install/elm.rb | 12 ++++++------ lib/install/react.rb | 4 ++-- lib/install/vue.rb | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/install/angular.rb b/lib/install/angular.rb index 10f1df401..2b5073f54 100644 --- a/lib/install/angular.rb +++ b/lib/install/angular.rb @@ -3,11 +3,11 @@ puts "Copying angular loader to config/webpack/loaders" copy_file "#{__dir__}/config/loaders/installers/angular.js", "config/webpack/loaders/angular.js" -puts "Copying angular example entry file to #{Webpacker::Configuration.source_entry_path}" -copy_file "#{__dir__}/examples/angular/hello_angular.js", "#{Webpacker::Configuration.source_entry_path}/hello_angular.js" +puts "Copying angular example entry file to #{Webpacker.config.source_entry_path}" +copy_file "#{__dir__}/examples/angular/hello_angular.js", "#{Webpacker.config.source_entry_path}/hello_angular.js" -puts "Copying hello_angular app to #{Webpacker::Configuration.source_path}" -directory "#{__dir__}/examples/angular/hello_angular", "#{Webpacker::Configuration.source_path}/hello_angular" +puts "Copying hello_angular app to #{Webpacker.config.source_path}" +directory "#{__dir__}/examples/angular/hello_angular", "#{Webpacker.config.source_path}/hello_angular" puts "Copying tsconfig.json to the Rails root directory for typescript" copy_file "#{__dir__}/examples/angular/tsconfig.json", "tsconfig.json" diff --git a/lib/install/elm.rb b/lib/install/elm.rb index d002e2bf9..a815498bc 100644 --- a/lib/install/elm.rb +++ b/lib/install/elm.rb @@ -4,12 +4,12 @@ copy_file "#{__dir__}/config/loaders/installers/elm.js", "config/webpack/loaders/elm.js" -puts "Copying elm example entry file to #{Webpacker::Configuration.source_entry_path}" -copy_file "#{__dir__}/examples/elm/Main.elm", "#{Webpacker::Configuration.source_entry_path}/Main.elm" +puts "Copying elm example entry file to #{Webpacker.config.source_entry_path}" +copy_file "#{__dir__}/examples/elm/Main.elm", "#{Webpacker.config.source_entry_path}/Main.elm" -puts "Copying elm app file to #{Webpacker::Configuration.source_entry_path}" +puts "Copying elm app file to #{Webpacker.config.source_entry_path}" copy_file "#{__dir__}/examples/elm/hello_elm.js", - "#{Webpacker::Configuration.source_entry_path}/hello_elm.js" + "#{Webpacker.config.source_entry_path}/hello_elm.js" puts "Installing all elm dependencies" run "yarn add elm elm-webpack-loader" @@ -17,10 +17,10 @@ run "yarn run elm package install -- --yes" puts "Updating Webpack paths to include Elm file extension" -insert_into_file Webpacker::Configuration.config_path, " - .elm\n", after: /extensions:\n/ +insert_into_file Webpacker.config.config_path, " - .elm\n", after: /extensions:\n/ puts "Updating elm source location" -gsub_file "elm-package.json", /\"\.\"\n/, %("#{Webpacker::Configuration.source_entry_path}"\n) +gsub_file "elm-package.json", /\"\.\"\n/, %("#{Webpacker.config.source_entry_path}"\n) puts "Updating .gitignore to include elm-stuff folder" insert_into_file ".gitignore", "/elm-stuff\n", before: "/node_modules\n" diff --git a/lib/install/react.rb b/lib/install/react.rb index fc837cbf7..1eb4d8a25 100644 --- a/lib/install/react.rb +++ b/lib/install/react.rb @@ -22,8 +22,8 @@ puts "Copying react loader to config/webpack/loaders" copy_file "#{__dir__}/config/loaders/installers/react.js", "config/webpack/loaders/react.js" -puts "Copying react example entry file to #{Webpacker::Configuration.source_entry_path}" -copy_file "#{__dir__}/examples/react/hello_react.jsx", "#{Webpacker::Configuration.source_entry_path}/hello_react.jsx" +puts "Copying react example entry file to #{Webpacker.config.source_entry_path}" +copy_file "#{__dir__}/examples/react/hello_react.jsx", "#{Webpacker.config.source_entry_path}/hello_react.jsx" puts "Installing all react dependencies" run "yarn add react react-dom babel-preset-react prop-types" diff --git a/lib/install/vue.rb b/lib/install/vue.rb index 9a9f8009d..20f0424df 100644 --- a/lib/install/vue.rb +++ b/lib/install/vue.rb @@ -3,11 +3,11 @@ puts "Copying vue loader to config/webpack/loaders" copy_file "#{__dir__}/config/loaders/installers/vue.js", "config/webpack/loaders/vue.js" -puts "Copying the example entry file to #{Webpacker::Configuration.source_entry_path}" -copy_file "#{__dir__}/examples/vue/hello_vue.js", "#{Webpacker::Configuration.source_entry_path}/hello_vue.js" +puts "Copying the example entry file to #{Webpacker.config.source_entry_path}" +copy_file "#{__dir__}/examples/vue/hello_vue.js", "#{Webpacker.config.source_entry_path}/hello_vue.js" -puts "Copying vue app file to #{Webpacker::Configuration.source_entry_path}" -copy_file "#{__dir__}/examples/vue/app.vue", "#{Webpacker::Configuration.source_entry_path}/app.vue" +puts "Copying vue app file to #{Webpacker.config.source_entry_path}" +copy_file "#{__dir__}/examples/vue/app.vue", "#{Webpacker.config.source_entry_path}/app.vue" puts "Installing all vue dependencies" run "yarn add vue vue-loader vue-template-compiler" From 18ff191746209c45ea3440c41a7dc650a0587ea8 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 11 Aug 2017 15:44:46 -0500 Subject: [PATCH 7/8] Bring back the defaults after all Need a better system for ensuring that the config is kept updated with new keys before we nix it. --- lib/webpacker/configuration.rb | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/webpacker/configuration.rb b/lib/webpacker/configuration.rb index b3eb77ee4..f78504db8 100644 --- a/lib/webpacker/configuration.rb +++ b/lib/webpacker/configuration.rb @@ -10,11 +10,11 @@ def refresh end def source_path - root_path.join(data[:source_path]) + root_path.join(fetch(:source_path)) end def source_entry_path - source_path.join(data[:source_entry_path]) + source_path.join(fetch(:source_entry_path)) end def public_path @@ -22,7 +22,7 @@ def public_path end def public_output_path - public_path.join(data[:public_output_path]) + public_path.join(fetch(:public_output_path)) end def public_manifest_path @@ -30,14 +30,18 @@ def public_manifest_path end def cache_path - root_path.join(data[:cache_path]) + root_path.join(fetch(:cache_path)) end def compile? - data[:compile] + fetch(:compile) end private + def fetch(key) + data.fetch(key, defaults[key]) + end + def data if env.development? refresh @@ -49,4 +53,9 @@ def data def load YAML.load(config_path.read)[env].deep_symbolize_keys end + + def defaults + @defaults ||= \ + YAML.load(File.read(File.expand_path("../../install/config/webpacker.yml", __FILE__)))[env].deep_symbolize_keys + end end From ead55077d347b837471353dccd2cde1dc7bfa745 Mon Sep 17 00:00:00 2001 From: Gaurav Tiwari Date: Fri, 11 Aug 2017 22:25:16 +0100 Subject: [PATCH 8/8] Add back source_dir --- lib/install/template.rb | 2 +- lib/webpacker/configuration.rb | 6 +++++- test/configuration_test.rb | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/install/template.rb b/lib/install/template.rb index 888958a8e..963c880ac 100644 --- a/lib/install/template.rb +++ b/lib/install/template.rb @@ -12,7 +12,7 @@ copy_file "#{__dir__}/config/.babelrc", ".babelrc" puts "Creating javascript app source directory" -directory "#{__dir__}/javascript", "app/javascript" +directory "#{__dir__}/javascript", Webpacker.config.source_dir puts "Copying binstubs" directory "#{__dir__}/bin", "bin" diff --git a/lib/webpacker/configuration.rb b/lib/webpacker/configuration.rb index f78504db8..bf6e67f52 100644 --- a/lib/webpacker/configuration.rb +++ b/lib/webpacker/configuration.rb @@ -10,7 +10,7 @@ def refresh end def source_path - root_path.join(fetch(:source_path)) + root_path.join(source_dir) end def source_entry_path @@ -37,6 +37,10 @@ def compile? fetch(:compile) end + def source_dir + fetch(:source_path) + end + private def fetch(key) data.fetch(key, defaults[key]) diff --git a/test/configuration_test.rb b/test/configuration_test.rb index 4fdfa4d55..5f47dc3e0 100644 --- a/test/configuration_test.rb +++ b/test/configuration_test.rb @@ -1,6 +1,10 @@ require "webpacker_test_helper" class ConfigurationTest < Minitest::Test + def test_source + assert_equal "app/javascript", Webpacker.config.source_dir + end + def test_source_path source_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/app/javascript").to_s assert_equal source_path, Webpacker.config.source_path.to_s