webpacker 6.0.0.beta.7 → 6.0.0.rc.5

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/jest.yml +5 -2
  3. data/.github/workflows/js-lint.yml +4 -1
  4. data/.github/workflows/rubocop.yml +1 -1
  5. data/.github/workflows/ruby.yml +12 -12
  6. data/.node-version +1 -1
  7. data/.rubocop.yml +1 -0
  8. data/CHANGELOG.md +21 -10
  9. data/Gemfile.lock +83 -83
  10. data/README.md +160 -157
  11. data/config/webpacker.yml +1 -1
  12. data/docs/developing_webpacker.md +29 -0
  13. data/docs/troubleshooting.md +53 -23
  14. data/docs/v6_upgrade.md +31 -42
  15. data/gemfiles/Gemfile-rails-edge +1 -1
  16. data/gemfiles/Gemfile-rails.6.1.x +12 -0
  17. data/lib/install/bin/yarn +18 -0
  18. data/lib/install/config/webpacker.yml +14 -17
  19. data/lib/install/package.json +17 -0
  20. data/lib/install/packs/entrypoints/application.js +3 -4
  21. data/lib/install/template.rb +28 -15
  22. data/lib/tasks/webpacker/check_node.rake +3 -1
  23. data/lib/tasks/webpacker/check_yarn.rake +4 -2
  24. data/lib/tasks/webpacker/clobber.rake +1 -1
  25. data/lib/tasks/webpacker/verify_config.rake +14 -0
  26. data/lib/tasks/webpacker/verify_install.rake +1 -11
  27. data/lib/tasks/yarn.rake +36 -0
  28. data/lib/webpacker/commands.rb +19 -15
  29. data/lib/webpacker/configuration.rb +15 -4
  30. data/lib/webpacker/dev_server.rb +6 -0
  31. data/lib/webpacker/dev_server_runner.rb +6 -3
  32. data/lib/webpacker/env.rb +5 -1
  33. data/lib/webpacker/helper.rb +14 -8
  34. data/lib/webpacker/instance.rb +4 -0
  35. data/lib/webpacker/manifest.rb +1 -2
  36. data/lib/webpacker/railtie.rb +1 -2
  37. data/lib/webpacker/runner.rb +1 -1
  38. data/lib/webpacker/version.rb +1 -1
  39. data/lib/webpacker.rb +1 -1
  40. data/package/__tests__/development.js +4 -4
  41. data/package/__tests__/env.js +8 -4
  42. data/package/babel/preset.js +0 -1
  43. data/package/config.js +3 -3
  44. data/package/env.js +6 -3
  45. data/package/environments/__tests__/base.js +3 -3
  46. data/package/environments/base.js +12 -7
  47. data/package/environments/development.js +37 -33
  48. data/package/index.js +2 -0
  49. data/package/inliningCss.js +7 -0
  50. data/package/rules/file.js +1 -1
  51. data/package/rules/sass.js +1 -2
  52. data/package/utils/get_style_rule.js +4 -2
  53. data/package.json +25 -29
  54. data/test/command_test.rb +76 -0
  55. data/test/configuration_test.rb +1 -1
  56. data/test/dev_server_runner_test.rb +5 -2
  57. data/test/helper_test.rb +48 -34
  58. data/test/manifest_test.rb +10 -2
  59. data/test/mounted_app/test/dummy/config/webpacker.yml +1 -1
  60. data/test/test_app/config/webpacker.yml +1 -3
  61. data/test/test_app/config/webpacker_other_location.yml +79 -0
  62. data/test/test_app/public/packs/manifest.json +12 -5
  63. data/test/webpacker_test.rb +17 -0
  64. data/webpacker.gemspec +1 -1
  65. data/yarn.lock +2202 -2680
  66. metadata +18 -9
@@ -3,7 +3,9 @@ namespace :webpacker do
3
3
  desc "Verifies if Node.js is installed"
4
4
  task :check_node do
5
5
  begin
6
- raise Errno::ENOENT if `which node || which nodejs`.strip.empty?
6
+ which_command = Gem.win_platform? ? "where" : "which"
7
+ raise Errno::ENOENT if `#{which_command} node || #{which_command} nodejs`.strip.empty?
8
+
7
9
  node_version = `node -v || nodejs -v`.strip
8
10
  raise Errno::ENOENT if node_version.blank?
9
11
 
@@ -3,14 +3,16 @@ namespace :webpacker do
3
3
  desc "Verifies if Yarn is installed"
4
4
  task :check_yarn do
5
5
  begin
6
- raise Errno::ENOENT if `which yarn`.strip.empty?
6
+ which_command = Gem.win_platform? ? "where" : "which"
7
+ raise Errno::ENOENT if `#{which_command} yarn`.strip.empty?
8
+
7
9
  yarn_version = `yarn --version`.strip
8
10
  raise Errno::ENOENT if yarn_version.blank?
9
11
 
10
12
  pkg_path = Pathname.new("#{__dir__}/../../../package.json").realpath
11
13
  yarn_range = JSON.parse(pkg_path.read)["engines"]["yarn"]
12
14
  is_valid = SemanticRange.satisfies?(yarn_version, yarn_range) rescue false
13
- is_unsupported = SemanticRange.satisfies?(yarn_version, ">=3.0.0") rescue false
15
+ is_unsupported = SemanticRange.satisfies?(yarn_version, ">=4.0.0") rescue false
14
16
 
15
17
  unless is_valid
16
18
  $stderr.puts "Webpacker requires Yarn \"#{yarn_range}\" and you are using #{yarn_version}"
@@ -2,7 +2,7 @@ require "webpacker/configuration"
2
2
 
3
3
  namespace :webpacker do
4
4
  desc "Remove the webpack compiled output directory"
5
- task clobber: ["webpacker:verify_install", :environment] do
5
+ task clobber: ["webpacker:verify_config", :environment] do
6
6
  Webpacker.clobber
7
7
  $stdout.puts "Removed webpack output path directory #{Webpacker.config.public_output_path}"
8
8
  end
@@ -0,0 +1,14 @@
1
+ require "webpacker/configuration"
2
+
3
+ namespace :webpacker do
4
+ desc "Verifies if the Webpacker config is present"
5
+ task :verify_config do
6
+ unless Webpacker.config.config_path.exist?
7
+ path = Webpacker.config.config_path.relative_path_from(Pathname.new(pwd)).to_s
8
+ $stderr.puts "Configuration #{path} file not found. \n"\
9
+ "Make sure webpacker:install is run successfully before " \
10
+ "running dependent tasks"
11
+ exit!
12
+ end
13
+ end
14
+ end
@@ -1,14 +1,4 @@
1
- require "webpacker/configuration"
2
-
3
1
  namespace :webpacker do
4
2
  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
- path = Webpacker.config.config_path.relative_path_from(Pathname.new(pwd)).to_s
8
- $stderr.puts "Configuration #{path} file not found. \n"\
9
- "Make sure webpacker:install is run successfully before " \
10
- "running dependent tasks"
11
- exit!
12
- end
13
- end
3
+ task verify_install: [:verify_config, :check_node, :check_yarn, :check_binstubs]
14
4
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Duplicate of the yarn tasks still present in Rails until Webpacker <5 have been deprecated
4
+
5
+ namespace :yarn do
6
+ desc "Install all JavaScript dependencies as specified via Yarn"
7
+ task :install do
8
+ # Install only production deps when for not usual envs.
9
+ valid_node_envs = %w[test development production]
10
+ node_env = ENV.fetch("NODE_ENV") do
11
+ valid_node_envs.include?(Rails.env) ? Rails.env : "production"
12
+ end
13
+
14
+ yarn_flags =
15
+ if `#{RbConfig.ruby} "#{Rails.root}/bin/yarn" --version`.start_with?("1")
16
+ "--no-progress --frozen-lockfile"
17
+ else
18
+ "--immutable"
19
+ end
20
+
21
+ system(
22
+ { "NODE_ENV" => node_env },
23
+ "#{RbConfig.ruby} \"#{Rails.root}/bin/yarn\" install #{yarn_flags}",
24
+ exception: true
25
+ )
26
+ rescue Errno::ENOENT
27
+ $stderr.puts "bin/yarn was not found."
28
+ $stderr.puts "Please run `bundle exec rails app:update:bin` to create it."
29
+ exit 1
30
+ end
31
+ end
32
+
33
+ # Run Yarn prior to Sprockets assets precompilation, so dependencies are available for use.
34
+ if Rake::Task.task_defined?("assets:precompile") && File.exist?(Rails.root.join("bin", "yarn"))
35
+ Rake::Task["assets:precompile"].enhance [ "yarn:install" ]
36
+ end
@@ -17,20 +17,21 @@ class Webpacker::Commands
17
17
  #
18
18
  def clean(count = 2, age = 3600)
19
19
  if config.public_output_path.exist? && config.public_manifest_path.exist?
20
- versions
21
- .sort
22
- .reverse
23
- .each_with_index
24
- .drop_while do |(mtime, _), index|
25
- max_age = [0, Time.now - Time.at(mtime)].max
26
- max_age < age || index < count
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 }
27
28
  end
28
- .each do |(_, files), index|
29
- files.each do |file|
30
- if File.file?(file)
31
- File.delete(file)
32
- logger.info "Removed #{file}"
33
- end
29
+ .flatten
30
+ .compact
31
+ .each do |file|
32
+ if File.file?(file)
33
+ File.delete(file)
34
+ logger.info "Removed #{file}"
34
35
  end
35
36
  end
36
37
  end
@@ -54,12 +55,15 @@ class Webpacker::Commands
54
55
  end
55
56
 
56
57
  private
57
- def versions
58
+ def packs
58
59
  all_files = Dir.glob("#{config.public_output_path}/**/*")
59
60
  manifest_config = Dir.glob("#{config.public_manifest_path}*")
60
61
 
61
62
  packs = all_files - manifest_config - current_version
62
- packs.reject { |file| File.directory?(file) }.group_by { |file| File.mtime(file).utc.to_i }
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
63
67
  end
64
68
 
65
69
  def current_version
@@ -73,8 +73,12 @@ class Webpacker::Configuration
73
73
  end
74
74
 
75
75
  def load
76
- YAML.load(config_path.read)[env].deep_symbolize_keys
77
-
76
+ config = begin
77
+ YAML.load_file(config_path.to_s, aliases: true)
78
+ rescue ArgumentError
79
+ YAML.load_file(config_path.to_s)
80
+ end
81
+ config[env].deep_symbolize_keys
78
82
  rescue Errno::ENOENT => e
79
83
  raise "Webpacker configuration file not found #{config_path}. " \
80
84
  "Please run rails webpacker:install " \
@@ -87,7 +91,14 @@ class Webpacker::Configuration
87
91
  end
88
92
 
89
93
  def defaults
90
- @defaults ||= \
91
- HashWithIndifferentAccess.new(YAML.load_file(File.expand_path("../../install/config/webpacker.yml", __FILE__))[env])
94
+ @defaults ||= begin
95
+ path = File.expand_path("../../install/config/webpacker.yml", __FILE__)
96
+ config = begin
97
+ YAML.load_file(path, aliases: true)
98
+ rescue ArgumentError
99
+ YAML.load_file(path)
100
+ end
101
+ HashWithIndifferentAccess.new(config[env])
102
+ end
92
103
  end
93
104
  end
@@ -51,12 +51,18 @@ class Webpacker::DevServer
51
51
  fetch(:pretty)
52
52
  end
53
53
 
54
+ def hmr?
55
+ fetch(:hmr)
56
+ end
57
+
54
58
  def env_prefix
55
59
  config.dev_server.fetch(:env_prefix, DEFAULT_ENV_PREFIX)
56
60
  end
57
61
 
58
62
  private
59
63
  def fetch(key)
64
+ return nil unless config.dev_server.present?
65
+
60
66
  ENV["#{env_prefix}_#{key.upcase}"] || config.dev_server.fetch(key, defaults[key])
61
67
  end
62
68
 
@@ -20,7 +20,7 @@ module Webpacker
20
20
 
21
21
  @config = Configuration.new(
22
22
  root_path: app_root,
23
- config_path: app_root.join("config/webpacker.yml"),
23
+ config_path: Pathname.new(@webpacker_config),
24
24
  env: ENV["RAILS_ENV"]
25
25
  )
26
26
 
@@ -30,6 +30,7 @@ module Webpacker
30
30
  @port = dev_server.port
31
31
  @pretty = dev_server.pretty?
32
32
  @https = dev_server.https?
33
+ @hot = dev_server.hmr?
33
34
 
34
35
  rescue Errno::ENOENT, NoMethodError
35
36
  $stdout.puts "webpack dev_server configuration not found in #{@config.config_path}[#{ENV["RAILS_ENV"]}]."
@@ -64,7 +65,7 @@ module Webpacker
64
65
  def execute_cmd
65
66
  env = Webpacker::Compiler.env
66
67
  env["WEBPACKER_CONFIG"] = @webpacker_config
67
- env["WEBPACK_DEV_SERVER"] = "true"
68
+ env["WEBPACK_SERVE"] = "true"
68
69
 
69
70
  cmd = if node_modules_bin_exist?
70
71
  ["#{@node_modules_bin_path}/webpack", "serve"]
@@ -73,12 +74,14 @@ module Webpacker
73
74
  end
74
75
 
75
76
  if @argv.include?("--debug-webpacker")
76
- cmd = [ "node", "--inspect-brk"] + cmd
77
+ cmd = [ "node", "--inspect-brk", "--trace-warnings" ] + cmd
77
78
  @argv.delete "--debug-webpacker"
78
79
  end
79
80
 
80
81
  cmd += ["--config", @webpack_config]
81
82
  cmd += ["--progress", "--color"] if @pretty
83
+
84
+ cmd += ["--hot"] if @hot
82
85
  cmd += @argv
83
86
 
84
87
  Dir.chdir(@app_path) do
data/lib/webpacker/env.rb CHANGED
@@ -27,7 +27,11 @@ class Webpacker::Env
27
27
 
28
28
  def available_environments
29
29
  if config_path.exist?
30
- YAML.load(config_path.read).keys
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
31
35
  else
32
36
  [].freeze
33
37
  end
@@ -81,11 +81,11 @@ module Webpacker::Helper
81
81
  # Example:
82
82
  #
83
83
  # <%= javascript_pack_tag 'calendar', 'map', 'data-turbolinks-track': 'reload' %> # =>
84
- # <script src="/packs/vendor-16838bab065ae1e314.chunk.js" data-turbolinks-track="reload"></script>
85
- # <script src="/packs/calendar~runtime-16838bab065ae1e314.chunk.js" data-turbolinks-track="reload"></script>
86
- # <script src="/packs/calendar-1016838bab065ae1e314.chunk.js" data-turbolinks-track="reload"></script>
87
- # <script src="/packs/map~runtime-16838bab065ae1e314.chunk.js" data-turbolinks-track="reload"></script>
88
- # <script src="/packs/map-16838bab065ae1e314.chunk.js" data-turbolinks-track="reload"></script>
84
+ # <script src="/packs/vendor-16838bab065ae1e314.chunk.js" data-turbolinks-track="reload" defer="true"></script>
85
+ # <script src="/packs/calendar~runtime-16838bab065ae1e314.chunk.js" data-turbolinks-track="reload" defer="true"></script>
86
+ # <script src="/packs/calendar-1016838bab065ae1e314.chunk.js" data-turbolinks-track="reload" defer="true"></script>
87
+ # <script src="/packs/map~runtime-16838bab065ae1e314.chunk.js" data-turbolinks-track="reload" defer="true"></script>
88
+ # <script src="/packs/map-16838bab065ae1e314.chunk.js" data-turbolinks-track="reload" defer="true"></script>
89
89
  #
90
90
  # DO:
91
91
  #
@@ -95,8 +95,8 @@ module Webpacker::Helper
95
95
  #
96
96
  # <%= javascript_pack_tag 'calendar' %>
97
97
  # <%= javascript_pack_tag 'map' %>
98
- def javascript_pack_tag(*names, **options)
99
- javascript_include_tag(*sources_from_manifest_entrypoints(names, type: :javascript), **options)
98
+ def javascript_pack_tag(*names, defer: true, **options)
99
+ javascript_include_tag(*sources_from_manifest_entrypoints(names, type: :javascript), **options.tap { |o| o[:defer] = defer })
100
100
  end
101
101
 
102
102
  # Creates a link tag, for preloading, that references a given Webpacker asset.
@@ -128,6 +128,10 @@ module Webpacker::Helper
128
128
  # <link rel="stylesheet" media="screen" href="/packs/calendar-8c7ce31a.chunk.css" />
129
129
  # <link rel="stylesheet" media="screen" href="/packs/map-8c7ce31a.chunk.css" />
130
130
  #
131
+ # When using the webpack-dev-server, CSS is inlined so HMR can be turned on for CSS,
132
+ # including CSS modules
133
+ # <%= stylesheet_pack_tag 'calendar', 'map' %> # => nil
134
+ #
131
135
  # DO:
132
136
  #
133
137
  # <%= stylesheet_pack_tag 'calendar', 'map' %>
@@ -137,6 +141,8 @@ module Webpacker::Helper
137
141
  # <%= stylesheet_pack_tag 'calendar' %>
138
142
  # <%= stylesheet_pack_tag 'map' %>
139
143
  def stylesheet_pack_tag(*names, **options)
144
+ return "" if Webpacker.inlining_css?
145
+
140
146
  stylesheet_link_tag(*sources_from_manifest_entrypoints(names, type: :stylesheet), **options)
141
147
  end
142
148
 
@@ -147,7 +153,7 @@ module Webpacker::Helper
147
153
  end
148
154
 
149
155
  def resolve_path_to_image(name, **options)
150
- path = name.starts_with?("media/images/") ? name : "media/images/#{name}"
156
+ path = name.starts_with?("static/") ? name : "static/#{name}"
151
157
  path_to_asset(current_webpacker_instance.manifest.lookup!(path), options)
152
158
  rescue
153
159
  path_to_asset(current_webpacker_instance.manifest.lookup!(name), options)
@@ -34,4 +34,8 @@ class Webpacker::Instance
34
34
  def commands
35
35
  @commands ||= Webpacker::Commands.new self
36
36
  end
37
+
38
+ def inlining_css?
39
+ dev_server.hmr? && dev_server.running?
40
+ end
37
41
  end
@@ -91,8 +91,7 @@ class Webpacker::Manifest
91
91
  # manifest hash the entrypoints are defined by their pack name without the extension.
92
92
  # When the user provides a name with a file extension, we want to try to strip it off.
93
93
  def manifest_name(name, pack_type)
94
- return name if File.extname(name.to_s).empty?
95
- File.basename(name, ".#{pack_type}")
94
+ name.chomp(".#{pack_type}")
96
95
  end
97
96
 
98
97
  def manifest_type(pack_type)
@@ -8,8 +8,7 @@ class Webpacker::Engine < ::Rails::Engine
8
8
  config.webpacker = ActiveSupport::OrderedOptions.new
9
9
 
10
10
  initializer "webpacker.proxy" do |app|
11
- insert_middleware = Webpacker.config.dev_server.present? rescue nil
12
- if insert_middleware
11
+ if (Webpacker.config.dev_server.present? rescue nil)
13
12
  app.middleware.insert_before 0,
14
13
  Rails::VERSION::MAJOR >= 5 ?
15
14
  Webpacker::DevServerProxy : "Webpacker::DevServerProxy", ssl_verify_none: true
@@ -12,7 +12,7 @@ module Webpacker
12
12
  @app_path = File.expand_path(".", Dir.pwd)
13
13
  @node_modules_bin_path = ENV["WEBPACKER_NODE_MODULES_BIN_PATH"] || `yarn bin`.chomp
14
14
  @webpack_config = File.join(@app_path, "config/webpack/#{ENV["NODE_ENV"]}.js")
15
- @webpacker_config = File.join(@app_path, "config/webpacker.yml")
15
+ @webpacker_config = ENV["WEBPACKER_CONFIG"] || File.join(@app_path, "config/webpacker.yml")
16
16
 
17
17
  unless File.exist?(@webpack_config)
18
18
  $stderr.puts "webpack config #{@webpack_config} not found, please run 'bundle exec rails webpacker:install' to install Webpacker with default configs or add the missing config file for your custom environment."
@@ -1,4 +1,4 @@
1
1
  module Webpacker
2
2
  # Change the version in package.json too, please!
3
- VERSION = "6.0.0.beta.7".freeze
3
+ VERSION = "6.0.0.rc.5".freeze
4
4
  end
data/lib/webpacker.rb CHANGED
@@ -30,7 +30,7 @@ module Webpacker
30
30
  Webpacker.logger = old_logger
31
31
  end
32
32
 
33
- delegate :logger, :logger=, :env, to: :instance
33
+ delegate :logger, :logger=, :env, :inlining_css?, to: :instance
34
34
  delegate :config, :compiler, :manifest, :commands, :dev_server, to: :instance
35
35
  delegate :bootstrap, :clean, :clobber, :compile, to: :commands
36
36
  end
@@ -11,10 +11,10 @@ describe('Development environment', () => {
11
11
  describe('webpackConfig', () => {
12
12
  beforeEach(() => jest.resetModules())
13
13
 
14
- test('should use development config and environment including devServer if WEBPACK_DEV_SERVER', () => {
14
+ test('should use development config and environment including devServer if WEBPACK_SERVE', () => {
15
15
  process.env.RAILS_ENV = 'development'
16
16
  process.env.NODE_ENV = 'development'
17
- process.env.WEBPACK_DEV_SERVER = 'YES'
17
+ process.env.WEBPACK_DEV_SERVER = 'true'
18
18
  const { webpackConfig } = require('../index')
19
19
 
20
20
  expect(webpackConfig.output.path).toEqual(resolve('public', 'packs'))
@@ -23,12 +23,12 @@ describe('Development environment', () => {
23
23
  devServer: {
24
24
  host: 'localhost',
25
25
  port: 3035,
26
- injectClient: true
26
+ hot: false
27
27
  }
28
28
  })
29
29
  })
30
30
 
31
- test('should use development config and environment if WEBPACK_DEV_SERVER', () => {
31
+ test('should use development config and environment if WEBPACK_SERVE', () => {
32
32
  process.env.RAILS_ENV = 'development'
33
33
  process.env.NODE_ENV = 'development'
34
34
  process.env.WEBPACK_DEV_SERVER = undefined
@@ -15,7 +15,8 @@ describe('Env', () => {
15
15
  railsEnv: 'development',
16
16
  nodeEnv: 'development',
17
17
  isProduction: false,
18
- isDevelopment: true
18
+ isDevelopment: true,
19
+ runningWebpackDevServer: false
19
20
  })
20
21
  })
21
22
 
@@ -26,7 +27,8 @@ describe('Env', () => {
26
27
  railsEnv: 'development',
27
28
  nodeEnv: 'production',
28
29
  isProduction: true,
29
- isDevelopment: false
30
+ isDevelopment: false,
31
+ runningWebpackDevServer: false
30
32
  })
31
33
  })
32
34
 
@@ -37,7 +39,8 @@ describe('Env', () => {
37
39
  railsEnv: 'production',
38
40
  nodeEnv: 'production',
39
41
  isProduction: true,
40
- isDevelopment: false
42
+ isDevelopment: false,
43
+ runningWebpackDevServer: false
41
44
  })
42
45
  })
43
46
 
@@ -48,7 +51,8 @@ describe('Env', () => {
48
51
  railsEnv: 'staging',
49
52
  nodeEnv: 'production',
50
53
  isProduction: true,
51
- isDevelopment: false
54
+ isDevelopment: false,
55
+ runningWebpackDevServer: false
52
56
  })
53
57
  })
54
58
  })