├── .gitignore
├── example
├── assets
│ └── icon.png
├── stores
│ └── clicks.js
├── manifest.json
├── views
│ ├── 404.js
│ └── main.js
├── index.js
├── package.json
├── README.md
└── sw.js
├── package.json
├── index.js
├── LICENSE
└── readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | coverage/
3 | npm-debug.log*
4 | .nyc_output
5 |
--------------------------------------------------------------------------------
/example/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YerkoPalma/service-worker-renderer/master/example/assets/icon.png
--------------------------------------------------------------------------------
/example/stores/clicks.js:
--------------------------------------------------------------------------------
1 | module.exports = store
2 |
3 | function store (state, emitter) {
4 | state.totalClicks = 0
5 |
6 | emitter.on('DOMContentLoaded', function () {
7 | emitter.on('clicks:add', function (count) {
8 | state.totalClicks += count
9 | emitter.emit(state.events.RENDER)
10 | })
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/example/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "short_name": "example",
4 | "description": "A very cute app",
5 | "start_url": "/",
6 | "display": "standalone",
7 | "background_color": "#ffc0cb",
8 | "theme_color": "#ffc0cb",
9 | "icons": [{
10 | "src": "/assets/icon.png",
11 | "type": "image/png",
12 | "sizes": "512x512"
13 | }]
14 | }
--------------------------------------------------------------------------------
/example/views/404.js:
--------------------------------------------------------------------------------
1 | var html = require('choo/html')
2 |
3 | var TITLE = '🚂🚋🚋 - route not found'
4 |
5 | module.exports = view
6 |
7 | function view (state, emit) {
8 | if (state.title !== TITLE) emit(state.events.DOMTITLECHANGE, TITLE)
9 | return html`
10 |
11 |
12 | 404 - route not found
13 |
14 |
19 |
20 | `
21 | }
22 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | var css = require('sheetify')
2 | var choo = require('choo')
3 | var store = require('./stores/clicks')
4 |
5 | css('tachyons')
6 |
7 | var app = choo()
8 | if (process.env.NODE_ENV !== 'production') {
9 | app.use(require('choo-devtools')())
10 | } else {
11 | // Enable once you want service workers support. At the moment you'll
12 | // need to insert the file names yourself & bump the dep version by hand.
13 | // app.use(require('choo-service-worker')())
14 | }
15 |
16 | app.use(store)
17 |
18 | app.route('/', require('./views/main'))
19 | app.route('/*', require('./views/404'))
20 |
21 | if (!module.parent) app.mount('body')
22 | else module.exports = app
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "service-worker-renderer",
3 | "description": "Service worker side renderer",
4 | "author": "YerkoPalma",
5 | "version": "0.1.0",
6 | "main": "index.js",
7 | "files": [
8 | "index.js"
9 | ],
10 | "scripts": {
11 | "test": "standard --verbose | snazzy && tape test.js | tap-summary",
12 | "start": "node index.js"
13 | },
14 | "repository": "YerkoPalma/service-worker-renderer",
15 | "license": "MIT",
16 | "keywords": [
17 | "service-worker",
18 | "server",
19 | "render",
20 | "web"
21 | ],
22 | "devDependencies": {
23 | "snazzy": "^7.0.0",
24 | "standard": "^10.0.3",
25 | "tap-summary": "^4.0.0",
26 | "tape": "^4.8.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/example/views/main.js:
--------------------------------------------------------------------------------
1 | var html = require('choo/html')
2 |
3 | var TITLE = '🚂🚋🚋'
4 |
5 | module.exports = view
6 |
7 | function view (state, emit) {
8 | if (state.title !== TITLE) emit(state.events.DOMTITLECHANGE, TITLE)
9 |
10 | return html`
11 |
12 |
13 | Choo choo!
14 |
15 |
16 |
17 |
Current number of clicks: ${state.totalClicks}
18 |
19 |
20 |
21 |
22 | `
23 |
24 | function handleClick () {
25 | emit('clicks:add', 1)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "build": "bankai build index.js",
7 | "create": "choo-scaffold",
8 | "inspect": "bankai inspect index.js",
9 | "start": "bankai start index.js",
10 | "test": "standard && npm run test-deps",
11 | "test-deps": "dependency-check . && dependency-check . --extra --no-dev -i tachyons"
12 | },
13 | "dependencies": {
14 | "choo": "^6.7.0",
15 | "choo-devtools": "^2.3.3",
16 | "choo-service-worker": "^2.3.1",
17 | "sheetify": "^7.0.0",
18 | "tachyons": "^4.9.1"
19 | },
20 | "devDependencies": {
21 | "bankai": "^9.3.1",
22 | "choo-scaffold": "^1.1.2",
23 | "dependency-check": "^3.0.0",
24 | "standard": "^10.0.3"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # example
2 | A very cute app
3 |
4 | ## Routes
5 | Route | File | Description |
6 | -------------------|--------------------|---------------------------------|
7 | `/` | `views/main.js` | The main view
8 | `/*` | `views/404.js` | Display unhandled routes
9 |
10 | ## Commands
11 | Command | Description |
12 | -----------------------|--------------------------------------------------|
13 | `$ npm start` | Start the development server
14 | `$ npm test` | Lint, validate deps & run tests
15 | `$ npm run build` | Compile all files into `dist/`
16 | `$ npm run create` | Generate a scaffold file
17 | `$ npm run inspect` | Inspect the bundle's dependencies
--------------------------------------------------------------------------------
/example/sw.js:
--------------------------------------------------------------------------------
1 | /* global self */
2 |
3 | var VERSION = require('./package.json').version
4 | var URLS = process.env.FILE_LIST
5 |
6 | // Respond with cached resources
7 | self.addEventListener('fetch', function (e) {
8 | e.respondWith(self.caches.match(e.request).then(function (request) {
9 | if (request) return request
10 | else return self.fetch(e.request)
11 | }))
12 | })
13 |
14 | // Register worker
15 | self.addEventListener('install', function (e) {
16 | e.waitUntil(self.caches.open(VERSION).then(function (cache) {
17 | return cache.addAll(URLS)
18 | }))
19 | })
20 |
21 | // Remove outdated resources
22 | self.addEventListener('activate', function (e) {
23 | e.waitUntil(self.caches.keys().then(function (keyList) {
24 | return Promise.all(keyList.map(function (key, i) {
25 | if (keyList[i] !== VERSION) return self.caches.delete(keyList[i])
26 | }))
27 | }))
28 | })
29 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-env serviceworker */
2 | (function () {
3 | self.getTemplate = function (templateUrl) {
4 | self.caches.match(templateUrl).then(function (response) {
5 | return response.text()
6 | })
7 | }
8 | self.renderTemplate = function (template, state) {
9 | return ''
10 | }
11 | function Router () {
12 | this.routes = new Map()
13 | this.current = null
14 | }
15 | Router.prototype.route = function (route, template) {
16 | // route should be a regex
17 | if (typeof route === 'string') {
18 | this.router.set(new RegExp('^' + route.replace(/:.*\//g, '(.*)/') + '$'), template)
19 | }
20 | this.routes.set(route, template)
21 | }
22 | Router.prototype.match = function (url, state) {
23 | for (var regex in this.router.keys()) {
24 | if (regex.test(url)) {
25 | this.current = this.routes.get(regex)
26 | break
27 | }
28 | }
29 | if (state) {
30 | return self.renderTemplate(this.current, state)
31 | }
32 | return this.current
33 | }
34 | })()
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Yerko Palma
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # service-worker-renderer
2 | [](https://travis-ci.org/YerkoPalma/service-worker-renderer) [](https://github.com/feross/standard)
3 |
4 | > Service worker side renderer
5 |
6 | ## Usage
7 |
8 | ```js
9 | // sw.js
10 | importScript('/.service-worker-renderer.js')
11 |
12 | self.addEventListener('fetch', async function (event) {
13 | event.respondWith(
14 | const template = await parseTemplate('/article-template.html')
15 | return new Response(renderTemplate(template, state), {
16 | headers: {
17 | 'Content-Type': 'text/html'
18 | }
19 | })
20 | )
21 | }
22 | ```
23 |
24 | ```js
25 | // sw.js
26 | importScript('/.service-worker-renderer.js')
27 |
28 | // define router
29 | self.addEventListener('install', function (event) {
30 | // ...
31 | var router = new Router()
32 | router.route('/', '/main-template.html')
33 | router.route('/article', '/article-template.html')
34 |
35 | self.router = router
36 | })
37 |
38 | self.addEventListener('fetch', function (event) {
39 | event.respondWith(
40 | return router.match(event.request.url, state)
41 | )
42 | }
43 | ```
44 |
45 | ## API
46 | ### `getParams`
47 | ### `parseTemplate`
48 | ### `renderTemplate`
49 | ### `Router`
50 | ## License
51 | [MIT](/license)
52 |
--------------------------------------------------------------------------------