webpacker 5.4.4 → 6.0.0.rc.6

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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.js +1 -1
  3. data/.github/workflows/jest.yml +7 -15
  4. data/.github/workflows/js-lint.yml +7 -15
  5. data/.github/workflows/rubocop.yml +1 -1
  6. data/.github/workflows/ruby.yml +18 -16
  7. data/.gitignore +2 -0
  8. data/.node-version +1 -1
  9. data/.rubocop.yml +5 -7
  10. data/CHANGELOG.md +30 -12
  11. data/CONTRIBUTING.md +20 -1
  12. data/Gemfile.lock +83 -83
  13. data/README.md +389 -179
  14. data/config/README.md +3 -0
  15. data/config/webpacker.yml +1 -0
  16. data/docs/deployment.md +9 -11
  17. data/docs/developing_webpacker.md +29 -0
  18. data/docs/troubleshooting.md +61 -25
  19. data/docs/v6_upgrade.md +113 -0
  20. data/gemfiles/Gemfile-rails.6.1.x +12 -0
  21. data/lib/install/{javascript/packs/application.js → application.js} +2 -5
  22. data/lib/install/bin/webpack +4 -7
  23. data/lib/install/bin/yarn +18 -0
  24. data/lib/install/config/webpack/base.js +3 -0
  25. data/lib/install/config/webpack/development.js +2 -2
  26. data/lib/install/config/webpack/production.js +2 -2
  27. data/lib/install/config/webpack/test.js +2 -2
  28. data/lib/install/config/webpacker.yml +21 -49
  29. data/lib/install/package.json +15 -0
  30. data/lib/install/template.rb +64 -29
  31. data/lib/tasks/webpacker/binstubs.rake +6 -4
  32. data/lib/tasks/webpacker/check_binstubs.rake +4 -4
  33. data/lib/tasks/webpacker/check_node.rake +3 -0
  34. data/lib/tasks/webpacker/check_yarn.rake +3 -0
  35. data/lib/tasks/webpacker/clobber.rake +1 -1
  36. data/lib/tasks/webpacker/compile.rake +4 -2
  37. data/lib/tasks/webpacker/info.rake +12 -10
  38. data/lib/tasks/webpacker/install.rake +6 -4
  39. data/lib/tasks/webpacker/verify_config.rake +14 -0
  40. data/lib/tasks/webpacker/verify_install.rake +1 -10
  41. data/lib/tasks/webpacker/yarn_install.rake +9 -7
  42. data/lib/tasks/webpacker.rake +2 -11
  43. data/lib/tasks/yarn.rake +38 -0
  44. data/lib/webpacker/commands.rb +21 -16
  45. data/lib/webpacker/compiler.rb +16 -9
  46. data/lib/webpacker/configuration.rb +8 -32
  47. data/lib/webpacker/dev_server.rb +6 -0
  48. data/lib/webpacker/dev_server_runner.rb +28 -4
  49. data/lib/webpacker/helper.rb +47 -81
  50. data/lib/webpacker/instance.rb +4 -0
  51. data/lib/webpacker/manifest.rb +2 -3
  52. data/lib/webpacker/railtie.rb +8 -2
  53. data/lib/webpacker/runner.rb +1 -1
  54. data/lib/webpacker/version.rb +1 -1
  55. data/lib/webpacker/webpack_runner.rb +29 -3
  56. data/lib/webpacker.rb +1 -1
  57. data/package/__tests__/config.js +5 -37
  58. data/package/__tests__/development.js +13 -21
  59. data/package/__tests__/env.js +16 -4
  60. data/package/__tests__/index.js +9 -0
  61. data/package/__tests__/production.js +6 -6
  62. data/package/__tests__/staging.js +7 -6
  63. data/package/__tests__/test.js +4 -5
  64. data/package/babel/preset.js +54 -0
  65. data/package/config.js +6 -14
  66. data/package/env.js +13 -4
  67. data/package/environments/__tests__/base.js +20 -52
  68. data/package/environments/base.js +68 -128
  69. data/package/environments/development.js +49 -47
  70. data/package/environments/production.js +66 -64
  71. data/package/environments/test.js +2 -2
  72. data/package/index.js +15 -8
  73. data/package/inliningCss.js +7 -0
  74. data/package/rules/babel.js +10 -8
  75. data/package/rules/coffee.js +6 -0
  76. data/package/rules/erb.js +15 -0
  77. data/package/rules/file.js +21 -19
  78. data/package/rules/index.js +16 -18
  79. data/package/rules/less.js +22 -0
  80. data/package/rules/raw.js +5 -0
  81. data/package/rules/sass.js +9 -10
  82. data/package/rules/stylus.js +26 -0
  83. data/package/utils/get_style_rule.js +28 -36
  84. data/package/utils/helpers.js +28 -35
  85. data/package.json +18 -38
  86. data/test/command_test.rb +76 -0
  87. data/test/compiler_test.rb +0 -12
  88. data/test/configuration_test.rb +4 -35
  89. data/test/dev_server_runner_test.rb +36 -6
  90. data/test/engine_rake_tasks_test.rb +39 -0
  91. data/test/helper_test.rb +79 -77
  92. data/test/manifest_test.rb +16 -0
  93. data/test/mounted_app/Rakefile +4 -0
  94. data/test/mounted_app/test/dummy/Rakefile +3 -0
  95. data/test/mounted_app/test/dummy/bin/rails +3 -0
  96. data/test/mounted_app/test/dummy/bin/rake +3 -0
  97. data/test/mounted_app/test/dummy/config/application.rb +10 -0
  98. data/test/mounted_app/test/dummy/config/environment.rb +3 -0
  99. data/test/mounted_app/test/dummy/config/webpacker.yml +75 -0
  100. data/test/mounted_app/test/dummy/config.ru +5 -0
  101. data/test/mounted_app/test/dummy/package.json +7 -0
  102. data/test/rake_tasks_test.rb +1 -10
  103. data/test/test_app/app/{javascript/packs → packs/entrypoints}/application.js +1 -1
  104. data/test/test_app/config/initializers/inspect_autoload_paths.rb +1 -0
  105. data/test/test_app/config/webpacker.yml +5 -31
  106. data/test/test_app/config/webpacker_other_location.yml +79 -0
  107. data/test/test_app/config/webpacker_public_root.yml +0 -1
  108. data/test/test_app/public/packs/manifest.json +36 -18
  109. data/test/test_app/some.config.js +0 -0
  110. data/test/webpack_runner_test.rb +9 -3
  111. data/test/webpacker_test.rb +21 -0
  112. data/webpacker.gemspec +2 -2
  113. data/yarn.lock +1277 -4620
  114. metadata +63 -92
  115. data/docs/assets.md +0 -119
  116. data/docs/cloud9.md +0 -310
  117. data/docs/css.md +0 -308
  118. data/docs/docker.md +0 -68
  119. data/docs/engines.md +0 -213
  120. data/docs/env.md +0 -63
  121. data/docs/es6.md +0 -72
  122. data/docs/folder-structure.md +0 -66
  123. data/docs/integrations.md +0 -220
  124. data/docs/misc.md +0 -23
  125. data/docs/props.md +0 -223
  126. data/docs/target.md +0 -22
  127. data/docs/testing.md +0 -136
  128. data/docs/typescript.md +0 -190
  129. data/docs/v4-upgrade.md +0 -142
  130. data/docs/webpack-dev-server.md +0 -92
  131. data/docs/webpack.md +0 -364
  132. data/docs/yarn.md +0 -23
  133. data/lib/install/angular.rb +0 -23
  134. data/lib/install/coffee.rb +0 -25
  135. data/lib/install/config/.browserslistrc +0 -1
  136. data/lib/install/config/babel.config.js +0 -82
  137. data/lib/install/config/postcss.config.js +0 -12
  138. data/lib/install/config/webpack/environment.js +0 -3
  139. data/lib/install/elm.rb +0 -39
  140. data/lib/install/erb.rb +0 -25
  141. data/lib/install/examples/angular/hello_angular/app/app.component.ts +0 -9
  142. data/lib/install/examples/angular/hello_angular/app/app.module.ts +0 -16
  143. data/lib/install/examples/angular/hello_angular/index.ts +0 -8
  144. data/lib/install/examples/angular/hello_angular/polyfills.ts +0 -73
  145. data/lib/install/examples/angular/hello_angular.js +0 -7
  146. data/lib/install/examples/coffee/hello_coffee.coffee +0 -4
  147. data/lib/install/examples/elm/Main.elm +0 -55
  148. data/lib/install/examples/elm/hello_elm.js +0 -16
  149. data/lib/install/examples/erb/hello_erb.js.erb +0 -6
  150. data/lib/install/examples/react/babel.config.js +0 -99
  151. data/lib/install/examples/react/hello_react.jsx +0 -26
  152. data/lib/install/examples/react/tsconfig.json +0 -21
  153. data/lib/install/examples/stimulus/application.js +0 -1
  154. data/lib/install/examples/stimulus/controllers/hello_controller.js +0 -18
  155. data/lib/install/examples/stimulus/controllers/index.js +0 -9
  156. data/lib/install/examples/svelte/app.svelte +0 -11
  157. data/lib/install/examples/svelte/hello_svelte.js +0 -20
  158. data/lib/install/examples/typescript/hello_typescript.ts +0 -4
  159. data/lib/install/examples/typescript/tsconfig.json +0 -24
  160. data/lib/install/examples/vue/app.vue +0 -22
  161. data/lib/install/examples/vue/hello_vue.js +0 -72
  162. data/lib/install/loaders/coffee.js +0 -6
  163. data/lib/install/loaders/elm.js +0 -25
  164. data/lib/install/loaders/erb.js +0 -11
  165. data/lib/install/loaders/svelte.js +0 -9
  166. data/lib/install/loaders/vue.js +0 -6
  167. data/lib/install/react.rb +0 -18
  168. data/lib/install/stimulus.rb +0 -12
  169. data/lib/install/svelte.rb +0 -29
  170. data/lib/install/typescript.rb +0 -39
  171. data/lib/install/vue.rb +0 -49
  172. data/lib/tasks/installers.rake +0 -42
  173. data/package/config_types/__tests__/config_list.js +0 -118
  174. data/package/config_types/__tests__/config_object.js +0 -43
  175. data/package/config_types/config_list.js +0 -75
  176. data/package/config_types/config_object.js +0 -55
  177. data/package/config_types/index.js +0 -7
  178. data/package/rules/module.css.js +0 -3
  179. data/package/rules/module.sass.js +0 -8
  180. data/package/rules/node_modules.js +0 -22
  181. data/package/utils/__tests__/deep_assign.js +0 -32
  182. data/package/utils/__tests__/deep_merge.js +0 -10
  183. data/package/utils/__tests__/get_style_rule.js +0 -65
  184. data/package/utils/__tests__/objectify.js +0 -9
  185. data/package/utils/deep_assign.js +0 -22
  186. data/package/utils/deep_merge.js +0 -22
  187. data/package/utils/objectify.js +0 -3
  188. /data/test/test_app/app/{javascript/packs → packs/entrypoints}/multi_entry.css +0 -0
  189. /data/test/test_app/app/{javascript/packs → packs/entrypoints}/multi_entry.js +0 -0
@@ -0,0 +1,54 @@
1
+ const { moduleExists } = require('@rails/webpacker')
2
+
3
+ module.exports = function config(api) {
4
+ const validEnv = ['development', 'test', 'production']
5
+ const currentEnv = api.env()
6
+ const isDevelopmentEnv = api.env('development')
7
+ const isProductionEnv = api.env('production')
8
+ const isTestEnv = api.env('test')
9
+
10
+ if (!validEnv.includes(currentEnv)) {
11
+ throw new Error(
12
+ `Please specify a valid NODE_ENV or BABEL_ENV environment variable. Valid values are "development", "test", and "production". Instead, received: "${JSON.stringify(
13
+ currentEnv
14
+ )}".`
15
+ )
16
+ }
17
+
18
+ return {
19
+ presets: [
20
+ isTestEnv && ['@babel/preset-env', { targets: { node: 'current' } }],
21
+ (isProductionEnv || isDevelopmentEnv) && [
22
+ '@babel/preset-env',
23
+ {
24
+ useBuiltIns: 'entry',
25
+ corejs: '3.8',
26
+ modules: 'auto',
27
+ bugfixes: true,
28
+ loose: true,
29
+ exclude: ['transform-typeof-symbol']
30
+ }
31
+ ],
32
+ moduleExists('@babel/preset-typescript') && [
33
+ '@babel/preset-typescript',
34
+ { allExtensions: true, isTSX: true }
35
+ ],
36
+ moduleExists('@babel/preset-react') && [
37
+ '@babel/preset-react',
38
+ {
39
+ development: isDevelopmentEnv || isTestEnv,
40
+ useBuiltIns: true
41
+ }
42
+ ]
43
+ ].filter(Boolean),
44
+ plugins: [
45
+ ['@babel/plugin-proposal-class-properties', { loose: true }],
46
+ ['@babel/plugin-transform-runtime', { helpers: false }],
47
+ isProductionEnv &&
48
+ moduleExists('babel-plugin-transform-react-remove-prop-types') && [
49
+ 'babel-plugin-transform-react-remove-prop-types',
50
+ { removeImport: true }
51
+ ]
52
+ ].filter(Boolean)
53
+ }
54
+ }
data/package/config.js CHANGED
@@ -1,32 +1,24 @@
1
1
  const { resolve } = require('path')
2
- const { safeLoad } = require('js-yaml')
2
+ const { load } = require('js-yaml')
3
3
  const { readFileSync } = require('fs')
4
- const deepMerge = require('./utils/deep_merge')
5
- const { isArray, ensureTrailingSlash } = require('./utils/helpers')
4
+ const { merge } = require('webpack-merge')
5
+ const { ensureTrailingSlash } = require('./utils/helpers')
6
6
  const { railsEnv } = require('./env')
7
7
  const configPath = require('./configPath')
8
8
 
9
9
  const defaultConfigPath = require.resolve('../lib/install/config/webpacker.yml')
10
10
 
11
11
  const getDefaultConfig = () => {
12
- const defaultConfig = safeLoad(readFileSync(defaultConfigPath), 'utf8')
12
+ const defaultConfig = load(readFileSync(defaultConfigPath), 'utf8')
13
13
  return defaultConfig[railsEnv] || defaultConfig.production
14
14
  }
15
15
 
16
16
  const defaults = getDefaultConfig()
17
- const app = safeLoad(readFileSync(configPath), 'utf8')[railsEnv]
17
+ const app = load(readFileSync(configPath), 'utf8')[railsEnv]
18
18
 
19
- if (isArray(app.extensions) && app.extensions.length) delete defaults.extensions
20
- if (isArray(app.static_assets_extensions) && app.static_assets_extensions.length) {
21
- delete defaults.static_assets_extensions
22
- }
23
-
24
- const config = deepMerge(defaults, app)
19
+ const config = merge(defaults, app)
25
20
  config.outputPath = resolve(config.public_root_path, config.public_output_path)
26
21
 
27
- // Merge resolved_paths into additional_paths for backwards-compat
28
- config.additional_paths = config.additional_paths.concat(config.resolved_paths || [])
29
-
30
22
  // Ensure that the publicPath includes our asset host so dynamic imports
31
23
  // (code-splitting chunks and static assets) load from the CDN instead of a relative path.
32
24
  const getPublicPath = () => {
data/package/env.js CHANGED
@@ -1,4 +1,4 @@
1
- const { safeLoad } = require('js-yaml')
1
+ const { load } = require('js-yaml')
2
2
  const { readFileSync } = require('fs')
3
3
 
4
4
  const NODE_ENVIRONMENTS = ['development', 'production', 'test']
@@ -6,13 +6,22 @@ const DEFAULT = 'production'
6
6
  const configPath = require('./configPath')
7
7
 
8
8
  const railsEnv = process.env.RAILS_ENV
9
- const nodeEnv = process.env.NODE_ENV
9
+ const rawNodeEnv = process.env.NODE_ENV
10
+ const nodeEnv
11
+ = rawNodeEnv && NODE_ENVIRONMENTS.includes(rawNodeEnv) ? rawNodeEnv : DEFAULT
12
+ const isProduction = nodeEnv === 'production'
13
+ const isDevelopment = nodeEnv === 'development'
10
14
 
11
- const config = safeLoad(readFileSync(configPath), 'utf8')
15
+ const config = load(readFileSync(configPath), 'utf8')
12
16
  const availableEnvironments = Object.keys(config).join('|')
13
17
  const regex = new RegExp(`^(${availableEnvironments})$`, 'g')
14
18
 
19
+ const runningWebpackDevServer = process.env.WEBPACK_SERVE === 'true'
20
+
15
21
  module.exports = {
16
22
  railsEnv: railsEnv && railsEnv.match(regex) ? railsEnv : DEFAULT,
17
- nodeEnv: nodeEnv && NODE_ENVIRONMENTS.includes(nodeEnv) ? nodeEnv : DEFAULT
23
+ nodeEnv,
24
+ isProduction,
25
+ isDevelopment,
26
+ runningWebpackDevServer
18
27
  }
@@ -9,93 +9,61 @@ chdirTestApp()
9
9
 
10
10
  const { resolve } = require('path')
11
11
  const rules = require('../../rules')
12
- const { ConfigList } = require('../../config_types')
13
- const Environment = require('../base')
12
+ const baseConfig = require('../base')
14
13
 
15
- describe('Environment', () => {
14
+ describe('Base config', () => {
16
15
  afterAll(chdirCwd)
17
16
 
18
- let environment
19
-
20
- describe('toWebpackConfig', () => {
21
- beforeEach(() => {
22
- environment = new Environment()
23
- })
24
-
17
+ describe('config', () => {
25
18
  test('should return entry', () => {
26
- const config = environment.toWebpackConfig()
27
- expect(config.entry.application).toEqual(
28
- resolve('app', 'javascript', 'packs', 'application.js')
19
+ expect(baseConfig.entry.application).toEqual(
20
+ resolve('app', 'packs', 'entrypoints', 'application.js')
29
21
  )
30
22
  })
31
23
 
32
24
  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')
25
+ expect(baseConfig.entry.multi_entry.sort()).toEqual([
26
+ resolve('app', 'packs', 'entrypoints', 'multi_entry.css'),
27
+ resolve('app', 'packs', 'entrypoints', 'multi_entry.js')
37
28
  ])
38
29
  })
39
30
 
40
31
  test('should return output', () => {
41
- const config = environment.toWebpackConfig()
42
- expect(config.output.filename).toEqual('js/[name]-[contenthash].js')
43
- expect(config.output.chunkFilename).toEqual(
44
- 'js/[name]-[contenthash].chunk.js'
32
+ expect(baseConfig.output.filename).toEqual('js/[name].js')
33
+ expect(baseConfig.output.chunkFilename).toEqual(
34
+ 'js/[name].chunk.js'
45
35
  )
46
36
  })
47
37
 
48
38
  test('should return default loader rules for each file in config/loaders', () => {
49
- const config = environment.toWebpackConfig()
50
39
  const defaultRules = Object.keys(rules)
51
- const configRules = config.module.rules
52
-
53
- expect(defaultRules.length).toEqual(7)
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
- })
40
+ const configRules = baseConfig.module.rules
64
41
 
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()
42
+ expect(defaultRules.length).toEqual(3)
43
+ expect(configRules.length).toEqual(3)
71
44
  })
72
45
 
73
46
  test('should return default plugins', () => {
74
- const config = environment.toWebpackConfig()
75
- expect(config.plugins.length).toEqual(4)
47
+ expect(baseConfig.plugins.length).toEqual(2)
76
48
  })
77
49
 
78
50
  test('should return default resolveLoader', () => {
79
- const config = environment.toWebpackConfig()
80
- expect(config.resolveLoader.modules).toEqual(['node_modules'])
51
+ expect(baseConfig.resolveLoader.modules).toEqual(['node_modules'])
81
52
  })
82
53
 
83
54
  test('should return default resolve.modules with additions', () => {
84
- const config = environment.toWebpackConfig()
85
- expect(config.resolve.modules).toEqual([
86
- resolve('app', 'javascript'),
55
+ expect(baseConfig.resolve.modules).toEqual([
56
+ resolve('app', 'packs'),
87
57
  resolve('app/assets'),
88
58
  resolve('/etc/yarn'),
59
+ resolve('some.config.js'),
89
60
  resolve('app/elm'),
90
61
  'node_modules'
91
62
  ])
92
63
  })
93
64
 
94
65
  test('returns plugins property as Array', () => {
95
- const config = environment.toWebpackConfig()
96
-
97
- expect(config.plugins).toBeInstanceOf(Array)
98
- expect(config.plugins).not.toBeInstanceOf(ConfigList)
66
+ expect(baseConfig.plugins).toBeInstanceOf(Array)
99
67
  })
100
68
  })
101
69
  })
@@ -1,176 +1,116 @@
1
1
  /* eslint global-require: 0 */
2
2
  /* eslint import/no-dynamic-require: 0 */
3
3
 
4
- const {
5
- basename, dirname, join, relative, resolve
6
- } = require('path')
7
- const { sync } = require('glob')
4
+ const { basename, dirname, join, relative, resolve } = require('path')
8
5
  const extname = require('path-complete-extname')
9
-
10
- const webpack = require('webpack')
11
- const MiniCssExtractPlugin = require('mini-css-extract-plugin')
12
- const WebpackAssetsManifest = require('webpack-assets-manifest')
13
- const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
14
6
  const PnpWebpackPlugin = require('pnp-webpack-plugin')
15
-
16
- const { isNotObject, prettyPrint } = require('../utils/helpers')
17
- const deepMerge = require('../utils/deep_merge')
18
-
19
- const { ConfigList, ConfigObject } = require('../config_types')
7
+ const { sync: globSync } = require('glob')
8
+ const WebpackAssetsManifest = require('webpack-assets-manifest')
9
+ const webpack = require('webpack')
20
10
  const rules = require('../rules')
11
+ const { isProduction } = require('../env')
21
12
  const config = require('../config')
22
-
23
- const getLoaderList = () => {
24
- const result = new ConfigList()
25
- Object.keys(rules).forEach((key) => result.append(key, rules[key]))
26
- return result
27
- }
28
-
29
- const getPluginList = () => {
30
- const result = new ConfigList()
31
- result.append(
32
- 'Environment',
33
- new webpack.EnvironmentPlugin(process.env)
34
- )
35
- result.append('CaseSensitivePaths', new CaseSensitivePathsPlugin())
36
- result.append(
37
- 'MiniCssExtract',
38
- new MiniCssExtractPlugin({
39
- filename: 'css/[name]-[contenthash:8].css',
40
- chunkFilename: 'css/[name]-[contenthash:8].chunk.css'
41
- })
42
- )
43
- result.append(
44
- 'Manifest',
45
- new WebpackAssetsManifest({
46
- entrypoints: true,
47
- writeToDisk: true,
48
- publicPath: config.publicPathWithoutCDN
49
- })
50
- )
51
- return result
52
- }
53
-
54
- const getExtensionsGlob = () => {
55
- const { extensions } = config
56
- return extensions.length === 1 ? `**/*${extensions[0]}` : `**/*{${extensions.join(',')}}`
57
- }
13
+ const { moduleExists } = require('../utils/helpers')
58
14
 
59
15
  const getEntryObject = () => {
60
- const result = new ConfigObject()
61
- const glob = getExtensionsGlob()
16
+ const entries = {}
62
17
  const rootPath = join(config.source_path, config.source_entry_path)
63
- const paths = sync(join(rootPath, glob))
64
- paths.forEach((path) => {
18
+
19
+ globSync(`${rootPath}/*.*`).forEach((path) => {
65
20
  const namespace = relative(join(rootPath), dirname(path))
66
21
  const name = join(namespace, basename(path, extname(path)))
67
22
  let assetPaths = resolve(path)
68
23
 
69
24
  // Allows for multiple filetypes per entry (https://webpack.js.org/guides/entry-advanced/)
70
25
  // Transforms the config object value to an array with all values under the same name
71
- let previousPaths = result.get(name)
26
+ let previousPaths = entries[name]
72
27
  if (previousPaths) {
73
- previousPaths = Array.isArray(previousPaths) ? previousPaths : [previousPaths]
28
+ previousPaths = Array.isArray(previousPaths)
29
+ ? previousPaths
30
+ : [previousPaths]
74
31
  previousPaths.push(assetPaths)
75
32
  assetPaths = previousPaths
76
33
  }
77
34
 
78
- result.set(name, assetPaths)
35
+ entries[name] = assetPaths
79
36
  })
80
- return result
37
+
38
+ return entries
81
39
  }
82
40
 
83
41
  const getModulePaths = () => {
84
- const result = new ConfigList()
85
- result.append('source', resolve(config.source_path))
42
+ const result = [resolve(config.source_path)]
43
+
86
44
  if (config.additional_paths) {
87
- config.additional_paths.forEach((path) => result.append(path, resolve(path)))
45
+ config.additional_paths.forEach((path) => result.push(resolve(path)))
88
46
  }
89
- result.append('node_modules', 'node_modules')
47
+ result.push('node_modules')
48
+
90
49
  return result
91
50
  }
92
51
 
93
- const getBaseConfig = () => new ConfigObject({
52
+ const getPlugins = () => {
53
+ const plugins = [
54
+ new webpack.EnvironmentPlugin(process.env),
55
+ new WebpackAssetsManifest({
56
+ entrypoints: true,
57
+ writeToDisk: true,
58
+ output: 'manifest.json',
59
+ entrypointsUseAssets: true,
60
+ publicPath: true
61
+ })
62
+ ]
63
+
64
+ if (moduleExists('css-loader') && moduleExists('mini-css-extract-plugin')) {
65
+ const hash = isProduction ? '-[contenthash:8]' : ''
66
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
67
+ plugins.push(
68
+ new MiniCssExtractPlugin({
69
+ filename: `css/[name]${hash}.css`,
70
+ chunkFilename: `css/[id]${hash}.css`
71
+ })
72
+ )
73
+ }
74
+
75
+ return plugins
76
+ }
77
+
78
+ // Don't use contentHash except for production for performance
79
+ // https://webpack.js.org/guides/build-performance/#avoid-production-specific-tooling
80
+ const hash = isProduction ? '-[contenthash]' : ''
81
+ module.exports = {
94
82
  mode: 'production',
95
83
  output: {
96
- filename: 'js/[name]-[contenthash].js',
97
- chunkFilename: 'js/[name]-[contenthash].chunk.js',
98
- hotUpdateChunkFilename: 'js/[id]-[hash].hot-update.js',
84
+ filename: `js/[name]${hash}.js`,
85
+ chunkFilename: `js/[name]${hash}.chunk.js`,
86
+
87
+ // https://webpack.js.org/configuration/output/#outputhotupdatechunkfilename
88
+ hotUpdateChunkFilename: 'js/[id].[fullhash].hot-update.js',
99
89
  path: config.outputPath,
100
90
  publicPath: config.publicPath
101
91
  },
102
-
92
+ entry: getEntryObject(),
103
93
  resolve: {
104
- extensions: config.extensions,
94
+ extensions: ['.js', '.jsx', '.mjs', '.ts', '.tsx', '.coffee'],
95
+ modules: getModulePaths(),
105
96
  plugins: [PnpWebpackPlugin]
106
97
  },
107
98
 
99
+ plugins: getPlugins(),
100
+
108
101
  resolveLoader: {
109
102
  modules: ['node_modules'],
110
103
  plugins: [PnpWebpackPlugin.moduleLoader(module)]
111
104
  },
112
105
 
113
- node: {
114
- dgram: 'empty',
115
- fs: 'empty',
116
- net: 'empty',
117
- tls: 'empty',
118
- child_process: 'empty'
119
- }
120
- })
121
-
122
- module.exports = class Base {
123
- constructor() {
124
- this.loaders = getLoaderList()
125
- this.plugins = getPluginList()
126
- this.config = getBaseConfig()
127
- this.entry = getEntryObject()
128
- this.resolvedModules = getModulePaths()
129
- }
130
-
131
- splitChunks(callback = null) {
132
- let appConfig = {}
133
- const defaultConfig = {
134
- optimization: {
135
- // Split vendor and common chunks
136
- // https://twitter.com/wSokra/status/969633336732905474
137
- splitChunks: {
138
- chunks: 'all',
139
- name: true
140
- },
141
- // Separate runtime chunk to enable long term caching
142
- // https://twitter.com/wSokra/status/969679223278505985
143
- runtimeChunk: true
144
- }
145
- }
146
-
147
- if (callback) {
148
- appConfig = callback(defaultConfig)
149
- if (isNotObject(appConfig)) {
150
- throw new Error(`
151
- ${prettyPrint(appConfig)} is not a valid splitChunks configuration.
152
- See https://webpack.js.org/plugins/split-chunks-plugin/#configuration
153
- `)
154
- }
155
- }
106
+ optimization: {
107
+ splitChunks: { chunks: 'all' },
156
108
 
157
- return this.config.merge(deepMerge(defaultConfig, appConfig))
158
- }
159
-
160
- toWebpackConfig() {
161
- return this.config.merge({
162
- entry: this.entry.toObject(),
163
-
164
- module: {
165
- strictExportPresence: true,
166
- rules: this.loaders.values()
167
- },
168
-
169
- plugins: this.plugins.values(),
109
+ runtimeChunk: 'single'
110
+ },
170
111
 
171
- resolve: {
172
- modules: this.resolvedModules.values()
173
- }
174
- })
112
+ module: {
113
+ strictExportPresence: true,
114
+ rules
175
115
  }
176
116
  }
@@ -1,53 +1,55 @@
1
- const webpack = require('webpack')
2
- const Base = require('./base')
1
+ const { merge } = require('webpack-merge')
2
+
3
+ const baseConfig = require('./base')
3
4
  const devServer = require('../dev_server')
5
+ const { runningWebpackDevServer } = require('../env')
6
+
4
7
  const { outputPath: contentBase, publicPath } = require('../config')
5
8
 
6
- module.exports = class extends Base {
7
- constructor() {
8
- super()
9
-
10
- this.config.merge({
11
- mode: 'development',
12
- devtool: 'cheap-module-source-map'
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
- })
9
+ let devConfig = {
10
+ mode: 'development',
11
+ devtool: 'cheap-module-source-map'
12
+ }
13
+
14
+ if (runningWebpackDevServer) {
15
+ const liveReload = devServer.live_reload !== undefined ? devServer.live_reload : !devServer.hmr
16
+
17
+ const devServerConfig = {
18
+ devMiddleware: {
19
+ publicPath
20
+ },
21
+ compress: devServer.compress,
22
+ allowedHosts: devServer.allowed_hosts,
23
+ host: devServer.host,
24
+ port: devServer.port,
25
+ https: devServer.https,
26
+ hot: devServer.hmr,
27
+ liveReload,
28
+ historyApiFallback: { disableDotRule: true },
29
+ headers: devServer.headers,
30
+ static: {
31
+ publicPath: contentBase
51
32
  }
52
33
  }
34
+
35
+ if (devServer.static) {
36
+ devServerConfig.static = { ...devServerConfig.static, ...devServer.static }
37
+ }
38
+
39
+ if (devServer.client) {
40
+ devServerConfig.client = devServer.client
41
+ }
42
+
43
+ devConfig = merge(devConfig, {
44
+ stats: {
45
+ colors: true,
46
+ entrypoints: false,
47
+ errorDetails: true,
48
+ modules: false,
49
+ moduleTrace: false
50
+ },
51
+ devServer: devServerConfig
52
+ })
53
53
  }
54
+
55
+ module.exports = merge(baseConfig, devConfig)