webpack_rails 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/webpack_rails.rb +8 -0
- data/lib/webpack_rails/engine.rb +12 -0
- data/lib/webpack_rails/processor.rb +24 -0
- data/lib/webpack_rails/sprockets_base_webpack.rb +14 -0
- data/lib/webpack_rails/sprockets_index_webpack.rb +15 -0
- data/lib/webpack_rails/task.rb +86 -0
- data/lib/webpack_rails/webpack-task.js +87 -0
- metadata +84 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4eefc65be79a7423acbb4aee442f794dda650b0a
|
4
|
+
data.tar.gz: fc8ff00a8a7ffb4048e783756c0d35041f7c81f7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c12944c42e4f37cf0ad6d559a6389553067ce9034590aa93f25929767656542795ae622657f0cda43c9f3a5217f9440a1feca69dfe68e7ff693e72e8c5f37e85
|
7
|
+
data.tar.gz: b737ff3f47506b20307bc35af43cb94e25bea7e61f3cd15473987fcfa3823873e194b297eaf5b3d0831fc1edddc66a4def50ecfd52e6d1fd6a46f84637c56cc6
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative './processor'
|
2
|
+
|
3
|
+
module WebpackRails
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
initializer :setup_webpack_rails, :after => "sprockets.environment", :group => :all do |app|
|
6
|
+
# where [name].bundle.js files should be
|
7
|
+
app.assets.append_path Rails.root.join('tmp/webpack/bundles')
|
8
|
+
# process
|
9
|
+
app.assets.register_preprocessor('application/javascript', WebpackRails::Processor)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
|
3
|
+
require_relative './sprockets_index_webpack'
|
4
|
+
require_relative './task'
|
5
|
+
|
6
|
+
module WebpackRails
|
7
|
+
class Processor < Tilt::Template
|
8
|
+
def prepare
|
9
|
+
end
|
10
|
+
|
11
|
+
def evaluate(context, locals)
|
12
|
+
return data unless context.pathname.to_s.include?('.bundle')
|
13
|
+
|
14
|
+
# wait til webpack is done before loading
|
15
|
+
result = WebpackRails::Task.run_webpack
|
16
|
+
|
17
|
+
result[:modules].map{|m| context.depend_on m}
|
18
|
+
|
19
|
+
bundle_contents = context.pathname.open.read
|
20
|
+
# rewrite $asset_paths in strings
|
21
|
+
bundle_contents.gsub(/['"]\$asset_path\/([^'"]+?)['"]/) {|s| "'#{context.asset_path($1)}'" }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'sprockets'
|
2
|
+
require_relative './task'
|
3
|
+
|
4
|
+
# reopen Sprockets::Base and monkeypatch resolve
|
5
|
+
class Sprockets::Base
|
6
|
+
original_resolve = instance_method(:resolve)
|
7
|
+
|
8
|
+
define_method :resolve, ->(logical_path, options = {}, &block) {
|
9
|
+
if logical_path.to_s.include?('.bundle')
|
10
|
+
WebpackRails::Task.run_webpack # ensure output files exist so original_resolve doesn't fail
|
11
|
+
end
|
12
|
+
original_resolve.bind(self).(logical_path, options, &block)
|
13
|
+
}
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'sprockets'
|
2
|
+
require_relative './task'
|
3
|
+
|
4
|
+
# reopen Sprockets::Index and monkeypatch find_asset
|
5
|
+
class Sprockets::Index
|
6
|
+
original_find_asset = instance_method(:find_asset)
|
7
|
+
|
8
|
+
define_method :find_asset, ->(path, options = {}) {
|
9
|
+
unless @_webpack_built
|
10
|
+
WebpackRails::Task.run_webpack # ensure output files exist so original_find_asset doesn't fail
|
11
|
+
@_webpack_built = true
|
12
|
+
end
|
13
|
+
original_find_asset.bind(self).(path, options)
|
14
|
+
}
|
15
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'node_task'
|
2
|
+
require 'benchmark'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module WebpackRails
|
6
|
+
class Task < NodeTask
|
7
|
+
# wraps NodeTask::Error
|
8
|
+
class Error < StandardError
|
9
|
+
def initialize(node_task_error)
|
10
|
+
super(node_task_error.to_s)
|
11
|
+
|
12
|
+
# TODO: expose @js_error from NodeTask::Error
|
13
|
+
js_error = node_task_error.instance_variable_get(:@js_error)
|
14
|
+
set_backtrace(js_error[:stack].split('\n')) if js_error
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def root_dir
|
20
|
+
@root_dir ||= defined?(Rails) ? Rails.root.to_s : Dir.pwd
|
21
|
+
end
|
22
|
+
|
23
|
+
def working_dir
|
24
|
+
@working_dir ||= _make_working_dir
|
25
|
+
end
|
26
|
+
|
27
|
+
def webpack_gem_dir
|
28
|
+
@webpack_gem_dir ||= File.dirname(File.expand_path(__FILE__))
|
29
|
+
end
|
30
|
+
|
31
|
+
def webpack_task_script
|
32
|
+
@webpack_task_script ||= File.join(webpack_gem_dir, 'webpack-task.js')
|
33
|
+
end
|
34
|
+
|
35
|
+
def app_node_path
|
36
|
+
@app_node_path ||= File.join(root_dir, 'node_modules')
|
37
|
+
end
|
38
|
+
|
39
|
+
def with_app_node_path
|
40
|
+
prev_node_path = ENV['NODE_PATH']
|
41
|
+
ENV['NODE_PATH'] = app_node_path
|
42
|
+
return_value = nil
|
43
|
+
Dir.chdir(root_dir) do
|
44
|
+
return_value = yield
|
45
|
+
end
|
46
|
+
ENV['NODE_PATH'] = prev_node_path
|
47
|
+
return_value
|
48
|
+
end
|
49
|
+
|
50
|
+
def run_webpack(opts = nil)
|
51
|
+
result = nil
|
52
|
+
|
53
|
+
task_duration = Benchmark.realtime do
|
54
|
+
result = with_app_node_path do
|
55
|
+
begin
|
56
|
+
task = self.new
|
57
|
+
task.run(opts)
|
58
|
+
rescue NodeTask::Error => e
|
59
|
+
raise self::Error.new(e)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
task_duration_ms = task_duration * 1000
|
65
|
+
if defined?(Rails) && task_duration_ms > 10
|
66
|
+
Rails.logger.info("Webpack: #{task_duration_ms.round(0)}ms")
|
67
|
+
end
|
68
|
+
|
69
|
+
result
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def _make_working_dir
|
75
|
+
# one node_task daemon will be created per unique working dir
|
76
|
+
wd = File.join(root_dir, 'tmp', 'webpack', 'task')
|
77
|
+
FileUtils.mkpath(wd)
|
78
|
+
wd
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def initialize
|
83
|
+
super(self.class.webpack_task_script)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
var webpack = require('webpack');
|
2
|
+
var fs = require('fs');
|
3
|
+
var path = require('path');
|
4
|
+
|
5
|
+
var logging = true;
|
6
|
+
function log(message) {
|
7
|
+
if (logging) fs.appendFile('log/webpack-task.log', message+'\n');
|
8
|
+
}
|
9
|
+
|
10
|
+
// TODO: add support for multiple builds using multiple webpack configs which
|
11
|
+
// can each be waited upon independently
|
12
|
+
var webpackConfig = require(path.resolve('config/webpack.config.js'));
|
13
|
+
|
14
|
+
// webpack Compiler.Watching instance
|
15
|
+
var watcher = makeWatcher();
|
16
|
+
// callbacks which will be called when next build completes
|
17
|
+
var currentBuildCallbacks = [];
|
18
|
+
// object with property 'stats' for success or 'error' for failure
|
19
|
+
var lastBuildResult = null;
|
20
|
+
|
21
|
+
function buildComplete(buildResult) {
|
22
|
+
lastBuildResult = buildResult;
|
23
|
+
|
24
|
+
currentBuildCallbacks.forEach(function(callback) {
|
25
|
+
log('async completion callback');
|
26
|
+
callback(buildResult);
|
27
|
+
});
|
28
|
+
currentBuildCallbacks = [];
|
29
|
+
|
30
|
+
fs.writeFile('tmp/webpack/webpack-build-result.json', JSON.stringify(buildResult, null, 2));
|
31
|
+
}
|
32
|
+
|
33
|
+
function makeWatcher() {
|
34
|
+
return webpack(webpackConfig).watch({
|
35
|
+
aggregateTimeout: 300, // wait so long for more changes
|
36
|
+
}, function(err, stats) {
|
37
|
+
if (err) {
|
38
|
+
buildComplete({
|
39
|
+
error: err,
|
40
|
+
});
|
41
|
+
} else if (stats.hasErrors()) {
|
42
|
+
var errWithDetails = new Error('Webpack build error');
|
43
|
+
errWithDetails.stack = (
|
44
|
+
'Webpack build error:\n' +
|
45
|
+
stats.toJson({errorDetails: true}).errors.join("\n") + ''
|
46
|
+
// err ? '\nOriginal stacktrace:\n' + (err.stack || err) : ''
|
47
|
+
);
|
48
|
+
|
49
|
+
buildComplete({
|
50
|
+
error: errWithDetails,
|
51
|
+
});
|
52
|
+
} else {
|
53
|
+
var statsData = stats.toJson({
|
54
|
+
hash: true,
|
55
|
+
assets: true,
|
56
|
+
modules: true,
|
57
|
+
chunkOrigins: true,
|
58
|
+
cached: true,
|
59
|
+
});
|
60
|
+
|
61
|
+
var modules = statsData.modules.map(function(moduleStats) {
|
62
|
+
var loadersEnd = moduleStats.identifier.lastIndexOf('!')
|
63
|
+
return moduleStats.identifier.slice(loadersEnd == -1 ? 0 : loadersEnd+1)
|
64
|
+
})
|
65
|
+
|
66
|
+
buildComplete({
|
67
|
+
// stats: statsData,
|
68
|
+
modules: modules,
|
69
|
+
});
|
70
|
+
}
|
71
|
+
});
|
72
|
+
}
|
73
|
+
|
74
|
+
module.exports = function waitForBuild(opts, done) {
|
75
|
+
function sendResults(buildResult) {
|
76
|
+
if (buildResult.error) done(buildResult.error);
|
77
|
+
else done(null, buildResult);
|
78
|
+
}
|
79
|
+
|
80
|
+
log('watcher.running: '+JSON.stringify(watcher.running));
|
81
|
+
|
82
|
+
if (!watcher.running) {
|
83
|
+
sendResults(lastBuildResult);
|
84
|
+
} else {
|
85
|
+
currentBuildCallbacks.push(sendResults);
|
86
|
+
}
|
87
|
+
};
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: webpack_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Friend
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: node_task
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.0
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.1.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.1.0
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.1.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: tilt
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.1'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.1'
|
47
|
+
description: Much longer explanation of the webpack_rails!
|
48
|
+
email: james@jsdf.co
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- lib/webpack_rails.rb
|
54
|
+
- lib/webpack_rails/engine.rb
|
55
|
+
- lib/webpack_rails/processor.rb
|
56
|
+
- lib/webpack_rails/sprockets_base_webpack.rb
|
57
|
+
- lib/webpack_rails/sprockets_index_webpack.rb
|
58
|
+
- lib/webpack_rails/task.rb
|
59
|
+
- lib/webpack_rails/webpack-task.js
|
60
|
+
homepage: https://rubygems.org/gems/webpack_rails
|
61
|
+
licenses:
|
62
|
+
- MIT
|
63
|
+
metadata: {}
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 2.2.2
|
81
|
+
signing_key:
|
82
|
+
specification_version: 4
|
83
|
+
summary: This is an webpack_rails!
|
84
|
+
test_files: []
|