webpacker 5.0.1 → 6.0.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) 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 +70 -0
  7. data/.gitignore +2 -0
  8. data/.node-version +1 -1
  9. data/.rubocop.yml +11 -16
  10. data/CHANGELOG.md +33 -1
  11. data/CONTRIBUTING.md +1 -1
  12. data/Gemfile.lock +91 -85
  13. data/README.md +27 -44
  14. data/docs/assets.md +21 -5
  15. data/docs/css.md +80 -30
  16. data/docs/deployment.md +18 -0
  17. data/docs/docker.md +2 -2
  18. data/docs/engines.md +1 -1
  19. data/docs/env.md +4 -1
  20. data/docs/es6.md +1 -1
  21. data/docs/integrations.md +2 -2
  22. data/docs/props.md +2 -38
  23. data/docs/react.md +183 -0
  24. data/docs/target.md +22 -0
  25. data/docs/testing.md +13 -3
  26. data/docs/troubleshooting.md +3 -1
  27. data/docs/typescript.md +92 -27
  28. data/docs/webpack-dev-server.md +17 -15
  29. data/docs/webpack.md +58 -107
  30. data/lib/install/config/webpack/base.js +3 -0
  31. data/lib/install/config/webpack/development.js +2 -2
  32. data/lib/install/config/webpack/production.js +2 -2
  33. data/lib/install/config/webpack/test.js +2 -2
  34. data/lib/install/config/webpacker.yml +9 -42
  35. data/lib/install/examples/{vue → vue3}/app.vue +10 -5
  36. data/lib/install/examples/vue3/hello_vue.js +15 -0
  37. data/lib/install/javascript/packs/application.css +9 -0
  38. data/lib/install/template.rb +33 -19
  39. data/lib/tasks/webpacker.rake +2 -11
  40. data/lib/tasks/webpacker/binstubs.rake +6 -4
  41. data/lib/tasks/webpacker/check_binstubs.rake +4 -4
  42. data/lib/tasks/webpacker/check_node.rake +1 -1
  43. data/lib/tasks/webpacker/check_yarn.rake +2 -3
  44. data/lib/tasks/webpacker/compile.rake +4 -2
  45. data/lib/tasks/webpacker/info.rake +12 -10
  46. data/lib/tasks/webpacker/install.rake +6 -4
  47. data/lib/tasks/webpacker/verify_install.rake +2 -1
  48. data/lib/tasks/webpacker/yarn_install.rake +9 -1
  49. data/lib/webpacker/commands.rb +1 -1
  50. data/lib/webpacker/compiler.rb +14 -9
  51. data/lib/webpacker/configuration.rb +7 -27
  52. data/lib/webpacker/dev_server_proxy.rb +3 -1
  53. data/lib/webpacker/dev_server_runner.rb +23 -4
  54. data/lib/webpacker/helper.rb +55 -46
  55. data/lib/webpacker/manifest.rb +1 -1
  56. data/lib/webpacker/railtie.rb +0 -43
  57. data/lib/webpacker/runner.rb +1 -0
  58. data/lib/webpacker/version.rb +1 -1
  59. data/lib/webpacker/webpack_runner.rb +7 -2
  60. data/package.json +27 -43
  61. data/package/__tests__/config.js +6 -27
  62. data/package/__tests__/dev_server.js +2 -0
  63. data/package/__tests__/development.js +18 -7
  64. data/package/__tests__/env.js +12 -4
  65. data/package/__tests__/production.js +6 -6
  66. data/package/__tests__/staging.js +7 -6
  67. data/package/__tests__/test.js +4 -5
  68. data/package/babel/preset-react.js +62 -0
  69. data/package/babel/preset.js +44 -0
  70. data/package/config.js +4 -9
  71. data/package/configPath.js +3 -0
  72. data/package/dev_server.js +1 -1
  73. data/package/env.js +9 -4
  74. data/package/environments/__tests__/base.js +21 -36
  75. data/package/environments/base.js +67 -128
  76. data/package/environments/development.js +46 -39
  77. data/package/environments/production.js +69 -67
  78. data/package/environments/test.js +2 -2
  79. data/package/index.js +6 -6
  80. data/package/rules/babel.js +20 -11
  81. data/package/rules/coffee.js +6 -0
  82. data/package/rules/erb.js +13 -0
  83. data/package/rules/file.js +19 -18
  84. data/package/rules/index.js +24 -18
  85. data/package/rules/less.js +18 -0
  86. data/package/rules/sass.js +6 -7
  87. data/package/rules/svg.js +23 -0
  88. data/package/utils/get_style_rule.js +22 -28
  89. data/package/utils/helpers.js +3 -35
  90. data/test/compiler_test.rb +4 -11
  91. data/test/configuration_test.rb +2 -32
  92. data/test/dev_server_runner_test.rb +25 -6
  93. data/test/engine_rake_tasks_test.rb +39 -0
  94. data/test/helper_test.rb +18 -9
  95. data/test/mounted_app/Rakefile +4 -0
  96. data/test/mounted_app/test/dummy/Rakefile +3 -0
  97. data/test/mounted_app/test/dummy/bin/rails +3 -0
  98. data/test/mounted_app/test/dummy/bin/rake +3 -0
  99. data/test/mounted_app/test/dummy/config.ru +5 -0
  100. data/test/mounted_app/test/dummy/config/application.rb +10 -0
  101. data/test/mounted_app/test/dummy/config/environment.rb +3 -0
  102. data/test/mounted_app/test/dummy/config/webpacker.yml +75 -0
  103. data/test/mounted_app/test/dummy/package.json +7 -0
  104. data/test/rake_tasks_test.rb +1 -10
  105. data/test/test_app/config/application.rb +0 -1
  106. data/test/test_app/config/webpacker.yml +3 -21
  107. data/test/test_app/config/webpacker_public_root.yml +0 -1
  108. data/test/test_app/public/packs/manifest.json +18 -13
  109. data/test/test_app/some.config.js +0 -0
  110. data/test/webpack_runner_test.rb +10 -4
  111. data/webpacker.gemspec +1 -1
  112. data/yarn.lock +2657 -6224
  113. metadata +53 -71
  114. data/.travis.yml +0 -43
  115. data/lib/install/angular.rb +0 -23
  116. data/lib/install/coffee.rb +0 -25
  117. data/lib/install/config/.browserslistrc +0 -1
  118. data/lib/install/config/babel.config.js +0 -72
  119. data/lib/install/config/postcss.config.js +0 -12
  120. data/lib/install/config/webpack/environment.js +0 -3
  121. data/lib/install/elm.rb +0 -39
  122. data/lib/install/erb.rb +0 -25
  123. data/lib/install/examples/angular/hello_angular.js +0 -7
  124. data/lib/install/examples/angular/hello_angular/app/app.component.ts +0 -9
  125. data/lib/install/examples/angular/hello_angular/app/app.module.ts +0 -16
  126. data/lib/install/examples/angular/hello_angular/index.ts +0 -8
  127. data/lib/install/examples/angular/hello_angular/polyfills.ts +0 -73
  128. data/lib/install/examples/coffee/hello_coffee.coffee +0 -4
  129. data/lib/install/examples/elm/Main.elm +0 -55
  130. data/lib/install/examples/elm/hello_elm.js +0 -16
  131. data/lib/install/examples/erb/hello_erb.js.erb +0 -6
  132. data/lib/install/examples/react/babel.config.js +0 -87
  133. data/lib/install/examples/react/hello_react.jsx +0 -26
  134. data/lib/install/examples/react/tsconfig.json +0 -20
  135. data/lib/install/examples/stimulus/application.js +0 -1
  136. data/lib/install/examples/stimulus/controllers/hello_controller.js +0 -18
  137. data/lib/install/examples/stimulus/controllers/index.js +0 -9
  138. data/lib/install/examples/svelte/app.svelte +0 -11
  139. data/lib/install/examples/svelte/hello_svelte.js +0 -20
  140. data/lib/install/examples/typescript/hello_typescript.ts +0 -4
  141. data/lib/install/examples/typescript/tsconfig.json +0 -23
  142. data/lib/install/examples/vue/hello_vue.js +0 -72
  143. data/lib/install/loaders/coffee.js +0 -6
  144. data/lib/install/loaders/elm.js +0 -25
  145. data/lib/install/loaders/erb.js +0 -11
  146. data/lib/install/loaders/svelte.js +0 -9
  147. data/lib/install/loaders/typescript.js +0 -11
  148. data/lib/install/loaders/vue.js +0 -6
  149. data/lib/install/react.rb +0 -18
  150. data/lib/install/stimulus.rb +0 -12
  151. data/lib/install/svelte.rb +0 -29
  152. data/lib/install/typescript.rb +0 -46
  153. data/lib/install/vue.rb +0 -49
  154. data/lib/tasks/installers.rake +0 -42
  155. data/package/config_types/__tests__/config_list.js +0 -118
  156. data/package/config_types/__tests__/config_object.js +0 -43
  157. data/package/config_types/config_list.js +0 -75
  158. data/package/config_types/config_object.js +0 -55
  159. data/package/config_types/index.js +0 -7
  160. data/package/rules/module.css.js +0 -3
  161. data/package/rules/module.sass.js +0 -8
  162. data/package/rules/node_modules.js +0 -24
  163. data/package/utils/__tests__/deep_assign.js +0 -32
  164. data/package/utils/__tests__/deep_merge.js +0 -10
  165. data/package/utils/__tests__/get_style_rule.js +0 -65
  166. data/package/utils/__tests__/objectify.js +0 -9
  167. data/package/utils/deep_assign.js +0 -22
  168. data/package/utils/deep_merge.js +0 -22
  169. data/package/utils/objectify.js +0 -3
@@ -13,7 +13,9 @@ describe('Env', () => {
13
13
  process.env.NODE_ENV = 'development'
14
14
  expect(require('../env')).toEqual({
15
15
  railsEnv: 'development',
16
- nodeEnv: 'development'
16
+ nodeEnv: 'development',
17
+ isProduction: false,
18
+ isDevelopment: true
17
19
  })
18
20
  })
19
21
 
@@ -22,7 +24,9 @@ describe('Env', () => {
22
24
  delete process.env.NODE_ENV
23
25
  expect(require('../env')).toEqual({
24
26
  railsEnv: 'development',
25
- nodeEnv: 'production'
27
+ nodeEnv: 'production',
28
+ isProduction: true,
29
+ isDevelopment: false
26
30
  })
27
31
  })
28
32
 
@@ -31,7 +35,9 @@ describe('Env', () => {
31
35
  delete process.env.RAILS_ENV
32
36
  expect(require('../env')).toEqual({
33
37
  railsEnv: 'production',
34
- nodeEnv: 'production'
38
+ nodeEnv: 'production',
39
+ isProduction: true,
40
+ isDevelopment: false
35
41
  })
36
42
  })
37
43
 
@@ -40,7 +46,9 @@ describe('Env', () => {
40
46
  process.env.NODE_ENV = 'staging'
41
47
  expect(require('../env')).toEqual({
42
48
  railsEnv: 'staging',
43
- nodeEnv: 'production'
49
+ nodeEnv: 'production',
50
+ isProduction: true,
51
+ isDevelopment: false
44
52
  })
45
53
  })
46
54
  })
@@ -8,19 +8,19 @@ chdirTestApp()
8
8
  describe('Production environment', () => {
9
9
  afterAll(chdirCwd)
10
10
 
11
- describe('toWebpackConfig', () => {
11
+ describe('webpackConfig', () => {
12
12
  beforeEach(() => jest.resetModules())
13
13
 
14
14
  test('should use production config and environment', () => {
15
15
  process.env.RAILS_ENV = 'production'
16
16
  process.env.NODE_ENV = 'production'
17
17
 
18
- const { environment } = require('../index')
19
- const config = environment.toWebpackConfig()
18
+ const { webpackConfig } = require('../index')
20
19
 
21
- expect(config.output.path).toEqual(resolve('public', 'packs'))
22
- expect(config.output.publicPath).toEqual('/packs/')
23
- expect(config).toMatchObject({
20
+ expect(webpackConfig.output.path).toEqual(resolve('public', 'packs'))
21
+ expect(webpackConfig.output.publicPath).toEqual('/packs/')
22
+
23
+ expect(webpackConfig).toMatchObject({
24
24
  devtool: 'source-map',
25
25
  stats: 'normal'
26
26
  })
@@ -8,19 +8,20 @@ chdirTestApp()
8
8
  describe('Custom environment', () => {
9
9
  afterAll(chdirCwd)
10
10
 
11
- describe('toWebpackConfig', () => {
11
+ describe('webpackConfig', () => {
12
12
  beforeEach(() => jest.resetModules())
13
13
 
14
14
  test('should use staging config and default production environment', () => {
15
15
  process.env.RAILS_ENV = 'staging'
16
16
  delete process.env.NODE_ENV
17
17
 
18
- const { environment } = require('../index')
19
- const config = environment.toWebpackConfig()
18
+ const { webpackConfig } = require('../index')
20
19
 
21
- expect(config.output.path).toEqual(resolve('public', 'packs-staging'))
22
- expect(config.output.publicPath).toEqual('/packs-staging/')
23
- expect(config).toMatchObject({
20
+ expect(webpackConfig.output.path).toEqual(
21
+ resolve('public', 'packs-staging')
22
+ )
23
+ expect(webpackConfig.output.publicPath).toEqual('/packs-staging/')
24
+ expect(webpackConfig).toMatchObject({
24
25
  devtool: 'source-map',
25
26
  stats: 'normal'
26
27
  })
@@ -15,12 +15,11 @@ describe('Test environment', () => {
15
15
  process.env.RAILS_ENV = 'test'
16
16
  process.env.NODE_ENV = 'test'
17
17
 
18
- const { environment } = require('../index')
19
- const config = environment.toWebpackConfig()
18
+ const { webpackConfig } = require('../index')
20
19
 
21
- expect(config.output.path).toEqual(resolve('public', 'packs-test'))
22
- expect(config.output.publicPath).toEqual('/packs-test/')
23
- expect(config.devServer).toEqual(undefined)
20
+ expect(webpackConfig.output.path).toEqual(resolve('public', 'packs-test'))
21
+ expect(webpackConfig.output.publicPath).toEqual('/packs-test/')
22
+ expect(webpackConfig.devServer).toEqual(undefined)
24
23
  })
25
24
  })
26
25
  })
@@ -0,0 +1,62 @@
1
+ module.exports = function config(api) {
2
+ const validEnv = ['development', 'test', 'production']
3
+ const currentEnv = api.env()
4
+ const isDevelopmentEnv = api.env('development')
5
+ const isProductionEnv = api.env('production')
6
+ const isTestEnv = api.env('test')
7
+
8
+ if (!validEnv.includes(currentEnv)) {
9
+ throw new Error(
10
+ `Please specify a valid NODE_ENV or BABEL_ENV environment variable. Valid values are "development", "test", and "production". Instead, received: "${JSON.stringify(currentEnv)}".`
11
+ )
12
+ }
13
+
14
+ return {
15
+ presets: [
16
+ isTestEnv && [
17
+ '@babel/preset-env',
18
+ {
19
+ targets: { node: 'current' },
20
+ modules: 'commonjs'
21
+ }
22
+ ],
23
+ (isProductionEnv || isDevelopmentEnv) && [
24
+ '@babel/preset-env',
25
+ {
26
+ useBuiltIns: 'entry',
27
+ corejs: '3.8',
28
+ modules: false,
29
+ bugfixes: true,
30
+ loose: true,
31
+ exclude: ['transform-typeof-symbol']
32
+ }
33
+ ],
34
+ [
35
+ '@babel/preset-react',
36
+ {
37
+ development: isDevelopmentEnv || isTestEnv,
38
+ useBuiltIns: true
39
+ }
40
+ ]
41
+ ].filter(Boolean),
42
+ plugins: [
43
+ 'babel-plugin-macros',
44
+ [
45
+ '@babel/plugin-proposal-class-properties',
46
+ { loose: true }
47
+ ],
48
+ [
49
+ '@babel/plugin-transform-runtime',
50
+ {
51
+ helpers: false,
52
+ regenerator: true,
53
+ corejs: false
54
+ }
55
+ ],
56
+ isProductionEnv && [
57
+ 'babel-plugin-transform-react-remove-prop-types',
58
+ { removeImport: true }
59
+ ]
60
+ ].filter(Boolean)
61
+ }
62
+ }
@@ -0,0 +1,44 @@
1
+ module.exports = function config(api) {
2
+ const validEnv = ['development', 'test', 'production']
3
+ const currentEnv = api.env()
4
+ const isDevelopmentEnv = api.env('development')
5
+ const isProductionEnv = api.env('production')
6
+ const isTestEnv = api.env('test')
7
+
8
+ if (!validEnv.includes(currentEnv)) {
9
+ throw new Error(
10
+ `Please specify a valid NODE_ENV or BABEL_ENV environment variable. Valid values are "development", "test", and "production". Instead, received: "${JSON.stringify(currentEnv)}".`
11
+ )
12
+ }
13
+
14
+ return {
15
+ presets: [
16
+ isTestEnv && [
17
+ '@babel/preset-env',
18
+ { targets: { node: 'current' } }
19
+ ],
20
+ (isProductionEnv || isDevelopmentEnv) && [
21
+ '@babel/preset-env',
22
+ {
23
+ useBuiltIns: 'entry',
24
+ corejs: '3.8',
25
+ modules: 'auto',
26
+ bugfixes: true,
27
+ loose: true,
28
+ exclude: ['transform-typeof-symbol']
29
+ }
30
+ ]
31
+ ].filter(Boolean),
32
+ plugins: [
33
+ 'babel-plugin-macros',
34
+ [
35
+ '@babel/plugin-proposal-class-properties',
36
+ { loose: true }
37
+ ],
38
+ [
39
+ '@babel/plugin-transform-runtime',
40
+ { helpers: false }
41
+ ]
42
+ ].filter(Boolean)
43
+ }
44
+ }
@@ -1,12 +1,12 @@
1
1
  const { resolve } = require('path')
2
2
  const { safeLoad } = 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
+ const configPath = require('./configPath')
7
8
 
8
9
  const defaultConfigPath = require.resolve('../lib/install/config/webpacker.yml')
9
- const configPath = resolve('config', 'webpacker.yml')
10
10
 
11
11
  const getDefaultConfig = () => {
12
12
  const defaultConfig = safeLoad(readFileSync(defaultConfigPath), 'utf8')
@@ -16,12 +16,7 @@ const getDefaultConfig = () => {
16
16
  const defaults = getDefaultConfig()
17
17
  const app = safeLoad(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
22
  // Ensure that the publicPath includes our asset host so dynamic imports
@@ -0,0 +1,3 @@
1
+ const { resolve } = require('path')
2
+
3
+ module.exports = process.env.WEBPACKER_CONFIG || resolve('config', 'webpacker.yml')
@@ -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
  }
@@ -1,13 +1,16 @@
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
- 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'
11
14
 
12
15
  const config = safeLoad(readFileSync(configPath), 'utf8')
13
16
  const availableEnvironments = Object.keys(config).join('|')
@@ -15,5 +18,7 @@ const regex = new RegExp(`^(${availableEnvironments})$`, 'g')
15
18
 
16
19
  module.exports = {
17
20
  railsEnv: railsEnv && railsEnv.match(regex) ? railsEnv : DEFAULT,
18
- nodeEnv: nodeEnv && NODE_ENVIRONMENTS.includes(nodeEnv) ? nodeEnv : DEFAULT
21
+ nodeEnv,
22
+ isProduction,
23
+ isDevelopment
19
24
  }
@@ -9,76 +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(
19
+ expect(baseConfig.entry.application).toEqual(
28
20
  resolve('app', 'javascript', 'packs', '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
- [
36
- resolve('app', 'javascript', 'packs', 'multi_entry.css'),
37
- resolve('app', 'javascript', 'packs', 'multi_entry.js')
38
- ]
39
- )
25
+ expect(baseConfig.entry.multi_entry.sort()).toEqual([
26
+ resolve('app', 'javascript', 'packs', 'multi_entry.css'),
27
+ resolve('app', 'javascript', 'packs', 'multi_entry.js')
28
+ ])
40
29
  })
41
30
 
42
31
  test('should return output', () => {
43
- const config = environment.toWebpackConfig()
44
- expect(config.output.filename).toEqual('js/[name]-[contenthash].js')
45
- expect(config.output.chunkFilename).toEqual('js/[name]-[contenthash].chunk.js')
32
+ expect(baseConfig.output.filename).toEqual('js/[name]-[contenthash].js')
33
+ expect(baseConfig.output.chunkFilename).toEqual(
34
+ 'js/[name]-[contenthash].chunk.js'
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
40
+ const configRules = baseConfig.module.rules
52
41
 
53
- expect(defaultRules.length).toEqual(7)
54
- expect(configRules.length).toEqual(8)
42
+ expect(defaultRules.length).toEqual(3)
43
+ expect(configRules.length).toEqual(3)
55
44
  })
56
45
 
57
46
  test('should return default plugins', () => {
58
- const config = environment.toWebpackConfig()
59
- expect(config.plugins.length).toEqual(4)
47
+ expect(baseConfig.plugins.length).toEqual(4)
60
48
  })
61
49
 
62
50
  test('should return default resolveLoader', () => {
63
- const config = environment.toWebpackConfig()
64
- expect(config.resolveLoader.modules).toEqual(['node_modules'])
51
+ expect(baseConfig.resolveLoader.modules).toEqual(['node_modules'])
65
52
  })
66
53
 
67
54
  test('should return default resolve.modules with additions', () => {
68
- const config = environment.toWebpackConfig()
69
- expect(config.resolve.modules).toEqual([
55
+ expect(baseConfig.resolve.modules).toEqual([
70
56
  resolve('app', 'javascript'),
71
57
  resolve('app/assets'),
72
58
  resolve('/etc/yarn'),
59
+ resolve('some.config.js'),
60
+ resolve('app/elm'),
73
61
  'node_modules'
74
62
  ])
75
63
  })
76
64
 
77
65
  test('returns plugins property as Array', () => {
78
- const config = environment.toWebpackConfig()
79
-
80
- expect(config.plugins).toBeInstanceOf(Array)
81
- expect(config.plugins).not.toBeInstanceOf(ConfigList)
66
+ expect(baseConfig.plugins).toBeInstanceOf(Array)
82
67
  })
83
68
  })
84
69
  })
@@ -1,177 +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 } = require('glob')
8
+ const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
9
+ const WebpackAssetsManifest = require('webpack-assets-manifest')
10
+ const webpack = require('webpack')
20
11
  const rules = require('../rules')
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(JSON.parse(JSON.stringify(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
- integrity: false,
47
- entrypoints: true,
48
- writeToDisk: true,
49
- publicPath: config.publicPathWithoutCDN
50
- })
51
- )
52
- return result
53
- }
54
-
55
- const getExtensionsGlob = () => {
56
- const { extensions } = config
57
- return extensions.length === 1 ? `**/*${extensions[0]}` : `**/*{${extensions.join(',')}}`
58
- }
13
+ const { isDevelopment } = require('../env')
59
14
 
60
15
  const getEntryObject = () => {
61
- const result = new ConfigObject()
62
- const glob = getExtensionsGlob()
16
+ const entries = {}
63
17
  const rootPath = join(config.source_path, config.source_entry_path)
64
- const paths = sync(join(rootPath, glob))
65
- paths.forEach((path) => {
18
+
19
+ sync(`${rootPath}/**/*.*`).forEach((path) => {
66
20
  const namespace = relative(join(rootPath), dirname(path))
67
21
  const name = join(namespace, basename(path, extname(path)))
68
22
  let assetPaths = resolve(path)
69
23
 
70
24
  // Allows for multiple filetypes per entry (https://webpack.js.org/guides/entry-advanced/)
71
25
  // Transforms the config object value to an array with all values under the same name
72
- let previousPaths = result.get(name)
26
+ let previousPaths = entries[name]
73
27
  if (previousPaths) {
74
- previousPaths = Array.isArray(previousPaths) ? previousPaths : [previousPaths]
28
+ previousPaths = Array.isArray(previousPaths)
29
+ ? previousPaths
30
+ : [previousPaths]
75
31
  previousPaths.push(assetPaths)
76
32
  assetPaths = previousPaths
77
33
  }
78
34
 
79
- result.set(name, assetPaths)
35
+ entries[name] = assetPaths
80
36
  })
81
- return result
37
+
38
+ return entries
82
39
  }
83
40
 
84
41
  const getModulePaths = () => {
85
- const result = new ConfigList()
86
- result.append('source', resolve(config.source_path))
87
- if (config.resolved_paths) {
88
- config.resolved_paths.forEach((path) => result.append(path, resolve(path)))
42
+ const result = [resolve(config.source_path)]
43
+
44
+ if (config.additional_paths) {
45
+ config.additional_paths.forEach((path) => result.push(resolve(path)))
89
46
  }
90
- result.append('node_modules', 'node_modules')
47
+ result.push('node_modules')
48
+
91
49
  return result
92
50
  }
93
51
 
94
- const getBaseConfig = () => new ConfigObject({
52
+ const getPlugins = () => {
53
+ const plugins = [
54
+ new webpack.EnvironmentPlugin(process.env),
55
+ PnpWebpackPlugin,
56
+ new CaseSensitivePathsPlugin(),
57
+ new WebpackAssetsManifest({
58
+ entrypoints: true,
59
+ writeToDisk: true,
60
+ output: 'manifest.json',
61
+ entrypointsUseAssets: true,
62
+ publicPath: true
63
+ })
64
+ ]
65
+
66
+ try {
67
+ if (require.resolve('css-loader')) {
68
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
69
+ plugins.push(
70
+ new MiniCssExtractPlugin({
71
+ filename: isDevelopment ? '[name].css' : '[name].[contenthash:8].css',
72
+ chunkFilename: isDevelopment ? '[id].css' : '[id].[contenthash:8].css'
73
+ })
74
+ )
75
+ }
76
+ } catch (e) {
77
+ /* Work out what to print here */
78
+ }
79
+
80
+ return plugins
81
+ }
82
+
83
+ module.exports = {
95
84
  mode: 'production',
96
85
  output: {
97
86
  filename: 'js/[name]-[contenthash].js',
98
87
  chunkFilename: 'js/[name]-[contenthash].chunk.js',
99
88
  hotUpdateChunkFilename: 'js/[id]-[hash].hot-update.js',
89
+ assetModuleFilename: 'static/[hash][ext][query]',
100
90
  path: config.outputPath,
101
91
  publicPath: config.publicPath
102
92
  },
103
-
93
+ entry: getEntryObject(),
104
94
  resolve: {
105
- extensions: config.extensions,
106
- plugins: [PnpWebpackPlugin]
95
+ extensions: ['.js', '.mjs', '.ts'],
96
+ modules: getModulePaths()
107
97
  },
108
98
 
99
+ plugins: getPlugins(),
100
+
109
101
  resolveLoader: {
110
102
  modules: ['node_modules'],
111
103
  plugins: [PnpWebpackPlugin.moduleLoader(module)]
112
104
  },
113
105
 
114
- node: {
115
- dgram: 'empty',
116
- fs: 'empty',
117
- net: 'empty',
118
- tls: 'empty',
119
- child_process: 'empty'
120
- }
121
- })
122
-
123
- module.exports = class Base {
124
- constructor() {
125
- this.loaders = getLoaderList()
126
- this.plugins = getPluginList()
127
- this.config = getBaseConfig()
128
- this.entry = getEntryObject()
129
- this.resolvedModules = getModulePaths()
130
- }
131
-
132
- splitChunks(callback = null) {
133
- let appConfig = {}
134
- const defaultConfig = {
135
- optimization: {
136
- // Split vendor and common chunks
137
- // https://twitter.com/wSokra/status/969633336732905474
138
- splitChunks: {
139
- chunks: 'all',
140
- name: false
141
- },
142
- // Separate runtime chunk to enable long term caching
143
- // https://twitter.com/wSokra/status/969679223278505985
144
- runtimeChunk: true
145
- }
146
- }
147
-
148
- if (callback) {
149
- appConfig = callback(defaultConfig)
150
- if (isNotObject(appConfig)) {
151
- throw new Error(`
152
- ${prettyPrint(appConfig)} is not a valid splitChunks configuration.
153
- See https://webpack.js.org/plugins/split-chunks-plugin/#configuration
154
- `)
155
- }
156
- }
106
+ optimization: {
107
+ splitChunks: { chunks: 'all' },
157
108
 
158
- return this.config.merge(deepMerge(defaultConfig, appConfig))
159
- }
160
-
161
- toWebpackConfig() {
162
- return this.config.merge({
163
- entry: this.entry.toObject(),
164
-
165
- module: {
166
- strictExportPresence: true,
167
- rules: [{ parser: { requireEnsure: false } }, ...this.loaders.values()]
168
- },
169
-
170
- plugins: this.plugins.values(),
109
+ runtimeChunk: { name: (entrypoint) => `runtime-${entrypoint.name}` }
110
+ },
171
111
 
172
- resolve: {
173
- modules: this.resolvedModules.values()
174
- }
175
- })
112
+ module: {
113
+ strictExportPresence: true,
114
+ rules
176
115
  }
177
116
  }