webpacker 5.0.1 → 6.0.0.beta

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 (172) 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/6_0_upgrade.md +43 -0
  11. data/CHANGELOG.md +49 -3
  12. data/CONTRIBUTING.md +1 -1
  13. data/Gemfile.lock +91 -85
  14. data/README.md +233 -133
  15. data/lib/install/config/webpack/base.js +3 -0
  16. data/lib/install/config/webpack/development.js +2 -2
  17. data/lib/install/config/webpack/production.js +2 -2
  18. data/lib/install/config/webpack/test.js +2 -2
  19. data/lib/install/config/webpacker.yml +9 -42
  20. data/lib/install/javascript/packs/application.css +9 -0
  21. data/lib/install/javascript/packs/application.js +3 -1
  22. data/lib/install/template.rb +33 -19
  23. data/lib/tasks/webpacker.rake +2 -11
  24. data/lib/tasks/webpacker/binstubs.rake +6 -4
  25. data/lib/tasks/webpacker/check_binstubs.rake +4 -4
  26. data/lib/tasks/webpacker/check_node.rake +1 -1
  27. data/lib/tasks/webpacker/check_yarn.rake +2 -3
  28. data/lib/tasks/webpacker/compile.rake +4 -2
  29. data/lib/tasks/webpacker/info.rake +12 -10
  30. data/lib/tasks/webpacker/install.rake +6 -4
  31. data/lib/tasks/webpacker/verify_install.rake +2 -1
  32. data/lib/tasks/webpacker/yarn_install.rake +9 -1
  33. data/lib/webpacker/commands.rb +1 -1
  34. data/lib/webpacker/compiler.rb +22 -11
  35. data/lib/webpacker/configuration.rb +7 -27
  36. data/lib/webpacker/dev_server_proxy.rb +3 -1
  37. data/lib/webpacker/dev_server_runner.rb +23 -4
  38. data/lib/webpacker/helper.rb +55 -46
  39. data/lib/webpacker/manifest.rb +1 -1
  40. data/lib/webpacker/railtie.rb +0 -43
  41. data/lib/webpacker/runner.rb +1 -0
  42. data/lib/webpacker/version.rb +1 -1
  43. data/lib/webpacker/webpack_runner.rb +7 -2
  44. data/package.json +27 -43
  45. data/package/__tests__/config.js +6 -27
  46. data/package/__tests__/dev_server.js +2 -0
  47. data/package/__tests__/development.js +18 -7
  48. data/package/__tests__/env.js +12 -4
  49. data/package/__tests__/production.js +6 -6
  50. data/package/__tests__/staging.js +7 -6
  51. data/package/__tests__/test.js +4 -5
  52. data/package/babel/preset.js +55 -0
  53. data/package/config.js +4 -9
  54. data/package/configPath.js +3 -0
  55. data/package/dev_server.js +1 -1
  56. data/package/env.js +9 -4
  57. data/package/environments/__tests__/base.js +21 -36
  58. data/package/environments/base.js +63 -127
  59. data/package/environments/development.js +46 -39
  60. data/package/environments/production.js +63 -70
  61. data/package/environments/test.js +2 -2
  62. data/package/index.js +13 -8
  63. data/package/rules/babel.js +20 -11
  64. data/package/rules/coffee.js +6 -0
  65. data/package/rules/erb.js +15 -0
  66. data/package/rules/file.js +19 -18
  67. data/package/rules/index.js +15 -18
  68. data/package/rules/less.js +22 -0
  69. data/package/rules/sass.js +13 -10
  70. data/package/rules/svg.js +20 -0
  71. data/package/utils/get_style_rule.js +26 -36
  72. data/package/utils/helpers.js +26 -35
  73. data/test/compiler_test.rb +4 -11
  74. data/test/configuration_test.rb +2 -32
  75. data/test/dev_server_runner_test.rb +25 -6
  76. data/test/engine_rake_tasks_test.rb +39 -0
  77. data/test/helper_test.rb +18 -9
  78. data/test/mounted_app/Rakefile +4 -0
  79. data/test/mounted_app/test/dummy/Rakefile +3 -0
  80. data/test/mounted_app/test/dummy/bin/rails +3 -0
  81. data/test/mounted_app/test/dummy/bin/rake +3 -0
  82. data/test/mounted_app/test/dummy/config.ru +5 -0
  83. data/test/mounted_app/test/dummy/config/application.rb +10 -0
  84. data/test/mounted_app/test/dummy/config/environment.rb +3 -0
  85. data/test/mounted_app/test/dummy/config/webpacker.yml +75 -0
  86. data/test/mounted_app/test/dummy/package.json +7 -0
  87. data/test/rake_tasks_test.rb +1 -10
  88. data/test/test_app/config/application.rb +0 -1
  89. data/test/test_app/config/webpacker.yml +3 -21
  90. data/test/test_app/config/webpacker_public_root.yml +0 -1
  91. data/test/test_app/public/packs/manifest.json +18 -13
  92. data/test/test_app/some.config.js +0 -0
  93. data/test/webpack_runner_test.rb +10 -4
  94. data/webpacker.gemspec +1 -1
  95. data/yarn.lock +2657 -6224
  96. metadata +49 -90
  97. data/.travis.yml +0 -43
  98. data/docs/assets.md +0 -119
  99. data/docs/cloud9.md +0 -310
  100. data/docs/css.md +0 -253
  101. data/docs/deployment.md +0 -130
  102. data/docs/docker.md +0 -68
  103. data/docs/engines.md +0 -213
  104. data/docs/env.md +0 -65
  105. data/docs/es6.md +0 -72
  106. data/docs/folder-structure.md +0 -66
  107. data/docs/integrations.md +0 -220
  108. data/docs/misc.md +0 -23
  109. data/docs/props.md +0 -223
  110. data/docs/testing.md +0 -137
  111. data/docs/troubleshooting.md +0 -156
  112. data/docs/typescript.md +0 -125
  113. data/docs/v4-upgrade.md +0 -142
  114. data/docs/webpack-dev-server.md +0 -92
  115. data/docs/webpack.md +0 -364
  116. data/docs/yarn.md +0 -23
  117. data/lib/install/angular.rb +0 -23
  118. data/lib/install/coffee.rb +0 -25
  119. data/lib/install/config/.browserslistrc +0 -1
  120. data/lib/install/config/babel.config.js +0 -72
  121. data/lib/install/config/postcss.config.js +0 -12
  122. data/lib/install/config/webpack/environment.js +0 -3
  123. data/lib/install/elm.rb +0 -39
  124. data/lib/install/erb.rb +0 -25
  125. data/lib/install/examples/angular/hello_angular.js +0 -7
  126. data/lib/install/examples/angular/hello_angular/app/app.component.ts +0 -9
  127. data/lib/install/examples/angular/hello_angular/app/app.module.ts +0 -16
  128. data/lib/install/examples/angular/hello_angular/index.ts +0 -8
  129. data/lib/install/examples/angular/hello_angular/polyfills.ts +0 -73
  130. data/lib/install/examples/coffee/hello_coffee.coffee +0 -4
  131. data/lib/install/examples/elm/Main.elm +0 -55
  132. data/lib/install/examples/elm/hello_elm.js +0 -16
  133. data/lib/install/examples/erb/hello_erb.js.erb +0 -6
  134. data/lib/install/examples/react/babel.config.js +0 -87
  135. data/lib/install/examples/react/hello_react.jsx +0 -26
  136. data/lib/install/examples/react/tsconfig.json +0 -20
  137. data/lib/install/examples/stimulus/application.js +0 -1
  138. data/lib/install/examples/stimulus/controllers/hello_controller.js +0 -18
  139. data/lib/install/examples/stimulus/controllers/index.js +0 -9
  140. data/lib/install/examples/svelte/app.svelte +0 -11
  141. data/lib/install/examples/svelte/hello_svelte.js +0 -20
  142. data/lib/install/examples/typescript/hello_typescript.ts +0 -4
  143. data/lib/install/examples/typescript/tsconfig.json +0 -23
  144. data/lib/install/examples/vue/app.vue +0 -22
  145. data/lib/install/examples/vue/hello_vue.js +0 -72
  146. data/lib/install/loaders/coffee.js +0 -6
  147. data/lib/install/loaders/elm.js +0 -25
  148. data/lib/install/loaders/erb.js +0 -11
  149. data/lib/install/loaders/svelte.js +0 -9
  150. data/lib/install/loaders/typescript.js +0 -11
  151. data/lib/install/loaders/vue.js +0 -6
  152. data/lib/install/react.rb +0 -18
  153. data/lib/install/stimulus.rb +0 -12
  154. data/lib/install/svelte.rb +0 -29
  155. data/lib/install/typescript.rb +0 -46
  156. data/lib/install/vue.rb +0 -49
  157. data/lib/tasks/installers.rake +0 -42
  158. data/package/config_types/__tests__/config_list.js +0 -118
  159. data/package/config_types/__tests__/config_object.js +0 -43
  160. data/package/config_types/config_list.js +0 -75
  161. data/package/config_types/config_object.js +0 -55
  162. data/package/config_types/index.js +0 -7
  163. data/package/rules/module.css.js +0 -3
  164. data/package/rules/module.sass.js +0 -8
  165. data/package/rules/node_modules.js +0 -24
  166. data/package/utils/__tests__/deep_assign.js +0 -32
  167. data/package/utils/__tests__/deep_merge.js +0 -10
  168. data/package/utils/__tests__/get_style_rule.js +0 -65
  169. data/package/utils/__tests__/objectify.js +0 -9
  170. data/package/utils/deep_assign.js +0 -22
  171. data/package/utils/deep_merge.js +0 -22
  172. data/package/utils/objectify.js +0 -3
@@ -23,33 +23,12 @@ describe('Config', () => {
23
23
  expect(config.publicPath).toEqual('http://foo.com/packs/')
24
24
  })
25
25
 
26
- test('should return extensions as listed in app config', () => {
27
- expect(config.extensions).toEqual([
28
- '.mjs',
29
- '.js',
30
- '.sass',
31
- '.scss',
32
- '.css',
33
- '.module.sass',
34
- '.module.scss',
35
- '.module.css',
36
- '.png',
37
- '.svg',
38
- '.gif',
39
- '.jpeg',
40
- '.jpg'
41
- ])
42
- })
43
-
44
- test('should return static assets extensions as listed in app config', () => {
45
- expect(config.static_assets_extensions).toEqual([
46
- '.jpg',
47
- '.jpeg',
48
- '.png',
49
- '.gif',
50
- '.tiff',
51
- '.ico',
52
- '.svg',
26
+ test('should return additional paths as listed in app config, with resolved paths', () => {
27
+ expect(config.additional_paths).toEqual([
28
+ 'app/assets',
29
+ '/etc/yarn',
30
+ 'some.config.js',
31
+ 'app/elm'
53
32
  ])
54
33
  })
55
34
  })
@@ -13,11 +13,13 @@ describe('DevServer', () => {
13
13
  process.env.RAILS_ENV = 'development'
14
14
  process.env.WEBPACKER_DEV_SERVER_HOST = '0.0.0.0'
15
15
  process.env.WEBPACKER_DEV_SERVER_PORT = 5000
16
+ process.env.WEBPACKER_DEV_SERVER_DISABLE_HOST_CHECK = false
16
17
 
17
18
  const devServer = require('../dev_server')
18
19
  expect(devServer).toBeDefined()
19
20
  expect(devServer.host).toEqual('0.0.0.0')
20
21
  expect(devServer.port).toEqual('5000')
22
+ expect(devServer.disable_host_check).toBe(false)
21
23
  })
22
24
 
23
25
  test('with custom env prefix', () => {
@@ -8,23 +8,34 @@ chdirTestApp()
8
8
  describe('Development environment', () => {
9
9
  afterAll(chdirCwd)
10
10
 
11
- describe('toWebpackConfig', () => {
11
+ describe('webpackConfig', () => {
12
12
  beforeEach(() => jest.resetModules())
13
13
 
14
- test('should use development config and environment', () => {
14
+ test('should use development config and environment including devServer if WEBPACK_DEV_SERVER', () => {
15
15
  process.env.RAILS_ENV = 'development'
16
16
  process.env.NODE_ENV = 'development'
17
- const { environment } = require('../index')
17
+ process.env.WEBPACK_DEV_SERVER = 'YES'
18
+ const { webpackConfig } = require('../index')
18
19
 
19
- const config = environment.toWebpackConfig()
20
- expect(config.output.path).toEqual(resolve('public', 'packs'))
21
- expect(config.output.publicPath).toEqual('/packs/')
22
- expect(config).toMatchObject({
20
+ expect(webpackConfig.output.path).toEqual(resolve('public', 'packs'))
21
+ expect(webpackConfig.output.publicPath).toEqual('/packs/')
22
+ expect(webpackConfig).toMatchObject({
23
23
  devServer: {
24
24
  host: 'localhost',
25
25
  port: 3035
26
26
  }
27
27
  })
28
28
  })
29
+
30
+ test('should use development config and environment if WEBPACK_DEV_SERVER', () => {
31
+ process.env.RAILS_ENV = 'development'
32
+ process.env.NODE_ENV = 'development'
33
+ process.env.WEBPACK_DEV_SERVER = undefined
34
+ const { webpackConfig } = require('../index')
35
+
36
+ expect(webpackConfig.output.path).toEqual(resolve('public', 'packs'))
37
+ expect(webpackConfig.output.publicPath).toEqual('/packs/')
38
+ expect(webpackConfig.devServer).toEqual(undefined)
39
+ })
29
40
  })
30
41
  })
@@ -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,55 @@
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-macros',
46
+ ['@babel/plugin-proposal-class-properties', { loose: true }],
47
+ ['@babel/plugin-transform-runtime', { helpers: false }],
48
+ isProductionEnv &&
49
+ moduleExists('babel-plugin-transform-react-remove-prop-types') && [
50
+ 'babel-plugin-transform-react-remove-prop-types',
51
+ { removeImport: true }
52
+ ]
53
+ ].filter(Boolean)
54
+ }
55
+ }
@@ -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(3)
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,113 @@
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 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')
14
+ const { moduleExists } = require('../utils/helpers')
59
15
 
60
16
  const getEntryObject = () => {
61
- const result = new ConfigObject()
62
- const glob = getExtensionsGlob()
17
+ const entries = {}
63
18
  const rootPath = join(config.source_path, config.source_entry_path)
64
- const paths = sync(join(rootPath, glob))
65
- paths.forEach((path) => {
19
+
20
+ globSync(`${rootPath}/**/*.*`).forEach((path) => {
66
21
  const namespace = relative(join(rootPath), dirname(path))
67
22
  const name = join(namespace, basename(path, extname(path)))
68
23
  let assetPaths = resolve(path)
69
24
 
70
25
  // Allows for multiple filetypes per entry (https://webpack.js.org/guides/entry-advanced/)
71
26
  // Transforms the config object value to an array with all values under the same name
72
- let previousPaths = result.get(name)
27
+ let previousPaths = entries[name]
73
28
  if (previousPaths) {
74
- previousPaths = Array.isArray(previousPaths) ? previousPaths : [previousPaths]
29
+ previousPaths = Array.isArray(previousPaths)
30
+ ? previousPaths
31
+ : [previousPaths]
75
32
  previousPaths.push(assetPaths)
76
33
  assetPaths = previousPaths
77
34
  }
78
35
 
79
- result.set(name, assetPaths)
36
+ entries[name] = assetPaths
80
37
  })
81
- return result
38
+
39
+ return entries
82
40
  }
83
41
 
84
42
  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)))
43
+ const result = [resolve(config.source_path)]
44
+
45
+ if (config.additional_paths) {
46
+ config.additional_paths.forEach((path) => result.push(resolve(path)))
89
47
  }
90
- result.append('node_modules', 'node_modules')
48
+ result.push('node_modules')
49
+
91
50
  return result
92
51
  }
93
52
 
94
- const getBaseConfig = () => new ConfigObject({
53
+ const getPlugins = () => {
54
+ const plugins = [
55
+ new webpack.EnvironmentPlugin(process.env),
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
+ if (moduleExists('css-loader') && moduleExists('mini-css-extract-plugin')) {
67
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
68
+ plugins.push(
69
+ new MiniCssExtractPlugin({
70
+ filename: isDevelopment ? '[name].css' : '[name].[contenthash:8].css',
71
+ chunkFilename: isDevelopment ? '[id].css' : '[id].[contenthash:8].css'
72
+ })
73
+ )
74
+ }
75
+
76
+ return plugins
77
+ }
78
+
79
+ module.exports = {
95
80
  mode: 'production',
96
81
  output: {
97
82
  filename: 'js/[name]-[contenthash].js',
98
83
  chunkFilename: 'js/[name]-[contenthash].chunk.js',
99
84
  hotUpdateChunkFilename: 'js/[id]-[hash].hot-update.js',
85
+ assetModuleFilename: 'static/[hash][ext][query]',
100
86
  path: config.outputPath,
101
87
  publicPath: config.publicPath
102
88
  },
103
-
89
+ entry: getEntryObject(),
104
90
  resolve: {
105
- extensions: config.extensions,
91
+ extensions: ['.js', '.mjs', '.ts', '.coffee'],
92
+ modules: getModulePaths(),
106
93
  plugins: [PnpWebpackPlugin]
107
94
  },
108
95
 
96
+ plugins: getPlugins(),
97
+
109
98
  resolveLoader: {
110
99
  modules: ['node_modules'],
111
100
  plugins: [PnpWebpackPlugin.moduleLoader(module)]
112
101
  },
113
102
 
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
- }
103
+ optimization: {
104
+ splitChunks: { chunks: 'all' },
157
105
 
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(),
106
+ runtimeChunk: 'single'
107
+ },
171
108
 
172
- resolve: {
173
- modules: this.resolvedModules.values()
174
- }
175
- })
109
+ module: {
110
+ strictExportPresence: true,
111
+ rules
176
112
  }
177
113
  }