seo_cache 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: 555ef8fa31e4a10781d79a8366b6b2d72b366c9a7c9760a4be215e937bc5ad47
4
- data.tar.gz: 17849429c79a3d5aff80ee63f2d85697ba8cef0b90fdd763dc3fa5c7d63aaabe
3
+ metadata.gz: 4a029127389aa4942e27c5fbca325e56c020dfe4d35ec743034649e45700b71f
4
+ data.tar.gz: cb8f7123d7ef7a959e86f53d65c127b4195cfc2b3c21938bf0fb31c6fdcbf507
5
5
  SHA512:
6
- metadata.gz: 159fcc02649cfafdc96046d64681164e48114907de82802d6ff94207ae3861b94bb4b99410b39291267cd31ca1763d8072480d7096a921bf66327d75ad9f9b39
7
- data.tar.gz: de661dfc3d73e00a04834de214b9dc11070899a2ba2647e898a80f0876d92e77d7c2a6442c31483ba263bdb2979a5c10b395d4ce7b1128bc6c2ff498dc8ee3fd
6
+ metadata.gz: bd0f5a06df0b92a34304fad8893e3b708ef5142bd62509664dba5689fab503ffa1ae7a50901c3ee14f626c92a4d0b3994a017989e3024c8b2e6dd0083cbe47e5
7
+ data.tar.gz: 7d1e4891181adb3b9deb3cb9c7773b9328befcebfc237f4c76ce3857b6c673751a14c72403126852782726c3b2998fb3253bf7a346d3f4f4f385542b538547bf
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 0.3.0
2
+
3
+ - Add more examples in README
4
+ - Switch chromedriver to webdrivers
5
+ - Add tests
6
+ - Set correct URL for Github
7
+
1
8
  ## 0.2.0
2
9
 
3
10
  - Improve README
data/README.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  Cache dedicated for SEO with Javascript rendering :fire:
4
4
 
5
+ ## Purpose
6
+
7
+ Google credo is: Don't waste my bot time!
8
+
9
+ So to reduce Googlebot crawling time, let's provide HTML files in a specific cache.
10
+
11
+ This cache is suitable for static (generated or not) pages but not for connected pages.
5
12
 
6
13
  ## Installation
7
14
 
@@ -19,42 +26,98 @@ Or install it yourself as:
19
26
 
20
27
  $ gem install seo_cache
21
28
 
22
- Install chrome driver on your device
29
+ Install chromium or chrome driver on your device (the chromedriver will be automatically downloaded).
23
30
 
24
- ## How it works
31
+ Declare the middleware. For instance in `config/initializers/seo_cache.rb`:
25
32
 
26
- Specific cache for bots to optimize time to first byte and render Javascript on server side.
33
+ ```ruby
34
+ require 'seo_cache'
35
+
36
+ # See options below
27
37
 
28
- Options:
38
+ Rails.application.config.middleware.use SeoCache::Middleware
39
+ ```
29
40
 
30
- Choose a cache mode (`disk` or `memory`):
41
+ ## Options
42
+
43
+ Chrome path (**required**) (`disk` or `memory`):
44
+
45
+ SeoCache.chrome_path = Rails.env.development? ? '/usr/bin/chromium-browser' : '/usr/bin/chromium'
46
+
47
+ Choose a cache mode (`memory` (default) or `disk`):
31
48
 
32
49
  SeoCache.cache_mode = 'memory'
33
50
 
34
- If cache on disk, specify the cache path (e.g. `Rails.root.join('public', 'seo_cache')`):
51
+ Disk cache path (required if disk cache):
52
+
53
+ SeoCache.disk_cache_path = Rails.root.join('public', 'seo_cache')
54
+
55
+ Redis URL (required if memory cache):
35
56
 
36
- SeoCache.disk_cache_path = nil
57
+ SeoCache.redis_url = "redis://localhost:6379/"
58
+
59
+ Redis prefix:
60
+
61
+ SeoCache.redis_namespace = '_my_project:seo_cache'
62
+
63
+ Specific log file (if you want to log missed cache urls):
64
+
65
+ SeoCache.logger_path = Rails.root.join('log', 'seo_cache.log')
66
+
67
+ Activate missed cache urls:
68
+
69
+ SeoCache.log_missed_cache = true
37
70
 
38
71
  URLs to blacklist:
39
72
 
40
- SeoCache.blacklist_urls = []
73
+ SeoCache.blacklist_params = %w[^/assets/.* ^/admin.*]
74
+
75
+ Params to blacklist:
76
+
77
+ SeoCache.blacklist_urls = %w[page]
41
78
 
42
79
  URLs to whitelist:
43
80
 
44
81
  SeoCache.whitelist_urls = []
45
82
 
46
- Query params un URl to blacklist:
83
+ Parameter to add manually to the URl to force page caching, if you want to cache a specific URL (e.g. `https://<my_website>/?_seo_cache_=true`):
84
+
85
+ SeoCache.force_cache_url_param = '_seo_cache_'
86
+
87
+ URL extension to ignore when caching (already defined):
88
+
89
+ SeoCache.extensions_to_ignore = [<your_list>]
90
+
91
+ List of bot agents (already defined):
92
+
93
+ SeoCache.crawler_user_agents = [<your_list>]
94
+
95
+ Parameter added to URL when generating the page, avoid infinite rendering (override only if already used):
47
96
 
48
- SeoCache.blacklist_params = []
97
+ SeoCache.prerender_url_param = '_prerender_'
98
+
99
+ Be aware, JS will be render twice: once by server rendering and once by client. For React, this not a problem but with jQuery plugins, it can duplicate elements in the page (you have to check the redundancy).
49
100
 
50
101
  ## Automatic caching
51
102
 
52
- To automate cache, create a cron rake task which called:
103
+ To automate caching, create a cron rake task (e.g. in `lib/tasks/populate_seo_cache.rake`):
53
104
 
54
105
  ```ruby
55
- SeoCache::PopulateCache.new('https://<your-domain-name>', paths_to_cache).new.perform
106
+ namespace :MyProject do
107
+
108
+ desc 'Populate cache for SEO'
109
+ task populate_seo_cache: :environment do |_task, _args|
110
+ require 'seo_cache/populate_cache'
111
+
112
+ paths_to_cache = public_paths_like_sitemap
113
+
114
+ SeoCache::PopulateCache.new('https://<your-domain-name>', paths_to_cache).new.perform
115
+ end
116
+ end
56
117
  ```
57
118
 
119
+ You can add the `force_cache: true` option to `SeoCache::PopulateCache` for overwrite cache data.
120
+
58
121
  ## Server
59
122
 
60
123
  If you use disk caching, add to your Nginx configuration:
@@ -89,6 +152,78 @@ location / {
89
152
  }
90
153
  ```
91
154
 
155
+ ## Heroku case
156
+
157
+ If you use Heroku server, you can't store file on dynos. But you have two alternatives :
158
+
159
+ - Use the memory mode
160
+
161
+ - Use a second server (a dedicated one) to store HTML files and combine with Nginx.
162
+
163
+ To intercept the request, use the following middleware in Rails:
164
+
165
+ In `config/initializers`, create a new file:
166
+
167
+ ```ruby
168
+ require 'bot_detector'
169
+
170
+ if Rails.env.production?
171
+ Rails.application.config.middleware.insert_before ActionDispatch::Static, BotDetector
172
+ end
173
+ ```
174
+
175
+ Then in `lib` directory, for instance, manage the request:
176
+
177
+ ```ruby
178
+ class BotRedirector
179
+ CRAWLER_USER_AGENTS = ['googlebot', 'yahoo', 'bingbot', 'baiduspider', 'facebookexternalhit', 'twitterbot', 'rogerbot', 'linkedinbot', 'embedly', 'bufferbot', 'quora link preview', 'showyoubot', 'outbrain', 'pinterest/0.', 'developers.google.com/+/web/snippet', 'www.google.com/webmasters/tools/richsnippets', 'slackbot', 'vkShare', 'W3C_Validator', 'redditbot', 'Applebot', 'WhatsApp', 'flipboard', 'tumblr', 'bitlybot', 'SkypeUriPreview', 'nuzzel', 'Discordbot', 'Google Page Speed', 'Qwantify'].freeze
180
+
181
+ IGNORE_URLS = [
182
+ '/robots.txt'
183
+ ].freeze
184
+
185
+ def initialize(app)
186
+ @app = app
187
+ end
188
+
189
+ def call(env)
190
+ if env['HTTP_USER_AGENT'].present? && CRAWLER_USER_AGENTS.any? { |crawler_user_agent| env['HTTP_USER_AGENT'].downcase.include?(crawler_user_agent.downcase) }
191
+ begin
192
+ request = Rack::Request.new(env)
193
+
194
+ return @app.call(env) if IGNORE_URLS.any? { |ignore_url| request.fullpath.downcase =~ /^#{ignore_url.downcase}/ }
195
+
196
+ url = URI.parse(ENV['SEO_SERVER'] + request.fullpath)
197
+ headers = {
198
+ 'User-Agent' => env['HTTP_USER_AGENT'],
199
+ 'Accept-Encoding' => 'gzip'
200
+ }
201
+ req = Net::HTTP::Get.new(url.request_uri, headers)
202
+ # req.basic_auth(ENV['SEO_USER_ID'], ENV['SEO_PASSWD']) # if authentication mechanism
203
+ http = Net::HTTP.new(url.host, url.port)
204
+ http.use_ssl = true if url.scheme == 'https'
205
+ response = http.request(req)
206
+ if response['Content-Encoding'] == 'gzip'
207
+ response.body = ActiveSupport::Gzip.decompress(response.body)
208
+ response['Content-Length'] = response.body.length
209
+ response.delete('Content-Encoding')
210
+ end
211
+
212
+ return [response.code.to_i, { 'Content-Type' => response.header['Content-Type'] }, [response.body]]
213
+ rescue => error
214
+ Rails.logger.error("[bot_redirection] #{error.message}")
215
+
216
+ @app.call(env)
217
+ end
218
+ else
219
+ @app.call(env)
220
+ end
221
+ end
222
+ end
223
+ ```
224
+
225
+ If you use a second server, all links must be relatives in your HTML files, to avoid multi-domains links.
226
+
92
227
  ## Inspiration
93
228
 
94
229
  Inspired by [prerender gem](https://github.com/prerender/prerender_rails).
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'logger'
5
+
6
+ module SeoCache
7
+ #
8
+ # @example Enable full logging
9
+ # SeoCache.logger.level = :debug
10
+ #
11
+ # @example Log to file
12
+ # SeoCache.logger.output = 'seo_cache.log'
13
+ #
14
+ # @example Use logger manually
15
+ # SeoCache.logger.info('This is info message')
16
+ # SeoCache.logger.warn('This is warning message')
17
+ #
18
+ class Logger
19
+ extend Forwardable
20
+ include ::Logger::Severity
21
+
22
+ def_delegators :@logger, :debug, :debug?,
23
+ :info, :info?,
24
+ :warn, :warn?,
25
+ :error, :error?,
26
+ :fatal, :fatal?,
27
+ :level
28
+
29
+ def initialize(logger_path = nil)
30
+ @logger = create_logger(logger_path || $stdout)
31
+ end
32
+
33
+ def output=(io)
34
+ # `Logger#reopen` was added in Ruby 2.3
35
+ if @logger.respond_to?(:reopen)
36
+ @logger.reopen(io)
37
+ else
38
+ @logger = create_logger(io)
39
+ end
40
+ end
41
+
42
+ #
43
+ # For Ruby < 2.3 compatibility
44
+ # Based on https://github.com/ruby/ruby/blob/ruby_2_3/lib/logger.rb#L250
45
+ #
46
+
47
+ def level=(severity)
48
+ if severity.is_a?(Integer)
49
+ @logger.level = severity
50
+ else
51
+ case severity.to_s.downcase
52
+ when 'debug'.freeze
53
+ @logger.level = DEBUG
54
+ when 'info'.freeze
55
+ @logger.level = INFO
56
+ when 'warn'.freeze
57
+ @logger.level = WARN
58
+ when 'error'.freeze
59
+ @logger.level = ERROR
60
+ when 'fatal'.freeze
61
+ @logger.level = FATAL
62
+ when 'unknown'.freeze
63
+ @logger.level = UNKNOWN
64
+ else
65
+ raise ArgumentError, "invalid log level: #{severity}"
66
+ end
67
+ end
68
+ end
69
+
70
+ #
71
+ # Returns IO object used by logger internally.
72
+ #
73
+ # Normally, we would have never needed it, but we want to
74
+ # use it as IO object for all child processes to ensure their
75
+ # output is redirected there.
76
+ #
77
+ # It is only used in debug level, in other cases output is suppressed.
78
+ #
79
+ # @api private
80
+ #
81
+ def io
82
+ @logger.instance_variable_get(:@logdev).instance_variable_get(:@dev)
83
+ end
84
+
85
+ #
86
+ # Marks code as deprecated with replacement.
87
+ #
88
+ # @param [String] old
89
+ # @param [String] new
90
+ #
91
+ def deprecate(old, new)
92
+ warn "[DEPRECATION] #{old} is deprecated. Use #{new} instead."
93
+ end
94
+
95
+ private
96
+
97
+ def create_logger(output)
98
+ logger = ::Logger.new(output)
99
+ logger.progname = 'SeoCache'
100
+ logger.level = ($DEBUG ? DEBUG : INFO)
101
+ logger.formatter = proc do |severity, time, progname, msg|
102
+ "#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
103
+ end
104
+
105
+ logger
106
+ end
107
+ end
108
+ end
@@ -35,7 +35,7 @@ module SeoCache
35
35
 
36
36
  def cache_exists?(path)
37
37
  if SeoCache.memory_cache? && @redis
38
- @redis.exists?(cache_path(path))
38
+ @redis.exists(cache_path(path))
39
39
  else
40
40
  File.exist?(cache_path(path))
41
41
  end
@@ -33,6 +33,8 @@ module SeoCache
33
33
  def init_driver
34
34
  # Selenium::WebDriver.logger.level = :info
35
35
 
36
+ Selenium::WebDriver::Chrome.path = SeoCache.chrome_path if SeoCache.chrome_path
37
+
36
38
  client = ::Selenium::WebDriver::Remote::Http::Persistent.new
37
39
  browser_options = ::Selenium::WebDriver::Chrome::Options.new
38
40
  browser_options.args << '--headless'
@@ -1,3 +1,3 @@
1
1
  module SeoCache
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
data/lib/seo_cache.rb CHANGED
@@ -1,23 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'net/http'
4
3
  require 'active_support'
5
- require 'selenium/webdriver'
6
- require 'chromedriver-helper'
7
- require 'selenium/webdriver/remote/http/persistent'
4
+ require 'net/http'
8
5
  require 'redis'
9
6
  require 'redis-namespace'
7
+ require 'selenium/webdriver'
8
+ require 'selenium/webdriver/remote/http/persistent'
9
+ require 'webdrivers'
10
10
 
11
+ require 'seo_cache/logger'
11
12
  require 'seo_cache/version'
12
13
  require 'seo_cache/middleware'
13
14
 
14
15
  module SeoCache
15
16
 
17
+ mattr_accessor :chrome_path
18
+ self.chrome_path = nil
19
+
16
20
  mattr_accessor :cache_mode # disk or memory
17
21
  self.cache_mode = 'memory'
18
22
 
19
23
  mattr_accessor :disk_cache_path
20
- self.disk_cache_path = nil
24
+ self.disk_cache_path = ''
21
25
 
22
26
  mattr_accessor :disk_cache_extension
23
27
  self.disk_cache_extension = '.html'
@@ -89,6 +93,15 @@ module SeoCache
89
93
  'Qwantify'
90
94
  ]
91
95
 
96
+ mattr_accessor :logger_path
97
+ self.logger_path = nil
98
+
99
+ mattr_accessor :logger_level
100
+ self.logger_level = :INFO
101
+
102
+ mattr_accessor :logger
103
+ # self.logger = SeoCache::Logger.new(SeoCache.logger_path)
104
+
92
105
  def self.memory_cache?
93
106
  SeoCache.cache_mode == 'memory'
94
107
  end
@@ -97,11 +110,17 @@ module SeoCache
97
110
  SeoCache.cache_mode == 'disk'
98
111
  end
99
112
 
113
+ def self.logger
114
+ @logger ||= SeoCache::Logger.new(SeoCache.logger_path)
115
+ end
116
+
100
117
  def self.log(message)
101
- Rails.logger.info { "[seo_cache] #{message}" }
118
+ SeoCache.logger.info(message)
119
+ # Rails.logger.info { "[seo_cache] #{message}" }
102
120
  end
103
121
 
104
122
  def self.log_error(message)
105
- Rails.logger.error { "[seo_cache] #{message}" }
123
+ SeoCache.logger.error(message)
124
+ # Rails.logger.error { "[seo_cache] #{message}" }
106
125
  end
107
126
  end
data/seo_cache.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = 'Cache dedicated for SEO with Javascript rendering'
12
12
  spec.description = 'Specific cache for bots to optimize time to first byte and render Javascript on server side.'
13
- spec.homepage = 'https://github.com/floXcoder/SeoCache'
13
+ spec.homepage = 'https://github.com/floXcoder/seo_cache'
14
14
  spec.license = 'MIT'
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -20,16 +20,18 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ['lib']
22
22
 
23
+ spec.add_dependency 'activesupport', '~> 5'
24
+ spec.add_dependency 'net-http-persistent', '~> 3'
23
25
  spec.add_dependency 'rack', '~> 2'
24
26
  spec.add_dependency 'railties', '~> 5'
25
- spec.add_dependency 'net-http-persistent', '~> 3'
26
- spec.add_dependency 'activesupport', '~> 5'
27
- spec.add_dependency 'selenium-webdriver', '~> 3'
28
- spec.add_dependency 'chromedriver-helper', '~> 2'
29
27
  spec.add_dependency 'redis', '~> 4'
30
28
  spec.add_dependency 'redis-namespace', '~> 1'
29
+ spec.add_dependency 'selenium-webdriver', '~> 3'
30
+ spec.add_dependency 'webdrivers', '~> 3'
31
31
 
32
32
  spec.add_development_dependency 'bundler', '~> 1'
33
33
  spec.add_development_dependency 'rake', '~> 12'
34
34
  spec.add_development_dependency 'rspec', '~> 3'
35
+ spec.add_development_dependency 'simplecov', '~> 0.16'
36
+ spec.add_development_dependency 'webmock', '~> 3'
35
37
  end
metadata CHANGED
@@ -1,59 +1,59 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seo_cache
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
  - FloXcoder
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-03-26 00:00:00.000000000 Z
11
+ date: 2019-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rack
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2'
19
+ version: '5'
20
20
  type: :runtime
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: '2'
26
+ version: '5'
27
27
  - !ruby/object:Gem::Dependency
28
- name: railties
28
+ name: net-http-persistent
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '5'
33
+ version: '3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '5'
40
+ version: '3'
41
41
  - !ruby/object:Gem::Dependency
42
- name: net-http-persistent
42
+ name: rack
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3'
47
+ version: '2'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3'
54
+ version: '2'
55
55
  - !ruby/object:Gem::Dependency
56
- name: activesupport
56
+ name: railties
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
@@ -67,61 +67,61 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '5'
69
69
  - !ruby/object:Gem::Dependency
70
- name: selenium-webdriver
70
+ name: redis
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '3'
75
+ version: '4'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '3'
82
+ version: '4'
83
83
  - !ruby/object:Gem::Dependency
84
- name: chromedriver-helper
84
+ name: redis-namespace
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '2'
89
+ version: '1'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '2'
96
+ version: '1'
97
97
  - !ruby/object:Gem::Dependency
98
- name: redis
98
+ name: selenium-webdriver
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '4'
103
+ version: '3'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '4'
110
+ version: '3'
111
111
  - !ruby/object:Gem::Dependency
112
- name: redis-namespace
112
+ name: webdrivers
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '1'
117
+ version: '3'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '1'
124
+ version: '3'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: bundler
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +164,34 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: '3'
167
+ - !ruby/object:Gem::Dependency
168
+ name: simplecov
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '0.16'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '0.16'
181
+ - !ruby/object:Gem::Dependency
182
+ name: webmock
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '3'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '3'
167
195
  description: Specific cache for bots to optimize time to first byte and render Javascript
168
196
  on server side.
169
197
  email:
@@ -186,13 +214,14 @@ files:
186
214
  - bin/console
187
215
  - bin/setup
188
216
  - lib/seo_cache.rb
217
+ - lib/seo_cache/logger.rb
189
218
  - lib/seo_cache/middleware.rb
190
219
  - lib/seo_cache/page_caching.rb
191
220
  - lib/seo_cache/page_render.rb
192
221
  - lib/seo_cache/populate_cache.rb
193
222
  - lib/seo_cache/version.rb
194
223
  - seo_cache.gemspec
195
- homepage: https://github.com/floXcoder/SeoCache
224
+ homepage: https://github.com/floXcoder/seo_cache
196
225
  licenses:
197
226
  - MIT
198
227
  metadata: {}