webpacker-remote 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 635f4710cb86e3d78d8ae1da64807ae12f0bf97e7e3b476fb87a58098c9370f5
4
- data.tar.gz: 0aa52bce7bfcf825119c82aa1cc215274c929fe3572c8e4e54523555693504ec
3
+ metadata.gz: 475ff81ecaa533d711986b6b21c70ef0e3e26b3b9934168bacba2bc27f64025e
4
+ data.tar.gz: c0b2f5706cc157d3d082435a38887c870f07e90a8228fca224e5b4d043b4ebd2
5
5
  SHA512:
6
- metadata.gz: 823dab789035d9160449e109532bac324ee377ed8afd8caea5d4a72395d625cc1826902d2554ac5f7ee8930f3232d759f0276b79e7b703ba033bd62b439fb34e
7
- data.tar.gz: 799fc8946cdc5a09b83ebe58ec6f7a244041b3e9607a0a33436feb1755fe0a3db7e3ae32ba0c00c2c6029023568e0b960f1ec5d6b75305e108691b321539afea
6
+ metadata.gz: 96e16850f5db27b9e12bba5877b29bab23cf617d409b6da98b37431b3b137af973ee3559f1593070c62cdf130d672bafea72ac24b72034622fbb851b3a287963
7
+ data.tar.gz: 2574263c55709fb4890190f57255572be16ba4887729be0c5ee1fcbe3e905092ac935f936d8eb3ff975d8193c0d4f895506dca2f500de02fe5f69b5aef826081
@@ -8,8 +8,8 @@ jobs:
8
8
  runs-on: ubuntu-latest
9
9
  strategy:
10
10
  matrix:
11
- ruby: [ '2.7' ]
12
- webpacker: [ '4.3.0', '5.2.1' ]
11
+ ruby: [ '2.7', '3.0', '3.1' ]
12
+ webpacker: [ 'webpacker|~> 4.3', 'webpacker|~> 5.4', 'shakapacker|~> 6.2' ]
13
13
  name: Ruby ${{ matrix.ruby }}, Webpacker ${{ matrix.webpacker }}
14
14
  steps:
15
15
  - uses: actions/checkout@v2
@@ -13,8 +13,8 @@ jobs:
13
13
  runs-on: ubuntu-latest
14
14
  strategy:
15
15
  matrix:
16
- ruby: [ '2.7' ]
17
- webpacker: [ '4.3.0', '5.2.1' ]
16
+ ruby: [ '2.7', '3.0', '3.1' ]
17
+ webpacker: [ 'webpacker|~> 4.3', 'webpacker|~> 5.4', 'shakapacker|~> 6.2' ]
18
18
  name: Ruby ${{ matrix.ruby }}, Webpacker ${{ matrix.webpacker }}
19
19
  steps:
20
20
  - uses: actions/checkout@v2
data/.gitignore CHANGED
@@ -5,3 +5,4 @@ Gemfile.lock
5
5
  bin
6
6
  coverage/
7
7
  *gem
8
+ .DS_Store
data/.rubocop.yml CHANGED
@@ -16,5 +16,20 @@ Metrics/BlockLength:
16
16
  Style/Documentation:
17
17
  Enabled: false
18
18
 
19
+ Gemspec/RequireMFA:
20
+ Enabled: false
21
+
22
+ Style/OpenStructUse:
23
+ Enabled: false
24
+
25
+ Gemspec/RequiredRubyVersion:
26
+ Enabled: false
27
+
28
+ Style/MutableConstant:
29
+ Enabled: false
30
+
31
+ Style/HashSyntax:
32
+ EnforcedShorthandSyntax: never
33
+
19
34
  Style/ClassAndModuleChildren:
20
35
  EnforcedStyle: compact
data/Gemfile CHANGED
@@ -14,6 +14,10 @@ gem 'rubocop-performance', '~> 1.9.2'
14
14
  gem 'rubocop-rake', '~> 0.5.1'
15
15
  gem 'rubocop-rspec', '~> 2.1.0'
16
16
 
17
+ # webpacker-4.3.0 default webpacker yml config
18
+ # incompatible with ruby-3.1 (comes with psych-4)
19
+ gem 'psych', '< 4'
20
+
17
21
  group :development do
18
22
  gem 'benchmark-ips', require: false
19
23
  gem 'pry-byebug', '~> 3.9'
data/README.md CHANGED
@@ -6,23 +6,30 @@
6
6
 
7
7
  - support for `create-react-app` developed in a separate repo
8
8
  - support for multiple external frontend builds, right now `webpacker` is [a singleton](https://github.com/rails/webpacker/blob/6ba995aed2b609a27e4e35ec28b2a7f688cce0cf/lib/webpacker/helper.rb#L5L7)
9
+ - support [shakapacker](https://github.com/shakacode/shakapacker)
10
+ - support for both webpack-asset-manifest-3 and webpack-asset-manifest-5 (including `assets` and without this key)
9
11
 
10
12
  ## Usage
11
13
 
14
+ - ensure you're using `webpack-asset-manifest` to generate proper manifest structure
12
15
  - build `webpack` bundle & upload `build` directory (incl. `manifest.json`) before deploy
13
16
  - in `config/initializers/remote_webpacker.rb`
14
17
 
15
18
  ```rb
19
+ # given we can fetch `https://asset_host/build/manifest.json`
20
+ # and it contains paths relative to `https://asset_host/build/`
16
21
  REMOTE_WEBPACKER = Webpacker::Remote.new(root_path: 'https://asset_host/build/', config_path: 'manifest.json')
17
22
  ```
18
23
 
19
24
  - in `app/views/layouts/application.html.erb` (**not** `javascript_pack_tag`)
20
25
 
21
26
  ```rb
22
- <%= javascript_packs_with_chunks_tag 'main', webpacker: REMOTE_WEBPACKER %>
27
+ <%= javascript_pack_tag 'main', webpacker: REMOTE_WEBPACKER %>
23
28
  #=> <script src='https://asset_host/build/static/js/main.2e302672.chunk.js'>
24
29
  ```
25
30
 
31
+ **NOTE** if you're on `webpacker` (not `shakapacker`), then you should use `javascript_packs_with_chunks_tag`
32
+
26
33
  Of course, you can use as many build as you like and do blue-green deployments using gems like `rollout`
27
34
 
28
35
  ## CRA Requirements
@@ -33,8 +40,8 @@ For `create-react-app` you should use `webpack-assets-manifest` instead of built
33
40
 
34
41
  ```diff
35
42
  + "customize-cra": "^1.0.0",
36
- + "react-app-rewired": "^2.1.8"
37
- + "webpack-assets-manifest": "^3.1.1"
43
+ + "react-app-rewired": "^2.2.1"
44
+ + "webpack-assets-manifest": "^5.1.0"
38
45
  ...
39
46
  - "build": "react-scripts build"
40
47
  + "build": "react-app-rewired build"
@@ -79,26 +86,26 @@ module.exports = override(
79
86
  {
80
87
  "entrypoints": {
81
88
  "main": {
82
- "js": [
83
- "static/js/runtime-main...js",
84
- "static/js/2...chunk.js",
85
- "static/js/main...chunk.js"
86
- ],
87
- "js.map": [
88
- "static/js/runtime-main...js.map",
89
- "static/js/2...chunk.js.map",
90
- "static/js/main...chunk.js.map"
91
- ],
92
- "css": [
93
- "static/css/2...chunk.css",
94
- "static/css/main...chunk.css"
95
- ]
89
+ "assets": {
90
+ "js": [
91
+ "static/js/main.hashsum.js"
92
+ ],
93
+ "css": [
94
+ "static/css/main.hashsum.css"
95
+ ]
96
+ }
96
97
  }
97
98
  },
98
- "main.css": "static/css/main...chunk.css",
99
- "main.js": "static/js/main...chunk.js",
100
- "main.js.map": "static/js/main...chunk.js.map",
101
- "runtime-main.js": "static/js/runtime-main...js",
102
- "runtime-main.js.map": "static/js/runtime-main...js.map"
99
+ "main.css": "static/css/main.hashsum.css",
100
+ "main.js": "static/js/main.hashsum.js"
103
101
  }
102
+ ```
103
+
104
+ ## Tests
105
+
106
+ Specify webpacker gem explicitly:
107
+
108
+ ```sh
109
+ WEBPACKER_GEM_VERSION='shakapacker|6.2.1' bundle exec rspec
110
+ WEBPACKER_GEM_VERSION='webpacker|5.4.3' bundle exec rspec
104
111
  ```
@@ -3,11 +3,34 @@
3
3
  require 'webpacker/configuration'
4
4
 
5
5
  class Webpacker::Remote::Configuration < Webpacker::Configuration
6
+ # rubocop:disable Lint/MissingSuper
7
+ def initialize(root_path:, config_path:, env:, **config_content)
8
+ # deliberately not calling `super` just emulating what's done there
9
+ # because we accept overloading to DI the content of `webpacker.yml` inline
10
+ @root_path = root_path
11
+ @config_path = config_path
12
+ @env = env
13
+
14
+ # addition
15
+ @config_content = config_content
16
+ end
17
+ # rubocop:enable Lint/MissingSuper
18
+
6
19
  def load
7
20
  {
8
21
  cache_manifest: true,
9
22
  check_yarn_integrity: false,
10
23
  compile: false
11
- }
24
+ }.merge(@config_content)
25
+ end
26
+
27
+ # shakapacker error message
28
+ def manifest_path
29
+ File.join(root_path.to_s, config_path.to_s)
30
+ end
31
+
32
+ # webpacker error message
33
+ def public_manifest_path
34
+ manifest_path
12
35
  end
13
36
  end
@@ -3,6 +3,7 @@
3
3
  # better version of https://github.com/rails/webpacker/issues/2054#issuecomment-564173103
4
4
  # rewrite all methods by accept direct injection instead of calling `current_webpacker_instance`
5
5
  # because we can have same layout with script/link tags from different webpackers
6
+ require 'webpacker/helper'
6
7
  module Webpacker::Remote::Helper
7
8
  METHODS = %i[
8
9
  javascript_pack_tag
@@ -11,7 +12,7 @@ module Webpacker::Remote::Helper
11
12
  stylesheet_packs_with_chunks_tag
12
13
  ].freeze
13
14
 
14
- METHODS.each do |meth|
15
+ METHODS.select { |meth| ::Webpacker::Helper.instance_methods.include?(meth) }.each do |meth|
15
16
  define_method meth do |*names, **options|
16
17
  return super(*names, **options) unless options[:webpacker]
17
18
 
@@ -24,7 +25,4 @@ module Webpacker::Remote::Helper
24
25
  end
25
26
  end
26
27
 
27
- unless ENV['SKIP_WEBPACKER_HELPER_OVERRIDE']
28
- require 'webpacker/helper'
29
- Webpacker::Helper.prepend Webpacker::Remote::Helper
30
- end
28
+ Webpacker::Helper.prepend Webpacker::Remote::Helper unless ENV['SKIP_WEBPACKER_HELPER_OVERRIDE']
@@ -4,13 +4,49 @@ require 'webpacker/manifest'
4
4
 
5
5
  class Webpacker::Remote::Manifest < Webpacker::Manifest
6
6
  def load
7
- @webpacker.public_manifest_content
7
+ # load from network, upstream version operates pathnames:
8
+ # if config.manifest_path.exist?
9
+ # JSON.parse config.manifest_path.read
10
+ # else
11
+ # {}
12
+ # end
13
+ if public_manifest_content_uri
14
+ public_manifest_content
15
+ else
16
+ {}
17
+ end
18
+ end
19
+
20
+ def public_manifest_content
21
+ JSON.parse(Net::HTTP.get_response(public_manifest_content_uri).body)
22
+ rescue JSON::ParserError, Errno::ECONNREFUSED, Net::OpenTimeout, Net::ReadTimeout, Errno::ENOENT => e
23
+ raise Webpacker::Remote::Error, <<~MSG
24
+ having {root_path: #{config.root_path.inspect}, config_path: #{config.config_path.inspect}}
25
+ #{e.class}: #{e.message}
26
+ MSG
8
27
  end
9
28
 
10
29
  def lookup_pack_with_chunks(name, pack_type = {})
11
- return unless (paths = super)
30
+ # `super` method copy
31
+ manifest_pack_type = manifest_type(pack_type[:type])
32
+ manifest_pack_name = manifest_name(name, manifest_pack_type)
33
+ assets = find('entrypoints')[manifest_pack_name]
34
+ # patched super behavior:
35
+ # - keys in webpack-assets-manifest-3: entrypoints.main.{js/css}
36
+ # - keys in webpack-assets-manifest-5: entrypoints.main.assets.{js/css}
37
+ # `shakapacker` just has this inline:
38
+ # find("entrypoints")[manifest_pack_name]["assets"][manifest_pack_type]
39
+ assets = assets['assets'] if assets.key?('assets')
40
+ paths = assets[manifest_pack_type]
41
+ # end of `super` method copy
12
42
 
43
+ # remote-webpacker addition: full URIs
44
+ # railsy webpacker returns relative paths from its manifest
45
+ # because `action_view` resolves them using `config.action_controller.asset_host`
46
+ # but remote-webpacker tuned to have bundles from several locations
13
47
  paths.map { |p| File.join(config.root_path.to_s, p) }
48
+ rescue NoMethodError
49
+ nil
14
50
  end
15
51
 
16
52
  def lookup(name, pack_type = {})
@@ -18,4 +54,18 @@ class Webpacker::Remote::Manifest < Webpacker::Manifest
18
54
 
19
55
  File.join(config.root_path.to_s, path)
20
56
  end
57
+
58
+ # additional api to be able to put additional data into the manifest
59
+ # because `find` and `data` are private
60
+ def manifest_data
61
+ data
62
+ end
63
+
64
+ private
65
+
66
+ def public_manifest_content_uri
67
+ URI.parse(File.join(config.root_path.to_s, config.config_path.to_s))
68
+ rescue URI::InvalidURIError
69
+ nil
70
+ end
21
71
  end
@@ -14,21 +14,18 @@ class Webpacker::Remote < Webpacker::Instance
14
14
 
15
15
  class Error < StandardError; end
16
16
 
17
- attr_reader :public_manifest_content
18
-
19
- # fetch early, fail fast
20
17
  # rubocop:disable Lint/MissingSuper
21
- def initialize(root_path: nil, config_path: nil)
22
- uri = File.join(root_path.to_s, config_path.to_s)
23
- @public_manifest_content = JSON.parse(self.class.get_http_response(uri))
18
+ def initialize(root_path: nil, config_path: nil, **config_content)
24
19
  # deliberately not calling `super` just emulating what's done there
20
+ # otherwise defaults in super initialize would call `Rails`
21
+ # let's unbind the gem from rails
25
22
  @config_path = config_path
26
23
  @root_path = root_path
27
- rescue StandardError => e
28
- raise Error, <<~MSG
29
- having {root_path: #{root_path.inspect}, config_path: #{config_path.inspect}}
30
- #{e.class}: #{e.message}
31
- MSG
24
+
25
+ # additions
26
+ @config_content = config_content.symbolize_keys
27
+ # fetch manifest eagerly to fail fast in initiazer unless cache_manifest: false
28
+ manifest.manifest_data if @config_content.fetch(:cache_manifest, true)
32
29
  end
33
30
  # rubocop:enable Lint/MissingSuper
34
31
 
@@ -40,7 +37,7 @@ class Webpacker::Remote < Webpacker::Instance
40
37
  @config ||= Webpacker::Remote::Configuration.new(
41
38
  root_path: root_path,
42
39
  config_path: config_path,
43
- env: env
40
+ **config_content
44
41
  )
45
42
  end
46
43
 
@@ -49,7 +46,9 @@ class Webpacker::Remote < Webpacker::Instance
49
46
  'production'
50
47
  end
51
48
 
52
- def self.get_http_response(uri)
53
- Net::HTTP.get_response(URI.parse(uri)).body
49
+ private
50
+
51
+ def config_content
52
+ { env: env }.merge(@config_content)
54
53
  end
55
54
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'webpacker-remote'
5
- spec.version = '0.2.0'
5
+ spec.version = '0.3.0'
6
6
  spec.authors = ['Vlad Bokov']
7
7
  spec.email = ['vlad@lunatic.cat']
8
8
  spec.license = 'MIT'
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.summary = 'Inject external webpack builds into Rails'
11
11
  spec.description = 'Use your webpack builds independently'
12
12
  spec.homepage = 'https://github.com/lunatic-cat/webpacker-remote'
13
- spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
13
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
14
14
 
15
15
  spec.metadata['homepage_uri'] = spec.homepage
16
16
  spec.metadata['source_code_uri'] = 'https://github.com/lunatic-cat/webpacker-remote'
@@ -20,8 +20,11 @@ Gem::Specification.new do |spec|
20
20
  end
21
21
  spec.require_paths = ['lib']
22
22
 
23
- spec.add_dependency('webpacker', ENV.fetch('WEBPACKER_GEM_VERSION', '< 6'))
24
-
23
+ spec.post_install_message = %(
24
+ This gem is compatible with both `webpacker` and `shakapacker` but has no dependency on any.
25
+ Specify correct one by yourself
26
+ )
27
+ spec.add_development_dependency(*ENV.fetch('WEBPACKER_GEM_VERSION', 'shakapacker|~> 6.2').split('|'))
25
28
  spec.add_development_dependency('rspec', '~> 3.0')
26
29
  spec.add_development_dependency('simplecov', '~> 0.19')
27
30
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webpacker-remote
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vlad Bokov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-30 00:00:00.000000000 Z
11
+ date: 2022-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: webpacker
14
+ name: shakapacker
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "<"
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '6'
20
- type: :runtime
19
+ version: '6.2'
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "<"
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '6'
26
+ version: '6.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -78,7 +78,8 @@ licenses:
78
78
  metadata:
79
79
  homepage_uri: https://github.com/lunatic-cat/webpacker-remote
80
80
  source_code_uri: https://github.com/lunatic-cat/webpacker-remote
81
- post_install_message:
81
+ post_install_message: "\n This gem is compatible with both `webpacker` and `shakapacker`
82
+ but has no dependency on any.\n Specify correct one by yourself\n "
82
83
  rdoc_options: []
83
84
  require_paths:
84
85
  - lib
@@ -86,14 +87,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
87
  requirements:
87
88
  - - ">="
88
89
  - !ruby/object:Gem::Version
89
- version: 2.4.0
90
+ version: 2.7.0
90
91
  required_rubygems_version: !ruby/object:Gem::Requirement
91
92
  requirements:
92
93
  - - ">="
93
94
  - !ruby/object:Gem::Version
94
95
  version: '0'
95
96
  requirements: []
96
- rubygems_version: 3.0.8
97
+ rubygems_version: 3.3.7
97
98
  signing_key:
98
99
  specification_version: 4
99
100
  summary: Inject external webpack builds into Rails