webpacker-remote 0.2.0 → 0.3.1

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: 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