Skip to content

Commit

Permalink
Merge pull request #397 from javan/customize-output-path
Browse files Browse the repository at this point in the history
Fix asset host support & improve output path
  • Loading branch information
javan authored May 18, 2017
2 parents 912fb06 + cc0dfb5 commit ebcc609
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 81 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/.bundle
/pkg
/test/test_app/log
node_modules
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
### Fixed
- Update `.babelrc` to fix compilation issues - [#306](https://github.com/rails/webpacker/issues/306)

- Duplicated asset hosts - [#320](https://github.com/rails/webpacker/issues/320), [#397](https://github.com/rails/webpacker/pull/397)

- Missing asset host when defined as a `Proc` or on `ActionController::Base.asset_host` directly - [#397](https://github.com/rails/webpacker/pull/397)

- Incorrect asset host when running `webpacker:compile` or `bin/webpack` in development mode - [#397](https://github.com/rails/webpacker/pull/397)

### Added
- [Elm](http://elm-lang.org) support. You can now add Elm support via the following methods:
- New app: `rails new <app> --webpack=elm`
- Within an existing app: `rails webpacker:install:elm`

- Support for custom `output` paths independent of `entry` in `paths.yml`. `output` is also now relative to `public/`. - [#397](https://github.com/rails/webpacker/pull/397)

Before (compile to `public/packs`):
```yaml
entry: packs
output: public
```
After (compile to `public/sweet/js`):
```yaml
entry: packs
output: sweet/js
```

## [1.2] - 2017-04-27
Some of the changes made requires you to run below commands to install new changes.

Expand Down
28 changes: 14 additions & 14 deletions lib/install/bin/webpack-dev-server.tt
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,26 @@ RAILS_ENV = ENV["RAILS_ENV"]
ENV["NODE_ENV"] ||= RAILS_ENV
NODE_ENV = ENV["NODE_ENV"]

APP_PATH = File.expand_path("../", __dir__)
CONFIG_PATH = File.join(APP_PATH, "config/webpack/paths.yml")
APP_PATH = File.expand_path("../", __dir__)

begin
paths = YAML.load(File.read(CONFIG_PATH))[NODE_ENV]

NODE_MODULES_PATH = File.join(APP_PATH.shellescape, paths["node_modules"])
WEBPACK_CONFIG_PATH = File.join(APP_PATH.shellescape, paths["config"])

DEV_SERVER_CONFIG = "#{WEBPACK_CONFIG_PATH}/development.server.js"
def load_yaml_config(config_file)
YAML.load_file(File.join(APP_PATH, config_file))[NODE_ENV]
rescue Errno::ENOENT, NoMethodError
puts "Configuration not found in config/webpacker/paths.yml."
puts "Configuration not found in #{config_file}."
puts "Please run bundle exec rails webpacker:install to install webpacker"
exit!
end

DEV_SERVER_BIN = "yarn run webpack-dev-server"
newenv = { "NODE_PATH" => NODE_MODULES_PATH }
cmdline = [DEV_SERVER_BIN, "--", "--progress", "--color", "--config", DEV_SERVER_CONFIG] + ARGV
paths = load_yaml_config("config/webpack/paths.yml")
NODE_MODULES_PATH = File.join(APP_PATH, paths["node_modules"])
WEBPACK_CONFIG = File.join(APP_PATH, paths["config"], "development.server.js")

dev_server = load_yaml_config("config/webpack/development.server.yml")
DEV_SERVER_HOST = "http#{"s" if dev_server["https"]}://#{dev_server["host"]}:#{dev_server["port"]}"

newenv = { "NODE_PATH" => NODE_MODULES_PATH.shellescape, "ASSET_HOST" => DEV_SERVER_HOST.shellescape }
cmdline = ["yarn", "run", "webpack-dev-server", "--", "--progress", "--color", "--config", WEBPACK_CONFIG] + ARGV

Dir.chdir(APP_PATH) do
exec newenv, cmdline.join(' ')
exec newenv, *cmdline
end
23 changes: 10 additions & 13 deletions lib/install/bin/webpack.tt
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,23 @@ RAILS_ENV = ENV["RAILS_ENV"]
ENV["NODE_ENV"] ||= RAILS_ENV
NODE_ENV = ENV["NODE_ENV"]

APP_PATH = File.expand_path("../", __dir__)
CONFIG_PATH = File.join(APP_PATH, "config/webpack/paths.yml")
APP_PATH = File.expand_path("../", __dir__)

begin
paths = YAML.load(File.read(CONFIG_PATH))[NODE_ENV]

NODE_MODULES_PATH = File.join(APP_PATH.shellescape, paths["node_modules"])
WEBPACK_CONFIG_PATH = File.join(APP_PATH.shellescape, paths["config"])
def load_yaml_config(config_file)
YAML.load_file(File.join(APP_PATH, config_file))[NODE_ENV]
rescue Errno::ENOENT, NoMethodError
puts "Configuration not found in config/webpack/paths.yml"
puts "Configuration not found in #{config_file}."
puts "Please run bundle exec rails webpacker:install to install webpacker"
exit!
end

WEBPACK_BIN = "yarn run webpack"
WEBPACK_CONFIG = "#{WEBPACK_CONFIG_PATH}/#{NODE_ENV}.js"
paths = load_yaml_config("config/webpack/paths.yml")
NODE_MODULES_PATH = File.join(APP_PATH, paths["node_modules"])
WEBPACK_CONFIG = File.join(APP_PATH, paths["config"], "#{NODE_ENV}.js")

newenv = { "NODE_PATH" => NODE_MODULES_PATH }
cmdline = [WEBPACK_BIN, "--", "--config", WEBPACK_CONFIG] + ARGV
newenv = { "NODE_PATH" => NODE_MODULES_PATH.shellescape }
cmdline = ["yarn", "run", "webpack", "--", "--config", WEBPACK_CONFIG] + ARGV

Dir.chdir(APP_PATH) do
exec newenv, cmdline.join(' ')
exec newenv, *cmdline
end
25 changes: 18 additions & 7 deletions lib/install/config/webpack/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,28 @@ const loadersDir = join(__dirname, 'loaders')
const paths = safeLoad(readFileSync(join(configPath, 'paths.yml'), 'utf8'))[env.NODE_ENV]
const devServer = safeLoad(readFileSync(join(configPath, 'development.server.yml'), 'utf8'))[env.NODE_ENV]

// Compute public path based on environment and ASSET_HOST in production
const ifHasCDN = env.ASSET_HOST !== undefined && env.NODE_ENV === 'production'
const devServerUrl = `http://${devServer.host}:${devServer.port}/${paths.entry}/`
const publicUrl = ifHasCDN ? `${env.ASSET_HOST}/${paths.entry}/` : `/${paths.entry}/`
const publicPath = env.NODE_ENV !== 'production' && devServer.enabled ? devServerUrl : publicUrl
function removeOuterSlashes(string) {
return string.replace(/^\/*/, '').replace(/\/*$/, '')
}

function formatPublicPath(host = '', path = '') {
let formattedHost = removeOuterSlashes(host)
if (formattedHost && !/^http/i.test(formattedHost)) {
formattedHost = `//${formattedHost}`
}
const formattedPath = removeOuterSlashes(path)
return `${formattedHost}/${formattedPath}/`
}

const output = {
path: resolve('public', paths.output),
publicPath: formatPublicPath(env.ASSET_HOST, paths.output)
}

module.exports = {
devServer,
env,
paths,
loadersDir,
publicUrl,
publicPath
output
}
9 changes: 4 additions & 5 deletions lib/install/config/webpack/development.server.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
// Note: You must restart bin/webpack-dev-server for changes to take effect

const { resolve } = require('path')
const merge = require('webpack-merge')
const devConfig = require('./development.js')
const { devServer, publicPath, paths } = require('./configuration.js')
const { devServer, output } = require('./configuration.js')

module.exports = merge(devConfig, {
devServer: {
host: devServer.host,
port: devServer.port,
contentBase: output.path,
publicPath: output.publicPath,
compress: true,
headers: { 'Access-Control-Allow-Origin': '*' },
historyApiFallback: true,
contentBase: resolve(paths.output, paths.entry),
publicPath
historyApiFallback: true
}
})
14 changes: 7 additions & 7 deletions lib/install/config/webpack/paths.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Note: You must restart bin/webpack-dev-server for changes to take effect

default: &default
config: config/webpack
entry: packs
output: public
manifest: manifest.json
node_modules: node_modules
source: app/javascript
default: &default # ~ = Rails.root
source: app/javascript # ~/:source
entry: packs # ~/:source/:entry
output: packs # ~/public/:output
manifest: manifest.json # ~/public/:output/:manifest
config: config/webpack # ~/:config
node_modules: node_modules # ~/:node_modules
extensions:
- .coffee
- .js
Expand Down
12 changes: 8 additions & 4 deletions lib/install/config/webpack/shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const { sync } = require('glob')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const ManifestPlugin = require('webpack-manifest-plugin')
const extname = require('path-complete-extname')
const { env, paths, publicPath, loadersDir } = require('./configuration.js')
const { env, paths, output, loadersDir } = require('./configuration.js')

const extensionGlob = `**/*{${paths.extensions.join(',')}}*`
const packPaths = sync(join(paths.source, paths.entry, extensionGlob))
Expand All @@ -26,8 +26,8 @@ module.exports = {

output: {
filename: '[name].js',
path: resolve(paths.output, paths.entry),
publicPath
path: output.path,
publicPath: output.publicPath
},

module: {
Expand All @@ -37,7 +37,11 @@ module.exports = {
plugins: [
new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
new ExtractTextPlugin(env.NODE_ENV === 'production' ? '[name]-[hash].css' : '[name].css'),
new ManifestPlugin({ fileName: paths.manifest, publicPath, writeToFileEmit: true })
new ManifestPlugin({
fileName: paths.manifest,
publicPath: output.publicPath,
writeToFileEmit: true
})
],

resolve: {
Expand Down
6 changes: 3 additions & 3 deletions lib/tasks/webpacker/clobber.rake
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ require "webpacker/configuration"
namespace :webpacker do
desc "Remove the webpack compiled output directory"
task clobber: ["webpacker:verify_install", :environment] do
packs_path = Webpacker::Configuration.packs_path
FileUtils.rm_r(packs_path) if File.exist?(packs_path)
puts "Removed webpack output path directory #{packs_path}"
output_path = Webpacker::Configuration.output_path
FileUtils.rm_r(output_path) if File.exist?(output_path)
puts "Removed webpack output path directory #{output_path}"
end
end

Expand Down
4 changes: 2 additions & 2 deletions lib/tasks/webpacker/compile.rake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace :webpacker do
desc "Compile javascript packs using webpack for production with digests"
task compile: ["webpacker:verify_install", :environment] do
puts "Compiling webpacker assets 🎉"
asset_host = Rails.application.config.action_controller.asset_host
asset_host = ActionController::Base.helpers.compute_asset_host
asset_env = asset_host ? "ASSET_HOST=#{asset_host}" : ""
result = `#{asset_env} NODE_ENV=#{Webpacker.env} ./bin/webpack --json`

Expand All @@ -15,7 +15,7 @@ namespace :webpacker do
exit! $?.exitstatus
end

puts "Compiled digests for all packs in #{Webpacker::Configuration.packs_path}: "
puts "Compiled digests for all packs in #{Webpacker::Configuration.entry_path}: "
puts JSON.parse(File.read(Webpacker::Configuration.manifest_path))
end
end
Expand Down
50 changes: 31 additions & 19 deletions lib/webpacker/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,54 @@

class Webpacker::Configuration < Webpacker::FileLoader
class << self
def config_path
Rails.root.join(paths.fetch(:config, "config/webpack"))
end

def entry_path
Rails.root.join(source_path, paths.fetch(:entry, "packs"))
source_path.join(fetch(:entry))
end

def file_path
Rails.root.join("config", "webpack", "paths.yml")
def output_path
public_path.join(fetch(:output))
end

def manifest_path
Rails.root.join(packs_path, paths.fetch(:manifest, "manifest.json"))
output_path.join(fetch(:manifest))
end

def packs_path
Rails.root.join(output_path, paths.fetch(:entry, "packs"))
def source_path
Rails.root.join(source)
end

def paths
load if Webpacker.env.development?
raise Webpacker::FileLoader::FileLoaderError.new("Webpacker::Configuration.load must be called first") unless instance
instance.data
def public_path
Rails.root.join("public")
end

def output_path
Rails.root.join(paths.fetch(:output, "public"))
def config_path
Rails.root.join(fetch(:config))
end

def file_path(root: Rails.root)
root.join("config/webpack/paths.yml")
end

def default_file_path
file_path(root: Pathname.new(__dir__).join("../install"))
end

def source
paths.fetch(:source, "app/javascript")
fetch(:source)
end

def source_path
Rails.root.join(source)
def fetch(key)
paths.fetch(key, default_paths[key])
end

def paths
load if Webpacker.env.development?
raise Webpacker::FileLoader::FileLoaderError.new("Webpacker::Configuration.load must be called first") unless instance
instance.data
end

def default_paths
@default_paths ||= HashWithIndifferentAccess.new(YAML.load(default_file_path.read)["default"])
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/webpacker/manifest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def lookup(name)
end

def lookup_path(name)
Rails.root.join(File.join(Webpacker::Configuration.output_path, lookup(name)))
Rails.root.join(File.join(Webpacker::Configuration.public_path, lookup(name)))
end

private
Expand Down
7 changes: 1 addition & 6 deletions test/configuration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,8 @@ def test_manifest_path
assert_equal Webpacker::Configuration.manifest_path.to_s, manifest_path
end

def test_packs_path
packs_path = File.join(File.dirname(__FILE__), "test_app/public/packs").to_s
assert_equal Webpacker::Configuration.packs_path.to_s, packs_path
end

def test_output_path
output_path = File.join(File.dirname(__FILE__), "test_app/public").to_s
output_path = File.join(File.dirname(__FILE__), "test_app/public/packs").to_s
assert_equal Webpacker::Configuration.output_path.to_s, output_path
end

Expand Down

0 comments on commit ebcc609

Please sign in to comment.