hauler 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []