webpacker 2.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +21 -21
- data/CHANGELOG.md +107 -4
- data/Gemfile +3 -1
- data/Gemfile.lock +15 -8
- data/README.md +137 -937
- data/docs/assets.md +106 -0
- data/docs/css.md +82 -0
- data/docs/deployment.md +39 -0
- data/docs/env.md +62 -0
- data/docs/es6.md +53 -0
- data/docs/folder-structure.md +66 -0
- data/docs/misc.md +23 -0
- data/docs/props.md +105 -0
- data/docs/testing.md +45 -0
- data/docs/troubleshooting.md +65 -0
- data/docs/typescript.md +115 -0
- data/docs/webpack-dev-server.md +32 -0
- data/docs/webpack.md +108 -0
- data/docs/yarn.md +12 -0
- data/lib/install/angular.rb +4 -7
- data/lib/install/bin/webpack-dev-server.tt +35 -11
- data/lib/install/bin/webpack.tt +3 -4
- data/lib/install/config/.babelrc +1 -0
- data/lib/install/config/.postcssrc.yml +1 -2
- data/lib/install/config/webpack/development.js +2 -31
- data/lib/install/config/webpack/environment.js +3 -0
- data/lib/install/config/webpack/production.js +2 -34
- data/lib/install/config/webpack/test.js +2 -5
- data/lib/install/config/webpacker.yml +20 -2
- data/lib/install/elm.rb +6 -11
- data/lib/install/examples/vue/hello_vue.js +31 -2
- data/lib/install/react.rb +2 -5
- data/lib/install/template.rb +3 -8
- data/lib/install/vue.rb +4 -7
- data/lib/tasks/webpacker.rake +1 -1
- data/lib/tasks/webpacker/{check_webpack_binstubs.rake → check_binstubs.rake} +3 -2
- data/lib/tasks/webpacker/check_node.rake +8 -6
- data/lib/tasks/webpacker/check_yarn.rake +2 -2
- data/lib/tasks/webpacker/clobber.rake +2 -3
- data/lib/tasks/webpacker/compile.rake +16 -18
- data/lib/tasks/webpacker/verify_install.rake +5 -5
- data/lib/tasks/webpacker/yarn_install.rake +1 -1
- data/lib/webpacker.rb +15 -11
- data/lib/webpacker/commands.rb +22 -0
- data/lib/webpacker/compiler.rb +66 -10
- data/lib/webpacker/configuration.rb +54 -38
- data/lib/webpacker/dev_server.rb +47 -0
- data/lib/webpacker/dev_server_proxy.rb +24 -0
- data/lib/webpacker/helper.rb +23 -5
- data/lib/webpacker/instance.rb +44 -0
- data/lib/webpacker/manifest.rb +58 -34
- data/lib/webpacker/railtie.rb +22 -3
- data/lib/webpacker/version.rb +2 -1
- data/package.json +37 -7
- data/package/asset_host.js +21 -0
- data/package/config.js +8 -0
- data/package/environment.js +95 -0
- data/package/environments/development.js +47 -0
- data/package/environments/production.js +34 -0
- data/package/environments/test.js +3 -0
- data/package/index.js +16 -0
- data/package/loaders/babel.js +11 -0
- data/{lib/install/config/loaders/core → package/loaders}/coffee.js +0 -0
- data/{lib/install/config/loaders/installers → package/loaders}/elm.js +4 -5
- data/{lib/install/config/loaders/core → package/loaders}/erb.js +0 -0
- data/package/loaders/file.js +15 -0
- data/package/loaders/style.js +31 -0
- data/{lib/install/config/loaders/installers/angular.js → package/loaders/typescript.js} +1 -1
- data/package/loaders/vue.js +12 -0
- data/test/compiler_test.rb +20 -0
- data/test/configuration_test.rb +43 -19
- data/test/dev_server_test.rb +24 -0
- data/test/helper_test.rb +21 -5
- data/test/manifest_test.rb +25 -19
- data/test/test_app/public/packs/manifest.json +3 -1
- data/test/webpacker_test_helper.rb +40 -0
- data/webpacker.gemspec +1 -1
- data/yarn.lock +4701 -578
- metadata +52 -29
- data/lib/install/config/loaders/core/assets.js +0 -12
- data/lib/install/config/loaders/core/babel.js +0 -5
- data/lib/install/config/loaders/core/sass.js +0 -15
- data/lib/install/config/loaders/installers/react.js +0 -5
- data/lib/install/config/loaders/installers/vue.js +0 -13
- data/lib/install/config/webpack/configuration.js +0 -35
- data/lib/install/config/webpack/shared.js +0 -58
- data/lib/webpacker/env.rb +0 -23
- data/lib/webpacker/file_loader.rb +0 -24
- data/test/env_test.rb +0 -14
- data/test/webpacker_test.rb +0 -15
data/lib/webpacker/manifest.rb
CHANGED
@@ -1,51 +1,75 @@
|
|
1
|
-
# Singleton registry for accessing the packs path using generated manifest.
|
1
|
+
# Singleton registry for accessing the packs path using a generated manifest.
|
2
2
|
# This allows javascript_pack_tag, stylesheet_pack_tag, asset_pack_path to take a reference to,
|
3
3
|
# say, "calendar.js" or "calendar.css" and turn it into "/packs/calendar.js" or
|
4
|
-
# "/packs/calendar.css" in development.
|
5
|
-
#
|
6
|
-
#
|
4
|
+
# "/packs/calendar.css" in development.
|
5
|
+
#
|
6
|
+
# In production mode, it returns compiles files, like
|
7
|
+
# "/packs/calendar-1016838bab065ae1e314.js" and "/packs/calendar-1016838bab065ae1e314.css",
|
8
|
+
# for long-term caching.
|
9
|
+
#
|
10
|
+
# When the configuration is set to on-demand compilation, with the `compile: true` option in
|
11
|
+
# the webpacker.yml file, any lookups will be preceeded by a compilation if one is needed.
|
12
|
+
class Webpacker::Manifest
|
13
|
+
class MissingEntryError < StandardError; end
|
7
14
|
|
8
|
-
|
15
|
+
delegate :config, :compiler, :dev_server, to: :@webpacker
|
9
16
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
Webpacker::Configuration.manifest_path
|
14
|
-
end
|
17
|
+
def initialize(webpacker)
|
18
|
+
@webpacker = webpacker
|
19
|
+
end
|
15
20
|
|
16
|
-
|
17
|
-
|
21
|
+
def refresh
|
22
|
+
@data = load
|
23
|
+
end
|
18
24
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
25
|
+
def lookup(name)
|
26
|
+
compile if compiling?
|
27
|
+
find name
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def compiling?
|
32
|
+
config.compile? && !dev_server.running?
|
24
33
|
end
|
25
34
|
|
26
|
-
def
|
27
|
-
|
35
|
+
def compile
|
36
|
+
Webpacker.logger.tagged("Webpacker") { compiler.compile }
|
28
37
|
end
|
29
38
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
39
|
+
def find(name)
|
40
|
+
data[name.to_s] || handle_missing_entry(name)
|
41
|
+
end
|
34
42
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
43
|
+
def handle_missing_entry(name)
|
44
|
+
raise Webpacker::Manifest::MissingEntryError, missing_file_from_manifest_error(name)
|
45
|
+
end
|
39
46
|
|
40
|
-
|
41
|
-
|
42
|
-
|
47
|
+
def missing_file_from_manifest_error(bundle_name)
|
48
|
+
msg = <<-MSG
|
49
|
+
Webpacker can't find #{bundle_name} in #{config.public_manifest_path}. Possible causes:
|
50
|
+
1. You want to set wepbacker.yml value of compile to true for your environment
|
51
|
+
unless you are using the `webpack -w` or the webpack-dev-server.
|
52
|
+
2. Webpack has not yet re-run to reflect updates.
|
53
|
+
3. You have misconfigured Webpacker's config/webpacker.yml file.
|
54
|
+
4. Your Webpack configuration is not creating a manifest.
|
55
|
+
Your manifest contains:
|
56
|
+
#{JSON.pretty_generate(@data)}
|
57
|
+
MSG
|
58
|
+
end
|
59
|
+
|
60
|
+
def data
|
61
|
+
if config.cache_manifest?
|
62
|
+
@data ||= load
|
63
|
+
else
|
64
|
+
refresh
|
43
65
|
end
|
44
|
-
|
66
|
+
end
|
45
67
|
|
46
|
-
private
|
47
68
|
def load
|
48
|
-
|
49
|
-
|
69
|
+
if config.public_manifest_path.exist?
|
70
|
+
JSON.parse config.public_manifest_path.read
|
71
|
+
else
|
72
|
+
{}
|
73
|
+
end
|
50
74
|
end
|
51
75
|
end
|
data/lib/webpacker/railtie.rb
CHANGED
@@ -1,9 +1,18 @@
|
|
1
1
|
require "rails/railtie"
|
2
2
|
|
3
3
|
require "webpacker/helper"
|
4
|
+
require "webpacker/dev_server_proxy"
|
4
5
|
|
5
6
|
class Webpacker::Engine < ::Rails::Engine
|
6
|
-
initializer
|
7
|
+
initializer "webpacker.proxy" do |app|
|
8
|
+
if Rails.env.development?
|
9
|
+
app.middleware.insert_before 0,
|
10
|
+
Rails::VERSION::MAJOR >= 5 ?
|
11
|
+
Webpacker::DevServerProxy : "Webpacker::DevServerProxy", ssl_verify_none: true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
initializer "webpacker.helper" do |app|
|
7
16
|
ActiveSupport.on_load :action_controller do
|
8
17
|
ActionController::Base.helper Webpacker::Helper
|
9
18
|
end
|
@@ -11,8 +20,18 @@ class Webpacker::Engine < ::Rails::Engine
|
|
11
20
|
ActiveSupport.on_load :action_view do
|
12
21
|
include Webpacker::Helper
|
13
22
|
end
|
23
|
+
end
|
24
|
+
|
25
|
+
initializer "webpacker.logger" do
|
26
|
+
config.after_initialize do |app|
|
27
|
+
Webpacker.logger = ::Rails.logger
|
28
|
+
end
|
29
|
+
end
|
14
30
|
|
15
|
-
|
16
|
-
|
31
|
+
initializer "webpacker.bootstrap" do
|
32
|
+
if defined?(Rails::Server) || defined?(Rails::Console)
|
33
|
+
Webpacker.bootstrap
|
34
|
+
Spring.after_fork { Webpacker.bootstrap } if defined?(Spring)
|
35
|
+
end
|
17
36
|
end
|
18
37
|
end
|
data/lib/webpacker/version.rb
CHANGED
data/package.json
CHANGED
@@ -1,12 +1,42 @@
|
|
1
1
|
{
|
2
|
-
"name": "webpacker",
|
3
|
-
"version": "
|
4
|
-
"description": "
|
5
|
-
"main": "index.js",
|
2
|
+
"name": "@rails/webpacker",
|
3
|
+
"version": "3.0.0",
|
4
|
+
"description": "Use Webpack to manage app-like JavaScript modules in Rails",
|
5
|
+
"main": "package/index.js",
|
6
|
+
"files": [
|
7
|
+
"package"
|
8
|
+
],
|
6
9
|
"engines": {
|
7
|
-
"node": ">= 6.
|
10
|
+
"node": ">= 6.0.0"
|
11
|
+
},
|
12
|
+
"dependencies": {
|
13
|
+
"babel-core": "^6.26.0",
|
14
|
+
"babel-loader": "^7.1.2",
|
15
|
+
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
16
|
+
"babel-plugin-transform-class-properties": "^6.24.1",
|
17
|
+
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
18
|
+
"babel-polyfill": "^6.26.0",
|
19
|
+
"babel-preset-env": "^1.6.0",
|
20
|
+
"coffee-loader": "^0.8.0",
|
21
|
+
"coffee-script": "^1.12.7",
|
22
|
+
"compression-webpack-plugin": "^1.0.0",
|
23
|
+
"css-loader": "^0.28.5",
|
24
|
+
"extract-text-webpack-plugin": "^3.0.0",
|
25
|
+
"file-loader": "^0.11.2",
|
26
|
+
"glob": "^7.1.2",
|
27
|
+
"js-yaml": "^3.9.1",
|
28
|
+
"node-sass": "^4.5.3",
|
29
|
+
"path-complete-extname": "^0.1.0",
|
30
|
+
"postcss-cssnext": "^3.0.2",
|
31
|
+
"postcss-loader": "^2.0.6",
|
32
|
+
"postcss-smart-import": "^0.7.5",
|
33
|
+
"rails-erb-loader": "^5.2.1",
|
34
|
+
"resolve-url-loader": "^2.1.0",
|
35
|
+
"sass-loader": "^6.0.6",
|
36
|
+
"style-loader": "^0.18.2",
|
37
|
+
"webpack": "^3.5.5",
|
38
|
+
"webpack-manifest-plugin": "^1.3.1"
|
8
39
|
},
|
9
|
-
"dependencies": {},
|
10
40
|
"devDependencies": {
|
11
41
|
"eslint": "^3.16.1",
|
12
42
|
"eslint-config-airbnb": "^14.1.0",
|
@@ -16,7 +46,7 @@
|
|
16
46
|
},
|
17
47
|
"scripts": {
|
18
48
|
"test": "echo \"Error: no test specified\" && exit 1",
|
19
|
-
"lint": "
|
49
|
+
"lint": "eslint {package,lib}/"
|
20
50
|
},
|
21
51
|
"repository": {
|
22
52
|
"type": "git",
|
@@ -0,0 +1,21 @@
|
|
1
|
+
const config = require('./config')
|
2
|
+
const { resolve } = require('path')
|
3
|
+
|
4
|
+
function removeOuterSlashes(string) {
|
5
|
+
return string.replace(/^\/*/, '').replace(/\/*$/, '')
|
6
|
+
}
|
7
|
+
|
8
|
+
function formatPublicPath(host = '', path = '') {
|
9
|
+
let formattedHost = removeOuterSlashes(host)
|
10
|
+
if (formattedHost && !/^http/i.test(formattedHost)) {
|
11
|
+
formattedHost = `//${formattedHost}`
|
12
|
+
}
|
13
|
+
const formattedPath = removeOuterSlashes(path)
|
14
|
+
return `${formattedHost}/${formattedPath}/`
|
15
|
+
}
|
16
|
+
|
17
|
+
module.exports = {
|
18
|
+
path: resolve('public', config.public_output_path),
|
19
|
+
publicPath: `/${config.public_output_path}/`.replace(/([^:]\/)\/+/g, '$1'),
|
20
|
+
publicPathWithHost: formatPublicPath(process.env.ASSET_HOST, config.public_output_path)
|
21
|
+
}
|
data/package/config.js
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
const { resolve } = require('path')
|
2
|
+
const { safeLoad } = require('js-yaml')
|
3
|
+
const { readFileSync } = require('fs')
|
4
|
+
|
5
|
+
const filePath = resolve('config', 'webpacker.yml')
|
6
|
+
const config = safeLoad(readFileSync(filePath), 'utf8')
|
7
|
+
|
8
|
+
module.exports = config[process.env.NODE_ENV]
|
@@ -0,0 +1,95 @@
|
|
1
|
+
/* eslint global-require: 0 */
|
2
|
+
/* eslint import/no-dynamic-require: 0 */
|
3
|
+
|
4
|
+
const config = require('./config')
|
5
|
+
const assetHost = require('./asset_host')
|
6
|
+
|
7
|
+
const { basename, dirname, join, relative, resolve } = require('path')
|
8
|
+
const { sync } = require('glob')
|
9
|
+
const extname = require('path-complete-extname')
|
10
|
+
|
11
|
+
const webpack = require('webpack')
|
12
|
+
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
13
|
+
const ManifestPlugin = require('webpack-manifest-plugin')
|
14
|
+
|
15
|
+
function getLoaderMap() {
|
16
|
+
const result = new Map()
|
17
|
+
const paths = sync(resolve(__dirname, 'loaders', '*.js'))
|
18
|
+
paths.forEach((path) => {
|
19
|
+
const name = basename(path, extname(path))
|
20
|
+
result.set(name, require(path))
|
21
|
+
})
|
22
|
+
return result
|
23
|
+
}
|
24
|
+
|
25
|
+
function getPluginMap() {
|
26
|
+
const result = new Map()
|
27
|
+
result.set('Environment', new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(process.env))))
|
28
|
+
result.set('ExtractText', new ExtractTextPlugin('[name]-[contenthash].css'))
|
29
|
+
result.set('Manifest', new ManifestPlugin({ publicPath: assetHost.publicPath, writeToFileEmit: true }))
|
30
|
+
return result
|
31
|
+
}
|
32
|
+
|
33
|
+
function getExtensionsGlob() {
|
34
|
+
const { extensions } = config
|
35
|
+
if (!extensions.length) {
|
36
|
+
throw new Error('You must configure at least one extension to compile in webpacker.yml')
|
37
|
+
}
|
38
|
+
return extensions.length === 1 ? `**/${extensions[0]}` : `**/*{${extensions.join(',')}}`
|
39
|
+
}
|
40
|
+
|
41
|
+
function getEntryObject() {
|
42
|
+
const result = {}
|
43
|
+
const glob = getExtensionsGlob()
|
44
|
+
const rootPath = join(config.source_path, config.source_entry_path)
|
45
|
+
const paths = sync(join(rootPath, glob))
|
46
|
+
paths.forEach((path) => {
|
47
|
+
const namespace = relative(join(rootPath), dirname(path))
|
48
|
+
const name = join(namespace, basename(path, extname(path)))
|
49
|
+
result[name] = resolve(path)
|
50
|
+
})
|
51
|
+
return result
|
52
|
+
}
|
53
|
+
|
54
|
+
function getModulePaths() {
|
55
|
+
let result = [resolve(config.source_path), 'node_modules']
|
56
|
+
if (config.resolved_paths) {
|
57
|
+
result = result.concat(config.resolved_paths)
|
58
|
+
}
|
59
|
+
return result
|
60
|
+
}
|
61
|
+
|
62
|
+
module.exports = class Environment {
|
63
|
+
constructor() {
|
64
|
+
this.loaders = getLoaderMap()
|
65
|
+
this.plugins = getPluginMap()
|
66
|
+
}
|
67
|
+
|
68
|
+
toWebpackConfig() {
|
69
|
+
return {
|
70
|
+
entry: getEntryObject(),
|
71
|
+
|
72
|
+
output: {
|
73
|
+
filename: '[name]-[chunkhash].js',
|
74
|
+
chunkFilename: '[name]-[chunkhash].chunk.js',
|
75
|
+
path: assetHost.path,
|
76
|
+
publicPath: assetHost.publicPath
|
77
|
+
},
|
78
|
+
|
79
|
+
module: {
|
80
|
+
rules: Array.from(this.loaders.values())
|
81
|
+
},
|
82
|
+
|
83
|
+
plugins: Array.from(this.plugins.values()),
|
84
|
+
|
85
|
+
resolve: {
|
86
|
+
extensions: config.extensions,
|
87
|
+
modules: getModulePaths()
|
88
|
+
},
|
89
|
+
|
90
|
+
resolveLoader: {
|
91
|
+
modules: ['node_modules']
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
const Environment = require('../environment')
|
2
|
+
const { dev_server } = require('../config')
|
3
|
+
const assetHost = require('../asset_host')
|
4
|
+
const webpack = require('webpack')
|
5
|
+
|
6
|
+
module.exports = class extends Environment {
|
7
|
+
constructor() {
|
8
|
+
super()
|
9
|
+
|
10
|
+
if (dev_server.hmr) {
|
11
|
+
this.plugins.set('HotModuleReplacement', new webpack.HotModuleReplacementPlugin())
|
12
|
+
this.plugins.set('NamedModules', new webpack.NamedModulesPlugin())
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
toWebpackConfig() {
|
17
|
+
const result = super.toWebpackConfig()
|
18
|
+
if (dev_server.hmr) {
|
19
|
+
result.output.filename = '[name]-[hash].js'
|
20
|
+
}
|
21
|
+
result.output.pathinfo = true
|
22
|
+
result.devtool = 'cheap-eval-source-map'
|
23
|
+
result.devServer = {
|
24
|
+
host: dev_server.host,
|
25
|
+
port: dev_server.port,
|
26
|
+
https: dev_server.https,
|
27
|
+
hot: dev_server.hmr,
|
28
|
+
contentBase: assetHost.path,
|
29
|
+
publicPath: assetHost.publicPath,
|
30
|
+
clientLogLevel: 'none',
|
31
|
+
compress: true,
|
32
|
+
historyApiFallback: true,
|
33
|
+
headers: {
|
34
|
+
'Access-Control-Allow-Origin': '*'
|
35
|
+
},
|
36
|
+
overlay: true,
|
37
|
+
watchContentBase: true,
|
38
|
+
watchOptions: {
|
39
|
+
ignored: /node_modules/
|
40
|
+
},
|
41
|
+
stats: {
|
42
|
+
errorDetails: true
|
43
|
+
}
|
44
|
+
}
|
45
|
+
return result
|
46
|
+
}
|
47
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
const Environment = require('../environment')
|
2
|
+
const webpack = require('webpack')
|
3
|
+
const CompressionPlugin = require('compression-webpack-plugin')
|
4
|
+
|
5
|
+
module.exports = class extends Environment {
|
6
|
+
constructor() {
|
7
|
+
super()
|
8
|
+
|
9
|
+
this.plugins.set('ModuleConcatenation', new webpack.optimize.ModuleConcatenationPlugin())
|
10
|
+
|
11
|
+
this.plugins.set('UglifyJs', new webpack.optimize.UglifyJsPlugin({
|
12
|
+
sourceMap: true,
|
13
|
+
compress: {
|
14
|
+
warnings: false
|
15
|
+
},
|
16
|
+
output: {
|
17
|
+
comments: false
|
18
|
+
}
|
19
|
+
}))
|
20
|
+
|
21
|
+
this.plugins.set('Compression', new CompressionPlugin({
|
22
|
+
asset: '[path].gz[query]',
|
23
|
+
algorithm: 'gzip',
|
24
|
+
test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
|
25
|
+
}))
|
26
|
+
}
|
27
|
+
|
28
|
+
toWebpackConfig() {
|
29
|
+
const result = super.toWebpackConfig()
|
30
|
+
result.devtool = 'source-map'
|
31
|
+
result.stats = 'normal'
|
32
|
+
return result
|
33
|
+
}
|
34
|
+
}
|
data/package/index.js
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
/* eslint global-require: 0 */
|
2
|
+
/* eslint import/no-dynamic-require: 0 */
|
3
|
+
|
4
|
+
const Environment = require('./environment')
|
5
|
+
const { resolve } = require('path')
|
6
|
+
const { existsSync } = require('fs')
|
7
|
+
|
8
|
+
function createEnvironment() {
|
9
|
+
const path = resolve(__dirname, 'environments', `${process.env.NODE_ENV}.js`)
|
10
|
+
const constructor = existsSync(path) ? require(path) : Environment
|
11
|
+
return new constructor()
|
12
|
+
}
|
13
|
+
|
14
|
+
const environment = createEnvironment()
|
15
|
+
|
16
|
+
module.exports = { environment, Environment }
|