webpacker 1.2 → 2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGELOG.md +93 -9
  4. data/Gemfile.lock +2 -2
  5. data/README.md +979 -93
  6. data/lib/install/angular.rb +2 -2
  7. data/lib/install/bin/webpack-dev-server.tt +20 -10
  8. data/lib/install/bin/webpack.tt +10 -15
  9. data/lib/install/config/.babelrc +13 -1
  10. data/lib/install/config/loaders/core/sass.js +3 -2
  11. data/lib/install/config/loaders/installers/elm.js +20 -0
  12. data/lib/install/config/loaders/installers/vue.js +1 -0
  13. data/lib/install/config/webpack/configuration.js +22 -13
  14. data/lib/install/config/webpack/development.js +17 -1
  15. data/lib/install/config/webpack/production.js +16 -2
  16. data/lib/install/config/webpack/shared.js +15 -11
  17. data/lib/install/config/{webpack/paths.yml → webpacker.yml} +12 -7
  18. data/lib/install/elm.rb +29 -0
  19. data/lib/install/examples/angular/tsconfig.json +1 -0
  20. data/lib/install/examples/elm/Main.elm +54 -0
  21. data/lib/install/examples/elm/hello_elm.js +11 -0
  22. data/lib/install/examples/vue/hello_vue.js +4 -8
  23. data/lib/install/react.rb +2 -2
  24. data/lib/install/template.rb +10 -11
  25. data/lib/install/vue.rb +2 -2
  26. data/lib/tasks/installers.rake +1 -0
  27. data/lib/tasks/webpacker.rake +11 -9
  28. data/lib/tasks/webpacker/check_webpack_binstubs.rake +11 -0
  29. data/lib/tasks/webpacker/check_yarn.rake +6 -3
  30. data/lib/tasks/webpacker/clobber.rake +3 -3
  31. data/lib/tasks/webpacker/compile.rake +14 -20
  32. data/lib/tasks/webpacker/verify_install.rake +2 -2
  33. data/lib/tasks/webpacker/yarn_install.rake +2 -2
  34. data/lib/webpacker.rb +16 -1
  35. data/lib/webpacker/compiler.rb +20 -0
  36. data/lib/webpacker/configuration.rb +30 -22
  37. data/lib/webpacker/env.rb +2 -6
  38. data/lib/webpacker/helper.rb +0 -2
  39. data/lib/webpacker/manifest.rb +23 -6
  40. data/lib/webpacker/version.rb +1 -1
  41. data/package.json +1 -1
  42. data/test/configuration_test.rb +32 -0
  43. data/test/env_test.rb +3 -5
  44. data/test/helper_test.rb +23 -0
  45. data/test/manifest_test.rb +30 -0
  46. data/test/test_app/config/secrets.yml +5 -0
  47. data/test/test_app/public/packs/manifest.json +4 -0
  48. data/test/webpacker_test.rb +2 -1
  49. metadata +20 -7
  50. data/lib/install/bin/yarn.tt +0 -11
  51. data/lib/install/config/webpack/development.server.js +0 -17
  52. data/lib/install/config/webpack/development.server.yml +0 -17
@@ -0,0 +1,11 @@
1
+ // Run this example by adding <%= javascript_pack_tag "hello_elm" %> to the head of your layout
2
+ // file, like app/views/layouts/application.html.erb. It will render "Hello Elm!" within the page.
3
+
4
+ import Elm from './Main'
5
+
6
+ document.addEventListener('DOMContentLoaded', () => {
7
+ const target = document.createElement('div')
8
+
9
+ document.body.appendChild(target)
10
+ Elm.Main.embed(target)
11
+ })
@@ -1,19 +1,15 @@
1
1
  /* eslint no-console: 0 */
2
- // Run this example by adding <%= javascript_pack_tag 'hello_vue' %>
3
- // to the head of your layout file,
2
+ // Run this example by adding <%= javascript_pack_tag 'hello_vue' %> and
3
+ // <%= stylesheet_pack_tag 'hello_vue' %> to the head of your layout file,
4
4
  // like app/views/layouts/application.html.erb.
5
5
  // All it does is render <div>Hello Vue</div> at the bottom of the page.
6
6
 
7
- import Vue from 'vue/dist/vue.esm'
7
+ import Vue from 'vue'
8
8
  import App from './app.vue'
9
9
 
10
10
  document.addEventListener('DOMContentLoaded', () => {
11
11
  document.body.appendChild(document.createElement('hello'))
12
- const app = new Vue({
13
- el: 'hello',
14
- template: '<App/>',
15
- components: { App }
16
- })
12
+ const app = new Vue(App).$mount('hello')
17
13
 
18
14
  console.log(app)
19
15
  })
@@ -19,13 +19,13 @@ else
19
19
  copy_file "#{__dir__}/examples/react/.babelrc", ".babelrc"
20
20
  end
21
21
 
22
- puts "Copying react loader to #{Webpacker::Configuration.config_path}/loaders"
22
+ puts "Copying react loader to config/webpack/loaders"
23
23
  copy_file "#{__dir__}/config/loaders/installers/react.js", "config/webpack/loaders/react.js"
24
24
 
25
25
  puts "Copying react example entry file to #{Webpacker::Configuration.entry_path}"
26
26
  copy_file "#{__dir__}/examples/react/hello_react.jsx", "#{Webpacker::Configuration.entry_path}/hello_react.jsx"
27
27
 
28
28
  puts "Installing all react dependencies"
29
- run "./bin/yarn add react react-dom babel-preset-react prop-types"
29
+ run "yarn add react react-dom babel-preset-react prop-types"
30
30
 
31
31
  puts "Webpacker now supports react.js 🎉"
@@ -1,7 +1,11 @@
1
1
  # Install webpacker
2
+ copy_file "#{__dir__}/config/webpacker.yml", "config/webpacker.yml"
3
+
2
4
  puts "Copying webpack core config and loaders"
3
5
  directory "#{__dir__}/config/webpack", "config/webpack"
4
6
  directory "#{__dir__}/config/loaders/core", "config/webpack/loaders"
7
+
8
+ puts "Copying .postcssrc.yml to app root directory"
5
9
  copy_file "#{__dir__}/config/.postcssrc.yml", ".postcssrc.yml"
6
10
 
7
11
  puts "Copying .babelrc to app root directory"
@@ -11,13 +15,7 @@ puts "Creating javascript app source directory"
11
15
  directory "#{__dir__}/javascript", "#{Webpacker::Configuration.source}"
12
16
 
13
17
  puts "Copying binstubs"
14
- template "#{__dir__}/bin/webpack-dev-server", "bin/webpack-dev-server"
15
- template "#{__dir__}/bin/webpack", "bin/webpack"
16
-
17
- if !File.exist?("bin/yarn")
18
- puts "Copying yarn"
19
- template "#{__dir__}/bin/yarn", "bin/yarn"
20
- end
18
+ directory "#{__dir__}/bin", "bin"
21
19
 
22
20
  chmod "bin", 0755 & ~File.umask, verbose: false
23
21
 
@@ -29,13 +27,14 @@ EOS
29
27
  end
30
28
 
31
29
  puts "Installing all JavaScript dependencies"
32
- run "./bin/yarn add webpack webpack-merge js-yaml path-complete-extname " \
30
+ run "yarn add webpack webpack-merge js-yaml path-complete-extname " \
33
31
  "webpack-manifest-plugin babel-loader@7.x coffee-loader coffee-script " \
34
- "babel-core babel-preset-env compression-webpack-plugin rails-erb-loader glob " \
32
+ "babel-core babel-preset-env babel-polyfill compression-webpack-plugin rails-erb-loader glob " \
35
33
  "extract-text-webpack-plugin node-sass file-loader sass-loader css-loader style-loader " \
36
- "postcss-loader autoprefixer postcss-smart-import precss"
34
+ "postcss-loader autoprefixer postcss-smart-import precss resolve-url-loader " \
35
+ "babel-plugin-syntax-dynamic-import babel-plugin-transform-class-properties"
37
36
 
38
37
  puts "Installing dev server for live reloading"
39
- run "./bin/yarn add --dev webpack-dev-server"
38
+ run "yarn add --dev webpack-dev-server"
40
39
 
41
40
  puts "Webpacker successfully installed 🎉 🍰"
@@ -1,6 +1,6 @@
1
1
  require "webpacker/configuration"
2
2
 
3
- puts "Copying vue loader to #{Webpacker::Configuration.config_path}/loaders"
3
+ puts "Copying vue loader to config/webpack/loaders"
4
4
  copy_file "#{__dir__}/config/loaders/installers/vue.js", "config/webpack/loaders/vue.js"
5
5
 
6
6
  puts "Copying the example entry file to #{Webpacker::Configuration.entry_path}"
@@ -10,6 +10,6 @@ puts "Copying vue app file to #{Webpacker::Configuration.entry_path}"
10
10
  copy_file "#{__dir__}/examples/vue/app.vue", "#{Webpacker::Configuration.entry_path}/app.vue"
11
11
 
12
12
  puts "Installing all vue dependencies"
13
- run "./bin/yarn add vue vue-loader vue-template-compiler"
13
+ run "yarn add vue vue-loader vue-template-compiler"
14
14
 
15
15
  puts "Webpacker now supports vue.js 🎉"
@@ -1,5 +1,6 @@
1
1
  INSTALLERS = {
2
2
  "Angular": :angular,
3
+ "Elm": :elm,
3
4
  "React": :react,
4
5
  "Vue": :vue
5
6
  }.freeze
@@ -1,13 +1,15 @@
1
1
  tasks = {
2
- "webpacker:install" => "Installs and setup webpack with yarn",
3
- "webpacker:compile" => "Compiles webpack bundles based on environment",
4
- "webpacker:check_node" => "Verifies if Node.js is installed",
5
- "webpacker:check_yarn" => "Verifies if yarn is installed",
6
- "webpacker:verify_install" => "Verifies if webpacker is installed",
7
- "webpacker:yarn_install" => "Support for older Rails versions. Install all JavaScript dependencies as specified via Yarn",
8
- "webpacker:install:react" => "Installs and setup example react component",
9
- "webpacker:install:vue" => "Installs and setup example vue component",
10
- "webpacker:install:angular" => "Installs and setup example angular2 component"
2
+ "webpacker:install" => "Installs and setup webpack with yarn",
3
+ "webpacker:compile" => "Compiles webpack bundles based on environment",
4
+ "webpacker:check_node" => "Verifies if Node.js is installed",
5
+ "webpacker:check_yarn" => "Verifies if yarn is installed",
6
+ "webpacker:check_webpack_binstubs" => "Verifies that bin/webpack & bin/webpack-dev-server are present",
7
+ "webpacker:verify_install" => "Verifies if webpacker is installed",
8
+ "webpacker:yarn_install" => "Support for older Rails versions. Install all JavaScript dependencies as specified via Yarn",
9
+ "webpacker:install:react" => "Installs and setup example React component",
10
+ "webpacker:install:vue" => "Installs and setup example Vue component",
11
+ "webpacker:install:angular" => "Installs and setup example Angular component",
12
+ "webpacker:install:elm" => "Installs and setup example Elm component"
11
13
  }.freeze
12
14
 
13
15
  desc "Lists all available tasks in webpacker"
@@ -0,0 +1,11 @@
1
+ namespace :webpacker do
2
+ desc "Verifies that bin/webpack & bin/webpack-dev-server are present."
3
+ task :check_webpack_binstubs do
4
+ unless File.exist?("bin/webpack") && File.exist?("bin/webpack-dev-server")
5
+ puts "Webpack binstubs not found.\n"\
6
+ "Make sure the bin directory or binstubs are not included in .gitignore\n"\
7
+ "Exiting!"
8
+ exit!
9
+ end
10
+ end
11
+ end
@@ -1,11 +1,14 @@
1
1
  namespace :webpacker do
2
2
  desc "Verifies if yarn is installed"
3
3
  task :check_yarn do
4
+ required_yarn_version = "0.20.1"
5
+
4
6
  begin
5
- version = `yarn --version`
6
- raise Errno::ENOENT if version.blank?
7
+ yarn_version = `yarn --version`
8
+
9
+ raise Errno::ENOENT if yarn_version.blank? || Gem::Version.new(yarn_version) < Gem::Version.new(required_yarn_version)
7
10
  rescue Errno::ENOENT
8
- puts "Webpacker requires yarn. Please download and install Yarn https://yarnpkg.com/lang/en/docs/install/"
11
+ puts "Webpacker requires Yarn version >= #{required_yarn_version}. Please download and install the latest version from https://yarnpkg.com/lang/en/docs/install/"
9
12
  puts "Exiting!" && exit!
10
13
  end
11
14
  end
@@ -3,9 +3,9 @@ require "webpacker/configuration"
3
3
  namespace :webpacker do
4
4
  desc "Remove the webpack compiled output directory"
5
5
  task clobber: ["webpacker:verify_install", :environment] do
6
- packs_path = Webpacker::Configuration.packs_path
7
- FileUtils.rm_r(packs_path) if File.exist?(packs_path)
8
- puts "Removed webpack output path directory #{packs_path}"
6
+ output_path = Webpacker::Configuration.output_path
7
+ FileUtils.rm_r(output_path) if File.exist?(output_path)
8
+ puts "Removed webpack output path directory #{output_path}"
9
9
  end
10
10
  end
11
11
 
@@ -1,35 +1,29 @@
1
+ require "open3"
1
2
  require "webpacker/env"
2
3
  require "webpacker/configuration"
3
- REGEX_MAP = /\A.*\.map\z/
4
4
 
5
5
  namespace :webpacker do
6
6
  desc "Compile javascript packs using webpack for production with digests"
7
7
  task compile: ["webpacker:verify_install", :environment] do
8
- puts "Compiling webpacker assets 🎉"
9
- asset_host = Rails.application.config.action_controller.asset_host
10
- result = `ASSET_HOST=#{asset_host} NODE_ENV=#{Webpacker::Env.current} ./bin/webpack --json`
8
+ puts "[Webpacker] Compiling assets 🎉"
11
9
 
12
- unless $?.success?
13
- puts JSON.parse(result)["errors"]
14
- exit! $?.exitstatus
15
- end
10
+ asset_host = ActionController::Base.helpers.compute_asset_host
11
+ env = { "NODE_ENV" => Webpacker.env, "ASSET_HOST" => asset_host }.freeze
16
12
 
17
- puts "Compiled digests for all packs in #{Webpacker::Configuration.packs_path}: "
18
- puts JSON.parse(File.read(Webpacker::Configuration.manifest_path))
19
- end
13
+ stdout_str, stderr_str, status = Open3.capture3(env, "./bin/webpack")
20
14
 
21
- desc "Compile javascript packs using webpack for test with digests"
22
- task compile_before_test: ["webpacker:compile"] do
23
- Webpacker::Manifest.load(Webpacker::Manifest.file_path)
15
+ if status.success?
16
+ $stdout.puts "\e[32m[Webpacker] Compiled digests for all packs in #{Webpacker::Configuration.entry_path}:\e[0m"
17
+ $stdout.puts "\e[32m#{JSON.parse(File.read(Webpacker::Configuration.manifest_path))}\e[0m"
18
+ else
19
+ $stdout.puts "[Webpacker] Compilation Failed"
20
+ $stdout.puts "\e[31m#{stdout_str}\e[0m"
21
+ $stderr.puts "\e[31m#{stderr_str}\e[0m"
22
+ exit!
23
+ end
24
24
  end
25
25
  end
26
26
 
27
- # Compile packs prior to system and controller tests running
28
- if Rake::Task.task_defined?("test:system")
29
- Rake::Task["test:system"].enhance(["webpacker:compile_before_test"])
30
- Rake::Task["test:controllers"].enhance(["webpacker:compile_before_test"])
31
- end
32
-
33
27
  # Compile packs after we've compiled all other assets during precompilation
34
28
  if Rake::Task.task_defined?("assets:precompile")
35
29
  Rake::Task["assets:precompile"].enhance do
@@ -2,12 +2,12 @@ require "webpacker/configuration"
2
2
 
3
3
  namespace :webpacker do
4
4
  desc "Verifies if webpacker is installed"
5
- task verify_install: [:check_node, :check_yarn] do
5
+ task verify_install: [:check_node, :check_yarn, :check_webpack_binstubs] do
6
6
  if File.exist?(Webpacker::Configuration.file_path)
7
7
  puts "Webpacker is installed 🎉 🍰"
8
8
  puts "Using #{Webpacker::Configuration.file_path} file for setting up webpack paths"
9
9
  else
10
- puts "Configuration config/webpack/paths.yml file not found. \n"\
10
+ puts "Configuration config/webpacker.yml file not found. \n"\
11
11
  "Make sure webpacker:install is run successfully before " \
12
12
  "running dependent tasks"
13
13
  exit!
@@ -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
- task :yarn_install do
4
- system("./bin/yarn")
3
+ task :yarn_install, [:arg1, :arg2] do |task, args|
4
+ system "yarn #{args[:arg1]} #{args[:arg2]}"
5
5
  end
6
6
  end
@@ -1,9 +1,24 @@
1
1
  module Webpacker
2
- def self.bootstrap
2
+ extend self
3
+
4
+ def bootstrap
3
5
  Webpacker::Env.load
4
6
  Webpacker::Configuration.load
5
7
  Webpacker::Manifest.load
6
8
  end
9
+
10
+ def compile
11
+ Webpacker::Compiler.compile
12
+ Webpacker::Manifest.load
13
+ end
14
+
15
+ def env
16
+ Webpacker::Env.current.inquiry
17
+ end
7
18
  end
8
19
 
20
+ require "webpacker/env"
21
+ require "webpacker/configuration"
22
+ require "webpacker/manifest"
23
+ require "webpacker/compiler"
9
24
  require "webpacker/railtie" if defined?(Rails)
@@ -0,0 +1,20 @@
1
+ require "rake"
2
+
3
+ module Webpacker::Compiler
4
+ extend self
5
+
6
+ def compile
7
+ compile_task.invoke
8
+ compile_task.reenable
9
+ end
10
+
11
+ private
12
+ def compile_task
13
+ @compile_task ||= load_rake_task("webpacker:compile")
14
+ end
15
+
16
+ def load_rake_task(name)
17
+ @load_rakefile ||= Rake.load_rakefile(Rails.root.join("Rakefile"))
18
+ Rake::Task[name]
19
+ end
20
+ end
@@ -1,51 +1,59 @@
1
- # Loads webpacker configuration from config/webpack/paths.yml
1
+ # Loads webpacker configuration from config/webpacker.yml
2
+
2
3
  require "webpacker/file_loader"
3
- require "webpacker/env"
4
4
 
5
5
  class Webpacker::Configuration < Webpacker::FileLoader
6
6
  class << self
7
- def config_path
8
- Rails.root.join(paths.fetch(:config, "config/webpack"))
9
- end
10
-
11
7
  def entry_path
12
- Rails.root.join(source_path, paths.fetch(:entry, "packs"))
8
+ source_path.join(fetch(:source_entry_path))
13
9
  end
14
10
 
15
- def file_path
16
- Rails.root.join("config", "webpack", "paths.yml")
11
+ def output_path
12
+ public_path.join(fetch(:public_output_path))
17
13
  end
18
14
 
19
15
  def manifest_path
20
- Rails.root.join(packs_path, paths.fetch(:manifest, "manifest.json"))
16
+ output_path.join("manifest.json")
21
17
  end
22
18
 
23
- def packs_path
24
- Rails.root.join(output_path, paths.fetch(:entry, "packs"))
19
+ def source_path
20
+ Rails.root.join(source)
25
21
  end
26
22
 
27
- def paths
28
- load if Webpacker::Env.development?
29
- raise Webpacker::FileLoader::FileLoaderError.new("Webpacker::Configuration.load must be called first") unless instance
30
- instance.data
23
+ def public_path
24
+ Rails.root.join("public")
31
25
  end
32
26
 
33
- def output_path
34
- Rails.root.join(paths.fetch(:output, "public"))
27
+ def file_path(root: Rails.root)
28
+ root.join("config/webpacker.yml")
29
+ end
30
+
31
+ def default_file_path
32
+ file_path(root: Pathname.new(__dir__).join("../install"))
35
33
  end
36
34
 
37
35
  def source
38
- paths.fetch(:source, "app/javascript")
36
+ fetch(:source_path)
39
37
  end
40
38
 
41
- def source_path
42
- Rails.root.join(source)
39
+ def fetch(key)
40
+ data.fetch(key, defaults[key])
41
+ end
42
+
43
+ def data
44
+ load if Webpacker.env.development?
45
+ raise Webpacker::FileLoader::FileLoaderError.new("Webpacker::Configuration.load must be called first") unless instance
46
+ instance.data
47
+ end
48
+
49
+ def defaults
50
+ @defaults ||= HashWithIndifferentAccess.new(YAML.load(default_file_path.read)["default"])
43
51
  end
44
52
  end
45
53
 
46
54
  private
47
55
  def load
48
56
  return super unless File.exist?(@path)
49
- HashWithIndifferentAccess.new(YAML.load(File.read(@path))[Webpacker::Env.current])
57
+ HashWithIndifferentAccess.new(YAML.load(File.read(@path))[Webpacker.env])
50
58
  end
51
59
  end
@@ -1,4 +1,4 @@
1
- # Singleton registry for determining NODE_ENV from config/webpack/paths.yml
1
+ # Singleton registry for determining NODE_ENV from config/webpacker.yml
2
2
  require "webpacker/file_loader"
3
3
 
4
4
  class Webpacker::Env < Webpacker::FileLoader
@@ -8,12 +8,8 @@ class Webpacker::Env < Webpacker::FileLoader
8
8
  instance.data
9
9
  end
10
10
 
11
- def development?
12
- current == "development"
13
- end
14
-
15
11
  def file_path
16
- Rails.root.join("config", "webpack", "paths.yml")
12
+ Rails.root.join("config", "webpacker.yml")
17
13
  end
18
14
  end
19
15
 
@@ -1,5 +1,3 @@
1
- require "webpacker/manifest"
2
-
3
1
  module Webpacker::Helper
4
2
  # Computes the full path for a given webpacker asset.
5
3
  # Return relative path using manifest.json and passes it to asset_url helper
@@ -6,8 +6,6 @@
6
6
  # "/packs/calendar-1016838bab065ae1e314.css" for long-term caching
7
7
 
8
8
  require "webpacker/file_loader"
9
- require "webpacker/env"
10
- require "webpacker/configuration"
11
9
 
12
10
  class Webpacker::Manifest < Webpacker::FileLoader
13
11
  class << self
@@ -16,14 +14,33 @@ class Webpacker::Manifest < Webpacker::FileLoader
16
14
  end
17
15
 
18
16
  def lookup(name)
19
- load if Webpacker::Env.development?
20
- raise Webpacker::FileLoader::FileLoaderError.new("Webpacker::Manifest.load must be called first") unless instance
21
- instance.data[name.to_s] || raise(Webpacker::FileLoader::NotFoundError.new("Can't find #{name} in #{file_path}. Is webpack still compiling?"))
17
+ load if Webpacker.env.development?
18
+
19
+ if Webpacker.env.test?
20
+ find(name) || compile_and_find!(name)
21
+ else
22
+ find!(name)
23
+ end
22
24
  end
23
25
 
24
26
  def lookup_path(name)
25
- Rails.root.join(File.join(Webpacker::Configuration.output_path, lookup(name)))
27
+ Rails.root.join(File.join(Webpacker::Configuration.public_path, lookup(name)))
26
28
  end
29
+
30
+ private
31
+ def find(name)
32
+ instance.data[name.to_s] if instance
33
+ end
34
+
35
+ def find!(name)
36
+ raise Webpacker::FileLoader::FileLoaderError.new("Webpacker::Manifest.load must be called first") unless instance
37
+ instance.data[name.to_s] || raise(Webpacker::FileLoader::NotFoundError.new("Can't find #{name} in #{file_path}. Is webpack still compiling?"))
38
+ end
39
+
40
+ def compile_and_find!(name)
41
+ Webpacker.compile
42
+ find!(name)
43
+ end
27
44
  end
28
45
 
29
46
  private