shakapacker 6.1.1 → 6.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.node-version +1 -1
- data/CHANGELOG.md +16 -2
- data/Gemfile.lock +1 -1
- data/README.md +31 -15
- data/docs/customizing_babel_config.md +2 -0
- data/docs/style_loader_vs_mini_css.md +48 -0
- data/docs/using_esbuild_loader.md +1 -1
- data/docs/using_swc_loader.md +2 -2
- data/docs/v6_upgrade.md +69 -73
- data/lib/install/config/webpacker.yml +14 -0
- data/lib/install/template.rb +2 -2
- data/lib/webpacker/commands.rb +2 -2
- data/lib/webpacker/compiler.rb +1 -1
- data/lib/webpacker/configuration.rb +12 -4
- data/lib/webpacker/dev_server.rb +11 -2
- data/lib/webpacker/helper.rb +0 -7
- data/lib/webpacker/instance.rb +1 -1
- data/lib/webpacker/manifest.rb +3 -3
- data/lib/webpacker/railtie.rb +7 -0
- data/lib/webpacker/version.rb +1 -1
- data/lib/webpacker/version_checker.rb +152 -0
- data/package/__tests__/config.js +11 -0
- data/package/config.js +6 -0
- data/package/environments/base.js +1 -1
- data/package/inliningCss.js +1 -1
- data/package/rules/__tests__/file.js +35 -0
- data/package/rules/__tests__/index.js +11 -0
- data/package/rules/__tests__/raw.js +18 -0
- data/package/rules/file.js +2 -17
- data/package/rules/raw.js +2 -2
- data/package/swc/index.js +3 -3
- data/package.json +1 -1
- data/test/configuration_test.rb +24 -3
- data/test/fixtures/beta_package.json +13 -0
- data/test/fixtures/git_url_package.json +13 -0
- data/test/fixtures/github_url_package.json +13 -0
- data/test/fixtures/normal_package.json +13 -0
- data/test/fixtures/relative_path_package.json +13 -0
- data/test/fixtures/semver_caret_package.json +13 -0
- data/test/fixtures/semver_tilde_package.json +13 -0
- data/test/fixtures/without_package.json +13 -0
- data/test/helper_test.rb +12 -12
- data/test/test_app/config/webpacker.yml +4 -0
- data/test/test_app/config/webpacker_manifest_path.yml +80 -0
- data/test/version_checker_test.rb +271 -0
- data/test/webpacker_test.rb +15 -0
- metadata +28 -3
data/lib/webpacker/manifest.rb
CHANGED
@@ -80,8 +80,8 @@ class Webpacker::Manifest
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def load
|
83
|
-
if config.
|
84
|
-
JSON.parse config.
|
83
|
+
if config.manifest_path.exist?
|
84
|
+
JSON.parse config.manifest_path.read
|
85
85
|
else
|
86
86
|
{}
|
87
87
|
end
|
@@ -104,7 +104,7 @@ class Webpacker::Manifest
|
|
104
104
|
|
105
105
|
def missing_file_from_manifest_error(bundle_name)
|
106
106
|
<<-MSG
|
107
|
-
Webpacker can't find #{bundle_name} in #{config.
|
107
|
+
Webpacker can't find #{bundle_name} in #{config.manifest_path}. Possible causes:
|
108
108
|
1. You forgot to install node packages (try `yarn install`) or are running an incompatible version of Node
|
109
109
|
2. Your app has code with a non-standard extension (like a `.jsx` file) but the extension is not in the `extensions` config in `config/webpacker.yml`
|
110
110
|
3. You have set compile: false (see `config/webpacker.yml`) for this environment
|
data/lib/webpacker/railtie.rb
CHANGED
@@ -2,11 +2,18 @@ require "rails/railtie"
|
|
2
2
|
|
3
3
|
require "webpacker/helper"
|
4
4
|
require "webpacker/dev_server_proxy"
|
5
|
+
require "webpacker/version_checker"
|
5
6
|
|
6
7
|
class Webpacker::Engine < ::Rails::Engine
|
7
8
|
# Allows Webpacker config values to be set via Rails env config files
|
8
9
|
config.webpacker = ActiveSupport::OrderedOptions.new
|
9
10
|
|
11
|
+
initializer "webpacker.version_checker" do
|
12
|
+
if File.exist?(Webpacker::VersionChecker::NodePackageVersion.package_json_path)
|
13
|
+
Webpacker::VersionChecker.build.raise_if_gem_and_node_package_versions_differ
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
10
17
|
initializer "webpacker.proxy" do |app|
|
11
18
|
if (Webpacker.config.dev_server.present? rescue nil)
|
12
19
|
app.middleware.insert_before 0,
|
data/lib/webpacker/version.rb
CHANGED
@@ -0,0 +1,152 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "webpacker/version"
|
3
|
+
|
4
|
+
module Webpacker
|
5
|
+
class VersionChecker
|
6
|
+
attr_reader :node_package_version
|
7
|
+
|
8
|
+
MAJOR_MINOR_PATCH_VERSION_REGEX = /(\d+)\.(\d+)\.(\d+)/.freeze
|
9
|
+
|
10
|
+
def self.build
|
11
|
+
new(NodePackageVersion.build)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(node_package_version)
|
15
|
+
@node_package_version = node_package_version
|
16
|
+
end
|
17
|
+
|
18
|
+
def raise_if_gem_and_node_package_versions_differ
|
19
|
+
# Skip check if package is not in package.json or listed from relative path, git repo or github URL
|
20
|
+
return if node_package_version.skip_processing?
|
21
|
+
|
22
|
+
node_major_minor_patch = node_package_version.major_minor_patch
|
23
|
+
gem_major_minor_patch = gem_major_minor_patch_version
|
24
|
+
versions_match = node_major_minor_patch[0] == gem_major_minor_patch[0] &&
|
25
|
+
node_major_minor_patch[1] == gem_major_minor_patch[1] &&
|
26
|
+
node_major_minor_patch[2] == gem_major_minor_patch[2]
|
27
|
+
|
28
|
+
uses_wildcard = node_package_version.semver_wildcard?
|
29
|
+
|
30
|
+
if !Webpacker.config.ensure_consistent_versioning? && (uses_wildcard || !versions_match)
|
31
|
+
check_failed = if uses_wildcard
|
32
|
+
"Semver wildcard detected"
|
33
|
+
else
|
34
|
+
"Version mismatch detected"
|
35
|
+
end
|
36
|
+
|
37
|
+
warn <<-MSG.strip_heredoc
|
38
|
+
Webpacker::VersionChecker - #{check_failed}
|
39
|
+
|
40
|
+
You are currently not checking for consistent versions of shakapacker gem and npm package. A version mismatch or usage of semantic versioning wildcard (~ or ^) has been detected.
|
41
|
+
|
42
|
+
Version mismatch can lead to incorrect behavior and bugs. You should ensure that both the gem and npm package dependencies are locked to the same version.
|
43
|
+
|
44
|
+
You can enable the version check by setting `ensure_consistent_versioning: true` in your `webpacker.yml` file.
|
45
|
+
|
46
|
+
Checking for gem and npm package versions mismatch or wildcard will be enabled by default in the next major version of shakapacker.
|
47
|
+
MSG
|
48
|
+
|
49
|
+
return
|
50
|
+
end
|
51
|
+
|
52
|
+
raise_differing_versions_warning unless versions_match
|
53
|
+
|
54
|
+
raise_node_semver_version_warning if uses_wildcard
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def common_error_msg
|
60
|
+
<<-MSG.strip_heredoc
|
61
|
+
Detected: #{node_package_version.raw}
|
62
|
+
gem: #{gem_version}
|
63
|
+
Ensure the installed version of the gem is the same as the version of
|
64
|
+
your installed node package. Do not use >= or ~> in your Gemfile for shakapacker.
|
65
|
+
Do not use ^ or ~ in your package.json for shakapacker.
|
66
|
+
Run `yarn add shakapacker --exact` in the directory containing folder node_modules.
|
67
|
+
MSG
|
68
|
+
end
|
69
|
+
|
70
|
+
def raise_differing_versions_warning
|
71
|
+
msg = "**ERROR** Webpacker: Webpacker gem and node package versions do not match\n#{common_error_msg}"
|
72
|
+
raise msg
|
73
|
+
end
|
74
|
+
|
75
|
+
def raise_node_semver_version_warning
|
76
|
+
msg = "**ERROR** Webpacker: Your node package version for shakapacker contains a "\
|
77
|
+
"^ or ~\n#{common_error_msg}"
|
78
|
+
raise msg
|
79
|
+
end
|
80
|
+
|
81
|
+
def gem_version
|
82
|
+
Webpacker::VERSION
|
83
|
+
end
|
84
|
+
|
85
|
+
def gem_major_minor_patch_version
|
86
|
+
match = gem_version.match(MAJOR_MINOR_PATCH_VERSION_REGEX)
|
87
|
+
[match[1], match[2], match[3]]
|
88
|
+
end
|
89
|
+
|
90
|
+
class NodePackageVersion
|
91
|
+
attr_reader :package_json
|
92
|
+
|
93
|
+
def self.build
|
94
|
+
new(package_json_path)
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.package_json_path
|
98
|
+
Rails.root.join("package.json")
|
99
|
+
end
|
100
|
+
|
101
|
+
def initialize(package_json)
|
102
|
+
@package_json = package_json
|
103
|
+
end
|
104
|
+
|
105
|
+
def raw
|
106
|
+
parsed_package_contents = JSON.parse(package_json_contents)
|
107
|
+
parsed_package_contents.dig("dependencies", "shakapacker").to_s
|
108
|
+
end
|
109
|
+
|
110
|
+
def semver_wildcard?
|
111
|
+
raw.match(/[~^]/).present?
|
112
|
+
end
|
113
|
+
|
114
|
+
def skip_processing?
|
115
|
+
!package_specified? || relative_path? || git_url? || github_url?
|
116
|
+
end
|
117
|
+
|
118
|
+
def major_minor_patch
|
119
|
+
return if skip_processing?
|
120
|
+
|
121
|
+
match = raw.match(MAJOR_MINOR_PATCH_VERSION_REGEX)
|
122
|
+
unless match
|
123
|
+
raise "Cannot parse version number '#{raw}' (wildcard versions are not supported)"
|
124
|
+
end
|
125
|
+
|
126
|
+
[match[1], match[2], match[3]]
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def package_specified?
|
132
|
+
raw.present?
|
133
|
+
end
|
134
|
+
|
135
|
+
def relative_path?
|
136
|
+
raw.match(%r{(\.\.|\Afile:///)}).present?
|
137
|
+
end
|
138
|
+
|
139
|
+
def git_url?
|
140
|
+
raw.match(%r{^git}).present?
|
141
|
+
end
|
142
|
+
|
143
|
+
def github_url?
|
144
|
+
raw.match(%r{^([\w-]+\/[\w-]+)}).present?
|
145
|
+
end
|
146
|
+
|
147
|
+
def package_json_contents
|
148
|
+
@package_json_contents ||= File.read(package_json)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
data/package/__tests__/config.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
/* global test expect, describe */
|
2
2
|
|
3
3
|
const { chdirCwd, chdirTestApp, resetEnv } = require('../utils/helpers')
|
4
|
+
const { resolve } = require('path')
|
4
5
|
|
5
6
|
chdirTestApp()
|
6
7
|
|
@@ -31,4 +32,14 @@ describe('Config', () => {
|
|
31
32
|
'app/elm'
|
32
33
|
])
|
33
34
|
})
|
35
|
+
|
36
|
+
test('should default manifestPath to the public dir', () => {
|
37
|
+
expect(config.manifestPath).toEqual(resolve('public/packs/manifest.json'))
|
38
|
+
})
|
39
|
+
|
40
|
+
test('should allow overriding manifestPath', () => {
|
41
|
+
process.env.WEBPACKER_CONFIG = 'config/webpacker_manifest_path.yml'
|
42
|
+
const config = require('../config')
|
43
|
+
expect(config.manifestPath).toEqual(resolve('app/packs/manifest.json'))
|
44
|
+
})
|
34
45
|
})
|
data/package/config.js
CHANGED
@@ -29,4 +29,10 @@ const getPublicPath = () => {
|
|
29
29
|
config.publicPath = getPublicPath()
|
30
30
|
config.publicPathWithoutCDN = `/${config.public_output_path}/`
|
31
31
|
|
32
|
+
if (config.manifest_path) {
|
33
|
+
config.manifestPath = resolve(config.manifest_path)
|
34
|
+
} else {
|
35
|
+
config.manifestPath = resolve(config.outputPath, 'manifest.json')
|
36
|
+
}
|
37
|
+
|
32
38
|
module.exports = config
|
data/package/inliningCss.js
CHANGED
@@ -2,6 +2,6 @@ const { runningWebpackDevServer } = require('./env')
|
|
2
2
|
const devServer = require('./dev_server')
|
3
3
|
|
4
4
|
// This logic is tied to lib/webpacker/instance.rb
|
5
|
-
const inliningCss = runningWebpackDevServer && devServer.hmr
|
5
|
+
const inliningCss = runningWebpackDevServer && devServer.hmr && devServer.inline_css !== false
|
6
6
|
|
7
7
|
module.exports = inliningCss
|
@@ -0,0 +1,35 @@
|
|
1
|
+
const file = require('../file')
|
2
|
+
|
3
|
+
describe('file', () => {
|
4
|
+
test('test expected file types', () => {
|
5
|
+
const types = [
|
6
|
+
'.bmp',
|
7
|
+
'.gif',
|
8
|
+
'.jpg',
|
9
|
+
'.jpeg',
|
10
|
+
'.png',
|
11
|
+
'.tiff',
|
12
|
+
'.ico',
|
13
|
+
'.avif',
|
14
|
+
'.webp',
|
15
|
+
'.eot',
|
16
|
+
'.otf',
|
17
|
+
'.ttf',
|
18
|
+
'.woff',
|
19
|
+
'.woff2',
|
20
|
+
'.svg',
|
21
|
+
]
|
22
|
+
types.forEach(type => expect(file.test.test(type)).toBe(true))
|
23
|
+
})
|
24
|
+
|
25
|
+
test('exclude expected file types', () => {
|
26
|
+
const types = [
|
27
|
+
'.js',
|
28
|
+
'.mjs',
|
29
|
+
'.jsx',
|
30
|
+
'.ts',
|
31
|
+
'.tsx',
|
32
|
+
]
|
33
|
+
types.forEach(type => expect(file.exclude.test(type)).toBe(true))
|
34
|
+
})
|
35
|
+
})
|
@@ -0,0 +1,11 @@
|
|
1
|
+
const rules = require('../index')
|
2
|
+
|
3
|
+
describe('index', () => {
|
4
|
+
test('rule tests are regexes', () => {
|
5
|
+
rules.forEach(rule => expect(rule.test instanceof RegExp).toBe(true))
|
6
|
+
})
|
7
|
+
|
8
|
+
test('rule excludes are regexes', () => {
|
9
|
+
rules.forEach(rule => expect(rule.exclude instanceof RegExp).toBe(true))
|
10
|
+
})
|
11
|
+
})
|
@@ -0,0 +1,18 @@
|
|
1
|
+
const raw = require('../raw')
|
2
|
+
|
3
|
+
describe('raw', () => {
|
4
|
+
test('test expected file types', () => {
|
5
|
+
expect(raw.test.test('.html')).toBe(true)
|
6
|
+
})
|
7
|
+
|
8
|
+
test('exclude expected file types', () => {
|
9
|
+
const types = [
|
10
|
+
'.js',
|
11
|
+
'.mjs',
|
12
|
+
'.jsx',
|
13
|
+
'.ts',
|
14
|
+
'.tsx',
|
15
|
+
]
|
16
|
+
types.forEach(type => expect(raw.exclude.test(type)).toBe(true))
|
17
|
+
})
|
18
|
+
})
|
data/package/rules/file.js
CHANGED
@@ -2,23 +2,8 @@ const { dirname, join } = require('path')
|
|
2
2
|
const { source_path: sourcePath } = require('../config')
|
3
3
|
|
4
4
|
module.exports = {
|
5
|
-
test:
|
6
|
-
|
7
|
-
/\.gif$/,
|
8
|
-
/\.jpe?g$/,
|
9
|
-
/\.png$/,
|
10
|
-
/\.tiff$/,
|
11
|
-
/\.ico$/,
|
12
|
-
/\.avif$/,
|
13
|
-
/\.webp$/,
|
14
|
-
/\.eot$/,
|
15
|
-
/\.otf$/,
|
16
|
-
/\.ttf$/,
|
17
|
-
/\.woff$/,
|
18
|
-
/\.woff2$/,
|
19
|
-
/\.svg$/
|
20
|
-
],
|
21
|
-
exclude: [/\.(js|mjs|jsx|ts|tsx)$/],
|
5
|
+
test: /\.(bmp|gif|jpe?g|png|tiff|ico|avif|webp|eot|otf|ttf|woff|woff2|svg)$/,
|
6
|
+
exclude: /\.(js|mjs|jsx|ts|tsx)$/,
|
22
7
|
type: 'asset/resource',
|
23
8
|
generator: {
|
24
9
|
filename: (pathData) => {
|
data/package/rules/raw.js
CHANGED
data/package/swc/index.js
CHANGED
@@ -30,12 +30,12 @@ const getSwcLoaderConfig = (filenameToProcess) => {
|
|
30
30
|
: 'ecmascript',
|
31
31
|
[isTypescriptFile(filenameToProcess) ? 'tsx' : 'jsx']:
|
32
32
|
isJsxFile(filenameToProcess)
|
33
|
-
}
|
33
|
+
},
|
34
|
+
loose: true
|
34
35
|
},
|
35
36
|
sourceMaps: true,
|
36
37
|
env: {
|
37
|
-
coreJs:
|
38
|
-
loose: true,
|
38
|
+
coreJs: 3,
|
39
39
|
exclude: ['transform-typeof-symbol'],
|
40
40
|
mode: 'entry'
|
41
41
|
}
|
data/package.json
CHANGED
data/test/configuration_test.rb
CHANGED
@@ -38,9 +38,18 @@ class ConfigurationTest < Webpacker::Test
|
|
38
38
|
assert_equal @config.public_output_path.to_s, public_output_path
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
42
|
-
|
43
|
-
assert_equal @config.
|
41
|
+
def test_manifest_path
|
42
|
+
manifest_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/public/packs", "manifest.json").to_s
|
43
|
+
assert_equal @config.manifest_path.to_s, manifest_path
|
44
|
+
|
45
|
+
@config = Webpacker::Configuration.new(
|
46
|
+
root_path: @config.root_path,
|
47
|
+
config_path: Pathname.new(File.expand_path("./test_app/config/webpacker_manifest_path.yml", __dir__)),
|
48
|
+
env: "production"
|
49
|
+
)
|
50
|
+
|
51
|
+
manifest_path = File.expand_path File.join(File.dirname(__FILE__), "test_app/app/packs", "manifest.json").to_s
|
52
|
+
assert_equal @config.manifest_path.to_s, manifest_path
|
44
53
|
end
|
45
54
|
|
46
55
|
def test_cache_path
|
@@ -75,4 +84,16 @@ class ConfigurationTest < Webpacker::Test
|
|
75
84
|
assert Webpacker.config.compile?
|
76
85
|
end
|
77
86
|
end
|
87
|
+
|
88
|
+
def test_ensure_consistent_versioning?
|
89
|
+
refute @config.ensure_consistent_versioning?
|
90
|
+
|
91
|
+
with_rails_env("development") do
|
92
|
+
assert Webpacker.config.ensure_consistent_versioning?
|
93
|
+
end
|
94
|
+
|
95
|
+
with_rails_env("test") do
|
96
|
+
refute Webpacker.config.ensure_consistent_versioning?
|
97
|
+
end
|
98
|
+
end
|
78
99
|
end
|
data/test/helper_test.rb
CHANGED
@@ -14,7 +14,6 @@ class HelperTest < ActionView::TestCase
|
|
14
14
|
end.new
|
15
15
|
|
16
16
|
@javascript_pack_tag_loaded = nil
|
17
|
-
@stylesheet_pack_tag_loaded = nil
|
18
17
|
end
|
19
18
|
|
20
19
|
def test_asset_pack_path
|
@@ -149,19 +148,19 @@ class HelperTest < ActionView::TestCase
|
|
149
148
|
end
|
150
149
|
|
151
150
|
def hello_stimulus_stylesheet_chunks
|
152
|
-
%w[/packs/hello_stimulus-k344a6d59eef8632c9d1.chunk.css]
|
151
|
+
%w[/packs/1-c20632e7baf2c81200d3.chunk.css /packs/hello_stimulus-k344a6d59eef8632c9d1.chunk.css]
|
153
152
|
end
|
154
153
|
|
155
154
|
def test_stylesheet_pack_tag
|
156
155
|
assert_equal \
|
157
|
-
(application_stylesheet_chunks + hello_stimulus_stylesheet_chunks)
|
156
|
+
(application_stylesheet_chunks + hello_stimulus_stylesheet_chunks).uniq
|
158
157
|
.map { |chunk| stylesheet_link_tag(chunk) }.join("\n"),
|
159
158
|
stylesheet_pack_tag("application", "hello_stimulus")
|
160
159
|
end
|
161
160
|
|
162
161
|
def test_stylesheet_pack_tag_symbol
|
163
162
|
assert_equal \
|
164
|
-
(application_stylesheet_chunks + hello_stimulus_stylesheet_chunks)
|
163
|
+
(application_stylesheet_chunks + hello_stimulus_stylesheet_chunks).uniq
|
165
164
|
.map { |chunk| stylesheet_link_tag(chunk) }.join("\n"),
|
166
165
|
stylesheet_pack_tag(:application, :hello_stimulus)
|
167
166
|
end
|
@@ -172,15 +171,16 @@ class HelperTest < ActionView::TestCase
|
|
172
171
|
stylesheet_pack_tag("application", media: "all")
|
173
172
|
end
|
174
173
|
|
175
|
-
def
|
176
|
-
|
177
|
-
|
178
|
-
stylesheet_pack_tag(:hello_stimulus)
|
179
|
-
end
|
174
|
+
def test_stylesheet_pack_tag_multiple_invocations_are_allowed
|
175
|
+
app_style = stylesheet_pack_tag(:application)
|
176
|
+
stimulus_style = stylesheet_pack_tag(:hello_stimulus)
|
180
177
|
|
181
178
|
assert_equal \
|
182
|
-
|
183
|
-
|
184
|
-
|
179
|
+
application_stylesheet_chunks.map { |chunk| stylesheet_link_tag(chunk) }.join("\n"),
|
180
|
+
app_style
|
181
|
+
|
182
|
+
assert_equal \
|
183
|
+
hello_stimulus_stylesheet_chunks.map { |chunk| stylesheet_link_tag(chunk) }.join("\n"),
|
184
|
+
stimulus_style
|
185
185
|
end
|
186
186
|
end
|
@@ -9,6 +9,9 @@ default: &default
|
|
9
9
|
webpack_compile_output: false
|
10
10
|
webpack_loader: babel
|
11
11
|
|
12
|
+
# Location for manifest.json, defaults to {public_output_path}/manifest.json if unset
|
13
|
+
# manifest_path: public/packs/manifest.json
|
14
|
+
|
12
15
|
# Additional paths webpack should look up modules
|
13
16
|
# ['app/assets', 'engine/foo/app/assets']
|
14
17
|
additional_paths:
|
@@ -36,6 +39,7 @@ default: &default
|
|
36
39
|
development:
|
37
40
|
<<: *default
|
38
41
|
compile: true
|
42
|
+
ensure_consistent_versioning: true
|
39
43
|
|
40
44
|
# Reference: https://webpack.js.org/configuration/dev-server/
|
41
45
|
dev_server:
|