webpacker 3.2.2 → 3.3.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -1
  3. data/Gemfile.lock +38 -38
  4. data/README.md +48 -49
  5. data/docs/css.md +31 -1
  6. data/docs/docker.md +1 -1
  7. data/docs/typescript.md +36 -1
  8. data/{exe → lib/install/bin}/webpack +7 -0
  9. data/{exe → lib/install/bin}/webpack-dev-server +7 -0
  10. data/lib/install/binstubs.rb +4 -0
  11. data/lib/install/config/webpacker.yml +3 -0
  12. data/lib/install/loaders/erb.js +1 -1
  13. data/lib/install/template.rb +1 -2
  14. data/lib/install/typescript.rb +1 -1
  15. data/lib/tasks/webpacker.rake +1 -0
  16. data/lib/tasks/webpacker/binstubs.rake +12 -0
  17. data/lib/tasks/webpacker/check_binstubs.rake +1 -1
  18. data/lib/webpacker.rb +1 -0
  19. data/lib/webpacker/compiler.rb +4 -2
  20. data/lib/webpacker/dev_server_runner.rb +1 -1
  21. data/lib/webpacker/env.rb +39 -0
  22. data/lib/webpacker/instance.rb +1 -12
  23. data/lib/webpacker/version.rb +1 -1
  24. data/package.json +2 -2
  25. data/package/__tests__/config.js +7 -4
  26. data/package/__tests__/dev_server.js +26 -0
  27. data/package/__tests__/env.js +28 -0
  28. data/package/__tests__/index.js +31 -0
  29. data/package/config.js +14 -30
  30. data/package/config_types/__tests__/config_list.js +0 -5
  31. data/package/config_types/config_list.js +0 -9
  32. data/package/dev_server.js +23 -0
  33. data/package/env.js +23 -0
  34. data/package/{__tests__/environment.js → environments/__tests__/base.js} +6 -6
  35. data/package/{environment.js → environments/base.js} +4 -4
  36. data/package/environments/development.js +4 -3
  37. data/package/environments/production.js +31 -25
  38. data/package/environments/test.js +2 -2
  39. data/package/index.js +10 -6
  40. data/package/rules/babel.js +8 -6
  41. data/package/rules/css.js +2 -38
  42. data/package/rules/file.js +9 -7
  43. data/package/rules/index.js +4 -0
  44. data/package/rules/module.css.js +3 -0
  45. data/package/rules/module.sass.js +8 -0
  46. data/package/rules/sass.js +5 -12
  47. data/package/utils/__tests__/get_style_rule.js +36 -0
  48. data/package/utils/get_style_rule.js +62 -0
  49. data/package/utils/helpers.js +17 -3
  50. data/test/env_test.rb +19 -0
  51. data/test/test_app/bin/webpack +15 -0
  52. data/test/test_app/bin/webpack-dev-server +15 -0
  53. data/test/test_app/config/webpacker.yml +3 -0
  54. data/test/test_helper.rb +3 -1
  55. data/webpacker.gemspec +0 -2
  56. data/yarn.lock +8 -4
  57. metadata +26 -10
data/docs/docker.md CHANGED
@@ -11,7 +11,7 @@ services:
11
11
  build: .
12
12
  env_file:
13
13
  - '.env.docker'
14
- command: bundle exec webpack-dev-server
14
+ command: ./bin/webpack-dev-server
15
15
  volumes:
16
16
  - .:/webpacker-example-app
17
17
  ports:
data/docs/typescript.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  ## Typescript with React
5
5
 
6
- 1. Setup react using Webpacker [react installer](#react). Then run the typescript installer
6
+ 1. Setup react using Webpacker [react installer](../README.md#react). Then run the typescript installer
7
7
 
8
8
  ```bash
9
9
  bundle exec rails webpacker:install:typescript
@@ -13,6 +13,41 @@ yarn add @types/react @types/react-dom
13
13
  2. Rename the generated `hello_react.js` to `hello_react.tsx`. Make the file valid typescript and
14
14
  now you can use typescript, JSX with React.
15
15
 
16
+ ## Typescript with Vue components
17
+
18
+ 1. Setup vue using Webpacker [vue installer](../README.md#vue). Then run the typescript installer
19
+
20
+ ```bash
21
+ bundle exec rails webpacker:install:typescript
22
+ ```
23
+
24
+ 2. Rename generated `hello_vue.js` to `hello_vue.ts`.
25
+ 3. Change generated `config/webpack/loaders/typescript.js` from
26
+
27
+ ```js
28
+ module.exports = {
29
+ test: /\.(ts|tsx)?(\.erb)?$/,
30
+ use: [{
31
+ loader: 'ts-loader'
32
+ }]
33
+ }
34
+ ```
35
+
36
+ to
37
+
38
+ ```js
39
+ module.exports = {
40
+ test: /\.(ts|tsx)?(\.erb)?$/,
41
+ use: [{
42
+ loader: 'ts-loader',
43
+ options: {
44
+ appendTsSuffixTo: [/\.vue$/]
45
+ }
46
+ }]
47
+ }
48
+ ```
49
+
50
+ and now you can use `<script lang="ts">` in your `.vue` component files.
16
51
 
17
52
  ## HTML templates with Typescript and Angular
18
53
 
@@ -3,6 +3,13 @@
3
3
  ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
4
4
  ENV["NODE_ENV"] ||= ENV["RAILS_ENV"]
5
5
 
6
+ require "pathname"
7
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
8
+ Pathname.new(__FILE__).realpath)
9
+
10
+ require "rubygems"
11
+ require "bundler/setup"
12
+
6
13
  require "webpacker"
7
14
  require "webpacker/webpack_runner"
8
15
  Webpacker::WebpackRunner.run(ARGV)
@@ -3,6 +3,13 @@
3
3
  ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
4
4
  ENV["NODE_ENV"] ||= ENV["RAILS_ENV"]
5
5
 
6
+ require "pathname"
7
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
8
+ Pathname.new(__FILE__).realpath)
9
+
10
+ require "rubygems"
11
+ require "bundler/setup"
12
+
6
13
  require "webpacker"
7
14
  require "webpacker/dev_server_runner"
8
15
  Webpacker::DevServerRunner.run(ARGV)
@@ -0,0 +1,4 @@
1
+ say "Copying binstubs"
2
+ directory "#{__dir__}/bin", "bin"
3
+
4
+ chmod "bin", 0755 & ~File.umask, verbose: false
@@ -18,6 +18,9 @@ default: &default
18
18
  - .sass
19
19
  - .scss
20
20
  - .css
21
+ - .module.sass
22
+ - .module.scss
23
+ - .module.css
21
24
  - .png
22
25
  - .svg
23
26
  - .gif
@@ -5,7 +5,7 @@ module.exports = {
5
5
  use: [{
6
6
  loader: 'rails-erb-loader',
7
7
  options: {
8
- runner: 'bin/rails runner'
8
+ runner: (/^win/.test(process.platform) ? 'ruby ' : '') + 'bin/rails runner'
9
9
  }
10
10
  }]
11
11
  }
@@ -13,8 +13,7 @@ copy_file "#{__dir__}/config/.babelrc", ".babelrc"
13
13
  say "Creating JavaScript app source directory"
14
14
  directory "#{__dir__}/javascript", Webpacker.config.source_path
15
15
 
16
- say "Installing binstubs"
17
- run "bundle binstubs webpacker"
16
+ apply "#{__dir__}/binstubs.rb"
18
17
 
19
18
  say "Adding configurations"
20
19
 
@@ -41,6 +41,6 @@ copy_file "#{__dir__}/examples/typescript/hello_typescript.ts",
41
41
  "#{Webpacker.config.source_entry_path}/hello_typescript.ts"
42
42
 
43
43
  say "Installing all typescript dependencies"
44
- run "yarn add typescript ts-loader #{additional_packages}"
44
+ run "yarn add typescript ts-loader@3.5.0 #{additional_packages}"
45
45
 
46
46
  say "Webpacker now supports typescript 🎉", :green
@@ -5,6 +5,7 @@ tasks = {
5
5
  "webpacker:check_node" => "Verifies if Node.js is installed",
6
6
  "webpacker:check_yarn" => "Verifies if Yarn is installed",
7
7
  "webpacker:check_binstubs" => "Verifies that webpack & webpack-dev-server are present",
8
+ "webpacker:binstubs" => "Installs Webpacker binstubs in this application",
8
9
  "webpacker:verify_install" => "Verifies if Webpacker is installed",
9
10
  "webpacker:yarn_install" => "Support for older Rails versions. Install all JavaScript dependencies as specified via Yarn",
10
11
  "webpacker:install:react" => "Installs and setup example React component",
@@ -0,0 +1,12 @@
1
+ binstubs_template_path = File.expand_path("../../install/binstubs.rb", __dir__).freeze
2
+
3
+ namespace :webpacker do
4
+ desc "Installs Webpacker binstubs in this application"
5
+ task binstubs: [:check_node, :check_yarn] do
6
+ if Rails::VERSION::MAJOR >= 5
7
+ exec "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{binstubs_template_path}"
8
+ else
9
+ exec "#{RbConfig.ruby} ./bin/rake rails:template LOCATION=#{binstubs_template_path}"
10
+ end
11
+ end
12
+ end
@@ -1,7 +1,7 @@
1
1
  namespace :webpacker do
2
2
  desc "Verifies that webpack & webpack-dev-server are present."
3
3
  task :check_binstubs do
4
- unless Bundler.which(Gem.win_platform? ? "webpack.bat" : "webpack")
4
+ unless File.exist?("bin/webpack")
5
5
  $stderr.puts "webpack binstubs not found.\n"\
6
6
  "Have you run rails webpacker:install ?\n"\
7
7
  "Make sure the bin directory or binstubs are not included in .gitignore\n"\
data/lib/webpacker.rb CHANGED
@@ -19,6 +19,7 @@ module Webpacker
19
19
  end
20
20
 
21
21
  require "webpacker/instance"
22
+ require "webpacker/env"
22
23
  require "webpacker/configuration"
23
24
  require "webpacker/manifest"
24
25
  require "webpacker/compiler"
@@ -53,7 +53,7 @@ class Webpacker::Compiler
53
53
  def run_webpack
54
54
  logger.info "Compiling…"
55
55
 
56
- sterr, stdout, status = Open3.capture3(webpack_env, "bundle exec webpack")
56
+ sterr, stdout, status = Open3.capture3(webpack_env, "#{RbConfig.ruby} ./bin/webpack")
57
57
 
58
58
  if status.success?
59
59
  logger.info "Compiled all packs in #{config.public_output_path}"
@@ -78,6 +78,8 @@ class Webpacker::Compiler
78
78
  end
79
79
 
80
80
  def webpack_env
81
- env.merge("NODE_ENV" => @webpacker.env, "WEBPACKER_ASSET_HOST" => ActionController::Base.helpers.compute_asset_host)
81
+ env.merge("NODE_ENV" => @webpacker.env,
82
+ "WEBPACKER_ASSET_HOST" => ActionController::Base.helpers.compute_asset_host,
83
+ "WEBPACKER_RELATIVE_URL_ROOT" => ActionController::Base.relative_url_root)
82
84
  end
83
85
  end
@@ -14,7 +14,7 @@ module Webpacker
14
14
  private
15
15
  def load_config
16
16
  @config_file = File.join(@app_path, "config/webpacker.yml")
17
- dev_server = YAML.load_file(@config_file)[ENV["RAILS_ENV"]]["dev_server"]
17
+ dev_server = YAML.load_file(@config_file)[ENV["NODE_ENV"]]["dev_server"]
18
18
 
19
19
  @hostname = dev_server["host"]
20
20
  @port = dev_server["port"]
@@ -0,0 +1,39 @@
1
+ class Webpacker::Env
2
+ DEFAULT = "production".freeze
3
+
4
+ delegate :config_path, :logger, to: :@webpacker
5
+
6
+ def self.inquire(webpacker)
7
+ new(webpacker).inquire
8
+ end
9
+
10
+ def initialize(webpacker)
11
+ @webpacker = webpacker
12
+ end
13
+
14
+ def inquire
15
+ fallback_env_warning unless current
16
+ (current || DEFAULT).inquiry
17
+ end
18
+
19
+ private
20
+ def current
21
+ (ENV["NODE_ENV"] || Rails.env).presence_in(available_environments)
22
+ end
23
+
24
+ def fallback_env_warning
25
+ logger.info "NODE_ENV=#{ENV["NODE_ENV"]} and RAILS_ENV=#{Rails.env} environment is not defined in config/webpacker.yml, falling back to #{DEFAULT} environment"
26
+ end
27
+
28
+ def available_environments
29
+ if config_path.exist?
30
+ YAML.load(config_path.read).keys
31
+ else
32
+ [].freeze
33
+ end
34
+ rescue Psych::SyntaxError => e
35
+ raise "YAML syntax error occurred while parsing #{config_path}. " \
36
+ "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
37
+ "Error: #{e.message}"
38
+ end
39
+ end
@@ -8,9 +8,7 @@ class Webpacker::Instance
8
8
  end
9
9
 
10
10
  def env
11
- (ENV["NODE_ENV"].presence_in(available_environments) ||
12
- Rails.env.presence_in(available_environments) ||
13
- "production".freeze).inquiry
11
+ @env ||= Webpacker::Env.inquire self
14
12
  end
15
13
 
16
14
  def config
@@ -32,13 +30,4 @@ class Webpacker::Instance
32
30
  def commands
33
31
  @commands ||= Webpacker::Commands.new self
34
32
  end
35
-
36
- private
37
- def available_environments
38
- if config_path.exist?
39
- YAML.load(config_path.read).keys
40
- else
41
- [].freeze
42
- end
43
- end
44
33
  end
@@ -1,4 +1,4 @@
1
1
  module Webpacker
2
2
  # Change the version in package.json too, please!
3
- VERSION = "3.2.2".freeze
3
+ VERSION = "3.3.0".freeze
4
4
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rails/webpacker",
3
- "version": "3.2.2",
3
+ "version": "3.3.0",
4
4
  "description": "Use webpack to manage app-like JavaScript modules in Rails",
5
5
  "main": "package/index.js",
6
6
  "files": [
@@ -20,7 +20,7 @@
20
20
  "babel-polyfill": "^6.26.0",
21
21
  "babel-preset-env": "^1.6.1",
22
22
  "case-sensitive-paths-webpack-plugin": "^2.1.1",
23
- "compression-webpack-plugin": "^1.1.6",
23
+ "compression-webpack-plugin": "^1.1.10",
24
24
  "css-loader": "^0.28.9",
25
25
  "extract-text-webpack-plugin": "^3.0.2",
26
26
  "file-loader": "^1.1.6",
@@ -1,12 +1,12 @@
1
1
  /* global test expect, describe */
2
2
 
3
- const chdirApp = () => process.chdir('test/test_app')
4
- const chdirCwd = () => process.chdir(process.cwd())
5
- chdirApp()
3
+ const { chdirTestApp, chdirCwd } = require('../utils/helpers')
4
+
5
+ chdirTestApp()
6
6
 
7
7
  const config = require('../config')
8
8
 
9
- describe('Webpacker.yml config', () => {
9
+ describe('Config', () => {
10
10
  afterAll(chdirCwd)
11
11
 
12
12
  test('should return extensions as listed in app config', () => {
@@ -15,6 +15,9 @@ describe('Webpacker.yml config', () => {
15
15
  '.sass',
16
16
  '.scss',
17
17
  '.css',
18
+ '.module.sass',
19
+ '.module.scss',
20
+ '.module.css',
18
21
  '.png',
19
22
  '.svg',
20
23
  '.gif',
@@ -0,0 +1,26 @@
1
+ /* global test expect, describe */
2
+
3
+ const { chdirTestApp, chdirCwd } = require('../utils/helpers')
4
+
5
+ chdirTestApp()
6
+
7
+ describe('DevServer', () => {
8
+ beforeEach(() => jest.resetModules())
9
+ afterAll(chdirCwd)
10
+
11
+ test('with NODE_ENV set to development', () => {
12
+ process.env.NODE_ENV = 'development'
13
+ process.env.WEBPACKER_DEV_SERVER_HOST = '0.0.0.0'
14
+ process.env.WEBPACKER_DEV_SERVER_PORT = 5000
15
+
16
+ const devServer = require('../dev_server')
17
+ expect(devServer).toBeDefined()
18
+ expect(devServer.host).toEqual('0.0.0.0')
19
+ expect(devServer.port).toEqual('5000')
20
+ })
21
+
22
+ test('with NODE_ENV set to production', () => {
23
+ process.env.NODE_ENV = 'production'
24
+ expect(require('../dev_server')).toEqual({})
25
+ })
26
+ })
@@ -0,0 +1,28 @@
1
+ /* global test expect, describe */
2
+
3
+ const { chdirTestApp, chdirCwd } = require('../utils/helpers')
4
+
5
+ chdirTestApp()
6
+
7
+ describe('Env', () => {
8
+ beforeEach(() => jest.resetModules())
9
+ afterAll(chdirCwd)
10
+
11
+ test('with NODE_ENV set to development', () => {
12
+ process.env.NODE_ENV = 'development'
13
+ expect(require('../env')).toEqual('development')
14
+ })
15
+
16
+ test('with undefined NODE_ENV and RAILS_ENV set to development', () => {
17
+ delete process.env.NODE_ENV
18
+ process.env.RAILS_ENV = 'development'
19
+ expect(require('../env')).toEqual('development')
20
+ })
21
+
22
+ test('with a non-standard environment', () => {
23
+ process.env.NODE_ENV = 'foo'
24
+ process.env.RAILS_ENV = 'foo'
25
+ expect(require('../env')).toEqual('production')
26
+ delete process.env.RAILS_ENV
27
+ })
28
+ })
@@ -0,0 +1,31 @@
1
+ /* global test expect, describe */
2
+
3
+ const { chdirTestApp, chdirCwd } = require('../utils/helpers')
4
+
5
+ chdirTestApp()
6
+
7
+ describe('Webpacker', () => {
8
+ beforeEach(() => jest.resetModules())
9
+ afterAll(chdirCwd)
10
+
11
+ test('with NODE_ENV set to development', () => {
12
+ process.env.NODE_ENV = 'development'
13
+ const { environment } = require('../index')
14
+ expect(environment.toWebpackConfig()).toMatchObject({
15
+ devServer: {
16
+ host: 'localhost',
17
+ port: 3035
18
+ }
19
+ })
20
+ })
21
+
22
+ test('with a non-standard env', () => {
23
+ process.env.NODE_ENV = 'staging'
24
+ process.env.RAILS_ENV = 'staging'
25
+ const { environment } = require('../index')
26
+ expect(environment.toWebpackConfig()).toMatchObject({
27
+ devtool: 'nosources-source-map',
28
+ stats: 'normal'
29
+ })
30
+ })
31
+ })
data/package/config.js CHANGED
@@ -3,41 +3,25 @@ const { safeLoad } = require('js-yaml')
3
3
  const { readFileSync } = require('fs')
4
4
  const deepMerge = require('./utils/deep_merge')
5
5
  const { isArray } = require('./utils/helpers')
6
+ const env = require('./env')
6
7
 
7
- const defaultFilePath = require.resolve('../lib/install/config/webpacker.yml')
8
- const filePath = resolve('config', 'webpacker.yml')
8
+ const defaultConfigPath = require.resolve('../lib/install/config/webpacker.yml')
9
+ const configPath = resolve('config', 'webpacker.yml')
9
10
 
10
- const environment = process.env.NODE_ENV || 'development'
11
- const defaultConfig = safeLoad(readFileSync(defaultFilePath), 'utf8')[environment]
12
- const appConfig = safeLoad(readFileSync(filePath), 'utf8')[environment]
11
+ const getConfig = () => {
12
+ const defaults = safeLoad(readFileSync(defaultConfigPath), 'utf8')[env]
13
+ const app = safeLoad(readFileSync(configPath), 'utf8')[env]
13
14
 
14
- if (isArray(appConfig.extensions) && appConfig.extensions.length) {
15
- delete defaultConfig.extensions
16
- } else {
17
- /* eslint no-console: 0 */
18
- console.warn('No extensions specified in webpacker.yml, using default extensions\n')
19
- }
20
-
21
- const config = deepMerge(defaultConfig, appConfig)
15
+ if (isArray(app.extensions) && app.extensions.length) {
16
+ delete defaults.extensions
17
+ }
22
18
 
23
- const isBoolean = str => /^true/.test(str) || /^false/.test(str)
19
+ const config = deepMerge(defaults, app)
24
20
 
25
- const fetch = key =>
26
- (isBoolean(process.env[key]) ? JSON.parse(process.env[key]) : process.env[key])
21
+ config.outputPath = resolve('public', config.public_output_path)
22
+ config.publicPath = `/${config.public_output_path}/`.replace(/([^:]\/)\/+/g, '$1')
27
23
 
28
- const devServer = (key) => {
29
- const envValue = fetch(`WEBPACKER_DEV_SERVER_${key.toUpperCase().replace(/_/g, '')}`)
30
- if (typeof envValue === 'undefined' || envValue === null) return config.dev_server[key]
31
- return envValue
24
+ return config
32
25
  }
33
26
 
34
- if (config.dev_server) {
35
- Object.keys(config.dev_server).forEach((key) => {
36
- config.dev_server[key] = devServer(key)
37
- })
38
- }
39
-
40
- config.outputPath = resolve('public', config.public_output_path)
41
- config.publicPath = `/${config.public_output_path}/`.replace(/([^:]\/)\/+/g, '$1')
42
-
43
- module.exports = config
27
+ module.exports = getConfig()