webpacker 3.0.2 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.eslintignore +1 -0
- data/.travis.yml +10 -0
- data/CHANGELOG.md +110 -0
- data/Gemfile.lock +69 -67
- data/MIT-LICENSE +1 -1
- data/README.md +86 -30
- data/docs/assets.md +4 -4
- data/docs/cloud9.md +310 -0
- data/docs/css.md +32 -3
- data/docs/deployment.md +42 -4
- data/docs/docker.md +49 -0
- data/docs/env.md +5 -5
- data/docs/folder-structure.md +2 -2
- data/docs/testing.md +14 -34
- data/docs/troubleshooting.md +40 -4
- data/docs/typescript.md +2 -2
- data/docs/webpack-dev-server.md +21 -4
- data/docs/webpack.md +103 -25
- data/gemfiles/Gemfile-rails-edge +13 -0
- data/gemfiles/Gemfile-rails.4.2.x +10 -0
- data/gemfiles/Gemfile-rails.5.0.x +10 -0
- data/gemfiles/Gemfile-rails.5.1.x +10 -0
- data/lib/install/angular.rb +5 -5
- data/lib/install/config/webpacker.yml +7 -0
- data/lib/install/elm.rb +7 -7
- data/lib/install/examples/vue/hello_vue.js +30 -4
- data/lib/install/react.rb +5 -5
- data/lib/install/template.rb +19 -9
- data/lib/install/vue.rb +4 -4
- data/lib/tasks/installers.rake +2 -2
- data/lib/tasks/webpacker.rake +7 -6
- data/lib/tasks/webpacker/check_binstubs.rake +3 -3
- data/lib/tasks/webpacker/compile.rake +15 -8
- data/lib/tasks/webpacker/install.rake +4 -4
- data/lib/tasks/webpacker/verify_install.rake +1 -1
- data/lib/webpacker/compiler.rb +6 -6
- data/lib/webpacker/dev_server.rb +2 -2
- data/lib/webpacker/dev_server_proxy.rb +2 -1
- data/lib/webpacker/dev_server_runner.rb +4 -4
- data/lib/webpacker/helper.rb +3 -3
- data/lib/webpacker/manifest.rb +2 -2
- data/lib/webpacker/railtie.rb +41 -2
- data/lib/webpacker/runner.rb +1 -1
- data/lib/webpacker/version.rb +1 -1
- data/package.json +29 -21
- data/package/asset_host.js +4 -5
- data/package/config.js +7 -1
- data/package/config_types/__tests__/config_list.js +123 -0
- data/package/config_types/__tests__/config_object.js +43 -0
- data/package/config_types/config_list.js +83 -0
- data/package/config_types/config_object.js +55 -0
- data/package/config_types/index.js +7 -0
- data/package/environment.js +64 -40
- data/package/environments/development.js +31 -34
- data/package/environments/production.js +14 -11
- data/package/index.js +7 -2
- data/package/{loaders → rules}/babel.js +6 -4
- data/package/{loaders → rules}/coffee.js +3 -1
- data/package/rules/css.js +39 -0
- data/package/rules/elm.js +23 -0
- data/package/rules/erb.js +11 -0
- data/package/{loaders → rules}/file.js +1 -1
- data/package/rules/index.js +23 -0
- data/package/rules/sass.js +15 -0
- data/package/{loaders → rules}/typescript.js +3 -1
- data/package/rules/url.js +13 -0
- data/package/rules/vue.js +13 -0
- data/package/utils/__tests__/deep_assign.js +11 -0
- data/package/utils/__tests__/deep_merge.js +10 -0
- data/package/utils/__tests__/objectify.js +9 -0
- data/package/utils/deep_assign.js +22 -0
- data/package/utils/deep_merge.js +23 -0
- data/package/utils/helpers.js +32 -0
- data/package/utils/objectify.js +4 -0
- data/test/command_test.rb +1 -1
- data/test/compiler_test.rb +5 -1
- data/test/configuration_test.rb +1 -1
- data/test/dev_server_test.rb +1 -1
- data/test/helper_test.rb +15 -10
- data/test/manifest_test.rb +1 -1
- data/test/rake_tasks_test.rb +29 -0
- data/test/test_app/Rakefile +3 -0
- data/test/test_app/config/application.rb +11 -0
- data/test/test_app/config/environment.rb +4 -0
- data/test/{webpacker_test_helper.rb → test_helper.rb} +3 -14
- data/webpacker.gemspec +1 -1
- data/yarn.lock +1552 -829
- metadata +43 -16
- data/package/loaders/elm.js +0 -19
- data/package/loaders/erb.js +0 -9
- data/package/loaders/style.js +0 -31
- data/package/loaders/vue.js +0 -12
- data/test/test_app/config/secrets.yml +0 -5
@@ -0,0 +1,55 @@
|
|
1
|
+
const objectify = require('../utils/objectify')
|
2
|
+
const deepAssign = require('../utils/deep_assign')
|
3
|
+
const deepMerge = require('../utils/deep_merge')
|
4
|
+
const { isStrPath, prettyPrint } = require('../utils/helpers')
|
5
|
+
|
6
|
+
/**
|
7
|
+
* @class
|
8
|
+
* @extends { Object }
|
9
|
+
*/
|
10
|
+
class ConfigObject extends Object {
|
11
|
+
constructor(props = {}) {
|
12
|
+
super()
|
13
|
+
this.merge(props)
|
14
|
+
}
|
15
|
+
|
16
|
+
get(key) {
|
17
|
+
return isStrPath(key) ? objectify(key, this) : this[key]
|
18
|
+
}
|
19
|
+
|
20
|
+
set(key, value) {
|
21
|
+
Object.assign(this, deepAssign(this, key, value))
|
22
|
+
return this
|
23
|
+
}
|
24
|
+
|
25
|
+
delete(key) {
|
26
|
+
let obj = this
|
27
|
+
let propKey = key
|
28
|
+
|
29
|
+
if (isStrPath(key)) {
|
30
|
+
const keys = key.split('.')
|
31
|
+
propKey = keys.pop()
|
32
|
+
const parentObjPath = keys.join('.')
|
33
|
+
obj = objectify(parentObjPath, this)
|
34
|
+
}
|
35
|
+
|
36
|
+
if (!obj) throw new Error(`Prop not found: ${key} in ${prettyPrint(obj)}`)
|
37
|
+
delete obj[propKey]
|
38
|
+
|
39
|
+
return this
|
40
|
+
}
|
41
|
+
|
42
|
+
toObject() {
|
43
|
+
const object = {}
|
44
|
+
/* eslint no-return-assign: 0 */
|
45
|
+
Object.keys(this).forEach(key => (object[key] = this[key]))
|
46
|
+
return object
|
47
|
+
}
|
48
|
+
|
49
|
+
merge(config) {
|
50
|
+
Object.assign(this, deepMerge(this, config))
|
51
|
+
return this
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
module.exports = ConfigObject
|
data/package/environment.js
CHANGED
@@ -1,36 +1,38 @@
|
|
1
1
|
/* eslint global-require: 0 */
|
2
2
|
/* eslint import/no-dynamic-require: 0 */
|
3
3
|
|
4
|
-
const {
|
4
|
+
const {
|
5
|
+
basename, dirname, join, relative, resolve
|
6
|
+
} = require('path')
|
5
7
|
const { sync } = require('glob')
|
6
8
|
const extname = require('path-complete-extname')
|
7
9
|
|
8
10
|
const webpack = require('webpack')
|
9
11
|
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
10
12
|
const ManifestPlugin = require('webpack-manifest-plugin')
|
13
|
+
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
|
11
14
|
|
15
|
+
const { ConfigList, ConfigObject } = require('./config_types')
|
16
|
+
const rules = require('./rules')
|
12
17
|
const config = require('./config')
|
13
18
|
const assetHost = require('./asset_host')
|
14
19
|
|
15
|
-
|
16
|
-
const result = new
|
17
|
-
|
18
|
-
paths.forEach((path) => {
|
19
|
-
const name = basename(path, extname(path))
|
20
|
-
result.set(name, require(path))
|
21
|
-
})
|
20
|
+
const getLoaderList = () => {
|
21
|
+
const result = new ConfigList()
|
22
|
+
Object.keys(rules).forEach(key => result.append(key, rules[key]))
|
22
23
|
return result
|
23
24
|
}
|
24
25
|
|
25
|
-
|
26
|
-
const result = new
|
27
|
-
result.
|
28
|
-
result.
|
29
|
-
result.
|
26
|
+
const getPluginList = () => {
|
27
|
+
const result = new ConfigList()
|
28
|
+
result.append('Environment', new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(process.env))))
|
29
|
+
result.append('CaseSensitivePaths', new CaseSensitivePathsPlugin())
|
30
|
+
result.append('ExtractText', new ExtractTextPlugin('[name]-[contenthash].css'))
|
31
|
+
result.append('Manifest', new ManifestPlugin({ publicPath: assetHost.publicPath, writeToFileEmit: true }))
|
30
32
|
return result
|
31
33
|
}
|
32
34
|
|
33
|
-
|
35
|
+
const getExtensionsGlob = () => {
|
34
36
|
const { extensions } = config
|
35
37
|
if (!extensions.length) {
|
36
38
|
throw new Error('You must configure at least one extension to compile in webpacker.yml')
|
@@ -38,58 +40,80 @@ function getExtensionsGlob() {
|
|
38
40
|
return extensions.length === 1 ? `**/${extensions[0]}` : `**/*{${extensions.join(',')}}`
|
39
41
|
}
|
40
42
|
|
41
|
-
|
42
|
-
const result =
|
43
|
+
const getEntryObject = () => {
|
44
|
+
const result = new ConfigObject()
|
43
45
|
const glob = getExtensionsGlob()
|
44
46
|
const rootPath = join(config.source_path, config.source_entry_path)
|
45
47
|
const paths = sync(join(rootPath, glob))
|
46
48
|
paths.forEach((path) => {
|
47
49
|
const namespace = relative(join(rootPath), dirname(path))
|
48
50
|
const name = join(namespace, basename(path, extname(path)))
|
49
|
-
result
|
51
|
+
result.set(name, resolve(path))
|
50
52
|
})
|
51
53
|
return result
|
52
54
|
}
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
+
const getModulePaths = () => {
|
57
|
+
const result = new ConfigList()
|
58
|
+
result.append('source', resolve(config.source_path))
|
59
|
+
result.append('node_modules', 'node_modules')
|
56
60
|
if (config.resolved_paths) {
|
57
|
-
|
61
|
+
config.resolved_paths.forEach(path => result.append(basename(path), path))
|
58
62
|
}
|
59
63
|
return result
|
60
64
|
}
|
61
65
|
|
66
|
+
const getBaseConfig = () =>
|
67
|
+
new ConfigObject({
|
68
|
+
output: {
|
69
|
+
filename: '[name]-[chunkhash].js',
|
70
|
+
chunkFilename: '[name]-[chunkhash].chunk.js',
|
71
|
+
path: assetHost.path,
|
72
|
+
publicPath: assetHost.publicPath
|
73
|
+
},
|
74
|
+
|
75
|
+
resolve: {
|
76
|
+
extensions: config.extensions
|
77
|
+
},
|
78
|
+
|
79
|
+
resolveLoader: {
|
80
|
+
modules: ['node_modules']
|
81
|
+
},
|
82
|
+
|
83
|
+
node: {
|
84
|
+
dgram: 'empty',
|
85
|
+
fs: 'empty',
|
86
|
+
net: 'empty',
|
87
|
+
tls: 'empty',
|
88
|
+
child_process: 'empty'
|
89
|
+
}
|
90
|
+
})
|
91
|
+
|
62
92
|
module.exports = class Environment {
|
63
93
|
constructor() {
|
64
|
-
this.loaders =
|
65
|
-
this.plugins =
|
94
|
+
this.loaders = getLoaderList()
|
95
|
+
this.plugins = getPluginList()
|
96
|
+
this.config = getBaseConfig()
|
97
|
+
this.entry = getEntryObject()
|
98
|
+
this.resolvedModules = getModulePaths()
|
66
99
|
}
|
67
100
|
|
68
101
|
toWebpackConfig() {
|
69
|
-
return {
|
70
|
-
entry:
|
71
|
-
|
72
|
-
output: {
|
73
|
-
filename: '[name]-[chunkhash].js',
|
74
|
-
chunkFilename: '[name]-[chunkhash].chunk.js',
|
75
|
-
path: assetHost.path,
|
76
|
-
publicPath: assetHost.publicPath
|
77
|
-
},
|
102
|
+
return this.config.merge({
|
103
|
+
entry: this.entry.toObject(),
|
78
104
|
|
79
105
|
module: {
|
80
|
-
|
106
|
+
strictExportPresence: true,
|
107
|
+
rules: [
|
108
|
+
{ oneOf: this.loaders.values() }
|
109
|
+
]
|
81
110
|
},
|
82
111
|
|
83
|
-
plugins:
|
112
|
+
plugins: this.plugins.values(),
|
84
113
|
|
85
114
|
resolve: {
|
86
|
-
|
87
|
-
modules: getModulePaths()
|
88
|
-
},
|
89
|
-
|
90
|
-
resolveLoader: {
|
91
|
-
modules: ['node_modules']
|
115
|
+
modules: this.resolvedModules.values()
|
92
116
|
}
|
93
|
-
}
|
117
|
+
})
|
94
118
|
}
|
95
119
|
}
|
@@ -8,43 +8,40 @@ module.exports = class extends Environment {
|
|
8
8
|
super()
|
9
9
|
|
10
10
|
if (devServer.hmr) {
|
11
|
-
this.plugins.
|
12
|
-
this.plugins.
|
11
|
+
this.plugins.append('HotModuleReplacement', new webpack.HotModuleReplacementPlugin())
|
12
|
+
this.plugins.append('NamedModules', new webpack.NamedModulesPlugin())
|
13
|
+
this.config.output.filename = '[name]-[hash].js'
|
13
14
|
}
|
14
|
-
}
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
}
|
21
|
-
result.output.pathinfo = true
|
22
|
-
result.devtool = 'cheap-eval-source-map'
|
23
|
-
result.devServer = {
|
24
|
-
clientLogLevel: 'none',
|
25
|
-
compress: true,
|
26
|
-
disableHostCheck: devServer.disable_host_check,
|
27
|
-
host: devServer.host,
|
28
|
-
port: devServer.port,
|
29
|
-
https: devServer.https,
|
30
|
-
hot: devServer.hmr,
|
31
|
-
contentBase: assetHost.path,
|
32
|
-
inline: devServer.inline,
|
33
|
-
useLocalIp: devServer.use_local_ip,
|
34
|
-
public: devServer.public,
|
35
|
-
publicPath: assetHost.publicPath,
|
36
|
-
historyApiFallback: true,
|
37
|
-
headers: {
|
38
|
-
'Access-Control-Allow-Origin': '*'
|
16
|
+
this.config.merge({
|
17
|
+
devtool: 'cheap-module-source-map',
|
18
|
+
output: {
|
19
|
+
pathinfo: true
|
39
20
|
},
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
21
|
+
devServer: {
|
22
|
+
clientLogLevel: 'none',
|
23
|
+
compress: devServer.compress,
|
24
|
+
quiet: devServer.quiet,
|
25
|
+
disableHostCheck: devServer.disable_host_check,
|
26
|
+
host: devServer.host,
|
27
|
+
port: devServer.port,
|
28
|
+
https: devServer.https,
|
29
|
+
hot: devServer.hmr,
|
30
|
+
contentBase: assetHost.path,
|
31
|
+
inline: devServer.inline,
|
32
|
+
useLocalIp: devServer.use_local_ip,
|
33
|
+
public: devServer.public,
|
34
|
+
publicPath: assetHost.publicPath,
|
35
|
+
historyApiFallback: {
|
36
|
+
disableDotRule: true
|
37
|
+
},
|
38
|
+
headers: devServer.headers,
|
39
|
+
overlay: devServer.overlay,
|
40
|
+
stats: {
|
41
|
+
errorDetails: true
|
42
|
+
},
|
43
|
+
watchOptions: devServer.watch_options
|
46
44
|
}
|
47
|
-
}
|
48
|
-
return result
|
45
|
+
})
|
49
46
|
}
|
50
47
|
}
|
@@ -6,29 +6,32 @@ module.exports = class extends Environment {
|
|
6
6
|
constructor() {
|
7
7
|
super()
|
8
8
|
|
9
|
-
this.plugins.
|
9
|
+
this.plugins.append('ModuleConcatenation', new webpack.optimize.ModuleConcatenationPlugin())
|
10
10
|
|
11
|
-
this.plugins.
|
11
|
+
this.plugins.append('UglifyJs', new webpack.optimize.UglifyJsPlugin({
|
12
12
|
sourceMap: true,
|
13
|
+
mangle: {
|
14
|
+
safari10: true
|
15
|
+
},
|
13
16
|
compress: {
|
14
|
-
warnings: false
|
17
|
+
warnings: false,
|
18
|
+
comparisons: false
|
15
19
|
},
|
16
20
|
output: {
|
17
|
-
comments: false
|
21
|
+
comments: false,
|
22
|
+
ascii_only: true
|
18
23
|
}
|
19
24
|
}))
|
20
25
|
|
21
|
-
this.plugins.
|
26
|
+
this.plugins.append('Compression', new CompressionPlugin({
|
22
27
|
asset: '[path].gz[query]',
|
23
28
|
algorithm: 'gzip',
|
24
29
|
test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
|
25
30
|
}))
|
26
|
-
}
|
27
31
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
return result
|
32
|
+
this.config.merge({
|
33
|
+
devtool: 'nosources-source-map',
|
34
|
+
stats: 'normal'
|
35
|
+
})
|
33
36
|
}
|
34
37
|
}
|
data/package/index.js
CHANGED
@@ -4,8 +4,11 @@
|
|
4
4
|
const { resolve } = require('path')
|
5
5
|
const { existsSync } = require('fs')
|
6
6
|
const Environment = require('./environment')
|
7
|
+
const config = require('./config')
|
8
|
+
const assetHost = require('./asset_host')
|
9
|
+
const loaders = require('./rules')
|
7
10
|
|
8
|
-
|
11
|
+
const createEnvironment = () => {
|
9
12
|
const path = resolve(__dirname, 'environments', `${process.env.NODE_ENV}.js`)
|
10
13
|
const constructor = existsSync(path) ? require(path) : Environment
|
11
14
|
return new constructor()
|
@@ -13,4 +16,6 @@ function createEnvironment() {
|
|
13
16
|
|
14
17
|
const environment = createEnvironment()
|
15
18
|
|
16
|
-
module.exports = {
|
19
|
+
module.exports = {
|
20
|
+
environment, config, assetHost, loaders, Environment
|
21
|
+
}
|
@@ -4,8 +4,10 @@ const { cache_path } = require('../config')
|
|
4
4
|
module.exports = {
|
5
5
|
test: /\.(js|jsx)?(\.erb)?$/,
|
6
6
|
exclude: /node_modules/,
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
use: [{
|
8
|
+
loader: 'babel-loader',
|
9
|
+
options: {
|
10
|
+
cacheDirectory: join(cache_path, 'babel-loader')
|
11
|
+
}
|
12
|
+
}]
|
11
13
|
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
2
|
+
const path = require('path')
|
3
|
+
const { dev_server: devServer } = require('../config')
|
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 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
|
@@ -0,0 +1,23 @@
|
|
1
|
+
const { resolve } = require('path')
|
2
|
+
|
3
|
+
const isProduction = process.env.NODE_ENV === 'production'
|
4
|
+
const elmSource = resolve(process.cwd())
|
5
|
+
const elmMake = `${elmSource}/node_modules/.bin/elm-make`
|
6
|
+
|
7
|
+
const elmDefaultOptions = { cwd: elmSource, pathToMake: elmMake }
|
8
|
+
const developmentOptions = Object.assign(elmDefaultOptions, {
|
9
|
+
verbose: true,
|
10
|
+
warn: true,
|
11
|
+
debug: true
|
12
|
+
})
|
13
|
+
|
14
|
+
const elmWebpackLoader = {
|
15
|
+
loader: 'elm-webpack-loader',
|
16
|
+
options: isProduction ? elmDefaultOptions : developmentOptions
|
17
|
+
}
|
18
|
+
|
19
|
+
module.exports = {
|
20
|
+
test: /\.elm(\.erb)?$/,
|
21
|
+
exclude: [/elm-stuff/, /node_modules/],
|
22
|
+
use: isProduction ? [elmWebpackLoader] : [{ loader: 'elm-hot-loader' }, elmWebpackLoader]
|
23
|
+
}
|