shakapacker 6.0.0.rc.6

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 (147) hide show
  1. checksums.yaml +7 -0
  2. data/.eslintignore +4 -0
  3. data/.eslintrc.js +14 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
  5. data/.github/ISSUE_TEMPLATE/feature-request.md +18 -0
  6. data/.github/workflows/jest.yml +30 -0
  7. data/.github/workflows/js-lint.yml +31 -0
  8. data/.github/workflows/rubocop.yml +39 -0
  9. data/.github/workflows/ruby.yml +48 -0
  10. data/.gitignore +13 -0
  11. data/.node-version +1 -0
  12. data/.rubocop.yml +229 -0
  13. data/CHANGELOG.md +32 -0
  14. data/CONTRIBUTING.md +62 -0
  15. data/Gemfile +13 -0
  16. data/Gemfile.lock +183 -0
  17. data/MIT-LICENSE +20 -0
  18. data/README.md +666 -0
  19. data/Rakefile +11 -0
  20. data/config/README.md +3 -0
  21. data/config/webpacker.yml +1 -0
  22. data/docs/customizing_babel_config.md +59 -0
  23. data/docs/deployment.md +116 -0
  24. data/docs/developing_webpacker.md +29 -0
  25. data/docs/troubleshooting.md +212 -0
  26. data/docs/v6_upgrade.md +158 -0
  27. data/gemfiles/Gemfile-rails-edge +12 -0
  28. data/gemfiles/Gemfile-rails.5.2.x +9 -0
  29. data/gemfiles/Gemfile-rails.6.0.x +9 -0
  30. data/gemfiles/Gemfile-rails.6.1.x +12 -0
  31. data/lib/install/application.js +15 -0
  32. data/lib/install/bin/webpacker +15 -0
  33. data/lib/install/bin/webpacker-dev-server +18 -0
  34. data/lib/install/bin/yarn +18 -0
  35. data/lib/install/binstubs.rb +4 -0
  36. data/lib/install/config/webpack/webpack.config.js +5 -0
  37. data/lib/install/config/webpacker.yml +64 -0
  38. data/lib/install/package.json +15 -0
  39. data/lib/install/template.rb +100 -0
  40. data/lib/shakapacker/utils/git_utils.rb +23 -0
  41. data/lib/shakapacker/utils/version_syntax_converter.rb +24 -0
  42. data/lib/tasks/webpacker/binstubs.rake +15 -0
  43. data/lib/tasks/webpacker/check_binstubs.rake +12 -0
  44. data/lib/tasks/webpacker/check_node.rake +31 -0
  45. data/lib/tasks/webpacker/check_yarn.rake +33 -0
  46. data/lib/tasks/webpacker/clean.rake +25 -0
  47. data/lib/tasks/webpacker/clobber.rake +20 -0
  48. data/lib/tasks/webpacker/compile.rake +45 -0
  49. data/lib/tasks/webpacker/info.rake +21 -0
  50. data/lib/tasks/webpacker/install.rake +17 -0
  51. data/lib/tasks/webpacker/verify_config.rake +14 -0
  52. data/lib/tasks/webpacker/verify_install.rake +4 -0
  53. data/lib/tasks/webpacker/yarn_install.rake +18 -0
  54. data/lib/tasks/webpacker.rake +19 -0
  55. data/lib/tasks/yarn.rake +38 -0
  56. data/lib/webpacker/commands.rb +79 -0
  57. data/lib/webpacker/compiler.rb +130 -0
  58. data/lib/webpacker/configuration.rb +111 -0
  59. data/lib/webpacker/dev_server.rb +72 -0
  60. data/lib/webpacker/dev_server_proxy.rb +33 -0
  61. data/lib/webpacker/dev_server_runner.rb +96 -0
  62. data/lib/webpacker/env.rb +43 -0
  63. data/lib/webpacker/helper.rb +161 -0
  64. data/lib/webpacker/instance.rb +41 -0
  65. data/lib/webpacker/manifest.rb +120 -0
  66. data/lib/webpacker/railtie.rb +63 -0
  67. data/lib/webpacker/runner.rb +23 -0
  68. data/lib/webpacker/version.rb +4 -0
  69. data/lib/webpacker/webpack_runner.rb +58 -0
  70. data/lib/webpacker.rb +46 -0
  71. data/package/__tests__/config.js +34 -0
  72. data/package/__tests__/dev_server.js +45 -0
  73. data/package/__tests__/development.js +35 -0
  74. data/package/__tests__/env.js +58 -0
  75. data/package/__tests__/index.js +9 -0
  76. data/package/__tests__/production.js +29 -0
  77. data/package/__tests__/staging.js +30 -0
  78. data/package/__tests__/test.js +25 -0
  79. data/package/babel/preset.js +41 -0
  80. data/package/config.js +32 -0
  81. data/package/configPath.js +3 -0
  82. data/package/dev_server.js +20 -0
  83. data/package/env.js +27 -0
  84. data/package/environments/__tests__/base.js +69 -0
  85. data/package/environments/base.js +116 -0
  86. data/package/environments/development.js +55 -0
  87. data/package/environments/production.js +79 -0
  88. data/package/environments/test.js +3 -0
  89. data/package/index.js +33 -0
  90. data/package/inliningCss.js +7 -0
  91. data/package/rules/babel.js +30 -0
  92. data/package/rules/coffee.js +6 -0
  93. data/package/rules/css.js +3 -0
  94. data/package/rules/erb.js +15 -0
  95. data/package/rules/file.js +23 -0
  96. data/package/rules/index.js +18 -0
  97. data/package/rules/less.js +22 -0
  98. data/package/rules/raw.js +5 -0
  99. data/package/rules/sass.js +16 -0
  100. data/package/rules/stylus.js +26 -0
  101. data/package/utils/get_style_rule.js +37 -0
  102. data/package/utils/helpers.js +51 -0
  103. data/package.json +71 -0
  104. data/rakelib/release.rake +57 -0
  105. data/test/command_test.rb +109 -0
  106. data/test/compiler_test.rb +68 -0
  107. data/test/configuration_test.rb +78 -0
  108. data/test/dev_server_runner_test.rb +81 -0
  109. data/test/dev_server_test.rb +47 -0
  110. data/test/engine_rake_tasks_test.rb +39 -0
  111. data/test/env_test.rb +23 -0
  112. data/test/helper_test.rb +159 -0
  113. data/test/manifest_test.rb +89 -0
  114. data/test/mounted_app/Rakefile +4 -0
  115. data/test/mounted_app/test/dummy/Rakefile +3 -0
  116. data/test/mounted_app/test/dummy/bin/rails +3 -0
  117. data/test/mounted_app/test/dummy/bin/rake +3 -0
  118. data/test/mounted_app/test/dummy/config/application.rb +10 -0
  119. data/test/mounted_app/test/dummy/config/environment.rb +3 -0
  120. data/test/mounted_app/test/dummy/config/webpacker.yml +75 -0
  121. data/test/mounted_app/test/dummy/config.ru +5 -0
  122. data/test/mounted_app/test/dummy/package.json +7 -0
  123. data/test/rake_tasks_test.rb +71 -0
  124. data/test/test_app/Rakefile +3 -0
  125. data/test/test_app/app/packs/entrypoints/application.js +10 -0
  126. data/test/test_app/app/packs/entrypoints/multi_entry.css +4 -0
  127. data/test/test_app/app/packs/entrypoints/multi_entry.js +4 -0
  128. data/test/test_app/bin/webpacker +14 -0
  129. data/test/test_app/bin/webpacker-dev-server +14 -0
  130. data/test/test_app/config/application.rb +11 -0
  131. data/test/test_app/config/environment.rb +4 -0
  132. data/test/test_app/config/initializers/inspect_autoload_paths.rb +1 -0
  133. data/test/test_app/config/webpack/webpack.config.js +0 -0
  134. data/test/test_app/config/webpacker.yml +77 -0
  135. data/test/test_app/config/webpacker_other_location.yml +79 -0
  136. data/test/test_app/config/webpacker_public_root.yml +18 -0
  137. data/test/test_app/config.ru +5 -0
  138. data/test/test_app/package.json +13 -0
  139. data/test/test_app/public/packs/manifest.json +50 -0
  140. data/test/test_app/some.config.js +0 -0
  141. data/test/test_app/yarn.lock +11 -0
  142. data/test/test_helper.rb +33 -0
  143. data/test/webpack_runner_test.rb +57 -0
  144. data/test/webpacker_test.rb +34 -0
  145. data/webpacker.gemspec +31 -0
  146. data/yarn.lock +4029 -0
  147. metadata +331 -0
@@ -0,0 +1,161 @@
1
+ module Webpacker::Helper
2
+ # Returns the current Webpacker instance.
3
+ # Could be overridden to use multiple Webpacker
4
+ # configurations within the same app (e.g. with engines).
5
+ def current_webpacker_instance
6
+ Webpacker.instance
7
+ end
8
+
9
+ # Computes the relative path for a given Webpacker asset.
10
+ # Returns the relative path using manifest.json and passes it to path_to_asset helper.
11
+ # This will use path_to_asset internally, so most of their behaviors will be the same.
12
+ #
13
+ # Example:
14
+ #
15
+ # <%= asset_pack_path 'calendar.css' %> # => "/packs/calendar-1016838bab065ae1e122.css"
16
+ def asset_pack_path(name, **options)
17
+ path_to_asset(current_webpacker_instance.manifest.lookup!(name), options)
18
+ end
19
+
20
+ # Computes the absolute path for a given Webpacker asset.
21
+ # Returns the absolute path using manifest.json and passes it to url_to_asset helper.
22
+ # This will use url_to_asset internally, so most of their behaviors will be the same.
23
+ #
24
+ # Example:
25
+ #
26
+ # <%= asset_pack_url 'calendar.css' %> # => "http://example.com/packs/calendar-1016838bab065ae1e122.css"
27
+ def asset_pack_url(name, **options)
28
+ url_to_asset(current_webpacker_instance.manifest.lookup!(name), options)
29
+ end
30
+
31
+ # Computes the relative path for a given Webpacker image with the same automated processing as image_pack_tag.
32
+ # Returns the relative path using manifest.json and passes it to path_to_asset helper.
33
+ # This will use path_to_asset internally, so most of their behaviors will be the same.
34
+ def image_pack_path(name, **options)
35
+ resolve_path_to_image(name, **options)
36
+ end
37
+
38
+ # Computes the absolute path for a given Webpacker image with the same automated
39
+ # processing as image_pack_tag. Returns the relative path using manifest.json
40
+ # and passes it to path_to_asset helper. This will use path_to_asset internally,
41
+ # so most of their behaviors will be the same.
42
+ def image_pack_url(name, **options)
43
+ resolve_path_to_image(name, **options.merge(protocol: :request))
44
+ end
45
+
46
+ # Creates an image tag that references the named pack file.
47
+ #
48
+ # Example:
49
+ #
50
+ # <%= image_pack_tag 'application.png', size: '16x10', alt: 'Edit Entry' %>
51
+ # <img alt='Edit Entry' src='/packs/application-k344a6d59eef8632c9d1.png' width='16' height='10' />
52
+ #
53
+ # <%= image_pack_tag 'picture.png', srcset: { 'picture-2x.png' => '2x' } %>
54
+ # <img srcset= "/packs/picture-2x-7cca48e6cae66ec07b8e.png 2x" src="/packs/picture-c38deda30895059837cf.png" >
55
+ def image_pack_tag(name, **options)
56
+ if options[:srcset] && !options[:srcset].is_a?(String)
57
+ options[:srcset] = options[:srcset].map do |src_name, size|
58
+ "#{resolve_path_to_image(src_name)} #{size}"
59
+ end.join(", ")
60
+ end
61
+
62
+ image_tag(resolve_path_to_image(name), options)
63
+ end
64
+
65
+ # Creates a link tag for a favicon that references the named pack file.
66
+ #
67
+ # Example:
68
+ #
69
+ # <%= favicon_pack_tag 'mb-icon.png', rel: 'apple-touch-icon', type: 'image/png' %>
70
+ # <link href="/packs/mb-icon-k344a6d59eef8632c9d1.png" rel="apple-touch-icon" type="image/png" />
71
+ def favicon_pack_tag(name, **options)
72
+ favicon_link_tag(resolve_path_to_image(name), options)
73
+ end
74
+
75
+ # Creates script tags that reference the js chunks from entrypoints when using split chunks API,
76
+ # as compiled by webpack per the entries list in package/environments/base.js.
77
+ # By default, this list is auto-generated to match everything in
78
+ # app/packs/entrypoints/*.js and all the dependent chunks. In production mode, the digested reference is automatically looked up.
79
+ # See: https://webpack.js.org/plugins/split-chunks-plugin/
80
+ #
81
+ # Example:
82
+ #
83
+ # <%= javascript_pack_tag 'calendar', 'map', 'data-turbolinks-track': 'reload' %> # =>
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
+ #
90
+ # DO:
91
+ #
92
+ # <%= javascript_pack_tag 'calendar', 'map' %>
93
+ #
94
+ # DON'T:
95
+ #
96
+ # <%= javascript_pack_tag 'calendar' %>
97
+ # <%= javascript_pack_tag 'map' %>
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
+ end
101
+
102
+ # Creates a link tag, for preloading, that references a given Webpacker asset.
103
+ # In production mode, the digested reference is automatically looked up.
104
+ # See: https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
105
+ #
106
+ # Example:
107
+ #
108
+ # <%= preload_pack_asset 'fonts/fa-regular-400.woff2' %> # =>
109
+ # <link rel="preload" href="/packs/fonts/fa-regular-400-944fb546bd7018b07190a32244f67dc9.woff2" as="font" type="font/woff2" crossorigin="anonymous">
110
+ def preload_pack_asset(name, **options)
111
+ if self.class.method_defined?(:preload_link_tag)
112
+ preload_link_tag(current_webpacker_instance.manifest.lookup!(name), options)
113
+ else
114
+ raise "You need Rails >= 5.2 to use this tag."
115
+ end
116
+ end
117
+
118
+ # Creates link tags that reference the css chunks from entrypoints when using split chunks API,
119
+ # as compiled by webpack per the entries list in package/environments/base.js.
120
+ # By default, this list is auto-generated to match everything in
121
+ # app/packs/entrypoints/*.js and all the dependent chunks. In production mode, the digested reference is automatically looked up.
122
+ # See: https://webpack.js.org/plugins/split-chunks-plugin/
123
+ #
124
+ # Examples:
125
+ #
126
+ # <%= stylesheet_pack_tag 'calendar', 'map' %> # =>
127
+ # <link rel="stylesheet" media="screen" href="/packs/3-8c7ce31a.chunk.css" />
128
+ # <link rel="stylesheet" media="screen" href="/packs/calendar-8c7ce31a.chunk.css" />
129
+ # <link rel="stylesheet" media="screen" href="/packs/map-8c7ce31a.chunk.css" />
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
+ #
135
+ # DO:
136
+ #
137
+ # <%= stylesheet_pack_tag 'calendar', 'map' %>
138
+ #
139
+ # DON'T:
140
+ #
141
+ # <%= stylesheet_pack_tag 'calendar' %>
142
+ # <%= stylesheet_pack_tag 'map' %>
143
+ def stylesheet_pack_tag(*names, **options)
144
+ return "" if Webpacker.inlining_css?
145
+
146
+ stylesheet_link_tag(*sources_from_manifest_entrypoints(names, type: :stylesheet), **options)
147
+ end
148
+
149
+ private
150
+
151
+ def sources_from_manifest_entrypoints(names, type:)
152
+ names.map { |name| current_webpacker_instance.manifest.lookup_pack_with_chunks!(name.to_s, type: type) }.flatten.uniq
153
+ end
154
+
155
+ def resolve_path_to_image(name, **options)
156
+ path = name.starts_with?("static/") ? name : "static/#{name}"
157
+ path_to_asset(current_webpacker_instance.manifest.lookup!(path), options)
158
+ rescue
159
+ path_to_asset(current_webpacker_instance.manifest.lookup!(name), options)
160
+ end
161
+ end
@@ -0,0 +1,41 @@
1
+ class Webpacker::Instance
2
+ cattr_accessor(:logger) { ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT)) }
3
+
4
+ attr_reader :root_path, :config_path
5
+
6
+ def initialize(root_path: Rails.root, config_path: Rails.root.join("config/webpacker.yml"))
7
+ @root_path, @config_path = root_path, config_path
8
+ end
9
+
10
+ def env
11
+ @env ||= Webpacker::Env.inquire self
12
+ end
13
+
14
+ def config
15
+ @config ||= Webpacker::Configuration.new(
16
+ root_path: root_path,
17
+ config_path: config_path,
18
+ env: env
19
+ )
20
+ end
21
+
22
+ def compiler
23
+ @compiler ||= Webpacker::Compiler.new self
24
+ end
25
+
26
+ def dev_server
27
+ @dev_server ||= Webpacker::DevServer.new config
28
+ end
29
+
30
+ def manifest
31
+ @manifest ||= Webpacker::Manifest.new self
32
+ end
33
+
34
+ def commands
35
+ @commands ||= Webpacker::Commands.new self
36
+ end
37
+
38
+ def inlining_css?
39
+ dev_server.hmr? && dev_server.running?
40
+ end
41
+ end
@@ -0,0 +1,120 @@
1
+ # Singleton registry for accessing the packs path using a generated manifest.
2
+ # This allows javascript_pack_tag, stylesheet_pack_tag, asset_pack_path to take a reference to,
3
+ # say, "calendar.js" or "calendar.css" and turn it into "/packs/calendar-1016838bab065ae1e314.js" or
4
+ # "/packs/calendar-1016838bab065ae1e314.css".
5
+ #
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 preceded by a compilation if one is needed.
8
+ class Webpacker::Manifest
9
+ class MissingEntryError < StandardError; end
10
+
11
+ delegate :config, :compiler, :dev_server, to: :@webpacker
12
+
13
+ def initialize(webpacker)
14
+ @webpacker = webpacker
15
+ end
16
+
17
+ def refresh
18
+ @data = load
19
+ end
20
+
21
+ def lookup_pack_with_chunks(name, pack_type = {})
22
+ compile if compiling?
23
+
24
+ manifest_pack_type = manifest_type(pack_type[:type])
25
+ manifest_pack_name = manifest_name(name, manifest_pack_type)
26
+ find("entrypoints")[manifest_pack_name]["assets"][manifest_pack_type]
27
+ rescue NoMethodError
28
+ nil
29
+ end
30
+
31
+ def lookup_pack_with_chunks!(name, pack_type = {})
32
+ lookup_pack_with_chunks(name, pack_type) || handle_missing_entry(name, pack_type)
33
+ end
34
+
35
+ # Computes the relative path for a given Webpacker asset using manifest.json.
36
+ # If no asset is found, returns nil.
37
+ #
38
+ # Example:
39
+ #
40
+ # Webpacker.manifest.lookup('calendar.js') # => "/packs/calendar-1016838bab065ae1e122.js"
41
+ def lookup(name, pack_type = {})
42
+ compile if compiling?
43
+
44
+ find(full_pack_name(name, pack_type[:type]))
45
+ end
46
+
47
+ # Like lookup, except that if no asset is found, raises a Webpacker::Manifest::MissingEntryError.
48
+ def lookup!(name, pack_type = {})
49
+ lookup(name, pack_type) || handle_missing_entry(name, pack_type)
50
+ end
51
+
52
+ private
53
+ def compiling?
54
+ config.compile? && !dev_server.running?
55
+ end
56
+
57
+ def compile
58
+ Webpacker.logger.tagged("Webpacker") { compiler.compile }
59
+ end
60
+
61
+ def data
62
+ if config.cache_manifest?
63
+ @data ||= load
64
+ else
65
+ refresh
66
+ end
67
+ end
68
+
69
+ def find(name)
70
+ data[name.to_s].presence
71
+ end
72
+
73
+ def full_pack_name(name, pack_type)
74
+ return name unless File.extname(name.to_s).empty?
75
+ "#{name}.#{manifest_type(pack_type)}"
76
+ end
77
+
78
+ def handle_missing_entry(name, pack_type)
79
+ raise Webpacker::Manifest::MissingEntryError, missing_file_from_manifest_error(full_pack_name(name, pack_type[:type]))
80
+ end
81
+
82
+ def load
83
+ if config.public_manifest_path.exist?
84
+ JSON.parse config.public_manifest_path.read
85
+ else
86
+ {}
87
+ end
88
+ end
89
+
90
+ # The `manifest_name` method strips of the file extension of the name, because in the
91
+ # manifest hash the entrypoints are defined by their pack name without the extension.
92
+ # When the user provides a name with a file extension, we want to try to strip it off.
93
+ def manifest_name(name, pack_type)
94
+ name.chomp(".#{pack_type}")
95
+ end
96
+
97
+ def manifest_type(pack_type)
98
+ case pack_type
99
+ when :javascript then "js"
100
+ when :stylesheet then "css"
101
+ else pack_type.to_s
102
+ end
103
+ end
104
+
105
+ def missing_file_from_manifest_error(bundle_name)
106
+ <<-MSG
107
+ Webpacker can't find #{bundle_name} in #{config.public_manifest_path}. Possible causes:
108
+ 1. You forgot to install node packages (try `yarn install`) or are running an incompatible version of Node
109
+ 2. Your app has code with a non-standard extension (like a `.jsx` file) but the extension is not in the `extensions` config in `config/webpacker.yml`
110
+ 3. You have set compile: false (see `config/webpacker.yml`) for this environment
111
+ (unless you are using the `bin/webpacker -w` or the `bin/webpacker-dev-server`, in which case maybe you aren't running the dev server in the background?)
112
+ 4. webpack has not yet re-run to reflect updates.
113
+ 5. You have misconfigured Webpacker's `config/webpacker.yml` file.
114
+ 6. Your webpack configuration is not creating a manifest.
115
+
116
+ Your manifest contains:
117
+ #{JSON.pretty_generate(@data)}
118
+ MSG
119
+ end
120
+ end
@@ -0,0 +1,63 @@
1
+ require "rails/railtie"
2
+
3
+ require "webpacker/helper"
4
+ require "webpacker/dev_server_proxy"
5
+
6
+ class Webpacker::Engine < ::Rails::Engine
7
+ # Allows Webpacker config values to be set via Rails env config files
8
+ config.webpacker = ActiveSupport::OrderedOptions.new
9
+
10
+ initializer "webpacker.proxy" do |app|
11
+ if (Webpacker.config.dev_server.present? rescue nil)
12
+ app.middleware.insert_before 0,
13
+ Rails::VERSION::MAJOR >= 5 ?
14
+ Webpacker::DevServerProxy : "Webpacker::DevServerProxy", ssl_verify_none: true
15
+ end
16
+ end
17
+
18
+ initializer "webpacker.helper" do
19
+ ActiveSupport.on_load :action_controller do
20
+ ActionController::Base.helper Webpacker::Helper
21
+ end
22
+
23
+ ActiveSupport.on_load :action_view do
24
+ include Webpacker::Helper
25
+ end
26
+ end
27
+
28
+ initializer "webpacker.logger" do
29
+ config.after_initialize do
30
+ if ::Rails.logger.respond_to?(:tagged)
31
+ Webpacker.logger = ::Rails.logger
32
+ else
33
+ Webpacker.logger = ActiveSupport::TaggedLogging.new(::Rails.logger)
34
+ end
35
+ end
36
+ end
37
+
38
+ initializer "webpacker.bootstrap" do
39
+ if defined?(Rails::Server) || defined?(Rails::Console)
40
+ Webpacker.bootstrap
41
+ if defined?(Spring)
42
+ require "spring/watcher"
43
+ Spring.after_fork { Webpacker.bootstrap }
44
+ Spring.watch(Webpacker.config.config_path)
45
+ end
46
+ end
47
+ end
48
+
49
+ initializer "webpacker.set_source" do |app|
50
+ if Webpacker.config.config_path.exist?
51
+ app.config.javascript_path = Webpacker.config.source_path.relative_path_from(Rails.root.join("app")).to_s
52
+ end
53
+ end
54
+
55
+ initializer "webpacker.remove_app_packs_from_the_autoload_paths" do
56
+ Rails.application.config.before_initialize do
57
+ if Webpacker.config.config_path.exist?
58
+ source_path = Webpacker.config.source_path.to_s
59
+ ActiveSupport::Dependencies.autoload_paths.delete(source_path)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,23 @@
1
+ module Webpacker
2
+ class Runner
3
+ def self.run(argv)
4
+ $stdout.sync = true
5
+
6
+ new(argv).run
7
+ end
8
+
9
+ def initialize(argv)
10
+ @argv = argv
11
+
12
+ @app_path = File.expand_path(".", Dir.pwd)
13
+ @node_modules_bin_path = ENV["WEBPACKER_NODE_MODULES_BIN_PATH"] || `yarn bin`.chomp
14
+ @webpack_config = File.join(@app_path, "config/webpack/webpack.config.js")
15
+ @webpacker_config = ENV["WEBPACKER_CONFIG"] || File.join(@app_path, "config/webpacker.yml")
16
+
17
+ unless File.exist?(@webpack_config)
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."
19
+ exit!
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,4 @@
1
+ module Webpacker
2
+ # Change the version in package.json too, please!
3
+ VERSION = "6.0.0.rc.6".freeze
4
+ end
@@ -0,0 +1,58 @@
1
+ require "shellwords"
2
+ require "webpacker/runner"
3
+
4
+ module Webpacker
5
+ class WebpackRunner < Webpacker::Runner
6
+ WEBPACK_COMMANDS = [
7
+ "help",
8
+ "h",
9
+ "--help",
10
+ "-h",
11
+ "version",
12
+ "v",
13
+ "--version",
14
+ "-v",
15
+ "info",
16
+ "i"
17
+ ].freeze
18
+
19
+ def run
20
+ env = Webpacker::Compiler.env
21
+ env["WEBPACKER_CONFIG"] = @webpacker_config
22
+
23
+ cmd = if node_modules_bin_exist?
24
+ ["#{@node_modules_bin_path}/webpack"]
25
+ else
26
+ ["yarn", "webpack"]
27
+ end
28
+
29
+ if @argv.delete "--debug-webpacker"
30
+ cmd = ["node", "--inspect-brk"] + cmd
31
+ end
32
+
33
+ if @argv.delete "--trace-deprecation"
34
+ cmd = ["node", "--trace-deprecation"] + cmd
35
+ end
36
+
37
+ if @argv.delete "--no-deprecation"
38
+ cmd = ["node", "--no-deprecation"] + cmd
39
+ end
40
+
41
+ # Webpack commands are not compatible with --config option.
42
+ if (@argv & WEBPACK_COMMANDS).empty?
43
+ cmd += ["--config", @webpack_config]
44
+ end
45
+
46
+ cmd += @argv
47
+
48
+ Dir.chdir(@app_path) do
49
+ Kernel.exec env, *cmd
50
+ end
51
+ end
52
+
53
+ private
54
+ def node_modules_bin_exist?
55
+ File.exist?("#{@node_modules_bin_path}/webpack")
56
+ end
57
+ end
58
+ end
data/lib/webpacker.rb ADDED
@@ -0,0 +1,46 @@
1
+ require "active_support/core_ext/module/attribute_accessors"
2
+ require "active_support/core_ext/string/inquiry"
3
+ require "active_support/logger"
4
+ require "active_support/tagged_logging"
5
+
6
+ module Webpacker
7
+ extend self
8
+
9
+ def instance=(instance)
10
+ @instance = instance
11
+ end
12
+
13
+ def instance
14
+ @instance ||= Webpacker::Instance.new
15
+ end
16
+
17
+ def with_node_env(env)
18
+ original = ENV["NODE_ENV"]
19
+ ENV["NODE_ENV"] = env
20
+ yield
21
+ ensure
22
+ ENV["NODE_ENV"] = original
23
+ end
24
+
25
+ def ensure_log_goes_to_stdout
26
+ old_logger = Webpacker.logger
27
+ Webpacker.logger = Logger.new(STDOUT)
28
+ yield
29
+ ensure
30
+ Webpacker.logger = old_logger
31
+ end
32
+
33
+ delegate :logger, :logger=, :env, :inlining_css?, to: :instance
34
+ delegate :config, :compiler, :manifest, :commands, :dev_server, to: :instance
35
+ delegate :bootstrap, :clean, :clobber, :compile, to: :commands
36
+ end
37
+
38
+ require "webpacker/instance"
39
+ require "webpacker/env"
40
+ require "webpacker/configuration"
41
+ require "webpacker/manifest"
42
+ require "webpacker/compiler"
43
+ require "webpacker/commands"
44
+ require "webpacker/dev_server"
45
+
46
+ require "webpacker/railtie" if defined?(Rails)
@@ -0,0 +1,34 @@
1
+ /* global test expect, describe */
2
+
3
+ const { chdirCwd, chdirTestApp, resetEnv } = require('../utils/helpers')
4
+
5
+ chdirTestApp()
6
+
7
+ const config = require('../config')
8
+
9
+ describe('Config', () => {
10
+ beforeEach(() => jest.resetModules() && resetEnv())
11
+ afterAll(chdirCwd)
12
+
13
+ test('public path', () => {
14
+ process.env.RAILS_ENV = 'development'
15
+ const config = require('../config')
16
+ expect(config.publicPath).toEqual('/packs/')
17
+ })
18
+
19
+ test('public path with asset host', () => {
20
+ process.env.RAILS_ENV = 'development'
21
+ process.env.WEBPACKER_ASSET_HOST = 'http://foo.com/'
22
+ const config = require('../config')
23
+ expect(config.publicPath).toEqual('http://foo.com/packs/')
24
+ })
25
+
26
+ test('should return additional paths as listed in app config, with resolved paths', () => {
27
+ expect(config.additional_paths).toEqual([
28
+ 'app/assets',
29
+ '/etc/yarn',
30
+ 'some.config.js',
31
+ 'app/elm'
32
+ ])
33
+ })
34
+ })
@@ -0,0 +1,45 @@
1
+ /* global test expect, describe */
2
+
3
+ const { chdirTestApp, chdirCwd } = require('../utils/helpers')
4
+
5
+ chdirTestApp()
6
+
7
+ describe('DevServer', () => {
8
+ beforeEach(() => jest.resetModules())
9
+ afterAll(chdirCwd)
10
+
11
+ test('with NODE_ENV and RAILS_ENV set to development', () => {
12
+ process.env.NODE_ENV = 'development'
13
+ process.env.RAILS_ENV = 'development'
14
+ process.env.WEBPACKER_DEV_SERVER_HOST = '0.0.0.0'
15
+ process.env.WEBPACKER_DEV_SERVER_PORT = 5000
16
+ process.env.WEBPACKER_DEV_SERVER_DISABLE_HOST_CHECK = false
17
+
18
+ const devServer = require('../dev_server')
19
+ expect(devServer).toBeDefined()
20
+ expect(devServer.host).toEqual('0.0.0.0')
21
+ expect(devServer.port).toEqual('5000')
22
+ expect(devServer.disable_host_check).toBe(false)
23
+ })
24
+
25
+ test('with custom env prefix', () => {
26
+ const config = require('../config')
27
+ config.dev_server.env_prefix = 'TEST_WEBPACKER_DEV_SERVER'
28
+
29
+ process.env.NODE_ENV = 'development'
30
+ process.env.RAILS_ENV = 'development'
31
+ process.env.TEST_WEBPACKER_DEV_SERVER_HOST = '0.0.0.0'
32
+ process.env.TEST_WEBPACKER_DEV_SERVER_PORT = 5000
33
+
34
+ const devServer = require('../dev_server')
35
+ expect(devServer).toBeDefined()
36
+ expect(devServer.host).toEqual('0.0.0.0')
37
+ expect(devServer.port).toEqual('5000')
38
+ })
39
+
40
+ test('with NODE_ENV and RAILS_ENV set to production', () => {
41
+ process.env.RAILS_ENV = 'production'
42
+ process.env.NODE_ENV = 'production'
43
+ expect(require('../dev_server')).toEqual({})
44
+ })
45
+ })
@@ -0,0 +1,35 @@
1
+ /* test expect, describe, afterAll, beforeEach */
2
+
3
+ const { resolve } = require('path')
4
+ const { chdirTestApp, chdirCwd } = require('../utils/helpers')
5
+
6
+ chdirTestApp()
7
+
8
+ describe('Development environment', () => {
9
+ afterAll(chdirCwd)
10
+
11
+ describe('webpackConfig', () => {
12
+ beforeEach(() => jest.resetModules())
13
+
14
+ test('should use development config and environment including devServer if WEBPACK_SERVE', () => {
15
+ process.env.RAILS_ENV = 'development'
16
+ process.env.NODE_ENV = 'development'
17
+ process.env.WEBPACK_SERVE = 'true'
18
+ const { webpackConfig } = require('../index')
19
+
20
+ expect(webpackConfig.output.path).toEqual(resolve('public', 'packs'))
21
+ expect(webpackConfig.output.publicPath).toEqual('/packs/')
22
+ })
23
+
24
+ test('should use development config and environment if WEBPACK_SERVE', () => {
25
+ process.env.RAILS_ENV = 'development'
26
+ process.env.NODE_ENV = 'development'
27
+ process.env.WEBPACK_SERVE = undefined
28
+ const { webpackConfig } = require('../index')
29
+
30
+ expect(webpackConfig.output.path).toEqual(resolve('public', 'packs'))
31
+ expect(webpackConfig.output.publicPath).toEqual('/packs/')
32
+ expect(webpackConfig.devServer).toEqual(undefined)
33
+ })
34
+ })
35
+ })