webpacker 4.0.0.pre.3 → 4.0.0.rc.1

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.node-version +1 -1
  3. data/.travis.yml +6 -4
  4. data/CHANGELOG.md +38 -0
  5. data/CONTRIBUTING.md +33 -0
  6. data/Gemfile +1 -1
  7. data/Gemfile.lock +64 -59
  8. data/README.md +16 -4
  9. data/docs/assets.md +7 -4
  10. data/docs/css.md +51 -8
  11. data/docs/es6.md +1 -1
  12. data/docs/troubleshooting.md +1 -1
  13. data/docs/webpack.md +42 -1
  14. data/gemfiles/Gemfile-rails-edge +1 -1
  15. data/gemfiles/Gemfile-rails.4.2.x +1 -1
  16. data/gemfiles/Gemfile-rails.5.0.x +1 -1
  17. data/gemfiles/Gemfile-rails.5.1.x +1 -1
  18. data/gemfiles/Gemfile-rails.5.2.x +1 -1
  19. data/lib/install/coffee.rb +2 -2
  20. data/lib/install/config/babel.config.js +70 -0
  21. data/lib/install/config/postcss.config.js +12 -0
  22. data/lib/install/config/webpacker.yml +22 -0
  23. data/lib/install/elm.rb +2 -2
  24. data/lib/install/erb.rb +2 -2
  25. data/lib/install/examples/elm/Main.elm +5 -4
  26. data/lib/install/examples/elm/hello_elm.js +6 -2
  27. data/lib/install/examples/react/babel.config.js +83 -0
  28. data/lib/install/examples/vue/hello_vue.js +6 -4
  29. data/lib/install/loaders/typescript.js +8 -3
  30. data/lib/install/react.rb +6 -20
  31. data/lib/install/template.rb +5 -4
  32. data/lib/install/typescript.rb +3 -3
  33. data/lib/install/vue.rb +4 -4
  34. data/lib/tasks/webpacker/compile.rake +3 -5
  35. data/lib/tasks/webpacker/yarn_install.rake +1 -1
  36. data/lib/webpacker/compiler.rb +4 -13
  37. data/lib/webpacker/configuration.rb +8 -0
  38. data/lib/webpacker/dev_server.rb +0 -9
  39. data/lib/webpacker/dev_server_runner.rb +12 -5
  40. data/lib/webpacker/helper.rb +10 -14
  41. data/lib/webpacker/manifest.rb +58 -21
  42. data/lib/webpacker/railtie.rb +3 -2
  43. data/lib/webpacker/version.rb +1 -1
  44. data/lib/webpacker/webpack_runner.rb +13 -2
  45. data/package.json +31 -27
  46. data/package/__tests__/config.js +25 -3
  47. data/package/config.js +15 -7
  48. data/package/environments/__tests__/base.js +5 -3
  49. data/package/environments/base.js +41 -4
  50. data/package/environments/production.js +17 -6
  51. data/package/rules/babel.js +10 -4
  52. data/package/rules/file.js +2 -2
  53. data/package/rules/index.js +7 -2
  54. data/package/rules/node_modules.js +22 -0
  55. data/package/utils/__tests__/get_style_rule.js +20 -0
  56. data/package/utils/get_style_rule.js +6 -5
  57. data/package/utils/helpers.js +12 -1
  58. data/test/compiler_test.rb +2 -0
  59. data/test/dev_server_runner_test.rb +51 -0
  60. data/test/helper_test.rb +28 -5
  61. data/test/manifest_test.rb +10 -0
  62. data/test/rake_tasks_test.rb +34 -0
  63. data/test/test_app/config/application.rb +1 -0
  64. data/test/test_app/config/webpack/development.js +0 -0
  65. data/test/test_app/config/webpacker.yml +25 -0
  66. data/test/test_app/package.json +13 -0
  67. data/test/test_app/public/packs/manifest.json +10 -1
  68. data/test/test_app/yarn.lock +11 -0
  69. data/test/webpack_runner_test.rb +51 -0
  70. data/yarn.lock +2669 -1809
  71. metadata +20 -8
  72. data/lib/install/config/.babelrc +0 -41
  73. data/lib/install/config/.postcssrc.yml +0 -3
  74. data/lib/install/examples/react/.babelrc +0 -47
@@ -1,6 +1,11 @@
1
+ const PnpWebpackPlugin = require('pnp-webpack-plugin')
2
+
1
3
  module.exports = {
2
4
  test: /\.(ts|tsx)?(\.erb)?$/,
3
- use: [{
4
- loader: 'ts-loader'
5
- }]
5
+ use: [
6
+ {
7
+ loader: 'ts-loader',
8
+ options: PnpWebpackPlugin.tsLoaderOptions()
9
+ }
10
+ ]
6
11
  }
@@ -1,32 +1,18 @@
1
1
  require "webpacker/configuration"
2
+ require "fileutils"
2
3
 
3
- babelrc = Rails.root.join(".babelrc")
4
- babel_react_preset = ["@babel/preset-react", { "useBuiltIns": true }]
4
+ replace_babel_config = FileUtils.compare_file(Rails.root.join("babel.config.js"), "#{__dir__}/config/babel.config.js")
5
5
 
6
- if File.exist?(babelrc)
7
- react_babelrc = JSON.parse(File.read(babelrc))
8
- react_babelrc["presets"] ||= []
9
-
10
- unless react_babelrc["presets"].flatten.include?("@babel/preset-react")
11
- react_babelrc["presets"].push(babel_react_preset)
12
- say "Copying react preset to your .babelrc file"
13
-
14
- File.open(babelrc, "w") do |f|
15
- f.puts JSON.pretty_generate(react_babelrc)
16
- end
17
- end
18
- else
19
- say "Copying .babelrc to app root directory"
20
- copy_file "#{__dir__}/examples/react/.babelrc", ".babelrc"
21
- end
6
+ say "Copying babel.config.js to app root directory"
7
+ copy_file "#{__dir__}/examples/react/babel.config.js", "babel.config.js", force: replace_babel_config
22
8
 
23
9
  say "Copying react example entry file to #{Webpacker.config.source_entry_path}"
24
10
  copy_file "#{__dir__}/examples/react/hello_react.jsx", "#{Webpacker.config.source_entry_path}/hello_react.jsx"
25
11
 
26
12
  say "Updating webpack paths to include .jsx file extension"
27
- insert_into_file Webpacker.config.config_path, "- .jsx\n".indent(4), after: /extensions:\n/
13
+ insert_into_file Webpacker.config.config_path, "- .jsx\n".indent(4), after: /\s+extensions:\n/
28
14
 
29
15
  say "Installing all react dependencies"
30
- run "yarn add react react-dom @babel/preset-react prop-types"
16
+ run "yarn add react react-dom @babel/preset-react prop-types babel-plugin-transform-react-remove-prop-types"
31
17
 
32
18
  say "Webpacker now supports react.js 🎉", :green
@@ -4,11 +4,11 @@ copy_file "#{__dir__}/config/webpacker.yml", "config/webpacker.yml"
4
4
  puts "Copying webpack core config"
5
5
  directory "#{__dir__}/config/webpack", "config/webpack"
6
6
 
7
- say "Copying .postcssrc.yml to app root directory"
8
- copy_file "#{__dir__}/config/.postcssrc.yml", ".postcssrc.yml"
7
+ say "Copying postcss.config.js to app root directory"
8
+ copy_file "#{__dir__}/config/postcss.config.js", "postcss.config.js"
9
9
 
10
- say "Copying .babelrc to app root directory"
11
- copy_file "#{__dir__}/config/.babelrc", ".babelrc"
10
+ say "Copying babel.config.js to app root directory"
11
+ copy_file "#{__dir__}/config/babel.config.js", "babel.config.js"
12
12
 
13
13
  say "Copying .browserslistrc to app root directory"
14
14
  copy_file "#{__dir__}/config/.browserslistrc", ".browserslistrc"
@@ -27,6 +27,7 @@ if File.exists?(".gitignore")
27
27
  /public/packs
28
28
  /public/packs-test
29
29
  /node_modules
30
+ /yarn-error.log
30
31
  yarn-debug.log*
31
32
  .yarn-integrity
32
33
  EOS
@@ -24,17 +24,17 @@ insert_into_file Rails.root.join("config/webpack/environment.js").to_s,
24
24
  after: "require('@rails/webpacker')\n"
25
25
 
26
26
  insert_into_file Rails.root.join("config/webpack/environment.js").to_s,
27
- "environment.loaders.append('typescript', typescript)\n",
27
+ "environment.loaders.prepend('typescript', typescript)\n",
28
28
  before: "module.exports"
29
29
 
30
30
  say "Copying tsconfig.json to the Rails root directory for typescript"
31
31
  copy_file "#{__dir__}/examples/#{example_source}/tsconfig.json", "tsconfig.json"
32
32
 
33
33
  say "Updating webpack paths to include .ts file extension"
34
- insert_into_file Webpacker.config.config_path, "- .ts\n".indent(4), after: /extensions:\n/
34
+ insert_into_file Webpacker.config.config_path, "- .ts\n".indent(4), after: /\s+extensions:\n/
35
35
 
36
36
  say "Updating webpack paths to include .tsx file extension"
37
- insert_into_file Webpacker.config.config_path, "- .tsx\n".indent(4), after: /extensions:\n/
37
+ insert_into_file Webpacker.config.config_path, "- .tsx\n".indent(4), after: /\s+extensions:\n/
38
38
 
39
39
  say "Copying the example entry file to #{Webpacker.config.source_entry_path}"
40
40
  copy_file "#{__dir__}/examples/typescript/hello_typescript.ts",
@@ -9,7 +9,7 @@ insert_into_file Rails.root.join("config/webpack/environment.js").to_s,
9
9
  after: "require('@rails/webpacker')\n"
10
10
 
11
11
  insert_into_file Rails.root.join("config/webpack/environment.js").to_s,
12
- "environment.plugins.append('VueLoaderPlugin', new VueLoaderPlugin())\n",
12
+ "environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())\n",
13
13
  before: "module.exports"
14
14
 
15
15
  say "Adding vue loader to config/webpack/environment.js"
@@ -18,11 +18,11 @@ insert_into_file Rails.root.join("config/webpack/environment.js").to_s,
18
18
  after: "require('vue-loader')\n"
19
19
 
20
20
  insert_into_file Rails.root.join("config/webpack/environment.js").to_s,
21
- "environment.loaders.append('vue', vue)\n",
21
+ "environment.loaders.prepend('vue', vue)\n",
22
22
  before: "module.exports"
23
23
 
24
24
  say "Updating webpack paths to include .vue file extension"
25
- insert_into_file Webpacker.config.config_path, "- .vue\n".indent(4), after: /extensions:\n/
25
+ insert_into_file Webpacker.config.config_path, "- .vue\n".indent(4), after: /\s+extensions:\n/
26
26
 
27
27
  say "Copying the example entry file to #{Webpacker.config.source_entry_path}"
28
28
  copy_file "#{__dir__}/examples/vue/hello_vue.js",
@@ -33,7 +33,7 @@ copy_file "#{__dir__}/examples/vue/app.vue",
33
33
  "#{Webpacker.config.source_path}/app.vue"
34
34
 
35
35
  say "Installing all Vue dependencies"
36
- run "yarn add vue vue-loader@next vue-template-compiler"
36
+ run "yarn add vue vue-loader vue-template-compiler"
37
37
 
38
38
  if Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR > 1
39
39
  say "You need to enable unsafe-eval rule.", :yellow
@@ -9,11 +9,9 @@ ensure
9
9
  end
10
10
 
11
11
  def enhance_assets_precompile
12
- Rake::Task["assets:precompile"].enhance do
13
- unless Rake::Task.task_defined?("yarn:install")
14
- # For Rails < 5.1
15
- Rake::Task["webpacker:yarn_install"].invoke
16
- end
12
+ # For Rails < 5.1
13
+ deps = Rake::Task.task_defined?("yarn:install") ? [] : ["webpacker:yarn_install"]
14
+ Rake::Task["assets:precompile"].enhance(deps) do
17
15
  Rake::Task["webpacker:compile"].invoke
18
16
  end
19
17
  end
@@ -1,6 +1,6 @@
1
1
  namespace :webpacker do
2
2
  desc "Support for older Rails versions. Install all JavaScript dependencies as specified via Yarn"
3
3
  task :yarn_install do
4
- system "yarn install --no-progress --frozen-lockfile --production"
4
+ system "yarn install --no-progress"
5
5
  end
6
6
  end
@@ -18,9 +18,8 @@ class Webpacker::Compiler
18
18
 
19
19
  def compile
20
20
  if stale?
21
- record_compilation_digest
22
21
  run_webpack.tap do |success|
23
- remove_compilation_digest if !success
22
+ record_compilation_digest if success
24
23
  end
25
24
  else
26
25
  true
@@ -45,11 +44,7 @@ class Webpacker::Compiler
45
44
 
46
45
  def watched_files_digest
47
46
  files = Dir[*default_watched_paths, *watched_paths].reject { |f| File.directory?(f) }
48
- file_ids = if ENV["CI"]
49
- files.sort.map { |f| "#{File.basename(f)}/#{Digest::SHA1.file(f).hexdigest}" }
50
- else
51
- files.map { |f| "#{File.basename(f)}/#{File.mtime(f).utc.to_i}" }
52
- end
47
+ file_ids = files.sort.map { |f| "#{File.basename(f)}/#{Digest::SHA1.file(f).hexdigest}" }
53
48
  Digest::SHA1.hexdigest(file_ids.join("/"))
54
49
  end
55
50
 
@@ -58,18 +53,14 @@ class Webpacker::Compiler
58
53
  compilation_digest_path.write(watched_files_digest)
59
54
  end
60
55
 
61
- def remove_compilation_digest
62
- compilation_digest_path.delete if compilation_digest_path.exist?
63
- rescue Errno::ENOENT, Errno::ENOTDIR
64
- end
65
-
66
56
  def run_webpack
67
57
  logger.info "Compiling…"
68
58
 
69
59
  stdout, sterr , status = Open3.capture3(webpack_env, "#{RbConfig.ruby} #{@webpacker.root_path}/bin/webpack")
70
60
 
71
- if status.success?
61
+ if sterr == "" && status.success?
72
62
  logger.info "Compiled all packs in #{config.public_output_path}"
63
+ logger.info stdout if config.webpack_compile_output?
73
64
  else
74
65
  logger.error "Compilation failed:\n#{sterr}\n#{stdout}"
75
66
  end
@@ -67,6 +67,14 @@ class Webpacker::Configuration
67
67
  fetch(:check_yarn_integrity)
68
68
  end
69
69
 
70
+ def webpack_compile_output?
71
+ fetch(:webpack_compile_output)
72
+ end
73
+
74
+ def extract_css?
75
+ fetch(:extract_css)
76
+ end
77
+
70
78
  private
71
79
  def fetch(key)
72
80
  data.fetch(key, defaults[key])
@@ -20,15 +20,6 @@ class Webpacker::DevServer
20
20
  false
21
21
  end
22
22
 
23
- def hot_module_replacing?
24
- case fetch(:hmr)
25
- when true, "true"
26
- true
27
- else
28
- false
29
- end
30
- end
31
-
32
23
  def host
33
24
  fetch(:host)
34
25
  end
@@ -45,15 +45,22 @@ module Webpacker
45
45
 
46
46
  def execute_cmd
47
47
  env = Webpacker::Compiler.env
48
- cmd = [
49
- "#{@node_modules_bin_path}/webpack-dev-server",
50
- "--config", @webpack_config
51
- ]
48
+
49
+ cmd = if node_modules_bin_exist?
50
+ ["#{@node_modules_bin_path}/webpack-dev-server"]
51
+ else
52
+ ["yarn", "webpack-dev-server"]
53
+ end
54
+ cmd += ["--config", @webpack_config]
52
55
  cmd += ["--progress", "--color"] if @pretty
53
56
 
54
57
  Dir.chdir(@app_path) do
55
- exec env, *cmd
58
+ Kernel.exec env, *cmd
56
59
  end
57
60
  end
61
+
62
+ def node_modules_bin_exist?
63
+ File.exist?("#{@node_modules_bin_path}/webpack-dev-server")
64
+ end
58
65
  end
59
66
  end
@@ -5,13 +5,13 @@ module Webpacker::Helper
5
5
  #
6
6
  # Example:
7
7
  #
8
- # # In development mode with hot module replacement:
8
+ # # When extract_css is false in webpacker.yml and the file is a css:
9
9
  # <%= asset_pack_path 'calendar.css' %> # => nil
10
10
  #
11
- # # In production mode:
11
+ # # When extract_css is true in webpacker.yml or the file is not a css:
12
12
  # <%= asset_pack_path 'calendar.css' %> # => "/packs/calendar-1016838bab065ae1e122.css"
13
13
  def asset_pack_path(name, **options)
14
- unless stylesheet?(name) && Webpacker.dev_server.running? && Webpacker.dev_server.hot_module_replacing?
14
+ if Webpacker.config.extract_css? || !stylesheet?(name)
15
15
  asset_path(Webpacker.manifest.lookup!(name), **options)
16
16
  end
17
17
  end
@@ -22,13 +22,13 @@ module Webpacker::Helper
22
22
  #
23
23
  # Example:
24
24
  #
25
- # # In development mode with hot module replacement:
25
+ # # When extract_css is false in webpacker.yml and the file is a css:
26
26
  # <%= asset_pack_url 'calendar.css' %> # => nil
27
27
  #
28
- # # In production mode:
28
+ # # When extract_css is true in webpacker.yml or the file is not a css:
29
29
  # <%= asset_pack_url 'calendar.css' %> # => "http://example.com/packs/calendar-1016838bab065ae1e122.css"
30
30
  def asset_pack_url(name, **options)
31
- unless Webpacker.dev_server.running? && Webpacker.dev_server.hot_module_replacing?
31
+ if Webpacker.config.extract_css? || !stylesheet?(name)
32
32
  asset_url(Webpacker.manifest.lookup!(name), **options)
33
33
  end
34
34
  end
@@ -64,15 +64,15 @@ module Webpacker::Helper
64
64
  #
65
65
  # Examples:
66
66
  #
67
- # # In development mode with hot module replacement:
67
+ # # When extract_css is false in webpacker.yml:
68
68
  # <%= stylesheet_pack_tag 'calendar', 'data-turbolinks-track': 'reload' %> # =>
69
69
  # nil
70
70
  #
71
- # # In production mode:
71
+ # # When extract_css is true in webpacker.yml:
72
72
  # <%= stylesheet_pack_tag 'calendar', 'data-turbolinks-track': 'reload' %> # =>
73
73
  # <link rel="stylesheet" media="screen" href="/packs/calendar-1016838bab065ae1e122.css" data-turbolinks-track="reload" />
74
74
  def stylesheet_pack_tag(*names, **options)
75
- unless Webpacker.dev_server.running? && Webpacker.dev_server.hot_module_replacing?
75
+ if Webpacker.config.extract_css?
76
76
  stylesheet_link_tag(*sources_from_pack_manifest(names, type: :stylesheet), **options)
77
77
  end
78
78
  end
@@ -83,10 +83,6 @@ module Webpacker::Helper
83
83
  end
84
84
 
85
85
  def sources_from_pack_manifest(names, type:)
86
- names.map { |name| Webpacker.manifest.lookup!(pack_name_with_extension(name, type: type)) }
87
- end
88
-
89
- def pack_name_with_extension(name, type:)
90
- "#{name}#{compute_asset_extname(name, type: type)}"
86
+ names.map { |name| Webpacker.manifest.lookup!(name, type: type) }.flatten
91
87
  end
92
88
  end
@@ -4,7 +4,7 @@
4
4
  # "/packs/calendar-1016838bab065ae1e314.css".
5
5
  #
6
6
  # When the configuration is set to on-demand compilation, with the `compile: true` option in
7
- # the webpacker.yml file, any lookups will be preceeded by a compilation if one is needed.
7
+ # the webpacker.yml file, any lookups will be preceded by a compilation if one is needed.
8
8
  class Webpacker::Manifest
9
9
  class MissingEntryError < StandardError; end
10
10
 
@@ -18,13 +18,29 @@ class Webpacker::Manifest
18
18
  @data = load
19
19
  end
20
20
 
21
- def lookup(name)
21
+ def lookup(name, pack_type = {})
22
22
  compile if compiling?
23
- find name
23
+
24
+ # When using SplitChunks or RuntimeChunks the manifest hash will contain
25
+ # an extra object called "entrypoints". When the entrypoints key is not
26
+ # present in the manifest, or the name is not found in the entrypoints hash,
27
+ # it will raise a NoMethodError. If this happens, we should try to lookup
28
+ # a single instance of the pack based on the given name.
29
+ begin
30
+ manifest_pack_type = manifest_type(pack_type[:type])
31
+ manifest_pack_name = manifest_name(name, manifest_pack_type)
32
+
33
+ # Lookup the pack in the entrypoints of the manifest
34
+ find("entrypoints")[manifest_pack_name][manifest_pack_type]
35
+ rescue NoMethodError
36
+
37
+ # Lookup a single instance of the pack
38
+ find(full_pack_name(name, pack_type[:type]))
39
+ end
24
40
  end
25
41
 
26
- def lookup!(name)
27
- lookup(name) || handle_missing_entry(name)
42
+ def lookup!(name, pack_type = {})
43
+ lookup(name, pack_type) || handle_missing_entry(name)
28
44
  end
29
45
 
30
46
  private
@@ -36,14 +52,51 @@ class Webpacker::Manifest
36
52
  Webpacker.logger.tagged("Webpacker") { compiler.compile }
37
53
  end
38
54
 
55
+ def data
56
+ if config.cache_manifest?
57
+ @data ||= load
58
+ else
59
+ refresh
60
+ end
61
+ end
62
+
39
63
  def find(name)
40
64
  data[name.to_s].presence
41
65
  end
42
66
 
67
+ def full_pack_name(name, pack_type)
68
+ return name unless File.extname(name.to_s).empty?
69
+ "#{name}.#{manifest_type(pack_type)}"
70
+ end
71
+
43
72
  def handle_missing_entry(name)
44
73
  raise Webpacker::Manifest::MissingEntryError, missing_file_from_manifest_error(name)
45
74
  end
46
75
 
76
+ def load
77
+ if config.public_manifest_path.exist?
78
+ JSON.parse config.public_manifest_path.read
79
+ else
80
+ {}
81
+ end
82
+ end
83
+
84
+ # The `manifest_name` method strips of the file extension of the name, because in the
85
+ # manifest hash the entrypoints are defined by their pack name without the extension.
86
+ # When the user provides a name with a file extension, we want to try to strip it off.
87
+ def manifest_name(name, pack_type)
88
+ return name if File.extname(name.to_s).empty?
89
+ File.basename(name, pack_type)
90
+ end
91
+
92
+ def manifest_type(pack_type)
93
+ case pack_type
94
+ when :javascript then "js"
95
+ when :stylesheet then "css"
96
+ else pack_type.to_s
97
+ end
98
+ end
99
+
47
100
  def missing_file_from_manifest_error(bundle_name)
48
101
  <<-MSG
49
102
  Webpacker can't find #{bundle_name} in #{config.public_manifest_path}. Possible causes:
@@ -56,20 +109,4 @@ Your manifest contains:
56
109
  #{JSON.pretty_generate(@data)}
57
110
  MSG
58
111
  end
59
-
60
- def data
61
- if config.cache_manifest?
62
- @data ||= load
63
- else
64
- refresh
65
- end
66
- end
67
-
68
- def load
69
- if config.public_manifest_path.exist?
70
- JSON.parse config.public_manifest_path.read
71
- else
72
- {}
73
- end
74
- end
75
112
  end
@@ -30,13 +30,13 @@ class Webpacker::Engine < ::Rails::Engine
30
30
  # - add `config.webpacker.check_yarn_integrity = true`
31
31
  initializer "webpacker.yarn_check" do |app|
32
32
  if File.exist?("yarn.lock") && Webpacker.config.config_path.exist? && Webpacker.config.check_yarn_integrity?
33
- output = `yarn check --integrity 2>&1`
33
+ output = `yarn check --integrity && yarn check --verify-tree 2>&1`
34
34
 
35
35
  unless $?.success?
36
36
  $stderr.puts "\n\n"
37
37
  $stderr.puts "========================================"
38
38
  $stderr.puts " Your Yarn packages are out of date!"
39
- $stderr.puts " Please run `yarn install` to update."
39
+ $stderr.puts " Please run `yarn install --check-files` to update."
40
40
  $stderr.puts "========================================"
41
41
  $stderr.puts "\n\n"
42
42
  $stderr.puts "To disable this check, please change `check_yarn_integrity`"
@@ -83,6 +83,7 @@ class Webpacker::Engine < ::Rails::Engine
83
83
  if defined?(Rails::Server) || defined?(Rails::Console)
84
84
  Webpacker.bootstrap
85
85
  if defined?(Spring)
86
+ require "spring/watcher"
86
87
  Spring.after_fork { Webpacker.bootstrap }
87
88
  Spring.watch(Webpacker.config.config_path)
88
89
  end