webpacked 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: 2ce3d51fcf3507e85c3cbf4d1fcc7c69c87cb4e7
4
+ data.tar.gz: bf49978a1f8e89013bb85c874ad1bfc33a098898
5
+ SHA512:
6
+ metadata.gz: 2c4a063a8c24b5dbe279bc6cc147eb527120a650dc1182bdc1625b0fcae431348f1988630ee93708d688bd9a054707ba0dd9df1e7db0f4ec0d42fb1d0249d579
7
+ data.tar.gz: 045b0f5f1f83a426f9546f926ee6902b366b9cef4f8d06968e4b87effebb91c86859620e12dc0514ed6468af912d33fcc490435d96140f6f04e4267292c88e38
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Darkside73
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,157 @@
1
+ [![Build Status](https://travis-ci.org/Darkside73/webpacked.svg?branch=master)](https://travis-ci.org/Darkside73/webpacked) [![Gem Version](https://badge.fury.io/rb/webpacked.svg)](http://badge.fury.io/rb/webpacked)
2
+
3
+ # webpacked
4
+
5
+ **webpacked** helps you to integrate Webpack in to a Ruby on Rails application.
6
+
7
+ It can be used alongside sprockets but normaly you no need sprockets at all now: webpack replaces sprockets completely.
8
+ Using **webpacked** and webpack itself means that Javascript is a first-class citizen: you should use `npm` to manage packages (no more gemified Javascript libraries!).
9
+
10
+ In development mode assets are served via [webpack-dev-server](http://webpack.github.io/docs/webpack-dev-server.html) that brings a cool hot module reloading feature to your workflow. Webpack's manifest file is generated using [assets-webpack-plugin](https://github.com/kossnocorp/assets-webpack-plugin).
11
+
12
+ Also **webpacked** offers deploy automation within capistrano task (see detailed instructions bellow).
13
+
14
+ ## Requirements
15
+
16
+ 1. Node.js > 4
17
+ 1. NPM > 3
18
+
19
+ ## Installation
20
+
21
+ 1. Add `webpacked` to your Gemfile
22
+ 1. Run `bundle install` to install the gem
23
+ 1. Run `bin/rails generate webpacked:install` to get required files in your application, install NPM packages and foreman gem if you wish so
24
+ 1. Run `foreman start` (if you've decided to install it) to start `webpack-dev-server` and `rails server` at the same time
25
+
26
+ ## Usage
27
+
28
+ ### Webpack configuration
29
+
30
+ Webpack configs are divided into on three files:
31
+
32
+ 1. `frontend/base.config.js` contains common setup for all environments
33
+ 1. `frontend/development.config.js` contains setup specific for development
34
+ 1. `frontend/production.config.js` includes production optimizations
35
+
36
+ Follow comments in these files and webpack official docs to conclude what meets you requirements.
37
+
38
+ Environment is defined via `NODE_ENV` variable and initialized in`frontend/main.config.js`. Normally you don't need to manual set up `NODE_ENV` unless you want to add another environment for your frontend application.
39
+
40
+ In development mode webpack-dev-server starts using `npm run dev:server` command or simply `foreman start`. Internally it uses `frontend/dev-server.js`.
41
+
42
+ Just in case there are a bunch other preconfigured NPM commands shipped (you can find them in the `package.json`):
43
+
44
+ * `npm run build:dev` runs webpack build for development environment
45
+ * `npm run build:production` same for production environment
46
+
47
+ ### View helpers
48
+
49
+ To add webpacked assets in to your application, use following helpers:
50
+
51
+ ```erb
52
+ <% # layout.html.erb %>
53
+ <!DOCTYPE html>
54
+ <html>
55
+ <head>
56
+ <%= webpacked_css_tags 'application' %>
57
+ </head>
58
+ <body>
59
+ <%= webpacked_js_tags 'application' %>
60
+ </body>
61
+ </html>
62
+ ```
63
+
64
+ Where `'application'` is a one of the your entry points in webpack config.
65
+
66
+ NOTE: if you using [common chunks optimization](https://webpack.github.io/docs/code-splitting.html#split-app-and-vendor-code) (it is so indeed in production most likely), these helpers may produce additional CSS/Javascript include tag for that common bundle.
67
+
68
+ You should not concern about including any extra scripts to get hot module reloading works: it integrates transparently through a same webpack manifest file.
69
+
70
+ ### Controller helper
71
+
72
+ **webpacked** offers an optional approach to link entry points with Rails application. The idea is in mapping *controllers* to entry points. Consider the following code:
73
+
74
+ ```ruby
75
+ class ApplicationController < ActionController::Base
76
+ include Webpacked::ControllerHelper
77
+ webpacked_entry "application"
78
+ end
79
+
80
+ class FooController < ApplicationController
81
+ webpacked_entry "foo"
82
+ end
83
+
84
+ class BarController < ApplicationController
85
+ webpacked_entry "bar"
86
+ end
87
+ ```
88
+
89
+ ```erb
90
+ <%= webpacked_css_tags webpacked_entry_name %>
91
+ <%= webpacked_js_tags webpacked_entry_name %>
92
+ ```
93
+
94
+ In the example above the decision which entry point to use comes in controllers instead views. Therefore in layout we can use a common `webpacked_entry_name` helper method. Notice that `webpacked_entry` in `ApplicationController` will be used if concrete controller does not define its own entry.
95
+
96
+ ### Alternative ways
97
+
98
+ If you don't like none of the mentioned above, you can use more generic helpers to access webpack manifest:
99
+
100
+ * `asset_tag(entry, kind)` return include tags for entry point `entry`; `kind` could be `:js` or `:css`
101
+ * `webpacked_asset_path(entry, kind = nil)` return only assets path for given entry
102
+
103
+ Be aware that common entry point is not included by these methods. So if you use common chunks optimization do not forget to include `common` (or whatever name you pick) entry point manually.
104
+
105
+ ### Rails configuration and other assumptions
106
+
107
+ Gem exposes a few configuration options:
108
+
109
+ * `webpacked.enabled` default to `true`; you probably want to disable webpacked in test environment, so helpers will not fail if manifest does not exist
110
+ * `webpacked.manifest_path` default to `webpack-assets.json`
111
+ * `webpacked.load_manifest_on_initialize` default to `false`; if `true` then parse manifest on application bootstrap
112
+ * `webpacked.common_entry_name` default to `common` (if you've changes this, you need to change it in webpack config as well)
113
+ * `webpacked.bin` default to `node_modules/.bin/webpack`
114
+ * `webpacked.config` default to `frontend/main.config.js`
115
+ * `webpacked.dev_server` enabled only in development mode
116
+ * webpack-dev-server starts on port 3500 on localhost via HTTP (use `WEBPACK_DEV_HOST` and `WEBPACK_DEV_PORT` env variables to change it)
117
+ * assets compiled to `public/assets/webpack`; you can change it in webpack config (and `deploy.rb` if capistrano webpacked task used)
118
+
119
+ ## Capistrano deployment
120
+
121
+ ### Installation and usage
122
+
123
+ To deploy generated assets add `require "capistrano/webpacked"` to your `Capfile`. The `deploy:webpacked:build` task will run automaticaly as after `deploy:updated` hook.
124
+
125
+ Also you need to set up the `:assets_roles` in `deploy.rb` so **webpacked** to run its tasks.
126
+
127
+ What under hood? The task makes diff of files and folders (specified in `:webpacked_dependencies` option) in current release against previous release and decides whether to run production webpack build. If there is no diff then simply a manifest copied from previous release path. If some of dependencies were changed then production build starts *locally* and assets synchronized via `rsync` over SSH.
128
+
129
+ NOTE: scince webpack build runs locally, you should pay an extra attention to your working copy condition: current branch, not published commits, not commited changes, etc.
130
+
131
+ Additionally there are some extra tasks exposed (they are used by `deploy:webpacked:build` internally):
132
+
133
+ * `deploy:webpacked:build_force` unconditionally invokes production build on local machine
134
+ * `deploy:webpacked:sync` synchronize assets under `:webpacked_release_output_path` with remote server
135
+
136
+ ### Configuration
137
+
138
+ There are following options available to set up (example values are defaults in fact):
139
+
140
+ * `set :webpacked_dependencies, %w(frontend npm-shrinkwrap.json)` webpacked build will perform if one of these will be changed
141
+ * `set :webpacked_manifest_path, "webpack-assets.json"` same as `Rails.configuration.webpacked.manifest_path`
142
+ * `set :webpacked_deploy_manifest_path, "webpack-assets-deploy.json"` used for production manifest only; choose another path to not clash with local dev manifest
143
+ * `set :webpacked_local_output_path, "public/#{fetch(:assets_prefix)}/webpack"` where webpack generates its assets
144
+ * `set :webpacked_release_output_path, "public/#{fetch(:assets_prefix)}/webpack"` where webpack assets are stored on the deploy server (started from `shared_path`)
145
+
146
+ ## TODO
147
+
148
+ * deploy with remote webpack build performing
149
+
150
+ ## Contributing
151
+
152
+ Pull requests, issues and discussion are welcomed
153
+
154
+ ## Thanks
155
+
156
+ * Marketplacer team for their [webpack-rails](https://github.com/mipearson/webpack-rails) gem which guides this implementation in some way ;)
157
+ * Contributors of [capistrano-faster-assets](https://github.com/capistrano-plugins/capistrano-faster-assets) gem for conditionally assets compile idea
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+ require 'rspec/core/rake_task'
9
+ require 'rubocop/rake_task'
10
+
11
+ RuboCop::RakeTask.new
12
+ RSpec::Core::RakeTask.new(:spec)
13
+
14
+ RDoc::Task.new(:rdoc) do |rdoc|
15
+ rdoc.rdoc_dir = 'rdoc'
16
+ rdoc.title = 'Webpacked'
17
+ rdoc.options << '--line-numbers'
18
+ rdoc.rdoc_files.include('README.md')
19
+ rdoc.rdoc_files.include('lib/**/*.rb')
20
+ end
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ task default: [:spec, :rubocop]
@@ -0,0 +1,82 @@
1
+ # based on capistrano-faster-assets gem
2
+
3
+ class WebpackedBuildRequired < StandardError; end
4
+
5
+ namespace :deploy do
6
+ namespace :webpacked do
7
+ OPTIONS = lambda do |option|
8
+ {
9
+ dependencies: fetch(:webpacked_dependencies) || %w(frontend npm-shrinkwrap.json),
10
+ manifest_path: fetch(:webpacked_manifest_path) || 'webpack-assets.json',
11
+ deploy_manifest_path: fetch(:webpacked_local_manifest_path) || 'webpack-assets-deploy.json',
12
+ local_output_path: fetch(:webpacked_local_output_path) || "public/#{fetch(:assets_prefix)}/webpack",
13
+ release_output_path: fetch(:webpacked_release_output_path) || "public/#{fetch(:assets_prefix)}/webpack"
14
+ }.fetch(option)
15
+ end
16
+
17
+ desc 'Webpack build assets'
18
+ task :build do
19
+ on roles(fetch(:assets_roles)) do
20
+ with rails_env: fetch(:rails_env) do
21
+ begin
22
+ latest_release = capture(:ls, '-xr', releases_path).split[1]
23
+ raise WebpackedBuildRequired unless latest_release
24
+ latest_release_path = releases_path.join(latest_release)
25
+
26
+ OPTIONS.(:dependencies).each do |dep|
27
+ release = release_path.join(dep)
28
+ latest = latest_release_path.join(dep)
29
+ # skip if both directories/files do not exist
30
+ next if [release, latest].map { |d| test "test -e #{d}" }.uniq == [false]
31
+ # execute raises if there is a diff
32
+ begin
33
+ execute(:diff, '-Nqr', release, latest)
34
+ rescue SSHKit::Runner::ExecuteError
35
+ raise WebpackedBuildRequired
36
+ end
37
+ end
38
+
39
+ info 'Skipping webpack build, no diff found'
40
+
41
+ execute(
42
+ :cp,
43
+ latest_release_path.join(OPTIONS.(:manifest_path)),
44
+ release_path.join(OPTIONS.(:manifest_path))
45
+ )
46
+ rescue WebpackedBuildRequired
47
+ invoke 'deploy:webpacked:build_force'
48
+ end
49
+ end
50
+ end
51
+ end
52
+ after 'deploy:updated', 'deploy:webpacked:build'
53
+
54
+ task :build_force do
55
+ run_locally do
56
+ info 'Create webpack local build'
57
+ `RAILS_ENV=#{fetch(:rails_env)} npm run build:production`
58
+ invoke 'deploy:webpacked:sync'
59
+ end
60
+ end
61
+
62
+ desc 'Sync locally compiled assets with current release path'
63
+
64
+ task :sync do
65
+ on roles(fetch(:assets_roles)) do
66
+ info 'Sync assets...'
67
+ upload!(
68
+ OPTIONS.(:deploy_manifest_path),
69
+ release_path.join(OPTIONS.(:manifest_path))
70
+ )
71
+ execute(:mkdir, '-p', shared_path.join(OPTIONS.(:release_output_path)))
72
+ end
73
+ roles(fetch(:assets_roles)).each do |host|
74
+ run_locally do
75
+ local_output_path = fetch(:webpacked_local_output_path)
76
+ release_output_path = shared_path.join(OPTIONS.(:release_output_path))
77
+ `rsync -avzr --delete #{local_output_path} #{host.user}@#{host.hostname}:#{release_output_path.parent}`
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1 @@
1
+ load File.expand_path('../tasks/webpacked.rake', __FILE__)
@@ -0,0 +1,14 @@
1
+ Description:
2
+ Install basic configs for webpacked integration
3
+
4
+ Example:
5
+ bin/rails generate webpacked:install
6
+
7
+ This will create:
8
+ frontend/app
9
+ frontend/lib
10
+ frontend/base.config.js
11
+ frontend/development.config.js
12
+ frontend/main.config.js
13
+ frontend/production.config.js
14
+ frontend/dev-server.js
@@ -0,0 +1,53 @@
1
+ module Webpacked
2
+ # :nodoc:
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ def use_foreman
7
+ if yes?('Would you like to use foreman to start webpack-dev-server and rails server at same time?')
8
+ gem 'foreman'
9
+ copy_file 'Procfile'
10
+ run 'bundle install' if yes?("Run 'bundle install' for you?")
11
+ end
12
+ end
13
+
14
+ def copy_frontend_dir
15
+ directory 'frontend'
16
+ end
17
+
18
+ def prepare_package_json
19
+ get 'package.json' do |content|
20
+ content.gsub!(/\{\{(.+?)\}\}/) do
21
+ Rails.configuration.webpacked.send(Regexp.last_match(1))
22
+ end
23
+ create_file 'package.json', content
24
+ end
25
+ end
26
+
27
+ def add_to_gitignore
28
+ append_to_file '.gitignore' do
29
+ <<-EOF.strip_heredoc
30
+ # Added by webpacked
31
+ /node_modules
32
+ /public/assets/webpacked
33
+ EOF
34
+ end
35
+ end
36
+
37
+ def run_npm_install
38
+ run 'npm install' if yes?("Run 'npm install' for you?")
39
+ end
40
+
41
+ def whats_next
42
+ puts <<-EOF.strip_heredoc
43
+ Base webpacked setup completed. Now you can:
44
+ 1. Include 'Webpacked::ControllerHelper' into 'ApplicationController'
45
+ and set up entry points for your controllers via 'webpacked_entry' class method
46
+ 2. Add the webpacked helpers into your layout instead of regular Rails helpers
47
+ 3. Run 'npm run dev:server' to start webpack-dev-server or 'foreman start' to start it alongside rails server
48
+ See https://github.com/Darkside73/webpacked for more info.
49
+ Thanks for using webpacked gem ;)
50
+ EOF
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,2 @@
1
+ rails: bin/rails s -p 3000
2
+ webpack: sh -c 'npm run dev:server'
@@ -0,0 +1 @@
1
+ console.log("Hello from webpacked!")
@@ -0,0 +1,57 @@
1
+ const path = require('path')
2
+ const webpack = require('webpack')
3
+
4
+ module.exports = {
5
+ context: __dirname,
6
+ output: {
7
+ // where to generate webpack assets
8
+ path: path.join(__dirname, '..', 'public', 'assets', 'webpack'),
9
+ filename: 'bundle-[name].js'
10
+ },
11
+ entry: {
12
+ application: ['./app/base-entry'],
13
+ },
14
+ resolve: {
15
+ // Default extensions to require file without extension
16
+ extensions: ['', '.js'],
17
+ modulesDirectories: [ 'node_modules' ],
18
+ alias: {
19
+ // Handy shortcut: use absolute path `require(~lib/mylib)` from any place
20
+ lib: path.join(__dirname, 'lib'),
21
+ }
22
+ },
23
+ module: {
24
+ // Loaders with identical settings for both
25
+ // development and production environments
26
+ loaders: [
27
+
28
+ // Use ES6 syntax (highly recommended!)
29
+ // (run `npm install babel-loader babel-core babel-preset-es2015 --save-dev`)
30
+ // {
31
+ // test: /\.js$/,
32
+ // include: [ path.resolve(__dirname + 'frontend/app') ],
33
+ // loader: 'babel?presets[]=es2015'
34
+ // },
35
+
36
+ // Use Coffescript
37
+ // { test: /\.coffee$/, loader: 'coffee-loader' },
38
+
39
+ // Use Vue.js framework (run `npm install vue vue-loader --save-dev`)
40
+ // { test: /\.vue$/, loader: 'vue' },
41
+
42
+ // Makes `$` and `jQuery` available globally
43
+ // { test: require.resolve('jquery'), loader: 'expose?$!expose?jQuery' }
44
+ ],
45
+ },
46
+ plugins: [
47
+ // new webpack.ProvidePlugin({
48
+ // $: 'jquery',
49
+ // jQuery: 'jquery',
50
+ // }),
51
+
52
+ // Use `__RAILS_ENV__` variable in your Javascript code
53
+ // new webpack.DefinePlugin({
54
+ // __RAILS_ENV__: JSON.stringify(process.env.RAILS_ENV || 'production'),
55
+ // })
56
+ ]
57
+ }
@@ -0,0 +1,41 @@
1
+ const webpack = require('webpack')
2
+ const WebpackDevServer = require('webpack-dev-server')
3
+ const config = require('./main.config')
4
+ const webpackDevHost = process.env.WEBPACK_DEV_HOST || 'localhost'
5
+ const webpackDevPort = process.env.WEBPACK_DEV_PORT || 3500
6
+
7
+ config.output.publicPath = `http://${webpackDevHost}:${webpackDevPort}/assets/`;
8
+ for (var entryName in config.entry) {
9
+ config.entry[entryName].push(
10
+ `webpack-dev-server/client?http://${webpackDevHost}:${webpackDevPort}`,
11
+ 'webpack/hot/only-dev-server'
12
+ )
13
+ }
14
+
15
+ config.plugins.push(
16
+ new webpack.optimize.OccurenceOrderPlugin(),
17
+ new webpack.HotModuleReplacementPlugin(),
18
+ new webpack.NoErrorsPlugin()
19
+ )
20
+
21
+ new WebpackDevServer(webpack(config), {
22
+ publicPath: config.output.publicPath,
23
+ hot: true,
24
+ inline: true,
25
+ historyApiFallback: true,
26
+ quiet: false,
27
+ noInfo: false,
28
+ lazy: false,
29
+ stats: {
30
+ colors: true,
31
+ hash: false,
32
+ version: false,
33
+ chunks: false,
34
+ children: false,
35
+ }
36
+ }).listen(webpackDevPort, webpackDevHost, function (err, result) {
37
+ if (err) console.log(err)
38
+ console.log(
39
+ `=> 🔥 Webpack development server is running on port ${webpackDevPort}`
40
+ )
41
+ })
@@ -0,0 +1,32 @@
1
+ const AssetsPlugin = require('assets-webpack-plugin')
2
+
3
+ module.exports = {
4
+ debug: true,
5
+ displayErrorDetails: true,
6
+ outputPathinfo: true,
7
+ devtool: 'eval-source-map',
8
+ output: {
9
+ devtoolModuleFilenameTemplate: '[resourcePath]',
10
+ devtoolFallbackModuleFilenameTemplate: '[resourcePath]?[hash]'
11
+ },
12
+ module: {
13
+ loaders: [
14
+ { test: /\.css$/, loader: 'style!css?sourceMap' },
15
+ // {
16
+ // test: /\.scss$/,
17
+ // loader: 'style!css?sourceMap!resolve-url!sass?sourceMap'
18
+ // },
19
+ {
20
+ test: /\.(png|jpg|gif)$/,
21
+ loader: 'url?name=[path][name].[ext]&limit=8192'
22
+ },
23
+ {
24
+ test: /\.(ttf|eot|svg|woff(2)?)(\?.+)?$/,
25
+ loader: 'file?name=[path][name].[ext]'
26
+ },
27
+ ]
28
+ },
29
+ plugins: [
30
+ new AssetsPlugin({ prettyPrint: true }),
31
+ ]
32
+ }
@@ -0,0 +1,9 @@
1
+ const webpack = require('webpack')
2
+ const merge = require('webpack-merge')
3
+
4
+ const env = process.env.NODE_ENV || 'development'
5
+
6
+ module.exports = merge(
7
+ require('./base.config.js'),
8
+ require(`./${env}.config.js`)
9
+ )
@@ -0,0 +1,67 @@
1
+ const path = require('path')
2
+ const webpack = require('webpack')
3
+ const CleanPlugin = require('clean-webpack-plugin')
4
+ const ExtractTextPlugin = require("extract-text-webpack-plugin")
5
+ // const CompressionPlugin = require("compression-webpack-plugin")
6
+ const AssetsPlugin = require('assets-webpack-plugin')
7
+
8
+ module.exports = {
9
+ output: {
10
+ filename: './bundle-[name]-[chunkhash].js',
11
+ chunkFilename: 'bundle-[name]-[chunkhash].js',
12
+ publicPath: '/assets/webpack/'
13
+ },
14
+ module: {
15
+ loaders: [
16
+ {
17
+ test: /\.css$/,
18
+ loader: ExtractTextPlugin.extract("style-loader", "css?minimize")
19
+ },
20
+ // {
21
+ // test: /\.scss$/,
22
+ // loader: ExtractTextPlugin.extract(
23
+ // "style-loader", "css?minimize!resolve-url!sass?sourceMap"
24
+ // )
25
+ // },
26
+ { test: /\.(png|jpg|gif)$/, loader: 'url?limit=8192' },
27
+ {
28
+ test: /\.(ttf|eot|svg|woff(2)?)(\?.+)?$/,
29
+ loader: 'file'
30
+ },
31
+ ]
32
+ },
33
+ plugins: [
34
+ // Creates separate manifest for production
35
+ new AssetsPlugin({
36
+ prettyPrint: true, filename: 'webpack-assets-deploy.json'
37
+ }),
38
+
39
+ // Extacts CSS to stanalone file
40
+ new ExtractTextPlugin("bundle-[name]-[chunkhash].css", {
41
+ allChunks: true
42
+ }),
43
+
44
+ new CleanPlugin(
45
+ path.join('public', 'assets', 'webpack'),
46
+ { root: path.join(process.cwd()) }
47
+ ),
48
+
49
+ // Some webpack built-in optimizations
50
+ // Fill free to switch off if don't need some of it
51
+ new webpack.optimize.CommonsChunkPlugin('common', 'bundle-[name]-[hash].js'),
52
+ new webpack.optimize.DedupePlugin(),
53
+ new webpack.optimize.OccurenceOrderPlugin(),
54
+
55
+ //Enables Javascript source code uglifying
56
+ // new webpack.optimize.UglifyJsPlugin({
57
+ // mangle: true,
58
+ // compress: {
59
+ // warnings: false
60
+ // }
61
+ // }),
62
+
63
+ // Enables gzip compression for Javascript and CSS assets
64
+ // (remember to uncomment corresponding `require` on top of this file)
65
+ // new CompressionPlugin({ test: /\.js$|\.css$/ }),
66
+ ]
67
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "your-app-name",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "devDependencies": {
6
+ "assets-webpack-plugin": "^3.2.0",
7
+ "clean-webpack-plugin": "^0.1.6",
8
+ "css-loader": "^0.23.1",
9
+ "exports-loader": "^0.6.2",
10
+ "expose-loader": "^0.7.1",
11
+ "extract-text-webpack-plugin": "^1.0.0",
12
+ "file-loader": "^0.8.5",
13
+ "style-loader": "^0.13.0",
14
+ "url-loader": "^0.5.7",
15
+ "webpack": "^1.12.9",
16
+ "webpack-dev-server": "^1.14.0",
17
+ "webpack-hot-middleware": "^2.6.0",
18
+ "webpack-merge": "^0.6.0"
19
+ },
20
+ "scripts": {
21
+ "test": "echo \"Error: no test specified\" && exit 1",
22
+ "build:dev": "{{bin}} -v --config {{config}} --display-chunks --debug",
23
+ "build:production": "NODE_ENV=production {{bin}} -v --config {{config}} --display-chunks",
24
+ "dev:server": "node frontend/dev-server.js"
25
+ },
26
+ "author": "",
27
+ "license": "ISC"
28
+ }
@@ -0,0 +1,18 @@
1
+ module Webpacked
2
+ # Mixin for Rails controllers
3
+ module ControllerHelper
4
+ extend ActiveSupport::Concern
5
+
6
+ # :nodoc:
7
+ module ClassMethods
8
+ # Mix in controller's class method to set up an entry point name
9
+ # and reveal +webpacked_entry_name+ helper to get this name in view
10
+ def webpacked_entry(name)
11
+ helper_method :webpacked_entry_name
12
+ cattr_accessor :webpacked_entry_name
13
+
14
+ self.webpacked_entry_name = name
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ module Webpacked
2
+ # Add new view helpers
3
+ module Helper
4
+ # Return +javascript_include_tag+ for entry point.
5
+ # Also common Javascript file could be included
6
+ def webpacked_js_tags(entry)
7
+ webpacked_tags entry, :js
8
+ end
9
+
10
+ # Return +stylesheet_link_tag+ for entry point.
11
+ # Also common CSS file could be included
12
+ def webpacked_css_tags(entry)
13
+ webpacked_tags entry, :css
14
+ end
15
+
16
+ # Return include tags for entry point by given asset kind.
17
+ # Also common file could be included
18
+ def webpacked_tags(entry, kind)
19
+ common_entry = ::Rails.configuration.webpacked.common_entry_name
20
+ common_bundle = asset_tag(common_entry, kind)
21
+ page_bundle = asset_tag(entry, kind)
22
+ common_bundle ? common_bundle + page_bundle : page_bundle
23
+ end
24
+
25
+ # Return include tags for entry point by given asset kind.
26
+ # No extra common file included even if it exists
27
+ def asset_tag(entry, kind)
28
+ path = webpacked_asset_path(entry, kind)
29
+ if path
30
+ case kind
31
+ when :js then javascript_include_tag path
32
+ when :css then stylesheet_link_tag path
33
+ end
34
+ end
35
+ end
36
+
37
+ # Alias for Webpacked::Manifest.asset_paths
38
+ def webpacked_asset_path(entry, kind = nil)
39
+ Webpacked::Manifest.asset_paths(entry, kind)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,80 @@
1
+ module Webpacked
2
+ # Webpack manifest loading, caching and entry point retrieval
3
+ class Manifest
4
+ ASSET_KINDS = [:js, :css]
5
+
6
+ # Raised if webpack manifest not readable for whatever reason
7
+ class LoadError < StandardError
8
+ end
9
+
10
+ # Raised if something but +:js+ or +:css+ passed as asset kind
11
+ class UnknownAssetKindError < StandardError
12
+ def initialize(kind)
13
+ super "Unknown asset kind: #{kind}"
14
+ end
15
+ end
16
+
17
+ # Raised if an entry point does not exist in the webpack manifest
18
+ class EntryMissingError < StandardError
19
+ def initialize(entry)
20
+ super "Entry point is missed: #{entry}"
21
+ end
22
+ end
23
+
24
+ class << self
25
+ # Load manifest from file and cache it if +Rails.configuration.webpacked.dev_server+ set to +false+.
26
+ # Return entry point asset path for +:js+ or +:css+ kind or both if +kind+ skipped
27
+ def asset_paths(entry, kind = nil)
28
+ validate_asset_kind(kind)
29
+ if Rails.configuration.webpacked.dev_server
30
+ @manifest = load_manifest!
31
+ else
32
+ @manifest ||= load_manifest!
33
+ end
34
+ validate_entry(entry)
35
+
36
+ return @manifest[entry] unless kind
37
+ return @manifest[entry][kind] if @manifest[entry]
38
+ end
39
+
40
+ # Force to load manifest from file
41
+ def load_manifest!
42
+ manifest_path = Rails.configuration.webpacked.manifest_path
43
+ manifest_path = Rails.root.join(manifest_path)
44
+ manifest = {}
45
+ if File.exist?(manifest_path)
46
+ manifest = JSON.parse(File.read manifest_path).with_indifferent_access
47
+ clean_asset_paths(manifest)
48
+ elsif Rails.configuration.webpacked.enabled
49
+ raise LoadError, "File #{manifest_path} not found"
50
+ end
51
+ manifest
52
+ end
53
+
54
+ private
55
+
56
+ def validate_asset_kind(kind)
57
+ return unless kind
58
+ raise UnknownAssetKindError, kind unless ASSET_KINDS.include?(kind)
59
+ end
60
+
61
+ def validate_entry(entry)
62
+ unless entry == Rails.configuration.webpacked.common_entry_name
63
+ raise EntryMissingError, entry unless @manifest[entry]
64
+ end
65
+ end
66
+
67
+ def clean_asset_paths(manifest)
68
+ manifest.each do |entry, assets|
69
+ assets.each do |kind, asset_path|
70
+ manifest[entry][kind] = if asset_path =~ %r{(http[s]?)://}i
71
+ asset_path
72
+ else
73
+ Pathname.new(asset_path).cleanpath.to_s
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,2 @@
1
+ require 'webpacked/version'
2
+ require 'webpacked/railtie' if defined? ::Rails::Railtie
@@ -0,0 +1,30 @@
1
+ require 'rails'
2
+ require 'rails/railtie'
3
+ require 'webpacked/manifest'
4
+ require 'webpacked/helper'
5
+ require 'webpacked/controller_helper'
6
+
7
+ module Webpacked
8
+ # :nodoc:
9
+ class Railtie < ::Rails::Railtie
10
+ config.webpacked = ActiveSupport::OrderedOptions.new
11
+
12
+ config.webpacked.enabled = true
13
+ config.webpacked.manifest_path = 'webpack-assets.json'
14
+ config.webpacked.load_manifest_on_initialize = false
15
+ config.webpacked.common_entry_name = 'common'
16
+ config.webpacked.bin = 'node_modules/.bin/webpack'
17
+ config.webpacked.config = 'frontend/main.config.js'
18
+ config.webpacked.dev_server = Rails.env.development?
19
+
20
+ initializer 'webpacked.load_manifest' do
21
+ Webpacked::Manifest.load_manifest! if Rails.configuration.webpacked.load_manifest_on_initialize
22
+ end
23
+
24
+ config.after_initialize do
25
+ ActiveSupport.on_load(:action_view) do
26
+ include Webpacked::Helper
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ module Webpacked
2
+ VERSION = '0.1.0'
3
+ end
data/lib/webpacked.rb ADDED
@@ -0,0 +1 @@
1
+ require 'webpacked/rails'
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: webpacked
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrey Garbuz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-08-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Ready for production gem to use webpack and hot reload within Rails application
42
+ email:
43
+ - andrey.garbuz@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - MIT-LICENSE
49
+ - README.md
50
+ - Rakefile
51
+ - lib/capistrano/tasks/webpacked.rake
52
+ - lib/capistrano/webpacked.rb
53
+ - lib/generators/webpacked/USAGE
54
+ - lib/generators/webpacked/install_generator.rb
55
+ - lib/generators/webpacked/templates/Procfile
56
+ - lib/generators/webpacked/templates/frontend/app/base-entry.js
57
+ - lib/generators/webpacked/templates/frontend/base.config.js
58
+ - lib/generators/webpacked/templates/frontend/dev-server.js
59
+ - lib/generators/webpacked/templates/frontend/development.config.js
60
+ - lib/generators/webpacked/templates/frontend/main.config.js
61
+ - lib/generators/webpacked/templates/frontend/production.config.js
62
+ - lib/generators/webpacked/templates/package.json
63
+ - lib/webpacked.rb
64
+ - lib/webpacked/controller_helper.rb
65
+ - lib/webpacked/helper.rb
66
+ - lib/webpacked/manifest.rb
67
+ - lib/webpacked/rails.rb
68
+ - lib/webpacked/railtie.rb
69
+ - lib/webpacked/version.rb
70
+ homepage: https://github.com/Darkside73/webpacked
71
+ licenses:
72
+ - MIT
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 2.2.2
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 2.6.6
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Easy webpack and Rails integration
94
+ test_files: []