diff --git a/Gemfile b/Gemfile index f45829379..8760baf61 100644 --- a/Gemfile +++ b/Gemfile @@ -5,6 +5,7 @@ gemspec gem "rails" gem "rake", ">= 11.1" gem "rack-proxy", require: false +gem "semantic_range", require: false group :test do gem "minitest", "~> 5.0" diff --git a/Gemfile.lock b/Gemfile.lock index 251abf40e..500dae0f2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,6 +5,7 @@ PATH activesupport (>= 4.2) rack-proxy (>= 0.6.1) railties (>= 4.2) + semantic_range (>= 2.3.0) GEM remote: https://rubygems.org/ @@ -136,6 +137,7 @@ GEM rubocop-performance (1.3.0) rubocop (>= 0.68.0) ruby-progressbar (1.10.1) + semantic_range (2.3.0) sprockets (4.0.0) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -165,6 +167,7 @@ DEPENDENCIES rake (>= 11.1) rubocop (< 0.69) rubocop-performance + semantic_range webpacker! BUNDLED WITH diff --git a/lib/tasks/webpacker/check_node.rake b/lib/tasks/webpacker/check_node.rake index 63cdd03d4..b6d03c290 100644 --- a/lib/tasks/webpacker/check_node.rake +++ b/lib/tasks/webpacker/check_node.rake @@ -1,3 +1,4 @@ +require "semantic_range" namespace :webpacker do desc "Verifies if Node.js is installed" task :check_node do @@ -6,19 +7,25 @@ namespace :webpacker do raise Errno::ENOENT if node_version.blank? pkg_path = Pathname.new("#{__dir__}/../../../package.json").realpath - node_requirement = JSON.parse(pkg_path.read)["engines"]["node"] + node_range = JSON.parse(pkg_path.read)["engines"]["node"] + is_valid = SemanticRange.satisfies?(node_version, node_range) rescue false + semver_major = node_version[/\d+/] rescue nil + is_unstable = semver_major.to_i.odd? rescue false - requirement = Gem::Requirement.new(node_requirement) - version = Gem::Version.new(node_version.strip.tr("v", "")) + if is_unstable + $stderr.puts "Warning: you are using an unstable release of Node.js (#{node_version}). If you encounter issues with Node.js, consider switching to an Active LTS release. More info: https://docs.npmjs.com/try-the-latest-stable-version-of-node" + end - unless requirement.satisfied_by?(version) - $stderr.puts "Webpacker requires Node.js #{requirement} and you are using #{version}" + unless is_valid + $stderr.puts "Webpacker requires Node.js \"#{node_range}\" and you are using #{node_version}" $stderr.puts "Please upgrade Node.js https://nodejs.org/en/download/" - $stderr.puts "Exiting!" && exit! + $stderr.puts "Exiting!" + exit! end rescue Errno::ENOENT $stderr.puts "Node.js not installed. Please download and install Node.js https://nodejs.org/en/download/" - $stderr.puts "Exiting!" && exit! + $stderr.puts "Exiting!" + exit! end end end diff --git a/lib/tasks/webpacker/check_yarn.rake b/lib/tasks/webpacker/check_yarn.rake index 3445da9e1..d7c863c1b 100644 --- a/lib/tasks/webpacker/check_yarn.rake +++ b/lib/tasks/webpacker/check_yarn.rake @@ -1,3 +1,4 @@ +require "semantic_range" namespace :webpacker do desc "Verifies if Yarn is installed" task :check_yarn do @@ -6,19 +7,25 @@ namespace :webpacker do raise Errno::ENOENT if yarn_version.blank? pkg_path = Pathname.new("#{__dir__}/../../../package.json").realpath - yarn_requirement = JSON.parse(pkg_path.read)["engines"]["yarn"] + yarn_range = JSON.parse(pkg_path.read)["engines"]["yarn"] + is_valid = SemanticRange.satisfies?(yarn_version, yarn_range) rescue false + is_unsupported = SemanticRange.satisfies?(yarn_version, ">=2.0.0") rescue false - requirement = Gem::Requirement.new(yarn_requirement) - version = Gem::Version.new(yarn_version) - - unless requirement.satisfied_by?(version) - $stderr.puts "Webpacker requires Yarn #{requirement} and you are using #{version}" - $stderr.puts "Please upgrade Yarn https://yarnpkg.com/lang/en/docs/install/" - $stderr.puts "Exiting!" && exit! + unless is_valid + $stderr.puts "Webpacker requires Yarn \"#{yarn_range}\" and you are using #{yarn_version}" + if is_unsupported + $stderr.puts "This version of Webpacker does not support Yarn #{yarn_version}. Please downgrade to a supported version of Yarn https://yarnpkg.com/lang/en/docs/install/" + $stderr.puts "For information on using Webpacker with Yarn 2.0, see https://github.com/rails/webpacker/issues/2112" + else + $stderr.puts "Please upgrade Yarn https://yarnpkg.com/lang/en/docs/install/" + end + $stderr.puts "Exiting!" + exit! end rescue Errno::ENOENT $stderr.puts "Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/" - $stderr.puts "Exiting!" && exit! + $stderr.puts "Exiting!" + exit! end end end diff --git a/lib/tasks/webpacker/clean.rake b/lib/tasks/webpacker/clean.rake index 9303267aa..6d9d54311 100644 --- a/lib/tasks/webpacker/clean.rake +++ b/lib/tasks/webpacker/clean.rake @@ -11,11 +11,15 @@ namespace :webpacker do end end -# Run clean if the assets:clean is run -if Rake::Task.task_defined?("assets:clean") - Rake::Task["assets:clean"].enhance do - Rake::Task["webpacker:clean"].invoke +skip_webpacker_clean = %w(no false n f).include?(ENV["WEBPACKER_PRECOMPILE"]) + +unless skip_webpacker_clean + # Run clean if the assets:clean is run + if Rake::Task.task_defined?("assets:clean") + Rake::Task["assets:clean"].enhance do + Rake::Task["webpacker:clean"].invoke + end + else + Rake::Task.define_task("assets:clean" => "webpacker:clean") end -else - Rake::Task.define_task("assets:clean" => "webpacker:clean") end diff --git a/lib/tasks/webpacker/clobber.rake b/lib/tasks/webpacker/clobber.rake index 748ccd178..bf28731af 100644 --- a/lib/tasks/webpacker/clobber.rake +++ b/lib/tasks/webpacker/clobber.rake @@ -8,9 +8,13 @@ namespace :webpacker do end end -# Run clobber if the assets:clobber is run -if Rake::Task.task_defined?("assets:clobber") - Rake::Task["assets:clobber"].enhance do - Rake::Task["webpacker:clobber"].invoke +skip_webpacker_clobber = %w(no false n f).include?(ENV["WEBPACKER_PRECOMPILE"]) + +unless skip_webpacker_clobber + # Run clobber if the assets:clobber is run + if Rake::Task.task_defined?("assets:clobber") + Rake::Task["assets:clobber"].enhance do + Rake::Task["webpacker:clobber"].invoke + end end end diff --git a/package.json b/package.json index 106120912..133e22a23 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ ], "engines": { "node": ">=10.13.0", - "yarn": ">=1.0.0" + "yarn": ">=1 <2" }, "dependencies": { "@babel/core": "^7.7.7", @@ -45,7 +45,7 @@ "regenerator-runtime": "^0.13.3", "sass-loader": "^7.3.1", "style-loader": "^1.1.2", - "terser-webpack-plugin": "^2.3.2", + "terser-webpack-plugin": "^2.3.4", "webpack": "^4.41.5", "webpack-assets-manifest": "^3.1.1", "webpack-cli": "^3.3.10", diff --git a/test/rake_tasks_test.rb b/test/rake_tasks_test.rb index eb6e547bd..bdeec2ad8 100644 --- a/test/rake_tasks_test.rb +++ b/test/rake_tasks_test.rb @@ -28,6 +28,17 @@ def test_rake_task_webpacker_check_binstubs refute_includes output, "webpack binstubs not found." end + def test_check_node_version + output = Dir.chdir(test_app_path) { `rake webpacker:check_node 2>&1` } + refute_includes output, "Webpacker requires Node.js" + end + + def test_check_yarn_version + output = Dir.chdir(test_app_path) { `rake webpacker:check_yarn 2>&1` } + refute_includes output, "Yarn not installed" + refute_includes output, "Webpacker requires Yarn" + end + def test_rake_webpacker_yarn_install_in_non_production_environments assert_includes test_app_dev_dependencies, "right-pad" diff --git a/webpacker.gemspec b/webpacker.gemspec index c056bac1e..6ae568f9d 100644 --- a/webpacker.gemspec +++ b/webpacker.gemspec @@ -17,9 +17,10 @@ Gem::Specification.new do |s| s.required_ruby_version = ">= 2.3.0" - s.add_dependency "activesupport", ">= 4.2" - s.add_dependency "railties", ">= 4.2" - s.add_dependency "rack-proxy", ">= 0.6.1" + s.add_dependency "activesupport", ">= 4.2" + s.add_dependency "railties", ">= 4.2" + s.add_dependency "rack-proxy", ">= 0.6.1" + s.add_dependency "semantic_range", ">= 2.3.0" s.add_development_dependency "bundler", ">= 1.3.0" s.add_development_dependency "rubocop", "< 0.69" diff --git a/yarn.lock b/yarn.lock index 6d64a3f30..a6c6dbd4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3621,6 +3621,11 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" @@ -4612,6 +4617,14 @@ jest-worker@^24.6.0, jest-worker@^24.9.0: merge-stream "^2.0.0" supports-color "^6.1.0" +jest-worker@^25.1.0: + version "25.1.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.1.0.tgz#75d038bad6fdf58eba0d2ec1835856c497e3907a" + integrity sha512-ZHhHtlxOWSxCoNOKHGbiLzXnl42ga9CxDr27H36Qn+15pQZd3R/F24jrmjDelw9j/iHUIWMWs08/u2QN50HHOg== + dependencies: + merge-stream "^2.0.0" + supports-color "^7.0.0" + jest@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171" @@ -5751,6 +5764,13 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" +p-limit@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" + integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -7327,6 +7347,14 @@ schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.1: ajv "^6.10.2" ajv-keywords "^3.4.1" +schema-utils@^2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.4.tgz#a27efbf6e4e78689d91872ee3ccfa57d7bdd0f53" + integrity sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ== + dependencies: + ajv "^6.10.2" + ajv-keywords "^3.4.1" + scss-tokenizer@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" @@ -7841,6 +7869,13 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +supports-color@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + svgo@^1.0.0: version "1.3.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" @@ -7917,15 +7952,16 @@ terser-webpack-plugin@^1.4.3: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser-webpack-plugin@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.2.tgz#6d3d1b0590c8f729bfbaeb7fb2528b8b62db4c74" - integrity sha512-SmvB/6gtEPv+CJ88MH5zDOsZdKXPS/Uzv2//e90+wM1IHFUhsguPKEILgzqrM1nQ4acRXN/SV4Obr55SXC+0oA== +terser-webpack-plugin@^2.3.4: + version "2.3.4" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.4.tgz#ac045703bd8da0936ce910d8fb6350d0e1dee5fe" + integrity sha512-Nv96Nws2R2nrFOpbzF6IxRDpIkkIfmhvOws+IqMvYdFLO7o6wAILWFKONFgaYy8+T4LVz77DQW0f7wOeDEAjrg== dependencies: cacache "^13.0.1" find-cache-dir "^3.2.0" - jest-worker "^24.9.0" - schema-utils "^2.6.1" + jest-worker "^25.1.0" + p-limit "^2.2.2" + schema-utils "^2.6.4" serialize-javascript "^2.1.2" source-map "^0.6.1" terser "^4.4.3"