webpacker 4.0.2 → 5.4.3

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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.js +8 -8
  3. data/.github/workflows/jest.yml +38 -0
  4. data/.github/workflows/js-lint.yml +39 -0
  5. data/.github/workflows/rubocop.yml +39 -0
  6. data/.github/workflows/ruby.yml +58 -0
  7. data/.gitignore +1 -0
  8. data/.node-version +1 -1
  9. data/.rubocop.yml +115 -14
  10. data/.travis.yml +16 -18
  11. data/CHANGELOG.md +329 -130
  12. data/Gemfile +1 -1
  13. data/Gemfile.lock +127 -105
  14. data/README.md +84 -217
  15. data/docs/assets.md +20 -10
  16. data/docs/css.md +126 -7
  17. data/docs/deployment.md +55 -10
  18. data/docs/docker.md +33 -14
  19. data/docs/engines.md +60 -2
  20. data/docs/env.md +0 -2
  21. data/docs/es6.md +24 -5
  22. data/docs/integrations.md +220 -0
  23. data/docs/target.md +22 -0
  24. data/docs/testing.md +2 -3
  25. data/docs/troubleshooting.md +46 -7
  26. data/docs/typescript.md +93 -26
  27. data/docs/v4-upgrade.md +12 -2
  28. data/docs/webpack-dev-server.md +2 -2
  29. data/docs/webpack.md +21 -7
  30. data/gemfiles/Gemfile-rails-edge +2 -3
  31. data/gemfiles/Gemfile-rails.5.2.x +1 -2
  32. data/gemfiles/Gemfile-rails.6.0.x +9 -0
  33. data/lib/install/bin/webpack +0 -1
  34. data/lib/install/bin/webpack-dev-server +0 -1
  35. data/lib/install/coffee.rb +1 -1
  36. data/lib/install/config/babel.config.js +24 -12
  37. data/lib/install/config/webpacker.yml +3 -6
  38. data/lib/install/elm.rb +3 -3
  39. data/lib/install/erb.rb +2 -2
  40. data/lib/install/examples/angular/hello_angular/polyfills.ts +2 -2
  41. data/lib/install/examples/react/babel.config.js +31 -15
  42. data/lib/install/examples/react/tsconfig.json +2 -1
  43. data/lib/install/examples/svelte/app.svelte +11 -0
  44. data/lib/install/examples/svelte/hello_svelte.js +20 -0
  45. data/lib/install/examples/typescript/tsconfig.json +2 -1
  46. data/lib/install/examples/vue/hello_vue.js +2 -3
  47. data/lib/install/loaders/elm.js +9 -6
  48. data/lib/install/loaders/svelte.js +9 -0
  49. data/lib/install/svelte.rb +29 -0
  50. data/lib/install/template.rb +12 -4
  51. data/lib/install/typescript.rb +6 -13
  52. data/lib/install/vue.rb +1 -1
  53. data/lib/tasks/installers.rake +1 -0
  54. data/lib/tasks/webpacker/check_node.rake +15 -8
  55. data/lib/tasks/webpacker/check_yarn.rake +16 -10
  56. data/lib/tasks/webpacker/clean.rake +25 -0
  57. data/lib/tasks/webpacker/clobber.rake +8 -4
  58. data/lib/tasks/webpacker/compile.rake +10 -15
  59. data/lib/tasks/webpacker/yarn_install.rake +11 -1
  60. data/lib/tasks/webpacker.rake +2 -0
  61. data/lib/webpacker/commands.rb +53 -1
  62. data/lib/webpacker/compiler.rb +24 -9
  63. data/lib/webpacker/configuration.rb +36 -13
  64. data/lib/webpacker/dev_server.rb +1 -1
  65. data/lib/webpacker/dev_server_proxy.rb +5 -9
  66. data/lib/webpacker/dev_server_runner.rb +10 -4
  67. data/lib/webpacker/env.rb +6 -2
  68. data/lib/webpacker/helper.rb +71 -26
  69. data/lib/webpacker/manifest.rb +4 -4
  70. data/lib/webpacker/railtie.rb +6 -43
  71. data/lib/webpacker/runner.rb +1 -0
  72. data/lib/webpacker/version.rb +1 -1
  73. data/lib/webpacker/webpack_runner.rb +6 -0
  74. data/lib/webpacker.rb +9 -1
  75. data/package/__tests__/config.js +12 -24
  76. data/package/__tests__/dev_server.js +2 -0
  77. data/package/__tests__/development.js +14 -1
  78. data/package/config.js +6 -11
  79. data/package/configPath.js +3 -0
  80. data/package/config_types/config_list.js +3 -3
  81. data/package/config_types/config_object.js +1 -1
  82. data/package/dev_server.js +1 -1
  83. data/package/env.js +1 -2
  84. data/package/environments/__tests__/base.js +30 -3
  85. data/package/environments/base.js +20 -10
  86. data/package/environments/development.js +39 -37
  87. data/package/environments/production.js +12 -2
  88. data/package/rules/babel.js +12 -5
  89. data/package/rules/file.js +3 -2
  90. data/package/rules/node_modules.js +3 -4
  91. data/package/rules/sass.js +11 -2
  92. data/package/utils/__tests__/get_style_rule.js +9 -0
  93. data/package/utils/deep_merge.js +5 -5
  94. data/package/utils/get_style_rule.js +7 -12
  95. data/package/utils/helpers.js +10 -10
  96. data/package.json +43 -42
  97. data/test/command_test.rb +6 -0
  98. data/test/compiler_test.rb +10 -6
  99. data/test/configuration_test.rb +40 -30
  100. data/test/dev_server_runner_test.rb +1 -1
  101. data/test/dev_server_test.rb +22 -0
  102. data/test/helper_test.rb +58 -9
  103. data/test/manifest_test.rb +37 -6
  104. data/test/rake_tasks_test.rb +17 -0
  105. data/test/test_app/app/javascript/packs/multi_entry.css +4 -0
  106. data/test/test_app/app/javascript/packs/multi_entry.js +4 -0
  107. data/test/test_app/bin/webpack +0 -1
  108. data/test/test_app/bin/webpack-dev-server +0 -1
  109. data/test/test_app/config/application.rb +0 -1
  110. data/test/test_app/config/webpacker.yml +8 -1
  111. data/test/test_app/public/packs/manifest.json +4 -0
  112. data/test/webpack_runner_test.rb +1 -1
  113. data/webpacker.gemspec +7 -4
  114. data/yarn.lock +4552 -4077
  115. metadata +73 -19
  116. data/gemfiles/Gemfile-rails.4.2.x +0 -10
  117. data/gemfiles/Gemfile-rails.5.0.x +0 -10
  118. data/gemfiles/Gemfile-rails.5.1.x +0 -10
  119. data/lib/install/loaders/typescript.js +0 -11
@@ -0,0 +1,3 @@
1
+ const { resolve } = require('path')
2
+
3
+ module.exports = process.env.WEBPACKER_CONFIG || resolve('config', 'webpacker.yml')
@@ -38,7 +38,7 @@ class ConfigList extends Array {
38
38
  }
39
39
 
40
40
  getIndex(key, shouldThrow = false) {
41
- const index = this.findIndex(entry => (
41
+ const index = this.findIndex((entry) => (
42
42
  entry === key
43
43
  || entry.key === key
44
44
  || (entry.constructor && entry.constructor.name === key)
@@ -64,11 +64,11 @@ class ConfigList extends Array {
64
64
  }
65
65
 
66
66
  values() {
67
- return this.map(item => item.value)
67
+ return this.map((item) => item.value)
68
68
  }
69
69
 
70
70
  keys() {
71
- return this.map(item => item.key)
71
+ return this.map((item) => item.key)
72
72
  }
73
73
  }
74
74
 
@@ -42,7 +42,7 @@ class ConfigObject extends Object {
42
42
  toObject() {
43
43
  const object = {}
44
44
  /* eslint no-return-assign: 0 */
45
- Object.keys(this).forEach(key => (object[key] = this[key]))
45
+ Object.keys(this).forEach((key) => (object[key] = this[key]))
46
46
  return object
47
47
  }
48
48
 
@@ -12,7 +12,7 @@ if (devServerConfig) {
12
12
  const envPrefix = config.dev_server.env_prefix || 'WEBPACKER_DEV_SERVER'
13
13
 
14
14
  Object.keys(devServerConfig).forEach((key) => {
15
- const envValue = fetch(`${envPrefix}_${key.toUpperCase().replace(/_/g, '')}`)
15
+ const envValue = fetch(`${envPrefix}_${key.toUpperCase()}`)
16
16
  if (envValue !== undefined) devServerConfig[key] = envValue
17
17
  })
18
18
  }
data/package/env.js CHANGED
@@ -1,10 +1,9 @@
1
- const { resolve } = require('path')
2
1
  const { safeLoad } = require('js-yaml')
3
2
  const { readFileSync } = require('fs')
4
3
 
5
4
  const NODE_ENVIRONMENTS = ['development', 'production', 'test']
6
5
  const DEFAULT = 'production'
7
- const configPath = resolve('config', 'webpacker.yml')
6
+ const configPath = require('./configPath')
8
7
 
9
8
  const railsEnv = process.env.RAILS_ENV
10
9
  const nodeEnv = process.env.NODE_ENV
@@ -29,10 +29,20 @@ describe('Environment', () => {
29
29
  )
30
30
  })
31
31
 
32
+ test('should return multi file entry points', () => {
33
+ const config = environment.toWebpackConfig()
34
+ expect(config.entry.multi_entry.sort()).toEqual([
35
+ resolve('app', 'javascript', 'packs', 'multi_entry.css'),
36
+ resolve('app', 'javascript', 'packs', 'multi_entry.js')
37
+ ])
38
+ })
39
+
32
40
  test('should return output', () => {
33
41
  const config = environment.toWebpackConfig()
34
- expect(config.output.filename).toEqual('js/[name]-[chunkhash].js')
35
- expect(config.output.chunkFilename).toEqual('js/[name]-[chunkhash].chunk.js')
42
+ expect(config.output.filename).toEqual('js/[name]-[contenthash].js')
43
+ expect(config.output.chunkFilename).toEqual(
44
+ 'js/[name]-[contenthash].chunk.js'
45
+ )
36
46
  })
37
47
 
38
48
  test('should return default loader rules for each file in config/loaders', () => {
@@ -41,7 +51,23 @@ describe('Environment', () => {
41
51
  const configRules = config.module.rules
42
52
 
43
53
  expect(defaultRules.length).toEqual(7)
44
- expect(configRules.length).toEqual(8)
54
+ expect(configRules.length).toEqual(7)
55
+ })
56
+
57
+ test('should return cache path for nodeModules rule', () => {
58
+ const nodeModulesLoader = rules.nodeModules.use.find(
59
+ (rule) => rule.loader === 'babel-loader'
60
+ )
61
+
62
+ expect(nodeModulesLoader.options.cacheDirectory).toBeTruthy()
63
+ })
64
+
65
+ test('should return cache path for babel-loader rule', () => {
66
+ const babelLoader = rules.babel.use.find(
67
+ (rule) => rule.loader === 'babel-loader'
68
+ )
69
+
70
+ expect(babelLoader.options.cacheDirectory).toBeTruthy()
45
71
  })
46
72
 
47
73
  test('should return default plugins', () => {
@@ -60,6 +86,7 @@ describe('Environment', () => {
60
86
  resolve('app', 'javascript'),
61
87
  resolve('app/assets'),
62
88
  resolve('/etc/yarn'),
89
+ resolve('app/elm'),
63
90
  'node_modules'
64
91
  ])
65
92
  })
@@ -22,7 +22,7 @@ const config = require('../config')
22
22
 
23
23
  const getLoaderList = () => {
24
24
  const result = new ConfigList()
25
- Object.keys(rules).forEach(key => result.append(key, rules[key]))
25
+ Object.keys(rules).forEach((key) => result.append(key, rules[key]))
26
26
  return result
27
27
  }
28
28
 
@@ -30,7 +30,7 @@ const getPluginList = () => {
30
30
  const result = new ConfigList()
31
31
  result.append(
32
32
  'Environment',
33
- new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(process.env)))
33
+ new webpack.EnvironmentPlugin(process.env)
34
34
  )
35
35
  result.append('CaseSensitivePaths', new CaseSensitivePathsPlugin())
36
36
  result.append(
@@ -43,7 +43,6 @@ const getPluginList = () => {
43
43
  result.append(
44
44
  'Manifest',
45
45
  new WebpackAssetsManifest({
46
- integrity: false,
47
46
  entrypoints: true,
48
47
  writeToDisk: true,
49
48
  publicPath: config.publicPathWithoutCDN
@@ -65,7 +64,18 @@ const getEntryObject = () => {
65
64
  paths.forEach((path) => {
66
65
  const namespace = relative(join(rootPath), dirname(path))
67
66
  const name = join(namespace, basename(path, extname(path)))
68
- result.set(name, resolve(path))
67
+ let assetPaths = resolve(path)
68
+
69
+ // Allows for multiple filetypes per entry (https://webpack.js.org/guides/entry-advanced/)
70
+ // Transforms the config object value to an array with all values under the same name
71
+ let previousPaths = result.get(name)
72
+ if (previousPaths) {
73
+ previousPaths = Array.isArray(previousPaths) ? previousPaths : [previousPaths]
74
+ previousPaths.push(assetPaths)
75
+ assetPaths = previousPaths
76
+ }
77
+
78
+ result.set(name, assetPaths)
69
79
  })
70
80
  return result
71
81
  }
@@ -73,8 +83,8 @@ const getEntryObject = () => {
73
83
  const getModulePaths = () => {
74
84
  const result = new ConfigList()
75
85
  result.append('source', resolve(config.source_path))
76
- if (config.resolved_paths) {
77
- config.resolved_paths.forEach(path => result.append(path, resolve(path)))
86
+ if (config.additional_paths) {
87
+ config.additional_paths.forEach((path) => result.append(path, resolve(path)))
78
88
  }
79
89
  result.append('node_modules', 'node_modules')
80
90
  return result
@@ -83,8 +93,8 @@ const getModulePaths = () => {
83
93
  const getBaseConfig = () => new ConfigObject({
84
94
  mode: 'production',
85
95
  output: {
86
- filename: 'js/[name]-[chunkhash].js',
87
- chunkFilename: 'js/[name]-[chunkhash].chunk.js',
96
+ filename: 'js/[name]-[contenthash].js',
97
+ chunkFilename: 'js/[name]-[contenthash].chunk.js',
88
98
  hotUpdateChunkFilename: 'js/[id]-[hash].hot-update.js',
89
99
  path: config.outputPath,
90
100
  publicPath: config.publicPath
@@ -126,7 +136,7 @@ module.exports = class Base {
126
136
  // https://twitter.com/wSokra/status/969633336732905474
127
137
  splitChunks: {
128
138
  chunks: 'all',
129
- name: false
139
+ name: true
130
140
  },
131
141
  // Separate runtime chunk to enable long term caching
132
142
  // https://twitter.com/wSokra/status/969679223278505985
@@ -153,7 +163,7 @@ module.exports = class Base {
153
163
 
154
164
  module: {
155
165
  strictExportPresence: true,
156
- rules: [{ parser: { requireEnsure: false } }, ...this.loaders.values()]
166
+ rules: this.loaders.values()
157
167
  },
158
168
 
159
169
  plugins: this.plugins.values(),
@@ -7,45 +7,47 @@ module.exports = class extends Base {
7
7
  constructor() {
8
8
  super()
9
9
 
10
- if (devServer.hmr) {
11
- this.plugins.append('HotModuleReplacement', new webpack.HotModuleReplacementPlugin())
12
- this.config.output.filename = '[name]-[hash].js'
13
- }
14
-
15
10
  this.config.merge({
16
11
  mode: 'development',
17
- cache: true,
18
- devtool: 'cheap-module-source-map',
19
- output: {
20
- pathinfo: true
21
- },
22
- devServer: {
23
- clientLogLevel: 'none',
24
- compress: devServer.compress,
25
- quiet: devServer.quiet,
26
- disableHostCheck: devServer.disable_host_check,
27
- host: devServer.host,
28
- port: devServer.port,
29
- https: devServer.https,
30
- hot: devServer.hmr,
31
- contentBase,
32
- inline: devServer.inline,
33
- useLocalIp: devServer.use_local_ip,
34
- public: devServer.public,
35
- publicPath,
36
- historyApiFallback: {
37
- disableDotRule: true
38
- },
39
- headers: devServer.headers,
40
- overlay: devServer.overlay,
41
- stats: {
42
- entrypoints: false,
43
- errorDetails: false,
44
- modules: false,
45
- moduleTrace: false
46
- },
47
- watchOptions: devServer.watch_options
48
- }
12
+ devtool: 'cheap-module-source-map'
49
13
  })
14
+
15
+ if (process.env.WEBPACK_DEV_SERVER
16
+ && process.env.WEBPACK_DEV_SERVER !== 'undefined') {
17
+ if (devServer.hmr) {
18
+ this.plugins.append('HotModuleReplacement', new webpack.HotModuleReplacementPlugin())
19
+ this.config.output.filename = '[name]-[hash].js'
20
+ }
21
+
22
+ this.config.merge({
23
+ devServer: {
24
+ clientLogLevel: 'none',
25
+ compress: devServer.compress,
26
+ quiet: devServer.quiet,
27
+ disableHostCheck: devServer.disable_host_check,
28
+ host: devServer.host,
29
+ port: devServer.port,
30
+ https: devServer.https,
31
+ hot: devServer.hmr,
32
+ contentBase,
33
+ inline: devServer.inline,
34
+ useLocalIp: devServer.use_local_ip,
35
+ public: devServer.public,
36
+ publicPath,
37
+ historyApiFallback: {
38
+ disableDotRule: true
39
+ },
40
+ headers: devServer.headers,
41
+ overlay: devServer.overlay,
42
+ stats: {
43
+ entrypoints: false,
44
+ errorDetails: true,
45
+ modules: false,
46
+ moduleTrace: false
47
+ },
48
+ watchOptions: devServer.watch_options
49
+ }
50
+ })
51
+ }
50
52
  }
51
53
  }
@@ -13,11 +13,21 @@ module.exports = class extends Base {
13
13
  new CompressionPlugin({
14
14
  filename: '[path].gz[query]',
15
15
  algorithm: 'gzip',
16
- cache: true,
17
16
  test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/
18
17
  })
19
18
  )
20
19
 
20
+ if ('brotli' in process.versions) {
21
+ this.plugins.append(
22
+ 'Compression Brotli',
23
+ new CompressionPlugin({
24
+ filename: '[path].br[query]',
25
+ algorithm: 'brotliCompress',
26
+ test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/
27
+ })
28
+ )
29
+ }
30
+
21
31
  this.plugins.append(
22
32
  'OptimizeCSSAssets',
23
33
  new OptimizeCSSAssetsPlugin({
@@ -36,7 +46,7 @@ module.exports = class extends Base {
36
46
  optimization: {
37
47
  minimizer: [
38
48
  new TerserPlugin({
39
- parallel: true,
49
+ parallel: Number.parseInt(process.env.WEBPACKER_PARALLEL, 10) || true,
40
50
  cache: true,
41
51
  sourceMap: true,
42
52
  terserOptions: {
@@ -1,18 +1,25 @@
1
- const { join, resolve } = require('path')
2
- const { cache_path: cachePath, source_path: sourcePath, resolved_paths: resolvedPaths } = require('../config')
1
+ const { resolve } = require('path')
2
+ const { realpathSync } = require('fs')
3
+ const { source_path: sourcePath, additional_paths: additionalPaths } = require('../config')
3
4
  const { nodeEnv } = require('../env')
4
5
 
5
6
  // Process application Javascript code with Babel.
6
7
  // Uses application .babelrc to apply any transformations
7
8
  module.exports = {
8
- test: /\.(js|jsx|mjs)?(\.erb)?$/,
9
- include: [sourcePath, ...resolvedPaths].map(p => resolve(p)),
9
+ test: /\.(js|jsx|mjs|ts|tsx)?(\.erb)?$/,
10
+ include: [sourcePath, ...additionalPaths].map((p) => {
11
+ try {
12
+ return realpathSync(p)
13
+ } catch (e) {
14
+ return resolve(p)
15
+ }
16
+ }),
10
17
  exclude: /node_modules/,
11
18
  use: [
12
19
  {
13
20
  loader: 'babel-loader',
14
21
  options: {
15
- cacheDirectory: join(cachePath, 'babel-loader-node-modules'),
22
+ cacheDirectory: true,
16
23
  cacheCompression: nodeEnv === 'production',
17
24
  compact: nodeEnv === 'production'
18
25
  }
@@ -1,4 +1,4 @@
1
- const { join } = require('path')
1
+ const { join, normalize } = require('path')
2
2
  const { source_path: sourcePath, static_assets_extensions: fileExtensions } = require('../config')
3
3
 
4
4
  module.exports = {
@@ -8,11 +8,12 @@ module.exports = {
8
8
  loader: 'file-loader',
9
9
  options: {
10
10
  name(file) {
11
- if (file.includes(sourcePath)) {
11
+ if (file.includes(normalize(sourcePath))) {
12
12
  return 'media/[path][name]-[hash].[ext]'
13
13
  }
14
14
  return 'media/[folder]/[name]-[hash:8].[ext]'
15
15
  },
16
+ esModule: false,
16
17
  context: join(sourcePath)
17
18
  }
18
19
  }
@@ -1,19 +1,18 @@
1
- const { join } = require('path')
2
- const { cache_path: cachePath } = require('../config')
3
1
  const { nodeEnv } = require('../env')
4
2
 
5
3
  // Compile standard ES features for JS in node_modules with Babel.
4
+ // Regex details for exclude: https://regex101.com/r/SKPnnv/1
6
5
  module.exports = {
7
6
  test: /\.(js|mjs)$/,
8
7
  include: /node_modules/,
9
- exclude: /@babel(?:\/|\\{1,2})runtime/,
8
+ exclude: /(?:@?babel(?:\/|\\{1,2}|-).+)|regenerator-runtime|core-js|^webpack$|^webpack-assets-manifest$|^webpack-cli$|^webpack-sources$|^@rails\/webpacker$/,
10
9
  use: [
11
10
  {
12
11
  loader: 'babel-loader',
13
12
  options: {
14
13
  babelrc: false,
15
14
  presets: [['@babel/preset-env', { modules: false }]],
16
- cacheDirectory: join(cachePath, 'babel-loader-node-modules'),
15
+ cacheDirectory: true,
17
16
  cacheCompression: nodeEnv === 'production',
18
17
  compact: false,
19
18
  sourceMaps: false
@@ -1,8 +1,17 @@
1
+ /* eslint global-require: 0 */
2
+
1
3
  const getStyleRule = require('../utils/get_style_rule')
4
+ const { additional_paths: includePaths } = require('../config')
2
5
 
3
- module.exports = getStyleRule(/\.(scss|sass)$/i, false, [
6
+ module.exports = getStyleRule(/\.(scss|sass)(\.erb)?$/i, false, [
4
7
  {
5
8
  loader: 'sass-loader',
6
- options: { sourceMap: true }
9
+ options: {
10
+ sourceMap: true,
11
+ implementation: require('sass'),
12
+ sassOptions: {
13
+ includePaths
14
+ }
15
+ }
7
16
  }
8
17
  ])
@@ -44,6 +44,15 @@ describe('getStyleRule', () => {
44
44
  expect(cssRule.use).toMatchObject(expect.arrayContaining(expectation))
45
45
  })
46
46
 
47
+ test('adds style-loader when extract_css is true', () => {
48
+ const expectation = [{loader: 'style-loader'}]
49
+
50
+ require('../../config').extract_css = false
51
+ const cssRule = getStyleRule(/\.(css)$/i)
52
+
53
+ expect(cssRule.use).toMatchObject(expect.objectContaining(expectation))
54
+ })
55
+
47
56
  test(`doesn't add mini-css-extract-plugin when extract_css is false`, () => {
48
57
  const MiniCssExtractPlugin = require('mini-css-extract-plugin')
49
58
  const expectation = [MiniCssExtractPlugin.loader]
@@ -10,11 +10,11 @@ const deepMerge = (target, source) => {
10
10
  if (!(isObject(target) && isObject(source))) return source
11
11
 
12
12
  return [...Object.keys(target), ...Object.keys(source)].reduce(
13
- (result, key) => (Object.assign(
14
- {},
15
- result,
16
- { [key]: deepMerge(target[key], source[key]) }
17
- )),
13
+ (result, key) => ({
14
+
15
+ ...result,
16
+ [key]: deepMerge(target[key], source[key])
17
+ }),
18
18
  {}
19
19
  )
20
20
  }
@@ -1,17 +1,9 @@
1
1
  const MiniCssExtractPlugin = require('mini-css-extract-plugin')
2
2
  const { resolve } = require('path')
3
- const devServer = require('../dev_server')
4
3
  const config = require('../config')
5
4
 
6
- const inDevServer = process.argv.find(v => v.includes('webpack-dev-server'))
7
- const isHMR = inDevServer && (devServer && devServer.hmr)
8
-
9
5
  const styleLoader = {
10
- loader: 'style-loader',
11
- options: {
12
- hmr: isHMR,
13
- sourceMap: true
14
- }
6
+ loader: 'style-loader'
15
7
  }
16
8
 
17
9
  const getStyleRule = (test, modules = false, preprocessors = []) => {
@@ -21,8 +13,9 @@ const getStyleRule = (test, modules = false, preprocessors = []) => {
21
13
  options: {
22
14
  sourceMap: true,
23
15
  importLoaders: 2,
24
- localIdentName: '[name]__[local]___[hash:base64:5]',
25
- modules
16
+ modules: modules ? {
17
+ localIdentName: '[name]__[local]___[hash:base64:5]'
18
+ } : false
26
19
  }
27
20
  },
28
21
  {
@@ -44,7 +37,9 @@ const getStyleRule = (test, modules = false, preprocessors = []) => {
44
37
  }
45
38
 
46
39
  // sideEffects - See https://github.com/webpack/webpack/issues/6571
47
- return Object.assign({}, { test, use, sideEffects: !modules }, options)
40
+ return {
41
+ test, use, sideEffects: !modules, ...options
42
+ }
48
43
  }
49
44
 
50
45
  module.exports = getStyleRule
@@ -1,29 +1,29 @@
1
- const { stringify } = require('flatted/cjs')
1
+ const { stringify } = require('flatted')
2
2
 
3
- const isObject = value => typeof value === 'object'
3
+ const isObject = (value) => typeof value === 'object'
4
4
  && value !== null
5
5
  && (value.length === undefined || value.length === null)
6
6
 
7
- const isNotObject = value => !isObject(value)
7
+ const isNotObject = (value) => !isObject(value)
8
8
 
9
- const isBoolean = str => /^true/.test(str) || /^false/.test(str)
9
+ const isBoolean = (str) => /^true/.test(str) || /^false/.test(str)
10
10
 
11
- const isEmpty = value => value === null || value === undefined
11
+ const isEmpty = (value) => value === null || value === undefined
12
12
 
13
- const isString = key => key && typeof key === 'string'
13
+ const isString = (key) => key && typeof key === 'string'
14
14
 
15
15
  const isStrPath = (key) => {
16
16
  if (!isString(key)) throw new Error(`Key ${key} should be string`)
17
17
  return isString(key) && key.includes('.')
18
18
  }
19
19
 
20
- const isArray = value => Array.isArray(value)
20
+ const isArray = (value) => Array.isArray(value)
21
21
 
22
22
  const isEqual = (target, source) => stringify(target) === stringify(source)
23
23
 
24
- const canMerge = value => isObject(value) || isArray(value)
24
+ const canMerge = (value) => isObject(value) || isArray(value)
25
25
 
26
- const prettyPrint = obj => JSON.stringify(obj, null, 2)
26
+ const prettyPrint = (obj) => JSON.stringify(obj, null, 2)
27
27
 
28
28
  const chdirTestApp = () => {
29
29
  try {
@@ -39,7 +39,7 @@ const resetEnv = () => {
39
39
  process.env = {}
40
40
  }
41
41
 
42
- const ensureTrailingSlash = path => (path.endsWith('/') ? path : `${path}/`)
42
+ const ensureTrailingSlash = (path) => (path.endsWith('/') ? path : `${path}/`)
43
43
 
44
44
  module.exports = {
45
45
  chdirTestApp,
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rails/webpacker",
3
- "version": "4.0.2",
3
+ "version": "5.4.3",
4
4
  "description": "Use webpack to manage app-like JavaScript modules in Rails",
5
5
  "main": "package/index.js",
6
6
  "files": [
@@ -8,55 +8,56 @@
8
8
  "lib/install/config/webpacker.yml"
9
9
  ],
10
10
  "engines": {
11
- "node": ">=6.14.4",
12
- "yarn": ">=1.0.0"
11
+ "node": ">=10.17.0",
12
+ "yarn": ">=1 <4"
13
13
  },
14
14
  "dependencies": {
15
- "@babel/core": "^7.3.4",
16
- "@babel/plugin-proposal-class-properties": "^7.3.4",
17
- "@babel/plugin-proposal-object-rest-spread": "^7.3.4",
18
- "@babel/plugin-syntax-dynamic-import": "^7.2.0",
19
- "@babel/plugin-transform-destructuring": "^7.3.2",
20
- "@babel/plugin-transform-regenerator": "^7.3.4",
21
- "@babel/plugin-transform-runtime": "^7.3.4",
22
- "@babel/polyfill": "^7.2.5",
23
- "@babel/preset-env": "^7.3.4",
24
- "@babel/runtime": "^7.3.4",
25
- "babel-loader": "^8.0.5",
26
- "babel-plugin-dynamic-import-node": "^2.2.0",
27
- "babel-plugin-macros": "^2.5.0",
28
- "case-sensitive-paths-webpack-plugin": "^2.2.0",
29
- "compression-webpack-plugin": "^2.0.0",
30
- "css-loader": "^2.1.0",
31
- "file-loader": "^3.0.1",
32
- "flatted": "^2.0.0",
33
- "glob": "^7.1.3",
34
- "js-yaml": "^3.12.2",
35
- "mini-css-extract-plugin": "^0.5.0",
36
- "node-sass": "^4.11.0",
37
- "optimize-css-assets-webpack-plugin": "^5.0.1",
15
+ "@babel/core": "^7.15.0",
16
+ "@babel/plugin-proposal-class-properties": "^7.14.5",
17
+ "@babel/plugin-proposal-object-rest-spread": "^7.14.7",
18
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
19
+ "@babel/plugin-transform-destructuring": "^7.14.7",
20
+ "@babel/plugin-transform-regenerator": "^7.14.5",
21
+ "@babel/plugin-transform-runtime": "^7.15.0",
22
+ "@babel/preset-env": "^7.15.0",
23
+ "@babel/runtime": "^7.15.3",
24
+ "babel-loader": "^8.2.2",
25
+ "babel-plugin-dynamic-import-node": "^2.3.3",
26
+ "babel-plugin-macros": "^2.8.0",
27
+ "case-sensitive-paths-webpack-plugin": "^2.4.0",
28
+ "compression-webpack-plugin": "^4.0.1",
29
+ "core-js": "^3.16.2",
30
+ "css-loader": "^3.6.0",
31
+ "file-loader": "^6.2.0",
32
+ "flatted": "^3.2.2",
33
+ "glob": "^7.1.7",
34
+ "js-yaml": "^3.14.1",
35
+ "mini-css-extract-plugin": "^0.9.0",
36
+ "optimize-css-assets-webpack-plugin": "^5.0.8",
38
37
  "path-complete-extname": "^1.0.0",
39
- "pnp-webpack-plugin": "^1.3.1",
40
- "postcss-flexbugs-fixes": "^4.1.0",
38
+ "pnp-webpack-plugin": "^1.7.0",
39
+ "postcss-flexbugs-fixes": "^4.2.1",
41
40
  "postcss-import": "^12.0.1",
42
41
  "postcss-loader": "^3.0.0",
43
- "postcss-preset-env": "^6.6.0",
44
- "postcss-safe-parser": "^4.0.1",
45
- "sass-loader": "^7.1.0",
46
- "style-loader": "^0.23.1",
47
- "terser-webpack-plugin": "^1.2.3",
48
- "webpack": "^4.29.6",
42
+ "postcss-preset-env": "^6.7.0",
43
+ "postcss-safe-parser": "^4.0.2",
44
+ "regenerator-runtime": "^0.13.9",
45
+ "sass": "^1.38.0",
46
+ "sass-loader": "10.1.1",
47
+ "style-loader": "^1.3.0",
48
+ "terser-webpack-plugin": "^4.2.3",
49
+ "webpack": "^4.46.0",
49
50
  "webpack-assets-manifest": "^3.1.1",
50
- "webpack-cli": "^3.2.3",
51
- "webpack-sources": "^1.3.0"
51
+ "webpack-cli": "^3.3.12",
52
+ "webpack-sources": "^1.4.3"
52
53
  },
53
54
  "devDependencies": {
54
- "eslint": "^5.15.0",
55
- "eslint-config-airbnb": "^17.1.0",
56
- "eslint-plugin-import": "^2.16.0",
57
- "eslint-plugin-jsx-a11y": "^6.2.1",
58
- "eslint-plugin-react": "^7.12.4",
59
- "jest": "^24.1.0"
55
+ "eslint": "^7.32.0",
56
+ "eslint-config-airbnb": "^18.2.1",
57
+ "eslint-plugin-import": "^2.24.0",
58
+ "eslint-plugin-jsx-a11y": "^6.4.1",
59
+ "eslint-plugin-react": "^7.24.0",
60
+ "jest": "^27.0.6"
60
61
  },
61
62
  "jest": {
62
63
  "testRegex": "(/__tests__/.*|(\\.|/))\\.jsx?$",
data/test/command_test.rb CHANGED
@@ -24,4 +24,10 @@ class CommandTest < Minitest::Test
24
24
  end
25
25
  end
26
26
  end
27
+
28
+ def test_clean_command_works_with_nested_hashes_and_without_any_compiled_files
29
+ File.stub :delete, true do
30
+ assert Webpacker.commands.clean
31
+ end
32
+ end
27
33
  end