webpacker-remote 0.2.0 → 0.3.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 635f4710cb86e3d78d8ae1da64807ae12f0bf97e7e3b476fb87a58098c9370f5
4
- data.tar.gz: 0aa52bce7bfcf825119c82aa1cc215274c929fe3572c8e4e54523555693504ec
3
+ metadata.gz: 330da65c1800e5a6e36b5abddcbf8f3dc09a46cbf41194cbc1edd063b3866a9a
4
+ data.tar.gz: 6f93d74c08123747bc9fe5e983ef2c3e08bb26003f199c843b272d380090e14b
5
5
  SHA512:
6
- metadata.gz: 823dab789035d9160449e109532bac324ee377ed8afd8caea5d4a72395d625cc1826902d2554ac5f7ee8930f3232d759f0276b79e7b703ba033bd62b439fb34e
7
- data.tar.gz: 799fc8946cdc5a09b83ebe58ec6f7a244041b3e9607a0a33436feb1755fe0a3db7e3ae32ba0c00c2c6029023568e0b960f1ec5d6b75305e108691b321539afea
6
+ metadata.gz: dab57de3778d2a5589af327d0323db27dc99b918acb960c3acc3510977abda8d3665c4fd2d04258ca2eed9194d7b44f38a9a12bb020ca9a2350e185468285ca9
7
+ data.tar.gz: 8e9cfaa1cbc4a22cae87cd82d746bc883532127e48327cdde2f92eb3a09d1b111391011477fccede364c993c0fb4fc8a8b7540ea177c7a4a6ff15347dc49292a
@@ -8,12 +8,12 @@ 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', '3.2' ]
12
+ webpacker: [ 'webpacker|~> 4.3', 'webpacker|~> 5.4', 'shakapacker|~> 6.5' ]
13
13
  name: Ruby ${{ matrix.ruby }}, Webpacker ${{ matrix.webpacker }}
14
14
  steps:
15
15
  - uses: actions/checkout@v2
16
- - uses: actions/setup-ruby@v1
16
+ - uses: ruby/setup-ruby@v1
17
17
  with:
18
18
  ruby-version: ${{ matrix.ruby }}
19
19
  - uses: actions/cache@v2
@@ -13,12 +13,12 @@ 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', '3.2' ]
17
+ webpacker: [ 'webpacker|~> 4.3', 'webpacker|~> 5.4', 'shakapacker|~> 6.5' ]
18
18
  name: Ruby ${{ matrix.ruby }}, Webpacker ${{ matrix.webpacker }}
19
19
  steps:
20
20
  - uses: actions/checkout@v2
21
- - uses: actions/setup-ruby@v1
21
+ - uses: ruby/setup-ruby@v1
22
22
  with:
23
23
  ruby-version: ${{ matrix.ruby }}
24
24
  - uses: actions/cache@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,23 @@ Metrics/BlockLength:
16
16
  Style/Documentation:
17
17
  Enabled: false
18
18
 
19
+ Style/FetchEnvVar:
20
+ Enabled: false
21
+
22
+ Gemspec/RequireMFA:
23
+ Enabled: false
24
+
25
+ Style/OpenStructUse:
26
+ Enabled: false
27
+
28
+ Gemspec/RequiredRubyVersion:
29
+ Enabled: false
30
+
31
+ Style/MutableConstant:
32
+ Enabled: false
33
+
34
+ Style/HashSyntax:
35
+ EnforcedShorthandSyntax: never
36
+
19
37
  Style/ClassAndModuleChildren:
20
38
  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
@@ -2,27 +2,34 @@
2
2
 
3
3
  ![](https://github.com/lunatic-cat/webpacker-remote/workflows/ci/badge.svg)
4
4
  [![Gem Version](https://badge.fury.io/rb/webpacker-remote.svg)](https://badge.fury.io/rb/webpacker-remote)
5
- [![codecov](https://codecov.io/gh/lunatic-cat/webpacker-remote/branch/master/graph/badge.svg?token=X5K67X3V0Z)](undefined)
5
+ [![codecov](https://codecov.io/gh/lunatic-cat/webpacker-remote/branch/master/graph/badge.svg?token=X5K67X3V0Z)](https://app.codecov.io/gh/lunatic-cat/webpacker-remote)
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
  }
104
- ```
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
111
+ ```
@@ -3,11 +3,40 @@
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
+ public_manifest_path
30
+ end
31
+
32
+ # webpacker error message
33
+ def public_manifest_path
34
+ public_remote_manifest_path
35
+ end
36
+
37
+ private
38
+
39
+ def public_remote_manifest_path
40
+ File.join(root_path.to_s, config_path.to_s)
12
41
  end
13
42
  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,47 @@ 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
+ # be more failsafe than railsy webpacker since we do networking
21
+ def refresh
22
+ @data = load
23
+ rescue Webpacker::Remote::Error
24
+ @data
8
25
  end
9
26
 
10
27
  def lookup_pack_with_chunks(name, pack_type = {})
11
- return unless (paths = super)
28
+ # `super` method copy
29
+ manifest_pack_type = manifest_type(pack_type[:type])
30
+ manifest_pack_name = manifest_name(name, manifest_pack_type)
31
+ assets = find('entrypoints')[manifest_pack_name]
32
+ # patched super behavior:
33
+ # - keys in webpack-assets-manifest-3: entrypoints.main.{js/css}
34
+ # - keys in webpack-assets-manifest-5: entrypoints.main.assets.{js/css}
35
+ # `shakapacker` just has this inline:
36
+ # find("entrypoints")[manifest_pack_name]["assets"][manifest_pack_type]
37
+ assets = assets['assets'] if assets.key?('assets')
38
+ paths = assets[manifest_pack_type]
39
+ # end of `super` method copy
12
40
 
41
+ # remote-webpacker addition: full URIs
42
+ # railsy webpacker returns relative paths from its manifest
43
+ # because `action_view` resolves them using `config.action_controller.asset_host`
44
+ # but remote-webpacker tuned to have bundles from several locations
13
45
  paths.map { |p| File.join(config.root_path.to_s, p) }
46
+ rescue NoMethodError
47
+ nil
14
48
  end
15
49
 
16
50
  def lookup(name, pack_type = {})
@@ -18,4 +52,27 @@ class Webpacker::Remote::Manifest < Webpacker::Manifest
18
52
 
19
53
  File.join(config.root_path.to_s, path)
20
54
  end
55
+
56
+ # additional api to be able to put additional data into the manifest
57
+ # because `find` and `data` are private
58
+ def manifest_data
59
+ data
60
+ end
61
+
62
+ private
63
+
64
+ def public_manifest_content
65
+ JSON.parse(Net::HTTP.get_response(public_manifest_content_uri).body)
66
+ rescue JSON::ParserError, Errno::ECONNREFUSED, Net::OpenTimeout, Net::ReadTimeout, Errno::ENOENT => e
67
+ raise Webpacker::Remote::Error, <<~MSG
68
+ having {root_path: #{config.root_path.inspect}, config_path: #{config.config_path.inspect}}
69
+ #{e.class}: #{e.message}
70
+ MSG
71
+ end
72
+
73
+ def public_manifest_content_uri
74
+ URI.parse(File.join(config.root_path.to_s, config.config_path.to_s))
75
+ rescue URI::InvalidURIError
76
+ nil
77
+ end
21
78
  end
@@ -10,25 +10,20 @@ class Webpacker::Remote < Webpacker::Instance
10
10
  require 'webpacker/remote/configuration'
11
11
  require 'webpacker/remote/helper'
12
12
 
13
- VERSION = '0.1.0'
14
-
15
13
  class Error < StandardError; end
16
14
 
17
- attr_reader :public_manifest_content
18
-
19
- # fetch early, fail fast
20
15
  # 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))
16
+ def initialize(root_path: nil, config_path: nil, **config_content)
24
17
  # deliberately not calling `super` just emulating what's done there
18
+ # otherwise defaults in super initialize would call `Rails`
19
+ # let's unbind the gem from rails
25
20
  @config_path = config_path
26
21
  @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
22
+
23
+ # additions
24
+ @config_content = config_content.symbolize_keys
25
+ # fetch manifest eagerly to fail fast in initiazer unless cache_manifest: false
26
+ manifest.manifest_data if @config_content.fetch(:cache_manifest, true)
32
27
  end
33
28
  # rubocop:enable Lint/MissingSuper
34
29
 
@@ -40,7 +35,7 @@ class Webpacker::Remote < Webpacker::Instance
40
35
  @config ||= Webpacker::Remote::Configuration.new(
41
36
  root_path: root_path,
42
37
  config_path: config_path,
43
- env: env
38
+ **config_content
44
39
  )
45
40
  end
46
41
 
@@ -49,7 +44,9 @@ class Webpacker::Remote < Webpacker::Instance
49
44
  'production'
50
45
  end
51
46
 
52
- def self.get_http_response(uri)
53
- Net::HTTP.get_response(URI.parse(uri)).body
47
+ private
48
+
49
+ def config_content
50
+ { env: env }.merge(@config_content)
54
51
  end
55
52
  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.1'
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,12 @@ 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('|'))
28
+ spec.add_development_dependency('activesupport', '>= 4.2.0')
25
29
  spec.add_development_dependency('rspec', '~> 3.0')
26
30
  spec.add_development_dependency('simplecov', '~> 0.19')
27
31
  end
metadata CHANGED
@@ -1,29 +1,43 @@
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.1
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-12-28 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
+ - !ruby/object:Gem::Version
19
+ version: '6.2'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
18
32
  - !ruby/object:Gem::Version
19
- version: '6'
20
- type: :runtime
33
+ version: 4.2.0
34
+ type: :development
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - "<"
38
+ - - ">="
25
39
  - !ruby/object:Gem::Version
26
- version: '6'
40
+ version: 4.2.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -78,7 +92,8 @@ licenses:
78
92
  metadata:
79
93
  homepage_uri: https://github.com/lunatic-cat/webpacker-remote
80
94
  source_code_uri: https://github.com/lunatic-cat/webpacker-remote
81
- post_install_message:
95
+ post_install_message: "\n This gem is compatible with both `webpacker` and `shakapacker`
96
+ but has no dependency on any.\n Specify correct one by yourself\n "
82
97
  rdoc_options: []
83
98
  require_paths:
84
99
  - lib
@@ -86,14 +101,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
101
  requirements:
87
102
  - - ">="
88
103
  - !ruby/object:Gem::Version
89
- version: 2.4.0
104
+ version: 2.7.0
90
105
  required_rubygems_version: !ruby/object:Gem::Requirement
91
106
  requirements:
92
107
  - - ">="
93
108
  - !ruby/object:Gem::Version
94
109
  version: '0'
95
110
  requirements: []
96
- rubygems_version: 3.0.8
111
+ rubygems_version: 3.4.1
97
112
  signing_key:
98
113
  specification_version: 4
99
114
  summary: Inject external webpack builds into Rails