diff --git a/.travis.yml b/.travis.yml index 3e62c6222..399d1c0aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,9 @@ language: ruby before_install: - gem update --system rvm: - - 2.2.9 - - 2.3.6 - - 2.4.3 - - 2.5.0 + - 2.3.7 + - 2.4.4 + - 2.5.1 - ruby-head gemfile: - gemfiles/Gemfile-rails.4.2.x diff --git a/CHANGELOG.md b/CHANGELOG.md index 19723c008..fc0c6c9aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -**Please note that Webpacker 3.1.0 and 3.1.1 has some serious bugs so please consider using either 3.0.2 or 3.2.0** +**Please note that Webpacker 3.1.0 and 3.1.1 have some serious bugs so please consider using either 3.0.2 or 3.2.0** ## [3.4.3] - 2018-04-3 @@ -37,7 +37,7 @@ ### Breaking changes -- Fixes #1281 by installing binstubs only as local executables. To upgrade: +- Fixes [#1281](https://github.com/rails/webpacker/issues/1281) by installing binstubs only as local executables. To upgrade: ``` bundle exec rails webpacker:binstubs diff --git a/Gemfile.lock b/Gemfile.lock index d60409647..27105fadc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -57,7 +57,7 @@ GEM activesupport (>= 4.2.0) i18n (0.9.5) concurrent-ruby (~> 1.0) - loofah (2.2.0) + loofah (2.2.2) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.0) diff --git a/MIT-LICENSE b/MIT-LICENSE index c70c711fa..6067f3b46 100644 --- a/MIT-LICENSE +++ b/MIT-LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2017 David Heinemeier Hansson, Basecamp +Copyright (c) 2016-2018 David Heinemeier Hansson, Basecamp Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index 70afe2c5e..37b350ee6 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ Or add it to your `Gemfile`: ```ruby # Gemfile -gem 'webpacker', '~> 3.3' +gem 'webpacker', '~> 3.4' # OR if you prefer to use master gem 'webpacker', git: 'https://github.com/rails/webpacker.git' @@ -154,7 +154,7 @@ in the `app/javascript/packs/*.js` files and automatically reload the browser to ./bin/webpack-dev-server # watcher -./bin/webpack --colors --progress +./bin/webpack --watch --colors --progress # standalone build ./bin/webpack @@ -186,7 +186,7 @@ WEBPACKER_DEV_SERVER_HOST=0.0.0.0 ./bin/webpack-dev-server **Note:** You need to allow webpack-dev-server host as an allowed origin for `connect-src` if you are running your application in a restrict CSP environment (like Rails 5.2+). This can be done in Rails 5.2+ in the CSP initializer `config/initializers/content_security_policy.rb` with a snippet like this: ```ruby - p.connect_src :self, :https, 'http://localhost:3035', 'ws://localhost:3035' if Rails.env.development? + policy.connect_src :self, :https, 'http://localhost:3035', 'ws://localhost:3035' if Rails.env.development? ``` **Note:** Don't forget to prefix `ruby` when running these binstubs on Windows @@ -248,7 +248,7 @@ bundle exec rails webpacker:compile ### Upgrading -You can run following commands to upgrade Webpacker to the latest stable version. This process involves upgrading the gem and related npm modules: +You can run following commands to upgrade Webpacker to the latest stable version. This process involves upgrading the gem and related JavaScript packages: ```bash bundle update webpacker @@ -258,7 +258,7 @@ yarn add webpack-dev-server@^2.11.1 ### Yarn Integrity -By default, in development, webpacker runs a yarn integrity check to ensure that all local npm packages are up-to-date. This is similar to what bundler does currently in Rails, but for JavaScript packages. If your system is out of date, then Rails will not initialize. You will be asked to upgrade your local npm packages by running `yarn install`. +By default, in development, webpacker runs a yarn integrity check to ensure that all local JavaScript packages are up-to-date. This is similar to what bundler does currently in Rails, but for JavaScript packages. If your system is out of date, then Rails will not initialize. You will be asked to upgrade your local JavaScript packages by running `yarn install`. To turn off this option, you will need to override the default by adding a new config option to your Rails development environment configuration file (`config/environment/development.rb`): @@ -324,9 +324,9 @@ with the following code: ```ruby if Rails.env.development? - p.script_src :self, :https, :unsafe_eval + policy.script_src :self, :https, :unsafe_eval else - p.script_src :self, :https + policy.script_src :self, :https end ``` @@ -352,9 +352,9 @@ configuration: ```ruby if Rails.env.development? - p.script_src :self, :https, :unsafe_eval + policy.script_src :self, :https, :unsafe_eval else - p.script_src :self, :https + policy.script_src :self, :https end ``` You can read more about this in the [Vue docs](https://vuejs.org/v2/guide/installation.html#CSP-environments). @@ -486,7 +486,7 @@ Webpacker::Compiler.watched_paths << 'bower_components' ## Deployment -Webpacker hooks up a new `webpacker:compile` task to `assets:precompile`, which gets run whenever you run `assets:precompile`. If you are not using Sprockets, `webpacker:compile` is automatically aliased to `assets:precompile`. Remember to set NODE_ENV environment variable to production during deployment or when running this rake task. +Webpacker hooks up a new `webpacker:compile` task to `assets:precompile`, which gets run whenever you run `assets:precompile`. If you are not using Sprockets, `webpacker:compile` is automatically aliased to `assets:precompile`. Similar to sprockets both rake tasks will compile packs in production mode but will use `RAILS_ENV` to load configuration from `config/webpacker.yml` (if available). ## Docs diff --git a/docs/cloud9.md b/docs/cloud9.md index 824c84040..b098aebec 100644 --- a/docs/cloud9.md +++ b/docs/cloud9.md @@ -83,7 +83,7 @@ dev_server: use_local_ip: false ``` -into the these custom configuration: +into these custom configuration: ```yaml dev_server: diff --git a/docs/webpack.md b/docs/webpack.md index e1fb45de8..331b5dbc3 100644 --- a/docs/webpack.md +++ b/docs/webpack.md @@ -29,7 +29,7 @@ module.exports = { } // config/webpack/environment.js -const environment = require('./environment') +const { environment } = require('@rails/webpacker') const customConfig = require('./custom') // Set nested object prop using path notation diff --git a/lib/install/angular.rb b/lib/install/angular.rb index 3afdc4372..2f4de8db0 100644 --- a/lib/install/angular.rb +++ b/lib/install/angular.rb @@ -14,9 +14,9 @@ say "This can be done in Rails 5.2+ for development environment in the CSP initializer", :yellow say "config/initializers/content_security_policy.rb with a snippet like this:", :yellow say "if Rails.env.development?", :yellow - say " p.script_src :self, :https, :unsafe_eval", :yellow + say " policy.script_src :self, :https, :unsafe_eval", :yellow say "else", :yellow - say " p.script_src :self, :https", :yellow + say " policy.script_src :self, :https", :yellow say "end", :yellow end diff --git a/lib/install/bin/webpack b/lib/install/bin/webpack index 0869ad277..465832722 100755 --- a/lib/install/bin/webpack +++ b/lib/install/bin/webpack @@ -1,7 +1,7 @@ #!/usr/bin/env ruby ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" -ENV["NODE_ENV"] ||= ENV["NODE_ENV"] || "development" +ENV["NODE_ENV"] ||= "development" require "pathname" ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", diff --git a/lib/install/bin/webpack-dev-server b/lib/install/bin/webpack-dev-server index 251f65e8e..faa69f078 100755 --- a/lib/install/bin/webpack-dev-server +++ b/lib/install/bin/webpack-dev-server @@ -1,7 +1,7 @@ #!/usr/bin/env ruby ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" -ENV["NODE_ENV"] ||= ENV["NODE_ENV"] || "development" +ENV["NODE_ENV"] ||= "development" require "pathname" ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", diff --git a/lib/install/coffee.rb b/lib/install/coffee.rb index 37e88acbc..8f9b7a25c 100644 --- a/lib/install/coffee.rb +++ b/lib/install/coffee.rb @@ -22,4 +22,4 @@ say "Installing all Coffeescript dependencies" run "yarn add coffeescript@1.12.7 coffee-loader" -say "Webpacker now supports Coffeeescript 🎉", :green +say "Webpacker now supports Coffeescript 🎉", :green diff --git a/lib/install/examples/erb/hello_erb.js.erb b/lib/install/examples/erb/hello_erb.js.erb index 82a911491..b5a1765d0 100644 --- a/lib/install/examples/erb/hello_erb.js.erb +++ b/lib/install/examples/erb/hello_erb.js.erb @@ -1,5 +1,5 @@ -// Run this example by adding <%= javascript_pack_tag 'hello_erb' %> to the head of your layout file, -// like app/views/layouts/application.html.erb. +// Run this example by adding <%%= javascript_pack_tag 'hello_erb' %> to the head of your layout file, +// like app/views/layouts/application.html.erb. Don't forget to uncomment erb tag after adding it to your layout file. <% name = 'Erb' %> diff --git a/lib/install/template.rb b/lib/install/template.rb index d1c8ab89d..959db690e 100644 --- a/lib/install/template.rb +++ b/lib/install/template.rb @@ -19,7 +19,7 @@ check_yarn_integrity_config = ->(value) { <= 5 @@ -50,7 +50,7 @@ say "You need to allow webpack-dev-server host as allowed origin for connect-src.", :yellow say "This can be done in Rails 5.2+ for development environment in the CSP initializer", :yellow say "config/initializers/content_security_policy.rb with a snippet like this:", :yellow - say "p.connect_src :self, :https, \"http://localhost:3035\", \"ws://localhost:3035\" if Rails.env.development?", :yellow + say "policy.connect_src :self, :https, \"http://localhost:3035\", \"ws://localhost:3035\" if Rails.env.development?", :yellow end say "Webpacker successfully installed 🎉 🍰", :green diff --git a/lib/install/vue.rb b/lib/install/vue.rb index d514a7703..7ff4519d6 100644 --- a/lib/install/vue.rb +++ b/lib/install/vue.rb @@ -31,9 +31,9 @@ say "This can be done in Rails 5.2+ for development environment in the CSP initializer", :yellow say "config/initializers/content_security_policy.rb with a snippet like this:", :yellow say "if Rails.env.development?", :yellow - say " p.script_src :self, :https, :unsafe_eval", :yellow + say " policy.script_src :self, :https, :unsafe_eval", :yellow say "else", :yellow - say " p.script_src :self, :https", :yellow + say " policy.script_src :self, :https", :yellow say "end", :yellow end diff --git a/lib/tasks/webpacker.rake b/lib/tasks/webpacker.rake index ba44204d2..adf441b59 100644 --- a/lib/tasks/webpacker.rake +++ b/lib/tasks/webpacker.rake @@ -1,4 +1,5 @@ tasks = { + "webpacker:info" => "Provides information on Webpacker's environment", "webpacker:install" => "Installs and setup webpack with Yarn", "webpacker:compile" => "Compiles webpack bundles based on environment", "webpacker:clobber" => "Removes the webpack compiled output directory", diff --git a/lib/tasks/webpacker/info.rake b/lib/tasks/webpacker/info.rake new file mode 100644 index 000000000..3a44a12d9 --- /dev/null +++ b/lib/tasks/webpacker/info.rake @@ -0,0 +1,19 @@ +require "webpacker/version" + +namespace :webpacker do + desc "Provide information on Webpacker's environment" + task :info do + $stdout.puts "Ruby: #{`ruby --version`}" + $stdout.puts "Rails: #{Rails.version}" + $stdout.puts "Webpacker: #{Webpacker::VERSION}" + $stdout.puts "Node: #{`node --version`}" + $stdout.puts "Yarn: #{`yarn --version`}" + + $stdout.puts "\n" + $stdout.puts "@rails/webpacker: \n#{`npm list @rails/webpacker version`}" + + $stdout.puts "Is bin/webpack present?: #{File.exist? 'bin/webpack'}" + $stdout.puts "Is bin/webpack-dev-server present?: #{File.exist? 'bin/webpack-dev-server'}" + $stdout.puts "Is bin/yarn present?: #{File.exist? 'bin/yarn'}" + end +end diff --git a/lib/webpacker.rb b/lib/webpacker.rb index a58563d90..44a56639d 100644 --- a/lib/webpacker.rb +++ b/lib/webpacker.rb @@ -15,7 +15,7 @@ def instance def with_node_env(env) original = ENV["NODE_ENV"] - ENV["NODE_ENV"] = "production" + ENV["NODE_ENV"] = env yield ensure ENV["NODE_ENV"] = original diff --git a/lib/webpacker/compiler.rb b/lib/webpacker/compiler.rb index 14be5ac73..05ba069f7 100644 --- a/lib/webpacker/compiler.rb +++ b/lib/webpacker/compiler.rb @@ -19,7 +19,9 @@ def initialize(webpacker) def compile if stale? record_compilation_digest - run_webpack + run_webpack.tap do |success| + remove_compilation_digest if !success + end else true end @@ -50,10 +52,14 @@ def record_compilation_digest compilation_digest_path.write(watched_files_digest) end + def remove_compilation_digest + compilation_digest_path.delete if compilation_digest_path.exist? + end + def run_webpack logger.info "Compiling…" - sterr, stdout, status = Open3.capture3(webpack_env, "#{RbConfig.ruby} ./bin/webpack") + stdout, sterr , status = Open3.capture3(webpack_env, "#{RbConfig.ruby} ./bin/webpack") if status.success? logger.info "Compiled all packs in #{config.public_output_path}" diff --git a/lib/webpacker/dev_server.rb b/lib/webpacker/dev_server.rb index 49c918bc5..df6aa31fc 100644 --- a/lib/webpacker/dev_server.rb +++ b/lib/webpacker/dev_server.rb @@ -60,6 +60,6 @@ def fetch(key) end def defaults - config.send(:defaults)[:dev_server] + config.send(:defaults)[:dev_server] || {} end end diff --git a/lib/webpacker/dev_server_proxy.rb b/lib/webpacker/dev_server_proxy.rb index 04c3c1eee..ed73ebac0 100644 --- a/lib/webpacker/dev_server_proxy.rb +++ b/lib/webpacker/dev_server_proxy.rb @@ -11,6 +11,10 @@ def rewrite_response(response) def perform_request(env) if env["PATH_INFO"].start_with?("/#{public_output_uri_path}") && Webpacker.dev_server.running? env["HTTP_HOST"] = env["HTTP_X_FORWARDED_HOST"] = env["HTTP_X_FORWARDED_SERVER"] = Webpacker.dev_server.host_with_port + env["HTTP_X_FORWARDED_PROTO"] = env["HTTP_X_FORWARDED_SCHEME"] = Webpacker.dev_server.protocol + unless Webpacker.dev_server.https? + env["HTTPS"] = env["HTTP_X_FORWARDED_SSL"] = "off" + end env["SCRIPT_NAME"] = "" super(env) diff --git a/lib/webpacker/helper.rb b/lib/webpacker/helper.rb index 54e106dc2..38858da12 100644 --- a/lib/webpacker/helper.rb +++ b/lib/webpacker/helper.rb @@ -33,6 +33,16 @@ def asset_pack_url(name, **options) end end + # Creates a image tag that references the named pack file. + # + # Example: + # + # <%= image_pack_tag 'application.png', size: '16x10', alt: 'Edit Entry' %> + # Edit Entry + def image_pack_tag(name, **options) + image_tag(asset_path(Webpacker.manifest.lookup!(name)), **options) + end + # Creates a script tag that references the named pack file, as compiled by webpack per the entries list # in config/webpack/shared.js. By default, this list is auto-generated to match everything in # app/javascript/packs/*.js. In production mode, the digested reference is automatically looked up. diff --git a/lib/webpacker/railtie.rb b/lib/webpacker/railtie.rb index 31f5c747c..64a78a0f7 100644 --- a/lib/webpacker/railtie.rb +++ b/lib/webpacker/railtie.rb @@ -46,7 +46,8 @@ class Webpacker::Engine < ::Rails::Engine end initializer "webpacker.proxy" do |app| - if Rails.env.development? + insert_middleware = Webpacker.config.dev_server.present? rescue nil + if insert_middleware app.middleware.insert_before 0, Rails::VERSION::MAJOR >= 5 ? Webpacker::DevServerProxy : "Webpacker::DevServerProxy", ssl_verify_none: true diff --git a/package/__tests__/config.js b/package/__tests__/config.js index acdd99e58..ee722cf43 100644 --- a/package/__tests__/config.js +++ b/package/__tests__/config.js @@ -1,14 +1,30 @@ /* global test expect, describe */ -const { chdirTestApp, chdirCwd } = require('../utils/helpers') +const { chdirCwd, chdirTestApp } = require('../utils/helpers') chdirTestApp() const config = require('../config') describe('Config', () => { + beforeEach(() => jest.resetModules()) afterAll(chdirCwd) + test('public path', () => { + process.env.RAILS_ENV = 'development' + delete process.env.RAILS_RELATIVE_URL_ROOT + const config = require('../config') + expect(config.publicPath).toEqual('/packs/') + }) + + // also tests removal of extra slashes + test('public path with relative root', () => { + process.env.RAILS_ENV = 'development' + process.env.RAILS_RELATIVE_URL_ROOT = '/foo' + const config = require('../config') + expect(config.publicPath).toEqual('/foo/packs/') + }) + test('should return extensions as listed in app config', () => { expect(config.extensions).toEqual([ '.js', diff --git a/package/config.js b/package/config.js index 48ae7778a..e0dba2cec 100644 --- a/package/config.js +++ b/package/config.js @@ -20,6 +20,14 @@ if (isArray(app.extensions) && app.extensions.length) delete defaults.extensions const config = deepMerge(defaults, app) config.outputPath = resolve('public', config.public_output_path) -config.publicPath = `/${config.public_output_path}/`.replace(/([^:]\/)\/+/g, '$1') + +let publicPath = `/${config.public_output_path}/` +// Add prefix to publicPath. +if (process.env.RAILS_RELATIVE_URL_ROOT) { + publicPath = `/${process.env.RAILS_RELATIVE_URL_ROOT}${publicPath}` +} + +// Remove extra slashes. +config.publicPath = publicPath.replace(/(^\/|[^:]\/)\/+/g, '$1') module.exports = config diff --git a/test/compiler_test.rb b/test/compiler_test.rb index fd6c4c798..11f1edba9 100644 --- a/test/compiler_test.rb +++ b/test/compiler_test.rb @@ -1,12 +1,20 @@ require "test_helper" class CompilerTest < Minitest::Test - def setup + def remove_compilation_digest_path Webpacker.compiler.send(:compilation_digest_path).tap do |path| path.delete if path.exist? end end + def setup + remove_compilation_digest_path + end + + def teardown + remove_compilation_digest_path + end + def test_custom_environment_variables assert Webpacker.compiler.send(:webpack_env)["FOO"] == nil Webpacker.compiler.env["FOO"] = "BAR" @@ -29,6 +37,27 @@ def test_freshness assert !Webpacker.compiler.fresh? end + def test_freshness_on_compile_success + status = OpenStruct.new(success?: true) + + assert Webpacker.compiler.stale? + Open3.stub :capture3, [:sterr, :stdout, status] do + Webpacker.compiler.compile + assert Webpacker.compiler.fresh? + end + end + + def test_staleness_on_compile_fail + status = OpenStruct.new(success?: false) + + assert Webpacker.compiler.stale? + Open3.stub :capture3, [:sterr, :stdout, status] do + + Webpacker.compiler.compile + assert Webpacker.compiler.stale? + end + end + def test_compilation_digest_path assert Webpacker.compiler.send(:compilation_digest_path).to_s.ends_with?(Webpacker.env) end diff --git a/test/helper_test.rb b/test/helper_test.rb index 85d7a789d..9f4e59576 100644 --- a/test/helper_test.rb +++ b/test/helper_test.rb @@ -31,6 +31,12 @@ def test_asset_pack_url assert_equal "https://example.com/packs/bootstrap-c38deda30895059837cf.css", asset_pack_url("bootstrap.css") end + def test_image_pack_tag + assert_equal \ + "\"Edit", + image_pack_tag("application.png", size: "16x10", alt: "Edit Entry") + end + def test_javascript_pack_tag assert_equal \ %(), diff --git a/webpacker.gemspec b/webpacker.gemspec index af07b6120..8896f30ff 100644 --- a/webpacker.gemspec +++ b/webpacker.gemspec @@ -10,6 +10,11 @@ Gem::Specification.new do |s| s.homepage = "https://github.com/rails/webpacker" s.license = "MIT" + s.metadata = { + "source_code_uri" => "https://github.com/rails/webpacker/tree/v#{Webpacker::VERSION}", + "changelog_uri" => "https://github.com/rails/webpacker/blob/v#{Webpacker::VERSION}/CHANGELOG.md" + } + s.required_ruby_version = ">= 2.2.0" s.add_dependency "activesupport", ">= 4.2"