hauler 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: 517e3c307e0c965ff5d4d8db2ed055cb4e1c39a4
4
+ data.tar.gz: 864053fb64d3c840c4eea0b276dab19282eed481
5
+ SHA512:
6
+ metadata.gz: 7a3c900c022d9b185d912b9b69e087a2b81bd29352c36af60b6e94c3b9eb1a8fd8c69d05f214ca8d94421c6acd7221e9dada5f4b21b388d5837da9a53645d93a
7
+ data.tar.gz: f75794386bfcc518f0323d74c513f9527ded971b2d409c71a464eabbc41cfc68cc51a4700f726b1a46491dfc3764b3a41600a1a7b182a8c8af8c1f3c6bdbe531
data/.babelrc ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "plugins": ["transform-flow-strip-types"]
3
+ }
data/.eslintrc ADDED
@@ -0,0 +1,13 @@
1
+ ---
2
+ extends:
3
+ - airbnb
4
+
5
+ parser: babel-eslint
6
+
7
+ plugins:
8
+ - flow-vars
9
+
10
+ rules:
11
+ flow-vars/define-flow-type: 1
12
+ flow-vars/use-flow-type: 1
13
+ max-len: [2, 140, 2]
data/.flowconfig ADDED
@@ -0,0 +1,13 @@
1
+ [ignore]
2
+ dist/
3
+
4
+ [include]
5
+
6
+ [libs]
7
+ src/decls/
8
+
9
+ [options]
10
+ module.ignore_non_literal_requires=true
11
+
12
+ [version]
13
+ 0.30.0
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /dist/
6
+ /doc/
7
+ /node_modules/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+
12
+ /Gemfile.lock
13
+ /*.gem
data/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ Metrics/LineLength:
2
+ Max: 100
3
+
4
+ Style/NegatedIf:
5
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.12.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in hauler.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Arturo Guzman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/Makefile ADDED
@@ -0,0 +1,5 @@
1
+
2
+ build:
3
+ gem build hauler.gemspec
4
+
5
+ .PHONY: all;
data/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # Hauler
2
+
3
+ Replaces the default Rails asset management (Sprockets) with the superior Webpack.
4
+
5
+ Improve your DX (Developer Experience) by developing your application UI using
6
+ JavaScript Components.
7
+
8
+ 1. [Setup](#setup)
9
+ 1. [New Rails Application](#new-rails-application)
10
+ 1. [Existing Rails Application](#existing-rails-applications)
11
+ 1. [Installation](#installation)
12
+ 1. [Update](#update)
13
+ 1. [Usage](#usage)
14
+
15
+ ## Preparation
16
+
17
+ ### New Rails Application
18
+
19
+ Create your new application skipping all javascript assets and sprockets (where "*my_app*" refers to your app name).
20
+
21
+ ```bash
22
+ rails new my_app --skip-javascript --skip-turbolinks --skip-sprockets
23
+ ```
24
+
25
+ ### Existing Rails Applications
26
+
27
+ Remove sprockets from your application loaded modules inside the `config/application.rb` file.
28
+
29
+ If you used the default Rails generator, then replace the line `require 'rails/all'` with:
30
+
31
+ ```ruby
32
+ require 'rails'
33
+ # Pick the frameworks you want:
34
+ require 'active_model/railtie'
35
+ require 'active_job/railtie'
36
+ require 'active_record/railtie'
37
+ require 'action_controller/railtie'
38
+ require 'action_mailer/railtie'
39
+ require 'action_view/railtie'
40
+ # require 'sprockets/railtie'
41
+ require 'rails/test_unit/railtie'
42
+ ```
43
+
44
+ If you used a custom Rails app generation, just remove the line:
45
+
46
+ ```bash
47
+ require 'sprockets/railtie'
48
+ ```
49
+
50
+ ## Installation
51
+
52
+ Add this line to your application's Gemfile:
53
+
54
+ ```ruby
55
+ gem 'hauler'
56
+ ```
57
+
58
+ And then execute:
59
+
60
+ ```bash
61
+ bundle
62
+ bin/rails generate hauler:install
63
+ ```
64
+
65
+ Set your application `config.action_controller.asset_host` using an environment variable.
66
+
67
+ ```bash
68
+ export ASSET_HOST="//localhost:8080"
69
+ ```
70
+
71
+ ```ruby
72
+ # config/application.rb
73
+ config.action_controller.asset_host = ENV.fetch('ASSET_HOST')
74
+ ```
75
+
76
+ ## Update
77
+
78
+ ```bash
79
+ bin/rails generate hauler:install
80
+ ```
81
+
82
+ ## Usage
83
+
84
+ Run your rails server normally:
85
+
86
+ ```bash
87
+ bin/rails server
88
+ ```
89
+
90
+ In a different terminal window run Webpack dev server:
91
+
92
+ ```bash
93
+ npm start
94
+ ```
95
+
96
+
97
+ ## Development
98
+
99
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
100
+
101
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
102
+
103
+ ## Contributing
104
+
105
+ Bug reports and pull requests are welcome on GitHub at https://github.com/guzart/hauler.
106
+
107
+
108
+ ## License
109
+
110
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
111
+
112
+ # TODO
113
+
114
+ * add "start" script that runs the hauler.js binary
115
+ * install React dynamically, install if present or ask otherwise
116
+ * install Sass dynamically, install if present or ask otherwise
117
+ * add sensible defaults to the config template
118
+ * should be able to append loaders or override them
119
+ * one place for editing the asset host
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'hauler'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/dev-server.js ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+
3
+ const webpack = require('webpack');
4
+ const WebpackDevServer = require('webpack-dev-server');
5
+
6
+ const env = String(process.env.RAILS_ENV || process.env.NODE_ENV);
7
+ const Hauler = require('hauler');
8
+ const devServerConfig = Hauler.getDevServerConfig(env);
9
+ const compilerConfig = Hauler.getCompilerConfig(env);
10
+
11
+ // console.log(devServerConfig);
12
+ // console.log(compilerConfig);
13
+
14
+ const compiler = webpack(compilerConfig);
15
+ const devServer = new WebpackDevServer(compiler, devServerConfig);
16
+ devServer.listen(devServerConfig.port, devServerConfig.host, (err) => {
17
+ if (err) {
18
+ throw err;
19
+ }
20
+ });
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const pkgFilepath = path.join(process.cwd(), 'package.json');
7
+ const pkg = require(pkgFilepath);
8
+ if (!pkg.scripts) {
9
+ Object.assign(pkg, { scripts: {} });
10
+ }
11
+
12
+ Object.assign(pkg.scripts, {
13
+ start: './node_modules/hauler/bin/dev-server.js',
14
+ });
15
+
16
+ const output = JSON.stringify(pkg, null, 2);
17
+ fs.writeFileSync(pkgFilepath, `${output}\n`);
data/hauler.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hauler/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'hauler'
8
+ spec.version = Hauler::VERSION
9
+ spec.authors = ['Arturo Guzman']
10
+ spec.email = ['arturo@guzart.com']
11
+
12
+ spec.summary = 'Railtie to use webpack as an asset manager'
13
+ spec.description = <<-TXT
14
+ Railtie to generate the files needed to use webpack as a replacement of sprockets
15
+ TXT
16
+ spec.homepage = 'https://github.com/guzart/hauler'
17
+ spec.license = 'MIT'
18
+
19
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
20
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
21
+ if spec.respond_to?(:metadata)
22
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
23
+ else
24
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
25
+ end
26
+
27
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
28
+ f.match(%r{^(test|spec|features)/})
29
+ end
30
+ spec.bindir = 'exe'
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ['lib']
33
+
34
+ spec.add_development_dependency 'bundler', '~> 1.12'
35
+ spec.add_development_dependency 'rake', '~> 10.0'
36
+ spec.add_development_dependency 'minitest', '~> 5.0'
37
+ end
@@ -0,0 +1,34 @@
1
+ module Hauler
2
+ module Generators
3
+ #:nodoc:
4
+ class InstallGenerator < ::Rails::Generators::Base
5
+ desc 'Copy Hauler configuration files'
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ def copy_config_hauler
9
+ template 'config/hauler.js'
10
+ end
11
+
12
+ def copy_eslintrc
13
+ template 'eslintrc.json', '.eslintrc.json'
14
+ end
15
+
16
+ def copy_sass_lint_yml
17
+ template 'sass-lint.yml', '.sass-lint.yml'
18
+ end
19
+
20
+ def copy_package_json
21
+ has_package_json = File.exist?(Rails.root.join('package.json'))
22
+ template 'package.json' if !has_package_json
23
+ end
24
+
25
+ def copy_webpack_config
26
+ template 'webpack.config.js'
27
+ end
28
+
29
+ def install_npm
30
+ generate 'hauler:install_npm'
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,110 @@
1
+ module Hauler
2
+ module Generators
3
+ #:nodoc:
4
+ class InstallNpmGenerator < ::Rails::Generators::Base
5
+ desc 'Setup hauler project'
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ NPM_DEV_DEPENDENCIES = <<-TXT.freeze
9
+ babel-core@6.11.4
10
+ babel-loader@6.2.4
11
+ babel-plugin-transform-class-properties@6.11.5
12
+ babel-preset-es2015@6.9.0
13
+ babel-preset-stage-2@6.11.0
14
+ css-loader@0.23.1
15
+ extract-text-webpack-plugin@1.0.1
16
+ file-loader@0.9.0
17
+ image-webpack-loader@2.0.0
18
+ immutable-devtools@0.0.7
19
+ style-loader@0.13.1
20
+ url-loader@0.5.7
21
+ webpack@1.13.1
22
+ webpack-dev-server@1.14.1
23
+ TXT
24
+
25
+ LINTER_DEV_DEPENDENCES = <<-TXT.freeze
26
+ babel-eslint@6.1.2
27
+ eslint@2.13.1
28
+ eslint-config-airbnb@9.0.1
29
+ eslint-import-resolver-webpack@0.4.0
30
+ eslint-plugin-flow-vars@0.5.0
31
+ eslint-plugin-import@1.12.0
32
+ eslint-plugin-jsx-a11y@1.5.5
33
+ eslint-plugin-react@5.2.2
34
+ sass-lint@1.8.2
35
+ TXT
36
+
37
+ REACT_NPM_DEV_DEPENDENCIES = <<-TXT.freeze
38
+ babel-plugin-transform-react-constant-elements@6.9.1
39
+ babel-plugin-transform-react-inline-elements@6.8.0
40
+ babel-plugin-transform-react-remove-prop-types@0.2.8
41
+ babel-preset-react@6.11.1
42
+ react-hot-loader@2.0.0-alpha-4
43
+ redux-logger@2.6.1
44
+ TXT
45
+
46
+ REACT_NPM_DEPENDENCIES = <<-TXT.freeze
47
+ immutable@3.8.1
48
+ react@15.2.1
49
+ react-dom@15.2.1
50
+ react-redux@4.4.5
51
+ react-router@2.6.1
52
+ react-router-redux@4.0.5
53
+ react-router-scroll@0.2.1
54
+ redux@3.5.2
55
+ redux-immutable@3.0.6
56
+ redux-saga@0.11.0
57
+ reselect@2.5.3
58
+ TXT
59
+
60
+ SASS_NPM_DEV_DEPENDENCIES = <<-TXT.freeze
61
+ node-sass@3.8.0
62
+ sass-loader@4.0.0
63
+ TXT
64
+
65
+ NPM_DEPENDENCIES = <<-TXT.freeze
66
+ babel-polyfill@6.9.1
67
+ whatwg-fetch@1.0.0
68
+ TXT
69
+
70
+ def add_scripts_to_package
71
+ `./node_modules/hauler/bin/update-scripts.js`
72
+ end
73
+
74
+ def install_dev_dependencies
75
+ puts 'Installing NPM dev dependencies...'
76
+ install_deps(NPM_DEV_DEPENDENCIES)
77
+ end
78
+
79
+ def install_linter_dev_dependencies
80
+ puts 'Installing Linter NPM dev dependencies...'
81
+ install_deps(LINTER_DEV_DEPENDENCES)
82
+ end
83
+
84
+ def install_react_dependencies
85
+ puts 'Installing React NPM dev dependencies...'
86
+ install_deps(REACT_NPM_DEV_DEPENDENCIES)
87
+
88
+ puts 'Installing React NPM dependencies...'
89
+ install_deps(REACT_NPM_DEPENDENCIES, dev: false)
90
+ end
91
+
92
+ def install_sass_dependencies
93
+ puts 'Installing Sass NPM dependencies...'
94
+ install_deps(SASS_NPM_DEV_DEPENDENCIES)
95
+ end
96
+
97
+ def install_dependencies
98
+ puts 'Installing NPM dependencies...'
99
+ install_deps(NPM_DEPENDENCIES, dev: false)
100
+ end
101
+
102
+ private
103
+
104
+ def install_deps(list, dev: true)
105
+ flag = dev ? '--save-dev' : '--save'
106
+ `npm install #{flag} #{list.gsub(/\s+/m, ' ')}`
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,6 @@
1
+
2
+ module.exports = {
3
+ entries: [
4
+ '~app/assets/my_app/index.js',
5
+ ],
6
+ };
@@ -0,0 +1,27 @@
1
+ {
2
+ "extends": [
3
+ "airbnb",
4
+ "plugin:import/errors",
5
+ "plugin:import/warnings"
6
+ ],
7
+ "parser": "babel-eslint",
8
+ "plugins": [
9
+ "flow-vars"
10
+ ],
11
+ "rules": {
12
+ "flow-vars/define-flow-type": 1,
13
+ "flow-vars/use-flow-type": 1,
14
+ "max-len": [2, 140, 2]
15
+ },
16
+ "settings": {
17
+ "import/ignore": [
18
+ "node_modules",
19
+ "\\.(jpg|png|scss)"
20
+ ],
21
+ "import/resolver": {
22
+ "webpack": {
23
+ "config": "webpack.config.js"
24
+ }
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "private": true,
3
+ "scripts": {
4
+ },
5
+ "dependencies": {
6
+ },
7
+ "devDependencies": {
8
+ }
9
+ }
@@ -0,0 +1,6 @@
1
+ # https://github.com/sasstools/sass-lint/blob/master/lib/config/sass-lint.yml
2
+ options:
3
+ formatter: stylish
4
+
5
+ files:
6
+ include: '**/*.s+(a|c)ss'
@@ -0,0 +1,5 @@
1
+
2
+ const Hauler = require('hauler');
3
+ const env = String(process.env.RAILS_ENV || process.env.NODE_ENV);
4
+
5
+ module.exports = Hauler.getCompilerConfig(env);
@@ -0,0 +1,27 @@
1
+ require 'active_support/concern'
2
+ require 'action_view/helpers'
3
+
4
+ module Hauler
5
+ #:nodoc:
6
+ module AssetTagHelper
7
+ extend ::ActiveSupport::Concern
8
+
9
+ include ::ActionView::Helpers
10
+
11
+ included do
12
+ def hauler_javascript_include_tag(*sources)
13
+ if Rails.application.config.hauler.dev_server
14
+ # TODO: Get this from the configuration
15
+ return javascript_include_tag('http://localhost:3001/assets/' + sources.first + '.js')
16
+ end
17
+
18
+ javascript_include_tag(*sources)
19
+ end
20
+
21
+ def hauler_stylesheet_link_tag(*sources)
22
+ return nil if Rails.application.config.hauler.dev_server
23
+ stylesheet_link_tag(*sources)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ require 'rails'
2
+ require 'rails/railtie'
3
+ require 'active_support/ordered_options'
4
+ require 'hauler/asset_tag_helper'
5
+ # require 'yaml'
6
+ # require 'erb'
7
+
8
+ module Hauler
9
+ #:nodoc:
10
+ class Railtie < ::Rails::Railtie
11
+ config.hauler = ActiveSupport::OrderedOptions.new
12
+ config.hauler.dev_server = true
13
+
14
+ initializer 'hauler.configure_rails_initialization' do
15
+ # yaml = Pathname.new(Rails.root.join('config', 'assets.yml'))
16
+ # assets_config = YAML.load(ERB.new(yaml.read).result) || {}
17
+ # assets_config = assets_config[Rails.env]
18
+
19
+ # if config.action_controller.asset_host.blank?
20
+ # config.action_controller.asset_host = assets_config['asset_host']
21
+ # end
22
+
23
+ ::ActiveSupport.on_load :action_view do
24
+ include ::Hauler::AssetTagHelper
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module Hauler
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/hauler.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'hauler/version'
2
+ require 'hauler/railtie' if defined?(Rails)
data/make-package.js ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node --use_strict
2
+
3
+ const fs = require('fs');
4
+
5
+ const pkg = require('./package.json');
6
+ delete pkg.scripts;
7
+ Object.assign(pkg, {
8
+ main: 'index.js',
9
+ });
10
+
11
+ fs.writeFileSync('dist/package.json', JSON.stringify(pkg, null, 2));
12
+ fs.writeFileSync('dist/LICENSE.txt', fs.readFileSync('./LICENSE.txt').toString());
13
+ fs.writeFileSync('dist/README.md', fs.readFileSync('./README.md').toString());
data/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "hauler",
3
+ "version": "0.1.0",
4
+ "description": "NodeJS binary for the hauler gem",
5
+ "author": "Arturo Guzman @guzart",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/guzart/hauler.git"
10
+ },
11
+ "main": "dist/index.js",
12
+ "bin": {
13
+ "hauler-server": "bin/dev-server.js",
14
+ "hauler-update-scripts": "bin/update-scripts"
15
+ },
16
+ "directories": {
17
+ "test": "test"
18
+ },
19
+ "scripts": {
20
+ "build": "npm-run-all clean compile generate_package",
21
+ "clean": "rm -rf ./dist",
22
+ "compile": "./node_modules/babel-cli/bin/babel.js --out-dir=./dist --ignore=./decls ./src",
23
+ "dev": "npm-run-all clean watch",
24
+ "generate_package": "node make-package.js",
25
+ "test": "echo \"Error: no test specified\" && exit 1",
26
+ "watch": "./node_modules/babel-cli/bin/babel.js --watch=./src --ignore=./decls --out-dir=./dist"
27
+ },
28
+ "devDependencies": {
29
+ "babel-cli": "^6.11.4",
30
+ "babel-eslint": "^6.1.2",
31
+ "babel-plugin-transform-flow-strip-types": "^6.8.0",
32
+ "eslint": "^3.2.0",
33
+ "eslint-plugin-flow-vars": "^0.5.0",
34
+ "eslint-plugin-flowtype": "^2.4.0",
35
+ "flow-bin": "^0.30.0"
36
+ }
37
+ }
@@ -0,0 +1,17 @@
1
+
2
+ export type ProjectConfig = {
3
+ entries?: {[name: string]: string | Array<string>},
4
+ javascriptLoader?: WebpackLoader,
5
+ sassLoader?: WebpackLoader,
6
+ fontLoader?: WebpackLoader,
7
+ imageLoader?: WebpackLoader,
8
+ prependPlugins?: Array<WebpackPlugin>,
9
+ plugins?: Array<WebpackPlugin>,
10
+ appendPlugins?: Array<WebpackPlugin>,
11
+ devServer?: WebpackDevServerConfig,
12
+ compiler?: WebpackConfig,
13
+ };
14
+
15
+ export type DevServerConfigFactory = (env: string) => WebpackDevServerConfig;
16
+
17
+ export type ProjectConfigFactory = (env: string) => ProjectConfig;
@@ -0,0 +1,119 @@
1
+ // @flow
2
+
3
+ export type WebpackDevServerStatsConfig = {
4
+ colors?: boolean,
5
+ hash?: boolean,
6
+ version?: boolean,
7
+ timings?: boolean,
8
+ chunks?: boolean,
9
+ chunkModules?: boolean,
10
+ modules?: boolean,
11
+ children?: boolean,
12
+ cached?: boolean,
13
+ reasons?: boolean,
14
+ source?: boolean,
15
+ errorDetails?: boolean,
16
+ chunkOrigins?: boolean,
17
+ };
18
+
19
+ export type WebpackDevServerConfig = {
20
+ contentBase?: string,
21
+ quiet?: boolean,
22
+ noInfo?: boolean,
23
+ host?: string,
24
+ port?: number,
25
+ hot?: boolean,
26
+ inline?: boolean,
27
+ publicPath?: string,
28
+ headers?: Object,
29
+ stats?: WebpackDevServerStatsConfig,
30
+ };
31
+
32
+ export type WebpackEntry = string | Array<string> | { [key: string]: WebpackEntry };
33
+
34
+ export type WebpackResolveConfig = {
35
+ alias?: Object,
36
+ root?: string | Array<string>,
37
+ modulesDirectories?: Array<string>,
38
+ fallback?: string | Array<string>,
39
+ extensions?: Array<string>,
40
+ packageMains?: Array<string>,
41
+ packageAlias?: string | Array<string> | Object,
42
+ unsafeCache?: true | RegExp | Array<RegExp>,
43
+ };
44
+
45
+ export type WebpackResolveLoaderConfig = WebpackResolveConfig & {
46
+ moduleTemplates?: Array<string>,
47
+ };
48
+
49
+ export type WebpackLoader = {
50
+ test?: Object,
51
+ exclude?: Object,
52
+ include?: Object,
53
+ loader?: string,
54
+ loaders?: Array<string>,
55
+ query?: Object,
56
+ };
57
+
58
+ export type WebpackModuleConfig = {
59
+ loaders?: Array<WebpackLoader>;
60
+ preLoaders?: Array<WebpackLoader>;
61
+ postLoaders?: Array<WebpackLoader>;
62
+ noParse?: Object | Array<Object>;
63
+ }
64
+
65
+ export type WebpackPlugin = Object;
66
+
67
+ export type WebpackOutputConfig = {
68
+ filename?: string,
69
+ path?: string,
70
+ publicPath?: string,
71
+ chunkFilename?: string,
72
+ sourceMapFilename?: string,
73
+ devtoolModuleFilenameTemplate?: string,
74
+ devtoolFallbackModuleFilenameTemplate?: string,
75
+ devtoolLineToLine?: {
76
+ test?: Object,
77
+ include?: Object,
78
+ exclude?: Object,
79
+ },
80
+ hotUpdateChunkFilename?: string,
81
+ hotUpdateMainFilename?: string,
82
+ jsonpFunction?: string,
83
+ hotUpdatefunction?: string,
84
+ pathinfo?: boolean,
85
+ library?: string,
86
+ libraryTarget?: 'var' | 'this' | 'commonjs' | 'commonjs2' | 'amd' | 'umd',
87
+ umdNamedDefine?: boolean,
88
+ sourcePrefix?: string,
89
+ crossOriginLoading?: false | 'anonymous' | 'use-credentials',
90
+ };
91
+
92
+ export type WebpackConfig = {
93
+ context?: string,
94
+ entry?: WebpackEntry,
95
+ output?: WebpackOutputConfig,
96
+ module?: WebpackModuleConfig,
97
+ resolve?: WebpackResolveConfig,
98
+ resolveLoader?: WebpackResolveLoaderConfig,
99
+ externals?: Array<any>,
100
+ target?: 'web' | 'webworker' | 'node' | 'async-node' | 'node-webkit' | 'electron',
101
+ bail?: boolean,
102
+ profile?: boolean,
103
+ cache?: boolean,
104
+ watch?: boolean,
105
+ watchOptions?: {
106
+ aggregateTimeout?: number,
107
+ poll?: boolean,
108
+ },
109
+ debug?: boolean,
110
+ devtool?: string,
111
+ devServer?: WebpackDevServerConfig,
112
+ node?: Object,
113
+ amd?: Object,
114
+ loader?: any,
115
+ recordsPath?: string,
116
+ recordsInputPath?: string,
117
+ recordsOutputPath?: string,
118
+ plugins?: Array<WebpackPlugin>,
119
+ };
@@ -0,0 +1,117 @@
1
+ // @flow
2
+
3
+ const ExtractTextPlugin = require('extract-text-webpack-plugin');
4
+ const webpack = require('webpack');
5
+
6
+ function getPlugins(env: string) {
7
+ let plugins = [
8
+ new webpack.ProvidePlugin({ fetch: 'exports?self.fetch!whatwg-fetch' }),
9
+ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify(env) } }),
10
+ new webpack.optimize.CommonsChunkPlugin({
11
+ name: 'vendor',
12
+ children: true,
13
+ minChunks: 2,
14
+ async: true,
15
+ }),
16
+ ];
17
+
18
+ if (env === 'development') {
19
+ plugins = plugins.concat([
20
+ new webpack.NoErrorsPlugin(),
21
+ ]);
22
+ }
23
+
24
+ if (env === 'production') {
25
+ plugins = plugins.concat([
26
+ new webpack.optimize.OccurrenceOrderPlugin(true),
27
+ new webpack.optimize.DedupePlugin(),
28
+ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }),
29
+ new ExtractTextPlugin('[name].[contenthash].css'),
30
+ ]);
31
+ }
32
+
33
+ return plugins;
34
+ }
35
+
36
+ function configFactory(env: string) {
37
+ // individual loaders so that they can be replaced separately
38
+ const javascriptLoader = {
39
+ test: /\.jsx?$/,
40
+ loader: 'babel',
41
+ exclude: /node_modules/,
42
+ query: {
43
+ presets: ['es2015', 'react', 'stage-2'],
44
+ plugins: ['transform-class-properties'],
45
+ },
46
+ };
47
+
48
+ const sassLoader = {
49
+ test: /\.scss$/,
50
+ loader: 'style!css!sass',
51
+ };
52
+
53
+ const fontLoader = {
54
+ test: /\.(eot|svg|ttf|woff|woff2)$/,
55
+ loader: 'file',
56
+ };
57
+
58
+ const imageLoader = {
59
+ test: /\.(jpg|png|gif)$/,
60
+ loaders: [
61
+ 'file',
62
+ 'image-webpack?{progressive:true, optimizationLevel: 7, interlaced: false, pngquant:{quality: "65-90", speed: 4}}',
63
+ ],
64
+ };
65
+
66
+ if (env === 'production') {
67
+ javascriptLoader.query.plugins = javascriptLoader.query.plugins.concat([
68
+ 'transform-react-remove-prop-types',
69
+ 'transform-react-constant-elements',
70
+ 'transform-react-inline-elements',
71
+ ]);
72
+
73
+ sassLoader.loader = ExtractTextPlugin.extract(
74
+ 'style',
75
+ sassLoader.loader.replace('style!', '')
76
+ );
77
+ }
78
+
79
+ const appendPlugins = [];
80
+ const plugins = getPlugins(env);
81
+ const prependPlugins = [];
82
+
83
+ // straight webpack configuration
84
+ const compiler = {
85
+ output: {
86
+ filename: '[name].[chunkhash].js',
87
+ path: '~public/assets',
88
+ chunkFilename: '[name].[chunkhash].chunk.js',
89
+ },
90
+ resolve: {
91
+ root: [
92
+ '~app/assets',
93
+ '~lib/assets',
94
+ ],
95
+ },
96
+ devtool: '',
97
+ target: 'web',
98
+ };
99
+
100
+ if (env === 'development') {
101
+ compiler.output.filename = '[name].js';
102
+ compiler.output.chunkFilename = '[name].chunk.js';
103
+ }
104
+
105
+ return {
106
+ javascriptLoader,
107
+ sassLoader,
108
+ fontLoader,
109
+ imageLoader,
110
+ prependPlugins,
111
+ plugins,
112
+ appendPlugins,
113
+ compiler,
114
+ };
115
+ }
116
+
117
+ module.exports = configFactory;
@@ -0,0 +1,20 @@
1
+ function defaultConfigFactory() {
2
+ return {
3
+ quiet: false,
4
+ noInfo: false,
5
+ host: 'localhost',
6
+ port: 3001,
7
+ hot: true,
8
+ inline: true,
9
+ publicPath: '/assets/',
10
+ headers: { 'AccessControl-Allow-Origin': '*' },
11
+ stats: {
12
+ colors: true,
13
+ chunks: true,
14
+ chunkModules: true,
15
+ timings: true,
16
+ },
17
+ };
18
+ }
19
+
20
+ module.exports = defaultConfigFactory;
data/src/index.js ADDED
@@ -0,0 +1,122 @@
1
+ // @flow
2
+ // NOTE: This code is executed in a Gem, which makes any npm package unavailable
3
+
4
+ const compilerDefaultsFactory = require('./defaults/compiler_config_factory');
5
+ const devServerDefaultsFactory = require('./defaults/dev_server_config_factory');
6
+ const utils = require('./utils');
7
+
8
+ function extractLoaders(config: ProjectConfig): Array<WebpackLoader> {
9
+ return utils.compact([
10
+ config.javascriptLoader,
11
+ config.sassLoader,
12
+ config.fontLoader,
13
+ config.imageLoader,
14
+ ]);
15
+ }
16
+
17
+ function extractResolve(config: ProjectConfig): WebpackResolveConfig {
18
+ const resolve = config.compiler && config.compiler.resolve;
19
+ const modules = resolve && resolve.modules || ['node_modules'];
20
+ return utils.deepMerge(resolve, { modules: utils.railsPath(modules) });
21
+ }
22
+
23
+ function extractPlugins(config: ProjectConfig): Array<WebpackPlugin> {
24
+ const prepend = config.prependPlugins || [];
25
+ const plugins = config.plugins || [];
26
+ const appendPlugins = config.appendPlugins || [];
27
+ return prepend.concat(plugins).concat(appendPlugins);
28
+ }
29
+
30
+ function extractModule(config: ProjectConfig): WebpackModuleConfig {
31
+ const module = config.compiler && config.compiler.module;
32
+ return utils.deepMerge(module, {
33
+ loaders: extractLoaders(config),
34
+ });
35
+ }
36
+
37
+ function extractOutput(config: ProjectConfig): WebpackOutputConfig {
38
+ const output = config.compiler && config.compiler.output || {};
39
+ const path = output.path || '';
40
+ return utils.deepMerge(output, {
41
+ path: utils.railsPath(path),
42
+ });
43
+ }
44
+
45
+ function parseToCompilerConfig(config: ProjectConfig): WebpackConfig {
46
+ return {
47
+ entry: utils.railsPath(config.entries),
48
+ output: extractOutput(config),
49
+ module: extractModule(config),
50
+ plugins: extractPlugins(config),
51
+ resolve: extractResolve(config),
52
+ };
53
+ }
54
+
55
+ function extractPublicPath(config: WebpackDevServerConfig): string {
56
+ const publicPath = config.publicPath;
57
+ if (publicPath == null) {
58
+ return '';
59
+ }
60
+
61
+ if (publicPath.indexOf('http') !== -1) {
62
+ return publicPath;
63
+ }
64
+
65
+ const host = config.host || 'localhost';
66
+ const port = config.port || 30001;
67
+ return `http://${host}:${port}/${publicPath.replace(/^\//, '')}`;
68
+ }
69
+
70
+ function prepareDevServerConfig(config: WebpackDevServerConfig): WebpackDevServerConfig {
71
+ const output = Object.assign({}, config, {
72
+ publicPath: extractPublicPath(config),
73
+ });
74
+
75
+ return output;
76
+ }
77
+
78
+ const projectConfig: ProjectConfig = require(utils.railsPath('~config/hauler.js'));
79
+
80
+ /**
81
+ * Returns a factory for getting the project webpack dev server configuration using the
82
+ * value of the `devServer` property in the result of `{Rails.root}/config/hauler.js`
83
+ */
84
+ function webpackDevServerConfigFactory(defaultsFactory: DevServerConfigFactory) {
85
+ return (env: string): WebpackDevServerConfig => {
86
+ const defaultDevServerConfig = defaultsFactory(env);
87
+ const projectDevServerConfig = projectConfig.devServer;
88
+ const devServerConfig = utils.deepMerge(defaultDevServerConfig, projectDevServerConfig);
89
+ return prepareDevServerConfig(devServerConfig);
90
+ };
91
+ }
92
+
93
+ function webpackCompilerConfigFactory(defaultsFactory: ProjectConfigFactory) {
94
+ return (env: string) => {
95
+ const defaultProjectConfig = defaultsFactory(env);
96
+ const haulerProjectConfig = utils.deepMerge(defaultProjectConfig, projectConfig);
97
+ const webpackConfig = parseToCompilerConfig(haulerProjectConfig);
98
+ return utils.deepMerge(webpackConfig, projectConfig.compiler || {});
99
+ };
100
+ }
101
+
102
+ const Hauler = {
103
+ getCompilerConfigFactory() {
104
+ return webpackCompilerConfigFactory(compilerDefaultsFactory);
105
+ },
106
+
107
+ getCompilerConfig(env: string) {
108
+ const configFactory = Hauler.getCompilerConfigFactory();
109
+ return configFactory(env);
110
+ },
111
+
112
+ getDevServerConfig(env: string) {
113
+ const configFactory = Hauler.getDevServerConfigFactory();
114
+ return configFactory(env);
115
+ },
116
+
117
+ getDevServerConfigFactory() {
118
+ return webpackDevServerConfigFactory(devServerDefaultsFactory);
119
+ },
120
+ };
121
+
122
+ module.exports = Hauler;
data/src/utils.js ADDED
@@ -0,0 +1,103 @@
1
+ // @flow
2
+ export type Hash = {[name: string]: any};
3
+
4
+ const railsRoot = process.cwd();
5
+
6
+ function pathJoin(...pieces: Array<?string>): string {
7
+ const firstPiece = (pieces[0] || '').replace(/\/$/, '');
8
+ const output = [firstPiece];
9
+ pieces.slice(1).forEach(piece => {
10
+ if (piece == null) {
11
+ return;
12
+ }
13
+
14
+ const cleanPiece = piece.replace(/^\/|\/$/g, '');
15
+ output.push(cleanPiece);
16
+ });
17
+
18
+ return output.join('/');
19
+ }
20
+
21
+ function railsPath(value: any): any {
22
+ if (Array.isArray(value)) {
23
+ return value.map(item => railsPath(item));
24
+ }
25
+
26
+ if (value instanceof Object) {
27
+ const output = {};
28
+ Object.keys(value).forEach((key) => {
29
+ output[key] = railsPath(value[key]);
30
+ });
31
+ return output;
32
+ }
33
+
34
+ if (!/^~/.test(value)) {
35
+ return value;
36
+ }
37
+
38
+ return pathJoin(railsRoot, value.replace(/^~/, ''));
39
+ }
40
+
41
+ function compact<A>(list: Array<?A>): Array<A> {
42
+ const output = [];
43
+ list.forEach(item => {
44
+ if (item != null) {
45
+ output.push(item);
46
+ }
47
+ });
48
+
49
+ return output;
50
+ }
51
+
52
+ function merge<A: Hash, B: Hash>(a?: A, b?: B): A & B {
53
+ return Object.assign({}, a, b);
54
+ }
55
+
56
+ function deepMerge<A: Hash, B: Hash>(a?: A, b?: B): A & B {
57
+ const output = Object.assign({}, a, b);
58
+ if (a == null || b == null) {
59
+ return output;
60
+ }
61
+
62
+ if (Array.isArray(a) && Array.isArray(b)) {
63
+ return b;
64
+ }
65
+
66
+ const validB = b;
67
+ const keysB = Object.keys(validB);
68
+ keysB.forEach(keyB => {
69
+ const valueA = output[keyB];
70
+ const valueB = validB[keyB];
71
+ if (valueB === undefined) {
72
+ return;
73
+ }
74
+
75
+ if (valueA instanceof Object && valueB instanceof Object) {
76
+ Object.assign(output, { [keyB]: deepMerge(valueA, valueB) });
77
+ return;
78
+ }
79
+
80
+ Object.assign(output, { [keyB]: valueB });
81
+ });
82
+
83
+ return output;
84
+ }
85
+
86
+ function omit(keys: Array<string>, hash: Hash) {
87
+ const output = {};
88
+ Object.keys(hash).forEach((key) => {
89
+ if (keys.indexOf(key) === -1) {
90
+ output[key] = hash[key];
91
+ }
92
+ });
93
+ return output;
94
+ }
95
+
96
+ module.exports = {
97
+ pathJoin,
98
+ railsPath,
99
+ compact,
100
+ merge,
101
+ deepMerge,
102
+ omit,
103
+ };
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hauler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Arturo Guzman
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-07-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: 'Railtie to generate the files needed to use webpack as a replacement
56
+ of sprockets
57
+
58
+ '
59
+ email:
60
+ - arturo@guzart.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - ".babelrc"
66
+ - ".eslintrc"
67
+ - ".flowconfig"
68
+ - ".gitignore"
69
+ - ".rubocop.yml"
70
+ - ".travis.yml"
71
+ - Gemfile
72
+ - LICENSE.txt
73
+ - Makefile
74
+ - README.md
75
+ - Rakefile
76
+ - bin/console
77
+ - bin/dev-server.js
78
+ - bin/setup
79
+ - bin/update-scripts.js
80
+ - hauler.gemspec
81
+ - lib/generators/hauler/install_generator.rb
82
+ - lib/generators/hauler/install_npm_generator.rb
83
+ - lib/generators/hauler/templates/config/hauler.js
84
+ - lib/generators/hauler/templates/eslintrc.json
85
+ - lib/generators/hauler/templates/package.json
86
+ - lib/generators/hauler/templates/sass-lint.yml
87
+ - lib/generators/hauler/templates/webpack.config.js
88
+ - lib/hauler.rb
89
+ - lib/hauler/asset_tag_helper.rb
90
+ - lib/hauler/railtie.rb
91
+ - lib/hauler/version.rb
92
+ - make-package.js
93
+ - package.json
94
+ - src/decls/hauler.js
95
+ - src/decls/webpack.js
96
+ - src/defaults/compiler_config_factory.js
97
+ - src/defaults/dev_server_config_factory.js
98
+ - src/index.js
99
+ - src/utils.js
100
+ homepage: https://github.com/guzart/hauler
101
+ licenses:
102
+ - MIT
103
+ metadata:
104
+ allowed_push_host: https://rubygems.org
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.5.1
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Railtie to use webpack as an asset manager
125
+ test_files: []