webpacker 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
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