Skip to content
This repository has been archived by the owner on Dec 10, 2023. It is now read-only.

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
DreaMinder committed Sep 28, 2018
1 parent 7a7260e commit feceac8
Show file tree
Hide file tree
Showing 13 changed files with 337 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules/
.DS_Store
.nuxt/
dist/
package-lock.json
npm-debug.log*
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Nuxt payload extractor

Nuxt.js module that makes `nuxt generate` command to store html and payload separately. **Early stages of development, I warned ya!**

## Benefits

✓ If you use external API to fill your project with data, even after your site have been prerendered, you need to keep your API running to make client-side navigation possible. With this module your API data stores along with prerendered HTML, so the issue is solved

✓ Increases page download speed for crawlers

✓ Makes HTML source code look cleaner

✓ Decreases load on API server

✓ Makes prerendered and client rendered pages consistent in case API data changed after you deployed prerendered pages

✓ Decreases initial page download time x1.5-2 (which is actually doesn't affect perfomance)

## Setup
- Add `nuxt-payload-extractor` dependency
- Define nuxt module:

```js
{
modules: [
'nuxt-payload-extractor'
]
}
```

- Add asyncData custom logic

```js
async asyncData({ app, error, route }){
try {
let payload = {};
if(process.static && process.client)
payload = await app.$axios.$get(document.location.origin + route.path + '/payload.json')
else
payload.post = await app.$axios.$get(`/{your api data url}`)

return payload
} catch (e) {
console.error(e);
error({ statusCode: 404, message: e.message })
}
}
```

- Run `npm run generate`

## How it works

- Extracts `<script>window.__NUXT__= ... </script>` replasing it with `<script src="payload.js">`
- Makes two files along with `index.html` of prerendered page: `payload.js` for initial page load and `payload.json` for client-side navigation
18 changes: 18 additions & 0 deletions example/components/footer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<footer>
<a href="https://github.com/DreaMinder">Github</a>
</footer>
</template>

<style>
footer{
text-align: center;
padding: 20px;
background: #333;
}
footer a{
color: #fff
}
</style>
29 changes: 29 additions & 0 deletions example/components/header.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<template>
<header>
<nav>
<nuxt-link to="/extracted">Page with extracted payload</nuxt-link>
<nuxt-link to="/">Page with inlined payload</nuxt-link>
</nav>
</header>
</template>

<style>
header{
text-align: center;
padding: 40px;
background: #ebebeb;
}
header a{
display: inline-block;
margin: 10px;
text-transform: uppercase;
border-bottom: none
}
header a.nuxt-link-exact-active{
border-bottom: 1px solid #333
}
</style>
62 changes: 62 additions & 0 deletions example/layouts/default.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<template>
<div class="wrap">
<page-header />
<section class="content">
<nuxt />
</section>
<page-footer />
</div>
</template>

<script>
import pageHeader from '../components/header.vue'
import pageFooter from '../components/footer.vue'
export default {
components: {
pageHeader,
pageFooter
}
}
</script>

<style>
*, *:before, *:after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: "Roboto", sans-serif;
-webkit-font-smoothing: antialiased;
color: #333;
font-size: 15px;
line-height: 25px;
font-weight: 400;
min-width: 410px;
}
a{
border-bottom: 1px solid #333;
color: #111;
text-decoration: none;
}
.content{
padding: 40px;
max-width: 900px;
margin: 10px auto;
min-height: 80vh;
}
.page-enter-active, .page-leave-active {
transition: opacity .2s
}
.page-enter, .page-leave-active {
opacity: 0
}
</style>
29 changes: 29 additions & 0 deletions example/layouts/error.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<template>
<div class="wrap">
<div class="main">
<h1>{{ error.statusCode }}</h1>
<pre>{{ error.message }}</pre>
</div>
</div>
</template>

<script>
export default {
props: ['error'],
head: {
title: 'Error'
}
}
</script>

<style scoped>
.main{
text-align: center;
line-height: 100px;
padding: 100px;
}
h1{
font-size: 60px;
font-weight: 400;
}
</style>
18 changes: 18 additions & 0 deletions example/nuxt.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
head: {
title: 'Demo',
meta: [
{ charset: 'utf-8' }
],
link: [
{ rel: 'stylesheet', href: '//fonts.googleapis.com/css?family=Roboto:400,700&amp;subset=cyrillic' }
],
},
modules: [
'@nuxtjs/axios',
['nuxt-payload-extractor', {blacklist: ['/']}]
],
axios: {
prefix: '/api'
}
}
10 changes: 10 additions & 0 deletions example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"scripts": {
"dev": "nuxt",
"generate": "nuxt generate"
},
"dependencies": {
"nuxt": "latest",
"@nuxtjs/axios": "latest"
}
}
35 changes: 35 additions & 0 deletions example/pages/extracted.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<template>
<section>
<article class="post">
<h1>{{ post.title }}</h1>
<div v-html="post.content" />
</article>
</section>
</template>

<script>
export default {
async asyncData({ app, params, error, route }){
try {
let payload = {};
if(process.static && process.client && route.path !== '/') //lil hack for page without extracted payload
payload = await app.$axios.$get(document.location.origin + route.path + '/payload.json')
else
payload.post = await app.$axios.$get(`/post.json`)
return payload
} catch (e) {
console.error(e);
error({ statusCode: 404, message: e.message })
}
}
}
</script>

<style scoped>
section{
padding: 30px
}
</style>
4 changes: 4 additions & 0 deletions example/pages/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<script>
import Index from '@/pages/extracted'
export default Index
</script>
4 changes: 4 additions & 0 deletions example/static/api/post.json

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions lib/module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const fs = require('fs')
const path = require('path')

let extractPayload = function(html, route){
let chunks = html.split('<script>window.__NUXT__=')
let pre = chunks[0]
let payload = chunks[1].split('</script>').shift()
let post = chunks[1].split('</script>').slice(1).join('</script>')

return {
html: pre + '<script defer src="' + route + '/payload.js"></script>' + post,
payload
}
}

let writePayload = function(payload, route){
let dir = path.resolve(__dirname).replace('modules', 'dist') + route

if (!fs.existsSync(dir)) fs.mkdirSync(dir);
fs.writeFile(path.resolve(dir, 'payload.js'), 'window.__NUXT__=' + payload, 'utf8', function (err) {
if (err) return console.error(err);
});
// TODO get rid of json duplicate and eval, don't know how
fs.writeFile(path.resolve(dir, 'payload.json'), JSON.stringify(eval('('+payload+')').data[0]), 'utf8', function (err) {
if (err) return console.error(err);
});
}

module.exports = function extractor({ blacklist }) {
this.nuxt.hook('generate:page', async page => {
if(blacklist && blacklist.includes(page.route)) return page;

let { html, payload } = extractPayload(page.html, page.route)

writePayload(payload, page.route)

page.html = html

return page
})
}

module.exports.meta = require('../package.json')
24 changes: 24 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"contributors": [
{
"name": "DreaMinder",
"email": "dreaminder7@gmail.com"
}
],
"description": "Nuxt.js module that makes `nuxt generate` command to store html and payload separately.",
"files": [
"lib"
],
"homepage": "https://github.com/DreaMinder/nuxt-payload-extractor",
"license": "MIT",
"main": "lib/module.js",
"name": "Nuxt payload extractor",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/DreaMinder/nuxt-payload-extractor.git"
},
"version": "0.0.2"
}

0 comments on commit feceac8

Please sign in to comment.