webpacker 3.0.1 → 3.0.2

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintignore +3 -0
  3. data/.gitignore +0 -2
  4. data/.travis.yml +3 -3
  5. data/CHANGELOG.md +45 -1
  6. data/Gemfile.lock +144 -0
  7. data/README.md +23 -7
  8. data/docs/deployment.md +3 -6
  9. data/docs/env.md +1 -1
  10. data/docs/misc.md +1 -1
  11. data/docs/props.md +119 -1
  12. data/docs/testing.md +103 -0
  13. data/docs/typescript.md +2 -1
  14. data/docs/webpack-dev-server.md +44 -1
  15. data/docs/webpack.md +37 -1
  16. data/exe/webpack +8 -0
  17. data/exe/webpack-dev-server +8 -0
  18. data/lib/install/config/webpacker.yml +9 -2
  19. data/lib/install/elm.rb +11 -9
  20. data/lib/install/examples/elm/hello_elm.js +4 -3
  21. data/lib/install/examples/vue/hello_vue.js +1 -1
  22. data/lib/install/template.rb +3 -5
  23. data/lib/install/vue.rb +7 -5
  24. data/lib/tasks/webpacker/check_node.rake +6 -3
  25. data/lib/webpacker/configuration.rb +4 -0
  26. data/lib/webpacker/dev_server.rb +19 -5
  27. data/lib/webpacker/dev_server_proxy.rb +1 -1
  28. data/lib/webpacker/dev_server_runner.rb +51 -0
  29. data/lib/webpacker/helper.rb +5 -16
  30. data/lib/webpacker/manifest.rb +8 -8
  31. data/lib/webpacker/runner.rb +22 -0
  32. data/lib/webpacker/version.rb +1 -1
  33. data/lib/webpacker/webpack_runner.rb +15 -0
  34. data/package.json +4 -2
  35. data/package/config.js +19 -2
  36. data/package/environment.js +3 -3
  37. data/package/environments/development.js +15 -11
  38. data/package/environments/production.js +2 -2
  39. data/package/index.js +1 -1
  40. data/package/loaders/file.js +4 -4
  41. data/package/loaders/style.js +2 -2
  42. data/package/loaders/vue.js +2 -2
  43. data/test/configuration_test.rb +5 -0
  44. data/test/manifest_test.rb +10 -2
  45. data/webpacker.gemspec +3 -1
  46. data/yarn.lock +5133 -0
  47. metadata +16 -8
  48. data/lib/install/bin/webpack-dev-server.tt +0 -68
  49. data/lib/install/bin/webpack.tt +0 -27
@@ -2,7 +2,7 @@ require "rack/proxy"
2
2
 
3
3
  class Webpacker::DevServerProxy < Rack::Proxy
4
4
  def rewrite_response(response)
5
- status, headers, body = response
5
+ _status, headers, _body = response
6
6
  headers.delete "transfer-encoding"
7
7
  headers.delete "content-length" if Webpacker.dev_server.running? && Webpacker.dev_server.https?
8
8
  response
@@ -0,0 +1,51 @@
1
+ require "shellwords"
2
+ require "yaml"
3
+ require "socket"
4
+ require "webpacker/runner"
5
+
6
+ module Webpacker
7
+ class DevServerRunner < Webpacker::Runner
8
+ def run
9
+ load_config
10
+ detect_port!
11
+ execute_cmd
12
+ end
13
+
14
+ private
15
+ def load_config
16
+ @config_file = File.join(@app_path, "config/webpacker.yml")
17
+ dev_server = YAML.load_file(@config_file)[ENV["RAILS_ENV"]]["dev_server"]
18
+
19
+ @hostname = dev_server["host"]
20
+ @port = dev_server["port"]
21
+
22
+ rescue Errno::ENOENT, NoMethodError
23
+ $stdout.puts "Webpack dev_server configuration not found in #{@config_file}."
24
+ $stdout.puts "Please run bundle exec rails webpacker:install to install webpacker"
25
+ exit!
26
+ end
27
+
28
+ def detect_port!
29
+ server = TCPServer.new(@hostname, @port)
30
+ server.close
31
+
32
+ rescue Errno::EADDRINUSE
33
+ $stdout.puts "Another program is running on port #{@port}. Set a new port in #{@config_file} for dev_server"
34
+ exit!
35
+ end
36
+
37
+ def execute_cmd
38
+ env = { "NODE_PATH" => @node_modules_path.shellescape }
39
+ cmd = [
40
+ "#{@node_modules_path}/.bin/webpack-dev-server",
41
+ "--progress",
42
+ "--color",
43
+ "--config", @webpack_config
44
+ ]
45
+
46
+ Dir.chdir(@app_path) do
47
+ exec env, *cmd
48
+ end
49
+ end
50
+ end
51
+ end
@@ -2,26 +2,19 @@ module Webpacker::Helper
2
2
  # Computes the full path for a given webpacker asset.
3
3
  # Return relative path using manifest.json and passes it to asset_url helper
4
4
  # This will use asset_path internally, so most of their behaviors will be the same.
5
- # Examples:
6
5
  #
7
- # In development mode:
8
- # <%= asset_pack_path 'calendar.js' %> # => "/packs/calendar.js"
9
- # In production mode:
6
+ # Example:
7
+ #
10
8
  # <%= asset_pack_path 'calendar.css' %> # => "/packs/calendar-1016838bab065ae1e122.css"
11
9
  def asset_pack_path(name, **options)
12
- asset_path(Webpacker.manifest.lookup(name), **options)
10
+ asset_path(Webpacker.manifest.lookup!(name), **options)
13
11
  end
14
12
  # Creates a script tag that references the named pack file, as compiled by Webpack per the entries list
15
13
  # in config/webpack/shared.js. By default, this list is auto-generated to match everything in
16
14
  # app/javascript/packs/*.js. In production mode, the digested reference is automatically looked up.
17
15
  #
18
- # Examples:
19
- #
20
- # # In development mode:
21
- # <%= javascript_pack_tag 'calendar', 'data-turbolinks-track': 'reload' %> # =>
22
- # <script src="/packs/calendar.js" data-turbolinks-track="reload"></script>
16
+ # Example:
23
17
  #
24
- # # In production mode:
25
18
  # <%= javascript_pack_tag 'calendar', 'data-turbolinks-track': 'reload' %> # =>
26
19
  # <script src="/packs/calendar-1016838bab065ae1e314.js" data-turbolinks-track="reload"></script>
27
20
  def javascript_pack_tag(*names, **options)
@@ -37,10 +30,6 @@ module Webpacker::Helper
37
30
  #
38
31
  # Examples:
39
32
  #
40
- # # In development mode:
41
- # <%= stylesheet_pack_tag 'calendar', 'data-turbolinks-track': 'reload' %> # =>
42
- # <link rel="stylesheet" media="screen" href="/packs/calendar.css" data-turbolinks-track="reload" />
43
- #
44
33
  # # In development mode with hot module replacement:
45
34
  # <%= stylesheet_pack_tag 'calendar', 'data-turbolinks-track': 'reload' %> # =>
46
35
  # nil
@@ -56,7 +45,7 @@ module Webpacker::Helper
56
45
 
57
46
  private
58
47
  def sources_from_pack_manifest(names, type:)
59
- names.map { |name| Webpacker.manifest.lookup(pack_name_with_extension(name, type: type)) }
48
+ names.map { |name| Webpacker.manifest.lookup!(pack_name_with_extension(name, type: type)) }
60
49
  end
61
50
 
62
51
  def pack_name_with_extension(name, type:)
@@ -1,11 +1,7 @@
1
1
  # Singleton registry for accessing the packs path using a generated manifest.
2
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.js" or
4
- # "/packs/calendar.css" in development.
5
- #
6
- # In production mode, it returns compiles files, like
7
- # "/packs/calendar-1016838bab065ae1e314.js" and "/packs/calendar-1016838bab065ae1e314.css",
8
- # for long-term caching.
3
+ # say, "calendar.js" or "calendar.css" and turn it into "/packs/calendar-1016838bab065ae1e314.js" or
4
+ # "/packs/calendar-1016838bab065ae1e314.css".
9
5
  #
10
6
  # When the configuration is set to on-demand compilation, with the `compile: true` option in
11
7
  # the webpacker.yml file, any lookups will be preceeded by a compilation if one is needed.
@@ -27,6 +23,10 @@ class Webpacker::Manifest
27
23
  find name
28
24
  end
29
25
 
26
+ def lookup!(name)
27
+ lookup(name) || handle_missing_entry(name)
28
+ end
29
+
30
30
  private
31
31
  def compiling?
32
32
  config.compile? && !dev_server.running?
@@ -37,7 +37,7 @@ class Webpacker::Manifest
37
37
  end
38
38
 
39
39
  def find(name)
40
- data[name.to_s] || handle_missing_entry(name)
40
+ data[name.to_s].presence
41
41
  end
42
42
 
43
43
  def handle_missing_entry(name)
@@ -45,7 +45,7 @@ class Webpacker::Manifest
45
45
  end
46
46
 
47
47
  def missing_file_from_manifest_error(bundle_name)
48
- msg = <<-MSG
48
+ <<-MSG
49
49
  Webpacker can't find #{bundle_name} in #{config.public_manifest_path}. Possible causes:
50
50
  1. You want to set webpacker.yml value of compile to true for your environment
51
51
  unless you are using the `webpack -w` or the webpack-dev-server.
@@ -0,0 +1,22 @@
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_path = File.join(@app_path, "node_modules")
14
+ @webpack_config = File.join(@app_path, "config/webpack/#{ENV["NODE_ENV"]}.js")
15
+
16
+ unless File.exist?(@webpack_config)
17
+ 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."
18
+ exit!
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,4 +1,4 @@
1
1
  module Webpacker
2
2
  # Change the version in package.json too, please!
3
- VERSION = "3.0.1".freeze
3
+ VERSION = "3.0.2".freeze
4
4
  end
@@ -0,0 +1,15 @@
1
+ require "shellwords"
2
+ require "webpacker/runner"
3
+
4
+ module Webpacker
5
+ class WebpackRunner < Webpacker::Runner
6
+ def run
7
+ env = { "NODE_PATH" => @node_modules_path.shellescape }
8
+ cmd = [ "#{@node_modules_path}/.bin/webpack", "--config", @webpack_config ] + @argv
9
+
10
+ Dir.chdir(@app_path) do
11
+ exec env, *cmd
12
+ end
13
+ end
14
+ end
15
+ end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rails/webpacker",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "Use Webpack to manage app-like JavaScript modules in Rails",
5
5
  "main": "package/index.js",
6
6
  "files": [
@@ -19,7 +19,6 @@
19
19
  "babel-polyfill": "^6.26.0",
20
20
  "babel-preset-env": "^1.6.0",
21
21
  "coffee-loader": "^0.8.0",
22
- "coffeescript": "^1.12.7",
23
22
  "compression-webpack-plugin": "^1.0.0",
24
23
  "css-loader": "^0.28.5",
25
24
  "extract-text-webpack-plugin": "^3.0.0",
@@ -45,6 +44,9 @@
45
44
  "eslint-plugin-jsx-a11y": "^4.0.0",
46
45
  "eslint-plugin-react": "^6.10.0"
47
46
  },
47
+ "peerDependencies": {
48
+ "coffeescript": ">= 1.12.7 || >= 2.x"
49
+ },
48
50
  "scripts": {
49
51
  "test": "echo \"Error: no test specified\" && exit 1",
50
52
  "lint": "eslint {package,lib}/"
data/package/config.js CHANGED
@@ -3,6 +3,23 @@ const { safeLoad } = require('js-yaml')
3
3
  const { readFileSync } = require('fs')
4
4
 
5
5
  const filePath = resolve('config', 'webpacker.yml')
6
- const config = safeLoad(readFileSync(filePath), 'utf8')
6
+ const config = safeLoad(readFileSync(filePath), 'utf8')[process.env.NODE_ENV]
7
7
 
8
- module.exports = config[process.env.NODE_ENV]
8
+ const isBoolean = str => /^true/.test(str) || /^false/.test(str)
9
+
10
+ const fetch = key =>
11
+ (isBoolean(process.env[key]) ? JSON.parse(process.env[key]) : process.env[key])
12
+
13
+ const devServer = (key) => {
14
+ const envValue = fetch(`WEBPACKER_DEV_SERVER_${key.toUpperCase().replace(/_/g, '')}`)
15
+ if (typeof envValue === 'undefined' || envValue === null) return config.dev_server[key]
16
+ return envValue
17
+ }
18
+
19
+ if (config.dev_server) {
20
+ Object.keys(config.dev_server).forEach((key) => {
21
+ config.dev_server[key] = devServer(key)
22
+ })
23
+ }
24
+
25
+ module.exports = config
@@ -1,9 +1,6 @@
1
1
  /* eslint global-require: 0 */
2
2
  /* eslint import/no-dynamic-require: 0 */
3
3
 
4
- const config = require('./config')
5
- const assetHost = require('./asset_host')
6
-
7
4
  const { basename, dirname, join, relative, resolve } = require('path')
8
5
  const { sync } = require('glob')
9
6
  const extname = require('path-complete-extname')
@@ -12,6 +9,9 @@ const webpack = require('webpack')
12
9
  const ExtractTextPlugin = require('extract-text-webpack-plugin')
13
10
  const ManifestPlugin = require('webpack-manifest-plugin')
14
11
 
12
+ const config = require('./config')
13
+ const assetHost = require('./asset_host')
14
+
15
15
  function getLoaderMap() {
16
16
  const result = new Map()
17
17
  const paths = sync(resolve(__dirname, 'loaders', '*.js'))
@@ -1,13 +1,13 @@
1
+ const webpack = require('webpack')
1
2
  const Environment = require('../environment')
2
- const { dev_server } = require('../config')
3
+ const { dev_server: devServer } = require('../config')
3
4
  const assetHost = require('../asset_host')
4
- const webpack = require('webpack')
5
5
 
6
6
  module.exports = class extends Environment {
7
7
  constructor() {
8
8
  super()
9
9
 
10
- if (dev_server.hmr) {
10
+ if (devServer.hmr) {
11
11
  this.plugins.set('HotModuleReplacement', new webpack.HotModuleReplacementPlugin())
12
12
  this.plugins.set('NamedModules', new webpack.NamedModulesPlugin())
13
13
  }
@@ -15,25 +15,29 @@ module.exports = class extends Environment {
15
15
 
16
16
  toWebpackConfig() {
17
17
  const result = super.toWebpackConfig()
18
- if (dev_server.hmr) {
18
+ if (devServer.hmr) {
19
19
  result.output.filename = '[name]-[hash].js'
20
20
  }
21
21
  result.output.pathinfo = true
22
22
  result.devtool = 'cheap-eval-source-map'
23
23
  result.devServer = {
24
- host: dev_server.host,
25
- port: dev_server.port,
26
- https: dev_server.https,
27
- hot: dev_server.hmr,
28
- contentBase: assetHost.path,
29
- publicPath: assetHost.publicPath,
30
24
  clientLogLevel: 'none',
31
25
  compress: true,
26
+ disableHostCheck: devServer.disable_host_check,
27
+ host: devServer.host,
28
+ port: devServer.port,
29
+ https: devServer.https,
30
+ hot: devServer.hmr,
31
+ contentBase: assetHost.path,
32
+ inline: devServer.inline,
33
+ useLocalIp: devServer.use_local_ip,
34
+ public: devServer.public,
35
+ publicPath: assetHost.publicPath,
32
36
  historyApiFallback: true,
33
37
  headers: {
34
38
  'Access-Control-Allow-Origin': '*'
35
39
  },
36
- overlay: true,
40
+ overlay: devServer.overlay,
37
41
  watchOptions: {
38
42
  ignored: /node_modules/
39
43
  },
@@ -1,6 +1,6 @@
1
- const Environment = require('../environment')
2
1
  const webpack = require('webpack')
3
2
  const CompressionPlugin = require('compression-webpack-plugin')
3
+ const Environment = require('../environment')
4
4
 
5
5
  module.exports = class extends Environment {
6
6
  constructor() {
@@ -27,7 +27,7 @@ module.exports = class extends Environment {
27
27
 
28
28
  toWebpackConfig() {
29
29
  const result = super.toWebpackConfig()
30
- result.devtool = 'source-map'
30
+ result.devtool = 'nosources-source-map'
31
31
  result.stats = 'normal'
32
32
  return result
33
33
  }
data/package/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  /* eslint global-require: 0 */
2
2
  /* eslint import/no-dynamic-require: 0 */
3
3
 
4
- const Environment = require('./environment')
5
4
  const { resolve } = require('path')
6
5
  const { existsSync } = require('fs')
6
+ const Environment = require('./environment')
7
7
 
8
8
  function createEnvironment() {
9
9
  const path = resolve(__dirname, 'environments', `${process.env.NODE_ENV}.js`)
@@ -1,14 +1,14 @@
1
- const config = require('../config')
2
- const assetHost = require('../asset_host')
3
1
  const { join } = require('path')
2
+ const { source_path } = require('../config')
3
+ const assetHost = require('../asset_host')
4
4
 
5
5
  module.exports = {
6
- test: /\.(jpg|jpeg|png|gif|svg|eot|ttf|woff|woff2)$/i,
6
+ test: /\.(jpg|jpeg|png|gif|svg|eot|otf|ttf|woff|woff2)$/i,
7
7
  use: [{
8
8
  loader: 'file-loader',
9
9
  options: {
10
10
  name: '[path][name]-[hash].[ext]',
11
- context: join(config.source_path),
11
+ context: join(source_path),
12
12
  publicPath: assetHost.publicPathWithHost
13
13
  }
14
14
  }]
@@ -1,10 +1,10 @@
1
1
  const ExtractTextPlugin = require('extract-text-webpack-plugin')
2
2
  const path = require('path')
3
- const config = require('../config')
3
+ const { dev_server: devServer } = require('../config')
4
4
 
5
5
  const postcssConfigPath = path.resolve(process.cwd(), '.postcssrc.yml')
6
6
  const isProduction = process.env.NODE_ENV === 'production'
7
- const extractCSS = !(config.dev_server && config.dev_server.hmr)
7
+ const extractCSS = !(devServer && devServer.hmr)
8
8
 
9
9
  const extractOptions = {
10
10
  fallback: 'style-loader',
@@ -1,7 +1,7 @@
1
- const config = require('../config')
1
+ const { dev_server: devServer } = require('../config')
2
2
 
3
3
  const isProduction = process.env.NODE_ENV === 'production'
4
- const extractCSS = !(config.dev_server && config.dev_server.hmr)
4
+ const extractCSS = !(devServer && devServer.hmr)
5
5
 
6
6
  module.exports = {
7
7
  test: /\.vue(\.erb)?$/,
@@ -26,6 +26,11 @@ class ConfigurationTest < Webpacker::Test
26
26
  assert_equal Webpacker.config.cache_path.to_s, cache_path
27
27
  end
28
28
 
29
+ def test_extensions
30
+ webpacker_yml = YAML.load_file("lib/install/config/webpacker.yml")
31
+ assert_equal Webpacker.config.extensions, webpacker_yml["default"]["extensions"]
32
+ end
33
+
29
34
  def test_cache_manifest?
30
35
  with_node_env("development") do
31
36
  refute reloaded_config.cache_manifest?
@@ -1,19 +1,27 @@
1
1
  require "webpacker_test_helper"
2
2
 
3
3
  class ManifestTest < Minitest::Test
4
- def test_lookup_exception
4
+ def test_lookup_exception!
5
5
  manifest_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/public/packs", "manifest.json").to_s
6
6
  asset_file = "calendar.js"
7
7
 
8
8
  Webpacker.config.stub :compile?, false do
9
9
  error = assert_raises Webpacker::Manifest::MissingEntryError do
10
- Webpacker.manifest.lookup(asset_file)
10
+ Webpacker.manifest.lookup!(asset_file)
11
11
  end
12
12
 
13
13
  assert_match "Webpacker can't find #{asset_file} in #{manifest_path}", error.message
14
14
  end
15
15
  end
16
16
 
17
+ def test_lookup_success!
18
+ assert_equal Webpacker.manifest.lookup!("bootstrap.js"), "/packs/bootstrap-300631c4f0e0f9c865bc.js"
19
+ end
20
+
21
+ def test_lookup_nil
22
+ assert_nil Webpacker.manifest.lookup("foo.js")
23
+ end
24
+
17
25
  def test_lookup_success
18
26
  assert_equal Webpacker.manifest.lookup("bootstrap.js"), "/packs/bootstrap-300631c4f0e0f9c865bc.js"
19
27
  end