webpack_rails 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,8 @@
1
+ require 'sprockets'
2
+
3
+ module WebpackRails
4
+ require_relative './webpack_rails/sprockets_index_webpack'
5
+ require_relative './webpack_rails/task'
6
+ require_relative './webpack_rails/processor'
7
+ require_relative './webpack_rails/engine'
8
+ end
@@ -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: []