Skip to content

Commit

Permalink
FIRST!1!
Browse files Browse the repository at this point in the history
  • Loading branch information
dhh committed Dec 7, 2016
0 parents commit f4cc31d
Show file tree
Hide file tree
Showing 16 changed files with 267 additions and 0 deletions.
20 changes: 20 additions & 0 deletions MIT-LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Copyright (c) 2016 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
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Webpacker

Webpacker makes it easy to use the JavaScript preprocessor and bundler Webpack
to manage application-like JavaScript in Rails. It coexists with the asset pipeline,
as the purpose is only to use Webpack for app-like JavaScript, not images, css, or
even JavaScript Sprinkles.

It's designed to work with Rails 5.1+ and makes use of the Yarn dependency management
that's been made default from that version forward. You can either make use of Webpacker
during setup of a new application with --webpack or you can uncomment the gem and run
`bin/rails webpacker:install` in an existing application.

When Webpacker has been installed...

FIXME: Write the rest...

## License
Webpacker is released under the [MIT License](http://www.opensource.org/licenses/MIT).
7 changes: 7 additions & 0 deletions lib/install/bin/webpack-watcher.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<%= shebang %>

BIN_PATH = File.expand_path('.', __dir__)

Dir.chdir(BIN_PATH) do
exec "./webpack --watch --progress --color #{ARGV.join(" ")}"
end
15 changes: 15 additions & 0 deletions lib/install/bin/webpack.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<%= shebang %>

RAILS_ENV = ENV['RAILS_ENV'] || 'development'
WEBPACK_ENV = ENV['WEBPACK_ENV'] || RAILS_ENV

APP_PATH = File.expand_path('../', __dir__)
VENDOR_PATH = File.expand_path('../vendor', __dir__)

SET_NODE_PATH = "NODE_PATH=#{VENDOR_PATH}/node_modules"
WEBPACK_BIN = "./node_modules/webpack/bin/webpack.js"
WEBPACK_CONFIG = "#{APP_PATH}/config/webpack/#{WEBPACK_ENV}.js"

Dir.chdir(VENDOR_PATH) do
exec "#{SET_NODE_PATH} #{WEBPACK_BIN} --config #{WEBPACK_CONFIG} #{ARGV.join(" ")}"
end
14 changes: 14 additions & 0 deletions lib/install/config/development.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Note: You must restart bin/webpack-watcher for changes to take effect

var path = require('path')
var webpack = require('webpack')
var _ = require('lodash')

var config = module.exports = require('./shared.js')

config = _.merge(config, {
debug: true,
displayErrorDetails: true,
outputPathinfo: true,
devtool: 'sourcemap',
})
14 changes: 14 additions & 0 deletions lib/install/config/production.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Note: You must restart bin/webpack-watcher for changes to take effect

var path = require('path')
var webpack = require('webpack')
var _ = require('lodash')

var config = module.exports = require('./shared.js');

config.output = _.merge(config.output, { filename: '[name]-[hash].js' })

This comment has been minimized.

Copy link
@guilleiguaran

guilleiguaran Dec 7, 2016

Member

@dhh I'm using webpack-merge that was created specifically for those cases, I'll send a PR for this in a moment so we can check what approach seems better.

This comment has been minimized.

Copy link
@dhh

dhh via email Dec 7, 2016

Author Member

config.plugins.push(
new webpack.optimize.UglifyJsPlugin(),
new webpack.optimize.OccurenceOrderPlugin()
)
31 changes: 31 additions & 0 deletions lib/install/config/shared.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Note: You must restart bin/webpack-watcher for changes to take effect

var path = require('path')
var glob = require('glob')
var _ = require('lodash')

module.exports = {
entry: _.keyBy(glob.sync('../app/javascript/packs/*.js'), function(entry) { return path.basename(entry, '.js') }),

output: { filename: '[name].js', path: '../public/packs' },

module: {
loaders: [
{ test: /\.coffee$/, loader: "coffee-loader" }
]
},

plugins: [],

resolve: {
extensions: [ '', '.js', '.coffee' ],
root: [
path.resolve('../app/javascript'),
path.resolve('../vendor/node_modules')
]
},

resolveLoader: {
modulesDirectories: [ path.resolve('../vendor/node_modules') ]
}
}
1 change: 1 addition & 0 deletions lib/install/javascript/packs/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// var React = require('react')
15 changes: 15 additions & 0 deletions lib/install/template.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
INSTALL_PATH = File.dirname(__FILE__)

directory "#{INSTALL_PATH}/javascript", 'app/javascript'

directory "#{INSTALL_PATH}/bin", 'bin'
chmod 'bin', 0755 & ~File.umask, verbose: false

directory "#{INSTALL_PATH}/config", 'config/webpack'

run './bin/yarn add webpack lodash'

environment \
"# Make javascript_pack_tag lookup digest hash to enable long-term caching\n" +
" config.x.webpacker[:digesting] = true\n",
env: 'production'
22 changes: 22 additions & 0 deletions lib/tasks/webpacker.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
PACKS_PATH = Rails.root.join('public/packs')
PACK_DIGESTS_PATH = PACKS_PATH.join('digests.json')

WEBPACKER_APP_TEMPLATE_PATH = File.expand_path('../install/template.rb', File.dirname(__FILE__))

namespace :webpacker do
desc "compile javascript packs using webpack for production with digests"
task :compile do
webpack_digests_json = JSON.parse(`WEBPACK_ENV=production ./bin/webpack --json`)['assetsByChunkName'].to_json

FileUtils.mkdir_p(PACKS_PATH)
File.open(PACK_DIGESTS_PATH, 'w+') { |file| file.write webpack_digests_json }

puts "Compiled digests for all packs in #{PACK_DIGESTS_PATH}: "
puts webpack_digests_json
end

desc "install webpacker in this application"
task :install do
exec "./bin/rails app:template LOCATION=#{WEBPACKER_APP_TEMPLATE_PATH}"
end
end
4 changes: 4 additions & 0 deletions lib/webpacker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Webpacker
end

require 'webpacker/railtie' if defined?(Rails)
36 changes: 36 additions & 0 deletions lib/webpacker/digests.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
class Webpacker::Digests
class_attribute :instance

class << self
def load(path)
self.instance = new(path)
end

def lookup(name)
if instance
instance.lookup(name)
else
raise "Webpacker::Digests.load(path) must be called first"
end
end
end

def initialize(path)
@path = path
load
end

def lookup(name)
@digests[name.to_s]
end

private
def load
begin
@digests = JSON.parse(File.read(@path))
rescue Errno::ENOENT
Rails.logger.error \
"Missing digests file at #{@path}! You must first compile the packs via rails webpacker:compile"
end
end
end
7 changes: 7 additions & 0 deletions lib/webpacker/helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'webpacker/source'

module Webpacker::Helper
def javascript_pack_tag(name, **options)
tag.script src: Webpacker::Source.new(name).path, **options
end
end
18 changes: 18 additions & 0 deletions lib/webpacker/railtie.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require 'rails/railtie'

require 'webpacker/helper'
require 'webpacker/digests'

class Webpacker::Engine < ::Rails::Engine
initializer :webpacker do
ActiveSupport.on_load :action_controller do
ActionController::Base.helper Webpacker::Helper
end

if Rails.configuration.x.webpacker[:digesting]
Webpacker::Digests.load \
Rails.application.config.x.webpacker[:digests_path] ||
Rails.root.join('public/packs/digests.json')
end
end
end
28 changes: 28 additions & 0 deletions lib/webpacker/source.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class Webpacker::Source
def initialize(name)
@name = name
end

def path
if digesting?
"/packs/#{digested_filename}"
else
"/packs/#{filename}"
end
end

private
attr_accessor :name

def digesting?
Rails.configuration.x.webpacker[:digesting]
end

def digested_filename
Webpacker::Digests.lookup(name)
end

def filename
"#{name}.js"
end
end
17 changes: 17 additions & 0 deletions webpacker.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Gem::Specification.new do |s|
s.name = 'webpacker'
s.version = '0.1'
s.authors = 'David Heinemeier Hansson'
s.email = '[email protected]'
s.summary = 'Use Webpack to manage app-like JavaScript modules in Rails'
s.homepage = 'https://github.com/rails/webpacker'
s.license = 'MIT'

s.required_ruby_version = '>= 1.9.3'

s.add_dependency 'activesupport', '>= 3.0.0', '< 5.1'
s.add_dependency 'multi_json', '~> 1.2'

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- test/*`.split("\n")
end

0 comments on commit f4cc31d

Please sign in to comment.