webpacker 1.2 → 2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGELOG.md +93 -9
  4. data/Gemfile.lock +2 -2
  5. data/README.md +979 -93
  6. data/lib/install/angular.rb +2 -2
  7. data/lib/install/bin/webpack-dev-server.tt +20 -10
  8. data/lib/install/bin/webpack.tt +10 -15
  9. data/lib/install/config/.babelrc +13 -1
  10. data/lib/install/config/loaders/core/sass.js +3 -2
  11. data/lib/install/config/loaders/installers/elm.js +20 -0
  12. data/lib/install/config/loaders/installers/vue.js +1 -0
  13. data/lib/install/config/webpack/configuration.js +22 -13
  14. data/lib/install/config/webpack/development.js +17 -1
  15. data/lib/install/config/webpack/production.js +16 -2
  16. data/lib/install/config/webpack/shared.js +15 -11
  17. data/lib/install/config/{webpack/paths.yml → webpacker.yml} +12 -7
  18. data/lib/install/elm.rb +29 -0
  19. data/lib/install/examples/angular/tsconfig.json +1 -0
  20. data/lib/install/examples/elm/Main.elm +54 -0
  21. data/lib/install/examples/elm/hello_elm.js +11 -0
  22. data/lib/install/examples/vue/hello_vue.js +4 -8
  23. data/lib/install/react.rb +2 -2
  24. data/lib/install/template.rb +10 -11
  25. data/lib/install/vue.rb +2 -2
  26. data/lib/tasks/installers.rake +1 -0
  27. data/lib/tasks/webpacker.rake +11 -9
  28. data/lib/tasks/webpacker/check_webpack_binstubs.rake +11 -0
  29. data/lib/tasks/webpacker/check_yarn.rake +6 -3
  30. data/lib/tasks/webpacker/clobber.rake +3 -3
  31. data/lib/tasks/webpacker/compile.rake +14 -20
  32. data/lib/tasks/webpacker/verify_install.rake +2 -2
  33. data/lib/tasks/webpacker/yarn_install.rake +2 -2
  34. data/lib/webpacker.rb +16 -1
  35. data/lib/webpacker/compiler.rb +20 -0
  36. data/lib/webpacker/configuration.rb +30 -22
  37. data/lib/webpacker/env.rb +2 -6
  38. data/lib/webpacker/helper.rb +0 -2
  39. data/lib/webpacker/manifest.rb +23 -6
  40. data/lib/webpacker/version.rb +1 -1
  41. data/package.json +1 -1
  42. data/test/configuration_test.rb +32 -0
  43. data/test/env_test.rb +3 -5
  44. data/test/helper_test.rb +23 -0
  45. data/test/manifest_test.rb +30 -0
  46. data/test/test_app/config/secrets.yml +5 -0
  47. data/test/test_app/public/packs/manifest.json +4 -0
  48. data/test/webpacker_test.rb +2 -1
  49. metadata +20 -7
  50. data/lib/install/bin/yarn.tt +0 -11
  51. data/lib/install/config/webpack/development.server.js +0 -17
  52. data/lib/install/config/webpack/development.server.yml +0 -17
@@ -1,6 +1,6 @@
1
1
  require "webpacker/configuration"
2
2
 
3
- puts "Copying angular loader to #{Webpacker::Configuration.config_path}/loaders"
3
+ puts "Copying angular loader to config/webpack/loaders"
4
4
  copy_file "#{__dir__}/config/loaders/installers/angular.js", "config/webpack/loaders/angular.js"
5
5
 
6
6
  puts "Copying angular example entry file to #{Webpacker::Configuration.entry_path}"
@@ -13,6 +13,6 @@ puts "Copying tsconfig.json to the Rails root directory for typescript"
13
13
  copy_file "#{__dir__}/examples/angular/tsconfig.json", "tsconfig.json"
14
14
 
15
15
  puts "Installing all angular dependencies"
16
- run "./bin/yarn add typescript ts-loader core-js zone.js rxjs @angular/core @angular/common @angular/compiler @angular/platform-browser @angular/platform-browser-dynamic"
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
17
 
18
18
  puts "Webpacker now supports angular and typescript 🎉"
@@ -10,24 +10,34 @@ RAILS_ENV = ENV["RAILS_ENV"]
10
10
  ENV["NODE_ENV"] ||= RAILS_ENV
11
11
  NODE_ENV = ENV["NODE_ENV"]
12
12
 
13
- APP_PATH = File.expand_path("../", __dir__)
14
- CONFIG_PATH = File.join(APP_PATH, "config/webpack/paths.yml")
13
+ APP_PATH = File.expand_path("../", __dir__)
14
+ CONFIG_FILE = File.join(APP_PATH, "config/webpacker.yml")
15
+ NODE_MODULES_PATH = File.join(APP_PATH, "node_modules")
16
+ WEBPACK_CONFIG = File.join(APP_PATH, "config/webpack/development.js")
17
+
18
+ def args(key)
19
+ index = ARGV.index(key)
20
+ index ? ARGV[index + 1] : nil
21
+ end
15
22
 
16
23
  begin
17
- paths = YAML.load(File.read(CONFIG_PATH))[NODE_ENV]
24
+ dev_server = YAML.load_file(CONFIG_FILE)["development"]["dev_server"]
18
25
 
19
- NODE_MODULES_PATH = File.join(APP_PATH.shellescape, paths["node_modules"])
20
- WEBPACK_CONFIG_PATH = File.join(APP_PATH.shellescape, paths["config"])
26
+ DEV_SERVER_HOST = "http#{"s" if args('--https') || dev_server["https"]}://#{args('--host') || dev_server["host"]}:#{args('--port') || dev_server["port"]}"
21
27
 
22
- WEBPACK_BIN = "#{NODE_MODULES_PATH}/.bin/webpack-dev-server"
23
- DEV_SERVER_CONFIG = "#{WEBPACK_CONFIG_PATH}/development.server.js"
24
28
  rescue Errno::ENOENT, NoMethodError
25
- puts "Configuration not found in config/webpacker/paths.yml."
29
+ puts "Webpack dev_server configuration not found in #{CONFIG_FILE}."
26
30
  puts "Please run bundle exec rails webpacker:install to install webpacker"
27
31
  exit!
28
32
  end
29
33
 
34
+ newenv = {
35
+ "NODE_PATH" => NODE_MODULES_PATH.shellescape,
36
+ "ASSET_HOST" => DEV_SERVER_HOST.shellescape
37
+ }.freeze
38
+
39
+ cmdline = ["yarn", "run", "webpack-dev-server", "--", "--progress", "--color", "--config", WEBPACK_CONFIG] + ARGV
40
+
30
41
  Dir.chdir(APP_PATH) do
31
- exec "NODE_PATH=#{NODE_MODULES_PATH} #{WEBPACK_BIN} --progress --color " \
32
- "--config #{DEV_SERVER_CONFIG} #{ARGV.join(" ")}"
42
+ exec newenv, *cmdline
33
43
  end
@@ -5,29 +5,24 @@ require "shellwords"
5
5
  require "yaml"
6
6
 
7
7
  ENV["RAILS_ENV"] ||= "development"
8
- RAILS_ENV = ENV["RAILS_ENV"]
8
+ RAILS_ENV = ENV["RAILS_ENV"]
9
9
 
10
10
  ENV["NODE_ENV"] ||= RAILS_ENV
11
- NODE_ENV = ENV["NODE_ENV"]
11
+ NODE_ENV = ENV["NODE_ENV"]
12
12
 
13
- APP_PATH = File.expand_path("../", __dir__)
14
- CONFIG_PATH = File.join(APP_PATH, "config/webpack/paths.yml")
13
+ APP_PATH = File.expand_path("../", __dir__)
14
+ NODE_MODULES_PATH = File.join(APP_PATH, "node_modules")
15
+ WEBPACK_CONFIG = File.join(APP_PATH, "config/webpack/#{NODE_ENV}.js")
15
16
 
16
- begin
17
- paths = YAML.load(File.read(CONFIG_PATH))[NODE_ENV]
18
-
19
- NODE_MODULES_PATH = File.join(APP_PATH.shellescape, paths["node_modules"])
20
- WEBPACK_CONFIG_PATH = File.join(APP_PATH.shellescape, paths["config"])
21
- rescue Errno::ENOENT, NoMethodError
22
- puts "Configuration not found in config/webpack/paths.yml"
17
+ unless File.exist?(WEBPACK_CONFIG)
18
+ puts "Webpack configuration not found."
23
19
  puts "Please run bundle exec rails webpacker:install to install webpacker"
24
20
  exit!
25
21
  end
26
22
 
27
- WEBPACK_BIN = "#{NODE_MODULES_PATH}/.bin/webpack"
28
- WEBPACK_CONFIG = "#{WEBPACK_CONFIG_PATH}/#{NODE_ENV}.js"
23
+ newenv = { "NODE_PATH" => NODE_MODULES_PATH.shellescape }
24
+ cmdline = ["yarn", "run", "webpack", "--", "--config", WEBPACK_CONFIG] + ARGV
29
25
 
30
26
  Dir.chdir(APP_PATH) do
31
- exec "NODE_PATH=#{NODE_MODULES_PATH} #{WEBPACK_BIN} --config #{WEBPACK_CONFIG}" \
32
- " #{ARGV.join(" ")}"
27
+ exec newenv, *cmdline
33
28
  end
@@ -1,5 +1,17 @@
1
1
  {
2
2
  "presets": [
3
- ["env", { "modules": false } ]
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-class-properties", { "spec": true }]
4
16
  ]
5
17
  }
@@ -7,8 +7,9 @@ module.exports = {
7
7
  fallback: 'style-loader',
8
8
  use: [
9
9
  { loader: 'css-loader', options: { minimize: env.NODE_ENV === 'production' } },
10
- 'postcss-loader',
11
- 'sass-loader'
10
+ { loader: 'postcss-loader', options: { sourceMap: true } },
11
+ 'resolve-url-loader',
12
+ { loader: 'sass-loader', options: { sourceMap: true } }
12
13
  ]
13
14
  })
14
15
  }
@@ -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
+ }
@@ -2,6 +2,7 @@ module.exports = {
2
2
  test: /.vue$/,
3
3
  loader: 'vue-loader',
4
4
  options: {
5
+ extractCSS: true,
5
6
  loaders: {
6
7
  js: 'babel-loader',
7
8
  file: 'file-loader',
@@ -1,26 +1,35 @@
1
- // Common configuration for webpacker loaded from config/webpack/paths.yml
1
+ // Common configuration for webpacker loaded from config/webpacker.yml
2
2
 
3
3
  const { join, resolve } = require('path')
4
4
  const { env } = require('process')
5
5
  const { safeLoad } = require('js-yaml')
6
6
  const { readFileSync } = require('fs')
7
7
 
8
- const configPath = resolve('config', 'webpack')
8
+ const configPath = resolve('config', 'webpacker.yml')
9
9
  const loadersDir = join(__dirname, 'loaders')
10
- const paths = safeLoad(readFileSync(join(configPath, 'paths.yml'), 'utf8'))[env.NODE_ENV]
11
- const devServer = safeLoad(readFileSync(join(configPath, 'development.server.yml'), 'utf8'))[env.NODE_ENV]
10
+ const settings = safeLoad(readFileSync(configPath), 'utf8')[env.NODE_ENV]
12
11
 
13
- // Compute public path based on environment and ASSET_HOST in production
14
- const ifHasCDN = env.ASSET_HOST !== undefined && env.NODE_ENV === 'production'
15
- const devServerUrl = `http://${devServer.host}:${devServer.port}/${paths.entry}/`
16
- const publicUrl = ifHasCDN ? `${env.ASSET_HOST}/${paths.entry}/` : `/${paths.entry}/`
17
- const publicPath = env.NODE_ENV !== 'production' ? devServerUrl : publicUrl
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
+ }
18
29
 
19
30
  module.exports = {
20
- devServer,
31
+ settings,
21
32
  env,
22
- paths,
23
33
  loadersDir,
24
- publicUrl,
25
- publicPath
34
+ output
26
35
  }
@@ -2,9 +2,10 @@
2
2
 
3
3
  const merge = require('webpack-merge')
4
4
  const sharedConfig = require('./shared.js')
5
+ const { settings, output } = require('./configuration.js')
5
6
 
6
7
  module.exports = merge(sharedConfig, {
7
- devtool: 'sourcemap',
8
+ devtool: 'cheap-eval-source-map',
8
9
 
9
10
  stats: {
10
11
  errorDetails: true
@@ -12,5 +13,20 @@ module.exports = merge(sharedConfig, {
12
13
 
13
14
  output: {
14
15
  pathinfo: true
16
+ },
17
+
18
+ devServer: {
19
+ clientLogLevel: 'none',
20
+ https: settings.dev_server.https,
21
+ host: settings.dev_server.host,
22
+ port: settings.dev_server.port,
23
+ contentBase: output.path,
24
+ publicPath: output.publicPath,
25
+ compress: true,
26
+ headers: { 'Access-Control-Allow-Origin': '*' },
27
+ historyApiFallback: true,
28
+ watchOptions: {
29
+ ignored: /node_modules/
30
+ }
15
31
  }
16
32
  })
@@ -9,13 +9,27 @@ const sharedConfig = require('./shared.js')
9
9
 
10
10
  module.exports = merge(sharedConfig, {
11
11
  output: { filename: '[name]-[chunkhash].js' },
12
+ devtool: 'source-map',
13
+ stats: 'normal',
12
14
 
13
15
  plugins: [
14
- new webpack.optimize.UglifyJsPlugin(),
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
+
15
29
  new CompressionPlugin({
16
30
  asset: '[path].gz[query]',
17
31
  algorithm: 'gzip',
18
- test: /\.(js|css|svg|eot|ttf|woff|woff2)$/
32
+ test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
19
33
  })
20
34
  ]
21
35
  })
@@ -9,16 +9,17 @@ const { sync } = require('glob')
9
9
  const ExtractTextPlugin = require('extract-text-webpack-plugin')
10
10
  const ManifestPlugin = require('webpack-manifest-plugin')
11
11
  const extname = require('path-complete-extname')
12
- const { env, paths, publicPath, loadersDir } = require('./configuration.js')
12
+ const { env, settings, output, loadersDir } = require('./configuration.js')
13
13
 
14
- const extensionGlob = `**/*{${paths.extensions.join(',')}}*`
15
- const packPaths = sync(join(paths.source, paths.entry, extensionGlob))
14
+ const extensionGlob = `**/*{${settings.extensions.join(',')}}*`
15
+ const entryPath = join(settings.source_path, settings.source_entry_path)
16
+ const packPaths = sync(join(entryPath, extensionGlob))
16
17
 
17
18
  module.exports = {
18
19
  entry: packPaths.reduce(
19
20
  (map, entry) => {
20
21
  const localMap = map
21
- const namespace = relative(join(paths.source, paths.entry), dirname(entry))
22
+ const namespace = relative(join(entryPath), dirname(entry))
22
23
  localMap[join(namespace, basename(entry, extname(entry)))] = resolve(entry)
23
24
  return localMap
24
25
  }, {}
@@ -26,8 +27,8 @@ module.exports = {
26
27
 
27
28
  output: {
28
29
  filename: '[name].js',
29
- path: resolve(paths.output, paths.entry),
30
- publicPath
30
+ path: output.path,
31
+ publicPath: output.publicPath
31
32
  },
32
33
 
33
34
  module: {
@@ -37,18 +38,21 @@ module.exports = {
37
38
  plugins: [
38
39
  new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
39
40
  new ExtractTextPlugin(env.NODE_ENV === 'production' ? '[name]-[hash].css' : '[name].css'),
40
- new ManifestPlugin({ fileName: paths.manifest, publicPath, writeToFileEmit: true })
41
+ new ManifestPlugin({
42
+ publicPath: output.publicPath,
43
+ writeToFileEmit: true
44
+ })
41
45
  ],
42
46
 
43
47
  resolve: {
44
- extensions: paths.extensions,
48
+ extensions: settings.extensions,
45
49
  modules: [
46
- resolve(paths.source),
47
- resolve(paths.node_modules)
50
+ resolve(settings.source_path),
51
+ 'node_modules'
48
52
  ]
49
53
  },
50
54
 
51
55
  resolveLoader: {
52
- modules: [paths.node_modules]
56
+ modules: ['node_modules']
53
57
  }
54
58
  }
@@ -1,14 +1,13 @@
1
1
  # Note: You must restart bin/webpack-dev-server for changes to take effect
2
2
 
3
3
  default: &default
4
- config: config/webpack
5
- entry: packs
6
- output: public
7
- manifest: manifest.json
8
- node_modules: node_modules
9
- source: app/javascript
4
+ source_path: app/javascript
5
+ source_entry_path: packs
6
+ public_output_path: packs
7
+
10
8
  extensions:
11
9
  - .coffee
10
+ - .erb
12
11
  - .js
13
12
  - .jsx
14
13
  - .ts
@@ -25,9 +24,15 @@ default: &default
25
24
  development:
26
25
  <<: *default
27
26
 
27
+ dev_server:
28
+ host: 0.0.0.0
29
+ port: 8080
30
+ https: false
31
+
28
32
  test:
29
33
  <<: *default
30
- manifest: manifest-test.json
34
+
35
+ public_output_path: packs-test
31
36
 
32
37
  production:
33
38
  <<: *default
@@ -0,0 +1,29 @@
1
+ require "webpacker/configuration"
2
+
3
+ puts "Copying elm loader to config/webpack/loaders"
4
+ copy_file "#{__dir__}/config/loaders/installers/elm.js",
5
+ "config/webpack/loaders/elm.js"
6
+
7
+ puts "Copying elm example entry file to #{Webpacker::Configuration.entry_path}"
8
+ copy_file "#{__dir__}/examples/elm/Main.elm", "#{Webpacker::Configuration.entry_path}/Main.elm"
9
+
10
+ puts "Copying elm app file to #{Webpacker::Configuration.entry_path}"
11
+ copy_file "#{__dir__}/examples/elm/hello_elm.js",
12
+ "#{Webpacker::Configuration.entry_path}/hello_elm.js"
13
+
14
+ puts "Installing all elm dependencies"
15
+ run "yarn add elm elm-webpack-loader"
16
+ run "yarn add --dev elm-hot-loader"
17
+ run "yarn run elm package install -- --yes"
18
+
19
+ puts "Updating Webpack paths to include Elm file extension"
20
+ insert_into_file Webpacker::Configuration.file_path, " - .elm\n", after: /extensions:\n/
21
+
22
+ puts "Updating elm source location"
23
+ source_path = File.join(Webpacker::Configuration.source, Webpacker::Configuration.fetch(:source_entry_path))
24
+ gsub_file "elm-package.json", /\"\.\"\n/, %("#{source_path}"\n)
25
+
26
+ puts "Updating .gitignore to include elm-stuff folder"
27
+ insert_into_file ".gitignore", "/elm-stuff\n", before: "/node_modules\n"
28
+
29
+ puts "Webpacker now supports elm 🎉"
@@ -12,6 +12,7 @@
12
12
  "exclude": [
13
13
  "**/*.spec.ts",
14
14
  "node_modules",
15
+ "vendor",
15
16
  "public"
16
17
  ],
17
18
  "compileOnSave": false
@@ -0,0 +1,54 @@
1
+ module Main exposing (..)
2
+
3
+ import Html exposing (Html, h1, text)
4
+ import Html.Attributes exposing (style)
5
+
6
+ -- MODEL
7
+
8
+ type alias Model =
9
+ {
10
+ }
11
+
12
+ -- INIT
13
+
14
+ init : (Model, Cmd Message)
15
+ init =
16
+ (Model, Cmd.none)
17
+
18
+ -- VIEW
19
+
20
+ view : Model -> Html Message
21
+ view model =
22
+ -- The inline style is being used for example purposes in order to keep this example simple and
23
+ -- avoid loading additional resources. Use a proper stylesheet when building your own app.
24
+ h1 [style [("display", "flex"), ("justify-content", "center")]]
25
+ [text "Hello Elm!"]
26
+
27
+ -- MESSAGE
28
+
29
+ type Message
30
+ = None
31
+
32
+ -- UPDATE
33
+
34
+ update : Message -> Model -> (Model, Cmd Message)
35
+ update message model =
36
+ (model, Cmd.none)
37
+
38
+ -- SUBSCRIPTIONS
39
+
40
+ subscriptions : Model -> Sub Message
41
+ subscriptions model =
42
+ Sub.none
43
+
44
+ -- MAIN
45
+
46
+ main : Program Never Model Message
47
+ main =
48
+ Html.program
49
+ {
50
+ init = init,
51
+ view = view,
52
+ update = update,
53
+ subscriptions = subscriptions
54
+ }