class SWHelper

Constants

WORKBOX_VERSION

Public Class Methods

new(site, config) click to toggle source
# File lib/jekyll-amp-pwa-plugin.rb, line 3
def initialize(site, config)
    @site = site
    @config = config
    @sw_filename = @config['sw_dest_filename'] || 'service-worker.js'
    @sw_src_filepath = @config['sw_src_filepath'] || 'service-worker.js'
end

Public Instance Methods

generate_workbox_precache() click to toggle source
# File lib/jekyll-amp-pwa-plugin.rb, line 40
def generate_workbox_precache()
    directory = @config['precache_glob_directory'] || '/'
    directory = @site.in_dest_dir(directory)
    patterns = @config['precache_glob_patterns'] || ['**/*.{html,js,css,eot,svg,ttf,woff}']
    ignores = @config['precache_glob_ignores'] || []
    recent_posts_num = @config['precache_recent_posts_num']

    # according to workbox precache {url: 'main.js', revision: 'xxxx'}
    @precache_list = []

    # find precache files with glob
    precache_files = []
    patterns.each do |pattern|
        Dir.glob(File.join(directory, pattern)) do |filepath|
            precache_files.push(filepath)
        end
    end
    precache_files = precache_files.uniq

    # precache recent n posts
    posts_path_url_map = {}
    if recent_posts_num
        precache_files.concat(
            @site.posts.docs
                .reverse.take(recent_posts_num)
                .map do |post|
                    posts_path_url_map[post.path] = post.url
                    post.path
                end
        )
    end

    # filter with ignores
    ignores.each do |pattern|
        Dir.glob(File.join(directory, pattern)) do |ignored_filepath|
            precache_files.delete(ignored_filepath)
        end
    end

    # generate md5 for each precache file
    md5 = Digest::MD5.new
    precache_files.each do |filepath|
        md5.reset
        md5 << File.read(filepath)
        if posts_path_url_map[filepath]
            url = posts_path_url_map[filepath]
        else
            url = filepath.sub(@site.dest, '')
        end
        @precache_list.push({
            url: @site.baseurl.to_s + url,
            revision: md5.hexdigest
        })
    end
end
write_sw() click to toggle source
# File lib/jekyll-amp-pwa-plugin.rb, line 96
    def write_sw()

        dest_js_directory = @config['dest_js_directory'] || 'js'

        # copy polyfill & workbox.js to js/
        script_directory = @site.in_dest_dir(dest_js_directory)
        FileUtils.mkdir_p(script_directory) unless Dir.exist?(script_directory)
        FileUtils.cp_r(File.expand_path('../vendor/', __FILE__) + '/.', script_directory)

        # generate precache list
        precache_list_str = @precache_list.map do |precache_item|
            precache_item.to_json
        end
        .join(",")

        # write service-worker.js
        sw_src_file_str = File.read(@site.in_source_dir(@sw_src_filepath))
        workbox_dir = File.join(@site.baseurl.to_s, dest_js_directory, "workbox-#{SWHelper::WORKBOX_VERSION}")
        import_scripts_str =
        <<-SCRIPT
            importScripts("#{workbox_dir}/workbox-sw.js");
            workbox.setConfig({modulePathPrefix: "#{workbox_dir}"});
        SCRIPT

        sw_dest_file = File.new(@site.in_dest_dir(@sw_filename), 'w')
        sw_dest_file.puts(
        <<-SCRIPT
            #{import_scripts_str}
            self.__precacheManifest = [#{precache_list_str}];
            #{sw_src_file_str}
        SCRIPT
        )
        sw_dest_file.close
    end
write_sw_register() click to toggle source
# File lib/jekyll-amp-pwa-plugin.rb, line 10
    def write_sw_register()
        sw_register_filename = 'sw-register.js'
        sw_register_file = File.new(@site.in_dest_dir(sw_register_filename), 'w')
        # add build version in url params
        sw_register_file.puts(
        <<-SCRIPT
        if ('serviceWorker' in navigator) {
            navigator.serviceWorker.register('#{@site.baseurl.to_s}/#{@sw_filename}?v=#{@site.time.to_i.to_s}').then(function(reg) {
                reg.onupdatefound = function() {
                    var installingWorker = reg.installing;
                    installingWorker.onstatechange = function() {
                        switch (installingWorker.state) {
                            case 'installed':
                                if (navigator.serviceWorker.controller) {
                                    var event = new Event('sw.update');
                                    window.dispatchEvent(event);
                                }
                                break;
                        }
                    };
                };
            }).catch(function(e) {
                console.error('Error during service worker registration:', e);
            });
        }
        SCRIPT
        )
        sw_register_file.close
    end