Skip to content

Commit

Permalink
Refactor code (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
jiangtj authored Feb 5, 2021
1 parent 9b509fa commit 144b47e
Show file tree
Hide file tree
Showing 19 changed files with 341 additions and 220 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/linter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Linter

on: [push, pull_request]

jobs:
linter:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Use Node.js 12.x
uses: actions/setup-node@v2
with:
node-version: '12.x'
- name: Cache NPM dependencies
uses: actions/cache@v1
with:
path: node_modules
key: ${{ runner.OS }}-npm-cache
restore-keys: |
${{ runner.OS }}-npm-cache
- name: Install Dependencies
run: npm install
- name: Lint
run: |
npm run eslint
env:
CI: true
60 changes: 60 additions & 0 deletions .github/workflows/tester.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Tester

on: [push, pull_request]

jobs:
tester:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: ['10.x', '12.x', '14.x']
fail-fast: false
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Cache NPM dependencies
uses: actions/cache@v1
with:
path: node_modules
key: ${{ runner.os }}-npm-cache
restore-keys: ${{ runner.os }}-npm-cache
- name: Install Dependencies
run: npm install
- name: Test
run: npm run test
env:
CI: true
coverage:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
node-version: ['12.x']
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Cache NPM dependencies
uses: actions/cache@v1
with:
path: node_modules
key: ${{ runner.os }}-npm-cache
restore-keys: ${{ runner.os }}-npm-cache
- name: Install Dependencies
run: npm install
- name: Run test
run: npm run test
# - name: Coverage
# run: npm run test-cov
# env:
# CI: true
# - name: Coveralls
# uses: coverallsapp/github-action@master
# with:
# github-token: ${{ secrets.github_token }}
2 changes: 2 additions & 0 deletions .yarnrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
disable-self-update-check true
registry "https://registry.npmjs.org"
47 changes: 18 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@

## Install

If you use [next](https://github.com/theme-next/hexo-theme-next) or [cake](https://github.com/jiangtj/hexo-theme-cake) theme, just install it.

```bash
yarn add @jiangtj/hexo-next-pwa
```

Others, you need to install hexo5.0 or the latest master branch
require: hexo5+ or [next](https://github.com/theme-next/hexo-theme-next)/[cake](https://github.com/jiangtj/hexo-theme-cake) theme

## Configure

I added some default configurations, see [default.yaml](default.yaml)

```yml
pwa:
# Generate manifest.json
Expand All @@ -40,44 +40,33 @@ pwa:
# type: image/png
# Generate sw.js
serviceWorker:
cdn: https://cdn.jsdelivr.net/npm/workbox-sw@5/build/workbox-sw.min.js
# See workbox-build's `generateSW()` API
# Here are some default configuration, see `./default.yaml`
precache:
# precache posts url
posts:
enable: true
sort: -date
limit: 10
# precache pages url
pages: true
options:
# sw file path
swDest: /sw.js
```
`serviceWorker.options` refer to [the workbox-build's `generateSW()` API](https://developers.google.cn/web/tools/workbox/reference-docs/latest/module-workbox-build#.generateSW). Some configurations are not supported for the time being. See the compatibility table below.
`serviceWorker.precache` define how to precache url.

| feature | status |
`serviceWorker.options` refer to [the workbox-build's `generateSW()` API](https://developers.google.cn/web/tools/workbox/reference-docs/latest/module-workbox-build#.generateSW). Some configurations are not supported, due to the precache manifest is generated in different ways.

| options | compatibility |
| :--- | :--- |
| swDest | ✔ relative to build directory |
| importScripts | ✔ |
| offlineGoogleAnalytics | ✔ |
| runtimeCaching | ✔ |
| swDest | relative to build directory |
| globDirectory | ✖ |
| additionalManifestEntries | ✖ |
| babelPresetEnvTargets | ✖ |
| cacheId | plan |
| cleanupOutdatedCaches | ✖ |
| clientsClaim | ✖ |
| directoryIndex | ✖ |
| dontCacheBustURLsMatching | ✖ |
| globFollow | ✖ |
| globIgnores | ✖ |
| globPatterns | ✖ |
| globStrict | ✖ |
| ignoreURLParametersMatching | ✖ |
| inlineWorkboxRuntime | ✖ |
| manifestTransforms | ✖ |
| maximumFileSizeToCacheInBytes | plan |
| mode | ✖ |
| maximumFileSizeToCacheInBytes | ✖ |
| modifyURLPrefix | ✖ |
| navigateFallback | ✖ |
| navigateFallbackDenylist | ✖ |
| navigateFallbackAllowlist | ✖ |
| navigationPreload | ✖ |
| skipWaiting | plan |
| sourcemap | ✖ |
| templatedURLs | ✖ |

20 changes: 12 additions & 8 deletions default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,41 @@ pwa:
# sizes: 512x512
# type: image/png
serviceWorker:
cdn: https://cdn.jsdelivr.net/npm/workbox-sw@5/build/workbox-sw.min.js
disableDevLogs: false
precache:
posts:
enable: true
sort: -date
limit: 10
pages: true
options:
swDest: /sw.js
importScripts: []
runtimeCaching:
- urlPattern: /
handler: NetworkFirst
options:
cacheName: index
- urlPattern: !!js/regexp /\.(?:js|css)$/
- urlPattern: regexp:\.(?:js|css)$
handler: StaleWhileRevalidate
options:
cacheName: js-css
- urlPattern: !!js/regexp /\.(?:png|gif|jpg|jpeg|svg)$/
- urlPattern: regexp:\.(?:png|gif|jpg|jpeg|svg)$
handler: CacheFirst
options:
cacheName: images
cacheableResponse:
statuses: [0, 200]
expiration:
maxEntries: 60
maxAgeSeconds: 2592000 # 30 * 24 * 60 * 60
- urlPattern: !!js/regexp /^https:\/\/fonts\.googleapis\.com/
- urlPattern: regexp:^https:\/\/fonts\.googleapis\.com
handler: StaleWhileRevalidate
options:
cacheName: google-fonts-stylesheets
- urlPattern: !!js/regexp /^https:\/\/fonts\.gstatic\.com/
- urlPattern: regexp:^https:\/\/fonts\.gstatic\.com
handler: CacheFirst
options:
cacheName: google-fonts-webfonts
cacheableResponse:
statuses: [0, 200]
expiration:
maxAgeSeconds: 31536000 # 365 * 24 * 60 * 60
offlineGoogleAnalytics: false
37 changes: 18 additions & 19 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,24 @@
'use strict';

const { generator } = hexo.extend;
const { mergeWith } = require('lodash');
const yaml = require('js-yaml');
const fs = require('fs');
const { join } = require('path');
const injector = require('hexo-extend-injector2')(hexo);
const config = require('./lib/get-default-config')(hexo);
const validate = require('./lib/validate-sw-options');

/**
* config
*/
const defaultConfig = yaml.load(fs.readFileSync(join(__dirname, 'default.yaml'), 'utf8'));
const config = mergeWith(defaultConfig.pwa, hexo.config.pwa, (objValue, srcValue) => {
if (Array.isArray(objValue)) {
return srcValue;
}
});
const { manifest, serviceWorker } = config;
serviceWorker.options = validate(serviceWorker.options);

/**
* generator manifest
*/
injector.register('head-end', `<link rel="manifest" href="${config.manifest.path}" />`);
injector.register('head-end', `<link rel="manifest" href="${manifest.path}" />`);
generator.register('pwa_manifest', () => {
const manifest = config.manifest;
return {
path: manifest.path,
data: JSON.stringify(
Object.assign({
name: config.title,
start_url: config.url
name: hexo.config.title,
start_url: hexo.config.url
}, manifest.body)
)
};
Expand All @@ -43,9 +33,18 @@ injector.register('body-end', `
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('${config.serviceWorker.options.swDest}');
navigator.serviceWorker.register('${serviceWorker.options.swDest}');
});
}
</script>
`);
generator.register('pwa_service_worker', () => require('./lib/generate-sw-string')(config.serviceWorker));

generator.register('pwa_service_worker', locals => {
return require('./lib/generate-sw-string')(locals, serviceWorker)
.then(({files}) => {
return files.map(file => ({
path: file.name,
data: file.contents
}));
});
});
19 changes: 0 additions & 19 deletions lib/define-cache.js

This file was deleted.

81 changes: 27 additions & 54 deletions lib/generate-sw-string.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,38 @@
'use strict';

const ejs = require('ejs');
const { resolve } = require('path');
const { upperFirst } = require('lodash');
const DefineCache = require('./define-cache');
const define = new DefineCache();
const getStringHash = require('./get-string-hash');
const writeServiceWorkerUsingDefaultTemplate = require('./write-sw-using-default-template');

const handeRuntimeCaching = runtimeCachingEntry => {
let capture = runtimeCachingEntry.urlPattern;
if (typeof capture === 'string') {
capture = `'${capture}'`;
}

const options = runtimeCachingEntry.options || {};

options.plugins = options.plugins || [];
['backgroundSync', 'broadcastUpdate', 'cacheableResponse', 'expiration'].forEach(item => {
if (options[item]) {
const plugin = {};
plugin.name = item;
plugin.options = options[item];
options.plugins.push(plugin);
delete options[item];
}
});
options.plugins = options.plugins.map(plugin => {
const pluginDefine = `${upperFirst(plugin.name)}Plugin`;
define.set(`workbox.${plugin.name}`, pluginDefine);
return `new ${pluginDefine}(${JSON.stringify(plugin.options)})`;
});
module.exports = async (locals, serviceWorker) => {

define.set('workbox.strategies', runtimeCachingEntry.handler);
const handler = `new ${runtimeCachingEntry.handler}(${JSON.stringify(options, (key, value) => {
if (key === 'plugins') {
return '$plugins-point';
}
return value;
})})`.replace('"$plugins-point"', `[${options.plugins.join(',')}]`);
const { precache, options } = serviceWorker;
const { pages, posts } = locals;

const method = runtimeCachingEntry.method || 'GET';
const manifestEntries = [];

define.set('workbox.routing', 'registerRoute');
return `registerRoute(${capture}, ${handler}, '${method}');`;
};

module.exports = serviceWorker => {
const options = Object.assign({
workboxCDN: serviceWorker.cdn,
disableDevLogs: serviceWorker.disableDevLogs
}, serviceWorker.options);
if (precache.posts.enable) {
posts.sort(precache.posts.sort)
.limit(precache.posts.limit)
.forEach(item => {
manifestEntries.push({
url: item.path,
revision: getStringHash(item.content)
});
});
}

if (options.runtimeCaching) {
options.runtimeCaching = options.runtimeCaching.map(handeRuntimeCaching);
if (precache.pages) {
pages.forEach(item => {
manifestEntries.push({
url: item.path,
revision: getStringHash(item.content)
});
});
}

options.importDefine = define.toString();
const files = await writeServiceWorkerUsingDefaultTemplate(Object.assign({
manifestEntries
}, options));

return {
path: options.swDest,
data: () => {
return ejs.renderFile(resolve(__dirname, '../templates/sw-template.ejs'), options);
}
};
return {files};
};
Loading

0 comments on commit 144b47e

Please sign in to comment.