webpacker-react-on-rails 2.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.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/.eslintrc.js +14 -0
  3. data/.gitignore +4 -0
  4. data/.rubocop.yml +124 -0
  5. data/.travis.yml +22 -0
  6. data/CHANGELOG.md +208 -0
  7. data/Gemfile +21 -0
  8. data/Gemfile.lock +137 -0
  9. data/MIT-LICENSE +20 -0
  10. data/README.md +1244 -0
  11. data/Rakefile +12 -0
  12. data/lib/install/angular.rb +18 -0
  13. data/lib/install/bin/webpack-dev-server.tt +71 -0
  14. data/lib/install/bin/webpack.tt +32 -0
  15. data/lib/install/config/.babelrc +18 -0
  16. data/lib/install/config/.postcssrc.yml +3 -0
  17. data/lib/install/config/loaders/core/assets.js +12 -0
  18. data/lib/install/config/loaders/core/babel.js +5 -0
  19. data/lib/install/config/loaders/core/coffee.js +4 -0
  20. data/lib/install/config/loaders/core/erb.js +9 -0
  21. data/lib/install/config/loaders/core/sass.js +18 -0
  22. data/lib/install/config/loaders/installers/angular.js +4 -0
  23. data/lib/install/config/loaders/installers/elm.js +20 -0
  24. data/lib/install/config/loaders/installers/react.js +5 -0
  25. data/lib/install/config/loaders/installers/vue.js +41 -0
  26. data/lib/install/config/webpack/configuration.js +45 -0
  27. data/lib/install/config/webpack/development.js +31 -0
  28. data/lib/install/config/webpack/production.js +35 -0
  29. data/lib/install/config/webpack/shared.js +53 -0
  30. data/lib/install/config/webpack/test.js +6 -0
  31. data/lib/install/config/webpacker.yml +47 -0
  32. data/lib/install/elm.rb +29 -0
  33. data/lib/install/examples/angular/hello_angular.js +7 -0
  34. data/lib/install/examples/angular/hello_angular/app/app.component.ts +9 -0
  35. data/lib/install/examples/angular/hello_angular/app/app.module.ts +16 -0
  36. data/lib/install/examples/angular/hello_angular/index.ts +6 -0
  37. data/lib/install/examples/angular/hello_angular/polyfills.ts +19 -0
  38. data/lib/install/examples/angular/tsconfig.json +19 -0
  39. data/lib/install/examples/elm/Main.elm +54 -0
  40. data/lib/install/examples/elm/hello_elm.js +11 -0
  41. data/lib/install/examples/react/.babelrc +6 -0
  42. data/lib/install/examples/react/hello_react.jsx +26 -0
  43. data/lib/install/examples/vue/app.vue +22 -0
  44. data/lib/install/examples/vue/hello_vue.js +43 -0
  45. data/lib/install/javascript/packs/application.js +10 -0
  46. data/lib/install/react.rb +31 -0
  47. data/lib/install/template.rb +42 -0
  48. data/lib/install/vue.rb +15 -0
  49. data/lib/tasks/installers.rake +22 -0
  50. data/lib/tasks/webpacker.rake +19 -0
  51. data/lib/tasks/webpacker/check_binstubs.rake +12 -0
  52. data/lib/tasks/webpacker/check_node.rake +20 -0
  53. data/lib/tasks/webpacker/check_yarn.rake +15 -0
  54. data/lib/tasks/webpacker/clobber.rake +17 -0
  55. data/lib/tasks/webpacker/compile.rake +38 -0
  56. data/lib/tasks/webpacker/install.rake +12 -0
  57. data/lib/tasks/webpacker/verify_install.rake +16 -0
  58. data/lib/tasks/webpacker/yarn_install.rake +6 -0
  59. data/lib/webpacker.rb +26 -0
  60. data/lib/webpacker/compiler.rb +59 -0
  61. data/lib/webpacker/configuration.rb +83 -0
  62. data/lib/webpacker/dev_server.rb +78 -0
  63. data/lib/webpacker/env.rb +23 -0
  64. data/lib/webpacker/file_loader.rb +47 -0
  65. data/lib/webpacker/helper.rb +69 -0
  66. data/lib/webpacker/manifest.rb +101 -0
  67. data/lib/webpacker/railtie.rb +18 -0
  68. data/lib/webpacker/version.rb +3 -0
  69. data/package.json +31 -0
  70. data/test/compiler_test.rb +25 -0
  71. data/test/configuration_test.rb +36 -0
  72. data/test/dev_server_test.rb +56 -0
  73. data/test/env_test.rb +14 -0
  74. data/test/helper_test.rb +45 -0
  75. data/test/manifest_test.rb +77 -0
  76. data/test/test_app/config/secrets.yml +5 -0
  77. data/test/test_app/public/packs/manifest.json +6 -0
  78. data/test/webpacker_test.rb +20 -0
  79. data/webpacker.gemspec +23 -0
  80. data/yarn.lock +1014 -0
  81. metadata +192 -0
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.libs << "test"
7
+ t.libs << "lib"
8
+ t.test_files = FileList["test/**/*_test.rb"]
9
+ t.verbose = true
10
+ end
11
+
12
+ task default: :test
@@ -0,0 +1,18 @@
1
+ require "webpacker/configuration"
2
+
3
+ puts "Copying angular loader to config/webpack/loaders"
4
+ copy_file "#{__dir__}/config/loaders/installers/angular.js", "config/webpack/loaders/angular.js"
5
+
6
+ puts "Copying angular example entry file to #{Webpacker::Configuration.entry_path}"
7
+ copy_file "#{__dir__}/examples/angular/hello_angular.js", "#{Webpacker::Configuration.entry_path}/hello_angular.js"
8
+
9
+ puts "Copying hello_angular app to #{Webpacker::Configuration.source_path}"
10
+ directory "#{__dir__}/examples/angular/hello_angular", "#{Webpacker::Configuration.source_path}/hello_angular"
11
+
12
+ puts "Copying tsconfig.json to the Rails root directory for typescript"
13
+ copy_file "#{__dir__}/examples/angular/tsconfig.json", "tsconfig.json"
14
+
15
+ puts "Installing all angular dependencies"
16
+ run "yarn add typescript ts-loader core-js zone.js rxjs @angular/core @angular/common @angular/compiler @angular/platform-browser @angular/platform-browser-dynamic"
17
+
18
+ puts "Webpacker now supports angular and typescript 🎉"
@@ -0,0 +1,71 @@
1
+ <%= shebang %>
2
+ $stdout.sync = true
3
+
4
+ require "shellwords"
5
+ require "yaml"
6
+ require "socket"
7
+
8
+ ENV["RAILS_ENV"] ||= "development"
9
+ RAILS_ENV = ENV["RAILS_ENV"]
10
+
11
+ ENV["NODE_ENV"] ||= RAILS_ENV
12
+ NODE_ENV = ENV["NODE_ENV"]
13
+
14
+ APP_PATH = File.expand_path("../", __dir__)
15
+ CONFIG_FILE = File.join(APP_PATH, "config/webpacker.yml")
16
+ NODE_MODULES_PATH = File.join(APP_PATH, "node_modules")
17
+ WEBPACK_CONFIG = File.join(APP_PATH, "config/webpack/#{NODE_ENV}.js")
18
+
19
+ LISTEN_IP_ADDR = "0.0.0.0"
20
+
21
+ def args(key)
22
+ index = ARGV.index(key)
23
+ index ? ARGV[index + 1] : nil
24
+ end
25
+
26
+ begin
27
+ dev_server = YAML.load_file(CONFIG_FILE)[RAILS_ENV]["dev_server"]
28
+
29
+ HOSTNAME = args('--host') || dev_server["host"]
30
+ PORT = args('--port') || dev_server["port"]
31
+ HTTPS = ARGV.include?('--https') || dev_server["https"]
32
+ DEV_SERVER_ADDR = "http#{"s" if HTTPS}://#{HOSTNAME}:#{PORT}"
33
+
34
+ rescue Errno::ENOENT, NoMethodError
35
+ $stdout.puts "Webpack dev_server configuration not found in #{CONFIG_FILE}."
36
+ $stdout.puts "Please run bundle exec rails webpacker:install to install webpacker"
37
+ exit!
38
+ end
39
+
40
+ begin
41
+ server = TCPServer.new(LISTEN_IP_ADDR, PORT)
42
+ server.close
43
+
44
+ rescue Errno::EADDRINUSE
45
+ $stdout.puts "Another program is running on port #{PORT}. Set a new port in #{CONFIG_FILE} for dev_server"
46
+ exit!
47
+ end
48
+
49
+ # Delete supplied host and port CLI arguments
50
+ ["--host", "--port"].each do |arg|
51
+ ARGV.delete(args(arg))
52
+ ARGV.delete(arg)
53
+ end
54
+
55
+ newenv = {
56
+ "NODE_PATH" => NODE_MODULES_PATH.shellescape,
57
+ "ASSET_HOST" => DEV_SERVER_ADDR.shellescape
58
+ }.freeze
59
+
60
+ if Gem.win_platform?
61
+ # Workaround for yarn not playing nicely with path separators
62
+ cmdline = ["#{NODE_MODULES_PATH}/.bin/webpack-dev-server", "--progress", "--color", "--config",
63
+ WEBPACK_CONFIG, "--host", LISTEN_IP_ADDR, "--port", PORT.to_s] + ARGV
64
+ else
65
+ cmdline = ["yarn", "run", "webpack-dev-server", "--", "--progress", "--color", "--config",
66
+ WEBPACK_CONFIG, "--host", LISTEN_IP_ADDR, "--port", PORT.to_s] + ARGV
67
+ end
68
+
69
+ Dir.chdir(APP_PATH) do
70
+ exec newenv, *cmdline
71
+ end
@@ -0,0 +1,32 @@
1
+ <%= shebang %>
2
+ $stdout.sync = true
3
+
4
+ require "shellwords"
5
+
6
+ ENV["RAILS_ENV"] ||= "development"
7
+ RAILS_ENV = ENV["RAILS_ENV"]
8
+
9
+ ENV["NODE_ENV"] ||= RAILS_ENV
10
+ NODE_ENV = ENV["NODE_ENV"]
11
+
12
+ APP_PATH = File.expand_path("../", __dir__)
13
+ NODE_MODULES_PATH = File.join(APP_PATH, "node_modules")
14
+ WEBPACK_CONFIG = File.join(APP_PATH, "config/webpack/#{NODE_ENV}.js")
15
+
16
+ unless File.exist?(WEBPACK_CONFIG)
17
+ puts "Webpack configuration not found."
18
+ puts "Please run bundle exec rails webpacker:install to install webpacker"
19
+ exit!
20
+ end
21
+
22
+ newenv = { "NODE_PATH" => NODE_MODULES_PATH.shellescape }
23
+ if Gem.win_platform?
24
+ # Workaround for yarn not playing nicely with path separators
25
+ cmdline = ["#{NODE_MODULES_PATH}/.bin/webpack", "--config", WEBPACK_CONFIG] + ARGV
26
+ else
27
+ cmdline = ["yarn", "run", "webpack", "--", "--config", WEBPACK_CONFIG] + ARGV
28
+ end
29
+
30
+ Dir.chdir(APP_PATH) do
31
+ exec newenv, *cmdline
32
+ end
@@ -0,0 +1,18 @@
1
+ {
2
+ "presets": [
3
+ ["env", {
4
+ "modules": false,
5
+ "targets": {
6
+ "browsers": "> 1%",
7
+ "uglify": true
8
+ },
9
+ "useBuiltIns": true
10
+ }]
11
+ ],
12
+
13
+ "plugins": [
14
+ "syntax-dynamic-import",
15
+ "transform-object-rest-spread",
16
+ ["transform-class-properties", { "spec": true }]
17
+ ]
18
+ }
@@ -0,0 +1,3 @@
1
+ plugins:
2
+ postcss-smart-import: {}
3
+ postcss-cssnext: {}
@@ -0,0 +1,12 @@
1
+ const { env, output } = require('../configuration.js')
2
+
3
+ module.exports = {
4
+ test: /\.(jpg|jpeg|png|gif|svg|eot|ttf|woff|woff2)$/i,
5
+ use: [{
6
+ loader: 'file-loader',
7
+ options: {
8
+ publicPath: output.publicPath,
9
+ name: env.NODE_ENV === 'production' ? '[name]-[hash].[ext]' : '[name].[ext]'
10
+ }
11
+ }]
12
+ }
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ test: /\.js(\.erb)?$/,
3
+ exclude: /node_modules/,
4
+ loader: 'babel-loader'
5
+ }
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ test: /\.coffee(\.erb)?$/,
3
+ loader: 'coffee-loader'
4
+ }
@@ -0,0 +1,9 @@
1
+ module.exports = {
2
+ test: /\.erb$/,
3
+ enforce: 'pre',
4
+ exclude: /node_modules/,
5
+ loader: 'rails-erb-loader',
6
+ options: {
7
+ runner: 'bin/rails runner'
8
+ }
9
+ }
@@ -0,0 +1,18 @@
1
+ const ExtractTextPlugin = require('extract-text-webpack-plugin')
2
+ const path = require('path')
3
+ const { env } = require('../configuration.js')
4
+
5
+ const postcssConfigPath = path.resolve(process.cwd(), '.postcssrc.yml')
6
+
7
+ module.exports = {
8
+ test: /\.(scss|sass|css)$/i,
9
+ use: ExtractTextPlugin.extract({
10
+ fallback: 'style-loader',
11
+ use: [
12
+ { loader: 'css-loader', options: { minimize: env.NODE_ENV === 'production' } },
13
+ { loader: 'postcss-loader', options: { sourceMap: true, config: { path: postcssConfigPath } } },
14
+ 'resolve-url-loader',
15
+ { loader: 'sass-loader', options: { sourceMap: true } }
16
+ ]
17
+ })
18
+ }
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ test: /\.ts$/,
3
+ loader: 'ts-loader'
4
+ }
@@ -0,0 +1,20 @@
1
+ const path = require('path')
2
+ const { env } = require('../configuration.js')
3
+
4
+ const elmSource = path.resolve(process.cwd())
5
+ const elmMake = `${elmSource}/node_modules/.bin/elm-make`
6
+ const elmDefaultOptions = `cwd=${elmSource}&pathToMake=${elmMake}`
7
+
8
+ const loaderOptions = () => {
9
+ if (env.NODE_ENV === 'production') {
10
+ return `elm-webpack-loader?${elmDefaultOptions}`
11
+ }
12
+
13
+ return `elm-hot-loader!elm-webpack-loader?${elmDefaultOptions}&verbose=true&warn=true&debug=true`
14
+ }
15
+
16
+ module.exports = {
17
+ test: /\.elm$/,
18
+ exclude: [/elm-stuff/, /node_modules/],
19
+ loader: loaderOptions()
20
+ }
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ test: /\.(js|jsx)?(\.erb)?$/,
3
+ exclude: /node_modules/,
4
+ loader: 'babel-loader'
5
+ }
@@ -0,0 +1,41 @@
1
+ const ExtractTextPlugin = require('extract-text-webpack-plugin')
2
+ const { env } = require('../configuration.js')
3
+
4
+ // Change it to false if you prefer Vue styles to be inlined by javascript in runtime
5
+ const extractStyles = false
6
+
7
+ const cssLoader = [
8
+ { loader: 'css-loader', options: { minimize: env.NODE_ENV === 'production' } },
9
+ { loader: 'postcss-loader', options: { sourceMap: true } },
10
+ 'resolve-url-loader'
11
+ ]
12
+ const sassLoader = cssLoader.concat([
13
+ { loader: 'sass-loader', options: { sourceMap: true, indentedSyntax: true } }
14
+ ])
15
+ const scssLoader = cssLoader.concat([
16
+ { loader: 'sass-loader', options: { sourceMap: true } }
17
+ ])
18
+
19
+ function vueStyleLoader(loader) {
20
+ if (extractStyles) {
21
+ return ExtractTextPlugin.extract({
22
+ fallback: 'vue-style-loader',
23
+ use: loader
24
+ })
25
+ }
26
+ return ['vue-style-loader'].concat(loader)
27
+ }
28
+
29
+ module.exports = {
30
+ test: /\.vue$/,
31
+ loader: 'vue-loader',
32
+ options: {
33
+ loaders: {
34
+ js: 'babel-loader',
35
+ file: 'file-loader',
36
+ css: vueStyleLoader(cssLoader),
37
+ scss: vueStyleLoader(scssLoader),
38
+ sass: vueStyleLoader(sassLoader)
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,45 @@
1
+ // Common configuration for webpacker loaded from config/webpacker.yml
2
+
3
+ const { join, resolve } = require('path')
4
+ const { env } = require('process')
5
+ const { safeLoad } = require('js-yaml')
6
+ const { readFileSync } = require('fs')
7
+
8
+ const configPath = resolve('config', 'webpacker.yml')
9
+ const loadersDir = join(__dirname, 'loaders')
10
+ const settings = safeLoad(readFileSync(configPath), 'utf8')[env.NODE_ENV]
11
+
12
+ function removeOuterSlashes(string) {
13
+ return string.replace(/^\/*/, '').replace(/\/*$/, '')
14
+ }
15
+
16
+ function formatPublicPath(host = '', path = '') {
17
+ let formattedHost = removeOuterSlashes(host)
18
+ if (formattedHost && !/^http/i.test(formattedHost)) {
19
+ formattedHost = `//${formattedHost}`
20
+ }
21
+ const formattedPath = removeOuterSlashes(path)
22
+ return `${formattedHost}/${formattedPath}/`
23
+ }
24
+
25
+ const output = {
26
+ path: resolve('public', settings.public_output_path),
27
+ publicPath: formatPublicPath(env.ASSET_HOST, settings.public_output_path)
28
+ }
29
+
30
+ let resolvedModules = [
31
+ resolve(settings.source_path),
32
+ 'node_modules'
33
+ ]
34
+
35
+ if (settings.resolved_paths && Array.isArray(settings.resolved_paths)) {
36
+ resolvedModules = resolvedModules.concat(settings.resolved_paths)
37
+ }
38
+
39
+ module.exports = {
40
+ settings,
41
+ resolvedModules,
42
+ env,
43
+ loadersDir,
44
+ output
45
+ }
@@ -0,0 +1,31 @@
1
+ // Note: You must restart bin/webpack-dev-server for changes to take effect
2
+
3
+ const merge = require('webpack-merge')
4
+ const sharedConfig = require('./shared.js')
5
+ const { settings, output } = require('./configuration.js')
6
+
7
+ module.exports = merge(sharedConfig, {
8
+ devtool: 'cheap-eval-source-map',
9
+
10
+ output: {
11
+ pathinfo: true
12
+ },
13
+
14
+ devServer: {
15
+ clientLogLevel: 'none',
16
+ https: settings.dev_server.https,
17
+ host: settings.dev_server.host,
18
+ port: settings.dev_server.port,
19
+ contentBase: output.path,
20
+ publicPath: output.publicPath,
21
+ compress: true,
22
+ headers: { 'Access-Control-Allow-Origin': '*' },
23
+ historyApiFallback: true,
24
+ watchOptions: {
25
+ ignored: /node_modules/
26
+ },
27
+ stats: {
28
+ errorDetails: true
29
+ }
30
+ }
31
+ })
@@ -0,0 +1,35 @@
1
+ // Note: You must restart bin/webpack-dev-server for changes to take effect
2
+
3
+ /* eslint global-require: 0 */
4
+
5
+ const webpack = require('webpack')
6
+ const merge = require('webpack-merge')
7
+ const CompressionPlugin = require('compression-webpack-plugin')
8
+ const sharedConfig = require('./shared.js')
9
+
10
+ module.exports = merge(sharedConfig, {
11
+ output: { filename: '[name]-[chunkhash].js' },
12
+ devtool: 'source-map',
13
+ stats: 'normal',
14
+
15
+ plugins: [
16
+ new webpack.optimize.UglifyJsPlugin({
17
+ minimize: true,
18
+ sourceMap: true,
19
+
20
+ compress: {
21
+ warnings: false
22
+ },
23
+
24
+ output: {
25
+ comments: false
26
+ }
27
+ }),
28
+
29
+ new CompressionPlugin({
30
+ asset: '[path].gz[query]',
31
+ algorithm: 'gzip',
32
+ test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
33
+ })
34
+ ]
35
+ })
@@ -0,0 +1,53 @@
1
+ // Note: You must restart bin/webpack-dev-server for changes to take effect
2
+
3
+ /* eslint global-require: 0 */
4
+ /* eslint import/no-dynamic-require: 0 */
5
+
6
+ const webpack = require('webpack')
7
+ const { basename, dirname, join, relative, resolve } = require('path')
8
+ const { sync } = require('glob')
9
+ const ExtractTextPlugin = require('extract-text-webpack-plugin')
10
+ const ManifestPlugin = require('webpack-manifest-plugin')
11
+ const extname = require('path-complete-extname')
12
+ const { env, settings, output, loadersDir, resolvedModules } = require('./configuration.js')
13
+
14
+ const extensionGlob = `**/*{${settings.extensions.join(',')}}*`
15
+ const entryPath = join(settings.source_path, settings.source_entry_path)
16
+ const packPaths = sync(join(entryPath, extensionGlob))
17
+
18
+ module.exports = {
19
+ entry: packPaths.reduce(
20
+ (map, entry) => {
21
+ const localMap = map
22
+ const namespace = relative(join(entryPath), dirname(entry))
23
+ localMap[join(namespace, basename(entry, extname(entry)))] = resolve(entry)
24
+ return localMap
25
+ }, {}
26
+ ),
27
+
28
+ output: {
29
+ filename: '[name].js',
30
+ path: output.path,
31
+ },
32
+
33
+ module: {
34
+ rules: sync(join(loadersDir, '*.js')).map(loader => require(loader))
35
+ },
36
+
37
+ plugins: [
38
+ new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
39
+ new ExtractTextPlugin(env.NODE_ENV === 'production' ? '[name]-[hash].css' : '[name].css'),
40
+ new ManifestPlugin({
41
+ writeToFileEmit: true
42
+ })
43
+ ],
44
+
45
+ resolve: {
46
+ extensions: settings.extensions,
47
+ modules: resolvedModules
48
+ },
49
+
50
+ resolveLoader: {
51
+ modules: ['node_modules']
52
+ }
53
+ }