webpacker 3.2.2 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -1
  3. data/Gemfile.lock +38 -38
  4. data/README.md +48 -49
  5. data/docs/css.md +31 -1
  6. data/docs/docker.md +1 -1
  7. data/docs/typescript.md +36 -1
  8. data/{exe → lib/install/bin}/webpack +7 -0
  9. data/{exe → lib/install/bin}/webpack-dev-server +7 -0
  10. data/lib/install/binstubs.rb +4 -0
  11. data/lib/install/config/webpacker.yml +3 -0
  12. data/lib/install/loaders/erb.js +1 -1
  13. data/lib/install/template.rb +1 -2
  14. data/lib/install/typescript.rb +1 -1
  15. data/lib/tasks/webpacker.rake +1 -0
  16. data/lib/tasks/webpacker/binstubs.rake +12 -0
  17. data/lib/tasks/webpacker/check_binstubs.rake +1 -1
  18. data/lib/webpacker.rb +1 -0
  19. data/lib/webpacker/compiler.rb +4 -2
  20. data/lib/webpacker/dev_server_runner.rb +1 -1
  21. data/lib/webpacker/env.rb +39 -0
  22. data/lib/webpacker/instance.rb +1 -12
  23. data/lib/webpacker/version.rb +1 -1
  24. data/package.json +2 -2
  25. data/package/__tests__/config.js +7 -4
  26. data/package/__tests__/dev_server.js +26 -0
  27. data/package/__tests__/env.js +28 -0
  28. data/package/__tests__/index.js +31 -0
  29. data/package/config.js +14 -30
  30. data/package/config_types/__tests__/config_list.js +0 -5
  31. data/package/config_types/config_list.js +0 -9
  32. data/package/dev_server.js +23 -0
  33. data/package/env.js +23 -0
  34. data/package/{__tests__/environment.js → environments/__tests__/base.js} +6 -6
  35. data/package/{environment.js → environments/base.js} +4 -4
  36. data/package/environments/development.js +4 -3
  37. data/package/environments/production.js +31 -25
  38. data/package/environments/test.js +2 -2
  39. data/package/index.js +10 -6
  40. data/package/rules/babel.js +8 -6
  41. data/package/rules/css.js +2 -38
  42. data/package/rules/file.js +9 -7
  43. data/package/rules/index.js +4 -0
  44. data/package/rules/module.css.js +3 -0
  45. data/package/rules/module.sass.js +8 -0
  46. data/package/rules/sass.js +5 -12
  47. data/package/utils/__tests__/get_style_rule.js +36 -0
  48. data/package/utils/get_style_rule.js +62 -0
  49. data/package/utils/helpers.js +17 -3
  50. data/test/env_test.rb +19 -0
  51. data/test/test_app/bin/webpack +15 -0
  52. data/test/test_app/bin/webpack-dev-server +15 -0
  53. data/test/test_app/config/webpacker.yml +3 -0
  54. data/test/test_helper.rb +3 -1
  55. data/webpacker.gemspec +0 -2
  56. data/yarn.lock +8 -4
  57. metadata +26 -10
@@ -8,11 +8,6 @@ test('new', () => {
8
8
  expect(list).toBeInstanceOf(Array)
9
9
  })
10
10
 
11
- test('set', () => {
12
- const list = new ConfigList()
13
- expect(list.set('key', 'value')).toEqual([{ key: 'key', value: 'value' }])
14
- })
15
-
16
11
  test('get', () => {
17
12
  const list = new ConfigList()
18
13
  list.append('key', 'value')
@@ -10,15 +10,6 @@ class ConfigList extends Array {
10
10
  return this[index].value
11
11
  }
12
12
 
13
- /**
14
- * @deprecated after the 3.0.2 release and will be removed in the next major release
15
- */
16
- set(key, value) {
17
- /* eslint no-console: 0 */
18
- console.warn('set is deprecated! Use append instead')
19
- return this.append(key, value)
20
- }
21
-
22
13
  append(key, value) {
23
14
  return this.add({ key, value })
24
15
  }
@@ -0,0 +1,23 @@
1
+ const { isBoolean, isEmpty } = require('./utils/helpers')
2
+ const config = require('./config')
3
+
4
+ const fetch = (key) => {
5
+ const value = process.env[key]
6
+ return isBoolean(value) ? JSON.parse(value) : value
7
+ }
8
+
9
+ const devServer = () => {
10
+ const devServerConfig = config.dev_server
11
+
12
+ if (devServerConfig) {
13
+ Object.keys(devServerConfig).forEach((key) => {
14
+ const envValue = fetch(`WEBPACKER_DEV_SERVER_${key.toUpperCase().replace(/_/g, '')}`)
15
+ if (isEmpty(envValue)) return devServerConfig[key]
16
+ devServerConfig[key] = envValue
17
+ })
18
+ }
19
+
20
+ return devServerConfig || {}
21
+ }
22
+
23
+ module.exports = devServer()
data/package/env.js ADDED
@@ -0,0 +1,23 @@
1
+ const { resolve } = require('path')
2
+ const { safeLoad } = require('js-yaml')
3
+ const { readFileSync } = require('fs')
4
+
5
+ const configPath = resolve('config', 'webpacker.yml')
6
+ const DEFAULT_ENV = 'production'
7
+
8
+ const env = () => {
9
+ const nodeEnv = process.env.NODE_ENV
10
+ const railsEnv = process.env.RAILS_ENV
11
+ const config = safeLoad(readFileSync(configPath), 'utf8')
12
+ const availableEnvironments = Object.keys(config).join('|')
13
+ const regex = new RegExp(availableEnvironments, 'g')
14
+
15
+ if (nodeEnv && nodeEnv.match(regex)) return nodeEnv
16
+ if (railsEnv && railsEnv.match(regex)) return railsEnv
17
+
18
+ /* eslint no-console: 0 */
19
+ console.warn(`NODE_ENV=${nodeEnv} and RAILS_ENV=${railsEnv} environment is not defined in config/webpacker.yml, falling back to ${DEFAULT_ENV}`)
20
+ return DEFAULT_ENV
21
+ }
22
+
23
+ module.exports = env()
@@ -3,14 +3,14 @@
3
3
  // environment.js expects to find config/webpacker.yml and resolved modules from
4
4
  // the root of a Rails project
5
5
 
6
- const chdirApp = () => process.chdir('test/test_app')
7
- const chdirCwd = () => process.chdir(process.cwd())
8
- chdirApp()
6
+ const { chdirTestApp, chdirCwd } = require('../../utils/helpers')
7
+
8
+ chdirTestApp()
9
9
 
10
10
  const { resolve } = require('path')
11
- const rules = require('../rules')
12
- const { ConfigList } = require('../config_types')
13
- const Environment = require('../environment')
11
+ const rules = require('../../rules')
12
+ const { ConfigList } = require('../../config_types')
13
+ const Environment = require('../base')
14
14
 
15
15
  describe('Environment', () => {
16
16
  afterAll(chdirCwd)
@@ -12,9 +12,9 @@ const ExtractTextPlugin = require('extract-text-webpack-plugin')
12
12
  const ManifestPlugin = require('webpack-manifest-plugin')
13
13
  const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
14
14
 
15
- const { ConfigList, ConfigObject } = require('./config_types')
16
- const rules = require('./rules')
17
- const config = require('./config')
15
+ const { ConfigList, ConfigObject } = require('../config_types')
16
+ const rules = require('../rules')
17
+ const config = require('../config')
18
18
 
19
19
  const getLoaderList = () => {
20
20
  const result = new ConfigList()
@@ -85,7 +85,7 @@ const getBaseConfig = () =>
85
85
  }
86
86
  })
87
87
 
88
- module.exports = class Environment {
88
+ module.exports = class Base {
89
89
  constructor() {
90
90
  this.loaders = getLoaderList()
91
91
  this.plugins = getPluginList()
@@ -1,8 +1,9 @@
1
1
  const webpack = require('webpack')
2
- const Environment = require('../environment')
3
- const { dev_server: devServer, outputPath: contentBase, publicPath } = require('../config')
2
+ const Base = require('./base')
3
+ const devServer = require('../dev_server')
4
+ const { outputPath: contentBase, publicPath } = require('../config')
4
5
 
5
- module.exports = class extends Environment {
6
+ module.exports = class extends Base {
6
7
  constructor() {
7
8
  super()
8
9
 
@@ -1,40 +1,46 @@
1
1
  const webpack = require('webpack')
2
2
  const CompressionPlugin = require('compression-webpack-plugin')
3
3
  const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
4
- const Environment = require('../environment')
4
+ const Base = require('./base')
5
5
 
6
- module.exports = class extends Environment {
6
+ module.exports = class extends Base {
7
7
  constructor() {
8
8
  super()
9
9
 
10
10
  this.plugins.append('ModuleConcatenation', new webpack.optimize.ModuleConcatenationPlugin())
11
11
 
12
- this.plugins.append('UglifyJs', new UglifyJsPlugin({
13
- parallel: true,
14
- cache: true,
15
- sourceMap: true,
16
- uglifyOptions: {
17
- ie8: false,
18
- ecma: 8,
19
- warnings: false,
20
- mangle: {
21
- safari10: true
22
- },
23
- compress: {
12
+ this.plugins.append(
13
+ 'UglifyJs',
14
+ new UglifyJsPlugin({
15
+ parallel: true,
16
+ cache: true,
17
+ sourceMap: true,
18
+ uglifyOptions: {
19
+ ie8: false,
20
+ ecma: 8,
24
21
  warnings: false,
25
- comparisons: false
26
- },
27
- output: {
28
- ascii_only: true
22
+ mangle: {
23
+ safari10: true
24
+ },
25
+ compress: {
26
+ warnings: false,
27
+ comparisons: false
28
+ },
29
+ output: {
30
+ ascii_only: true
31
+ }
29
32
  }
30
- }
31
- }))
33
+ })
34
+ )
32
35
 
33
- this.plugins.append('Compression', new CompressionPlugin({
34
- asset: '[path].gz[query]',
35
- algorithm: 'gzip',
36
- test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
37
- }))
36
+ this.plugins.append(
37
+ 'Compression',
38
+ new CompressionPlugin({
39
+ asset: '[path].gz[query]',
40
+ algorithm: 'gzip',
41
+ test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
42
+ })
43
+ )
38
44
 
39
45
  this.config.merge({
40
46
  devtool: 'nosources-source-map',
@@ -1,3 +1,3 @@
1
- const Environment = require('../environment')
1
+ const Base = require('./base')
2
2
 
3
- module.exports = class extends Environment {}
3
+ module.exports = class extends Base {}
data/package/index.js CHANGED
@@ -3,18 +3,22 @@
3
3
 
4
4
  const { resolve } = require('path')
5
5
  const { existsSync } = require('fs')
6
- const Environment = require('./environment')
7
- const config = require('./config')
6
+ const Environment = require('./environments/base')
8
7
  const loaders = require('./rules')
8
+ const env = require('./env')
9
+ const config = require('./config')
10
+ const devServer = require('./dev_server')
9
11
 
10
12
  const createEnvironment = () => {
11
- const path = resolve(__dirname, 'environments', `${process.env.NODE_ENV}.js`)
13
+ const path = resolve(__dirname, 'environments', `${env}.js`)
12
14
  const constructor = existsSync(path) ? require(path) : Environment
13
15
  return new constructor()
14
16
  }
15
17
 
16
- const environment = createEnvironment()
17
-
18
18
  module.exports = {
19
- environment, config, loaders, Environment
19
+ config,
20
+ devServer,
21
+ environment: createEnvironment(),
22
+ Environment,
23
+ loaders
20
24
  }
@@ -1,13 +1,15 @@
1
1
  const { join } = require('path')
2
- const { cache_path } = require('../config')
2
+ const { cache_path: cachePath } = require('../config')
3
3
 
4
4
  module.exports = {
5
5
  test: /\.(js|jsx)?(\.erb)?$/,
6
6
  exclude: /node_modules/,
7
- use: [{
8
- loader: 'babel-loader',
9
- options: {
10
- cacheDirectory: join(cache_path, 'babel-loader')
7
+ use: [
8
+ {
9
+ loader: 'babel-loader',
10
+ options: {
11
+ cacheDirectory: join(cachePath, 'babel-loader')
12
+ }
11
13
  }
12
- }]
14
+ ]
13
15
  }
data/package/rules/css.js CHANGED
@@ -1,39 +1,3 @@
1
- const ExtractTextPlugin = require('extract-text-webpack-plugin')
2
- const path = require('path')
3
- const { dev_server: devServer } = require('../config')
1
+ const getStyleRule = require('../utils/get_style_rule')
4
2
 
5
- const postcssConfigPath = path.resolve(process.cwd(), '.postcssrc.yml')
6
- const isProduction = process.env.NODE_ENV === 'production'
7
- const inDevServer = process.argv.find(v => v.includes('webpack-dev-server'))
8
- const isHMR = inDevServer && (devServer && devServer.hmr)
9
- const extractCSS = !(isHMR) || isProduction
10
-
11
- const styleLoader = {
12
- loader: 'style-loader',
13
- options: {
14
- hmr: isHMR,
15
- sourceMap: true
16
- }
17
- }
18
-
19
- const extractOptions = {
20
- fallback: styleLoader,
21
- use: [
22
- { loader: 'css-loader', options: { minimize: isProduction, sourceMap: true, importLoaders: 2 } },
23
- { loader: 'postcss-loader', options: { sourceMap: true, config: { path: postcssConfigPath } } }
24
- ]
25
- }
26
-
27
- // For production extract styles to a separate bundle
28
- const extractCSSLoader = {
29
- test: /\.(css)$/i,
30
- use: ExtractTextPlugin.extract(extractOptions)
31
- }
32
-
33
- // For hot-reloading use regular loaders
34
- const inlineCSSLoader = {
35
- test: /\.(css)$/i,
36
- use: [styleLoader].concat(extractOptions.use)
37
- }
38
-
39
- module.exports = extractCSS ? extractCSSLoader : inlineCSSLoader
3
+ module.exports = getStyleRule(/\.(css)$/i)
@@ -1,13 +1,15 @@
1
1
  const { join } = require('path')
2
- const { source_path } = require('../config')
2
+ const { source_path: sourcePath } = require('../config')
3
3
 
4
4
  module.exports = {
5
5
  test: /\.(jpg|jpeg|png|gif|tiff|ico|svg|eot|otf|ttf|woff|woff2)$/i,
6
- use: [{
7
- loader: 'file-loader',
8
- options: {
9
- name: '[path][name]-[hash].[ext]',
10
- context: join(source_path)
6
+ use: [
7
+ {
8
+ loader: 'file-loader',
9
+ options: {
10
+ name: '[path][name]-[hash].[ext]',
11
+ context: join(sourcePath)
12
+ }
11
13
  }
12
- }]
14
+ ]
13
15
  }
@@ -2,10 +2,14 @@ const babel = require('./babel')
2
2
  const file = require('./file')
3
3
  const css = require('./css')
4
4
  const sass = require('./sass')
5
+ const moduleCss = require('./module.css')
6
+ const moduleSass = require('./module.sass')
5
7
 
6
8
  module.exports = {
7
9
  babel,
8
10
  css,
9
11
  sass,
12
+ moduleCss,
13
+ moduleSass,
10
14
  file
11
15
  }
@@ -0,0 +1,3 @@
1
+ const getStyleRule = require('../utils/get_style_rule')
2
+
3
+ module.exports = getStyleRule(/\.(css)$/i, true)
@@ -0,0 +1,8 @@
1
+ const getStyleRule = require('../utils/get_style_rule')
2
+
3
+ module.exports = getStyleRule(/\.(scss|sass)$/i, true, [
4
+ {
5
+ loader: 'sass-loader',
6
+ options: { sourceMap: true }
7
+ }
8
+ ])
@@ -1,15 +1,8 @@
1
- const cssLoader = require('./css')
2
- const deepMerge = require('../utils/deep_merge')
1
+ const getStyleRule = require('../utils/get_style_rule')
3
2
 
4
- // Duplicate and remove css loader object reference
5
- let sassLoader = JSON.parse(JSON.stringify(cssLoader))
6
-
7
- sassLoader = deepMerge(sassLoader, {
8
- test: /\.(scss|sass)$/i,
9
- use: [{
3
+ module.exports = getStyleRule(/\.(scss|sass)$/i, false, [
4
+ {
10
5
  loader: 'sass-loader',
11
6
  options: { sourceMap: true }
12
- }]
13
- })
14
-
15
- module.exports = sassLoader
7
+ }
8
+ ])
@@ -0,0 +1,36 @@
1
+ const { chdirTestApp, chdirCwd } = require('../helpers')
2
+
3
+ chdirTestApp()
4
+
5
+ const getStyleRule = require('../get_style_rule')
6
+
7
+ describe('getStyleRule', () => {
8
+ afterAll(chdirCwd)
9
+
10
+ test('excludes modules by default', () => {
11
+ const cssRule = getStyleRule(/\.(css)$/i)
12
+ const expectation = {
13
+ test: /\.(css)$/i,
14
+ exclude: /\.module\.[a-z]+$/
15
+ }
16
+
17
+ expect(cssRule).toMatchObject(expectation)
18
+ })
19
+
20
+ test('includes modules if set to true', () => {
21
+ const cssRule = getStyleRule(/\.(scss)$/i, true)
22
+ const expectation = {
23
+ test: /\.(scss)$/i,
24
+ include: /\.module\.[a-z]+$/
25
+ }
26
+
27
+ expect(cssRule).toMatchObject(expectation)
28
+ })
29
+
30
+ test('adds extra preprocessors if supplied', () => {
31
+ const expectation = [{ foo: 'bar' }]
32
+ const cssRule = getStyleRule(/\.(css)$/i, true, expectation)
33
+
34
+ expect(cssRule.use).toMatchObject(expect.arrayContaining(expectation))
35
+ })
36
+ })
@@ -0,0 +1,62 @@
1
+ const ExtractTextPlugin = require('extract-text-webpack-plugin')
2
+ const path = require('path')
3
+ const devServer = require('../dev_server')
4
+
5
+ const postcssConfigPath = path.resolve(process.cwd(), '.postcssrc.yml')
6
+ const isProduction = process.env.NODE_ENV === 'production'
7
+ const inDevServer = process.argv.find(v => v.includes('webpack-dev-server'))
8
+ const isHMR = inDevServer && (devServer && devServer.hmr)
9
+ const extractCSS = !isHMR || isProduction
10
+
11
+ const styleLoader = {
12
+ loader: 'style-loader',
13
+ options: {
14
+ hmr: isHMR,
15
+ sourceMap: true
16
+ }
17
+ }
18
+
19
+ const getStyleRule = (test, modules = false, preprocessors = []) => {
20
+ const extractOptions = {
21
+ fallback: styleLoader,
22
+ use: [
23
+ {
24
+ loader: 'css-loader',
25
+ options: {
26
+ minimize: isProduction,
27
+ sourceMap: true,
28
+ importLoaders: 2,
29
+ modules
30
+ }
31
+ },
32
+ {
33
+ loader: 'postcss-loader',
34
+ options: {
35
+ sourceMap: true,
36
+ config: { path: postcssConfigPath }
37
+ }
38
+ },
39
+ ...preprocessors
40
+ ]
41
+ }
42
+
43
+ const options = modules ? { include: /\.module\.[a-z]+$/ } : { exclude: /\.module\.[a-z]+$/ }
44
+
45
+ // For production extract styles to a separate bundle
46
+ const extractCSSLoader = Object.assign(
47
+ {},
48
+ { test, use: ExtractTextPlugin.extract(extractOptions) },
49
+ options
50
+ )
51
+
52
+ // For hot-reloading use regular loaders
53
+ const inlineCSSLoader = Object.assign(
54
+ {},
55
+ { test, use: [styleLoader].concat(extractOptions.use) },
56
+ options
57
+ )
58
+
59
+ return extractCSS ? extractCSSLoader : inlineCSSLoader
60
+ }
61
+
62
+ module.exports = getStyleRule