Skip to content

Commit

Permalink
feat(global-amp-mode): configurable global default ampMode
Browse files Browse the repository at this point in the history
BREAKING CHANGE: module does not provide middleware anymore
  • Loading branch information
farnabaz committed Sep 15, 2019
1 parent 0629fe2 commit 0048a20
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 148 deletions.
5 changes: 0 additions & 5 deletions example/nuxt.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,5 @@ module.exports = {
],
amp: {
origin: 'http://localhost:3000'
},
router: {
middleware: [
'amp'
]
}
}
17 changes: 17 additions & 0 deletions lib/amp/components.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Vue from 'vue'
// @vue/component
const AMPMustache = {
name: 'AmpMustache',
render (h) {
return h('template', {
props: {
...this.$props
},
attrs: {
type: 'amp-mustache'
}
}, this.$slots.default)
}
}

Vue.component(AMPMustache.name, AMPMustache)
124 changes: 0 additions & 124 deletions lib/amp/middleware.js

This file was deleted.

126 changes: 108 additions & 18 deletions lib/amp/plugin.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import Vue from 'vue'
import './middleware'

import VueMeta from 'vue-meta'
import './components'

const [vueMetaMajor] = VueMeta.version.split('.')

function ensureKey (obj, key, d) {
if (!obj[key]) {
obj[key] = d
}
}

function pick (...args) {
for (const arg of args) {
Expand All @@ -9,17 +18,18 @@ function pick (...args) {
}
}

export default function ({ route, req }, inject) {
export default function (ctx, inject) {
const { route, req } = ctx
if (!route.matched[0]) {
return
}

const { options } = route.matched[0].components.default

const ampMode = pick(
let ampMode = pick(
options.amp,
route.meta.amp,
'hybrid'
'<%= options.mode %>'
)

let isAMP = false
Expand All @@ -28,13 +38,16 @@ export default function ({ route, req }, inject) {
case true:
case 'only':
isAMP = true
ampMode = 'only'
break
case 'hybrid':
isAMP = route.path === '/amp' || route.path.indexOf('/amp/') === 0
ampMode = 'hybrid'
break
case false:
default:
isAMP = false
ampMode = false
break
}

Expand All @@ -43,25 +56,102 @@ export default function ({ route, req }, inject) {
* This will use to detect amp request on render hook
*/
$request.isAMP = isAMP
ctx.$isAMP = isAMP

inject('req', $request)
inject('isAMP', isAMP)
inject('ampMode', ampMode)

if (ampMode !== false && !options._amp) {
options.head = createCustomHead(options.head)
options.layout = createCustomLayout(ctx, options, isAMP)
options._amp = true
}
}

// @vue/component
const AMPMustache = {
name: 'AmpMustache',
render (h) {
return h('template', {
props: {
...this.$props
},
attrs: {
type: 'amp-mustache'
}
}, this.$slots.default)
const createCustomHead = originalHead => function customHead () {
let origin
if (process.server) {
origin = '<%= options.origin %>'
} else {
origin = window.location.origin
}

let head
switch (typeof originalHead) {
case 'function':
head = originalHead.call(this)
break
case 'object':
head = { ...originalHead } // TODO
break
default:
head = {}
}

/**
* add page canonical
*/
ensureKey(head, 'link', [])

if (origin && !head.link.find(l => l.rel === 'canonical' || l.hid === 'canonical')) {
const path = this.$isAMP && this.$ampMode !== 'only'
? this.$route.fullPath.replace(/^\/amp(\/.*)?/, '$1')
: this.$route.fullPath

head.link.push({
rel: 'canonical',
hid: 'canonical',
href: origin + path
})
}

/**
* add amp requirement if page is served as AMP
*/
if (this.$isAMP) {
ensureKey(head, 'htmlAttrs', {})

if (vueMetaMajor >= 2) {
head.htmlAttrs.amp = true
} else {
head.htmlAttrs.amp = undefined
}

ensureKey(head, 'bodyAttrs', {})
ensureKey(head.bodyAttrs, 'class', '')
head.bodyAttrs.class += ' __amp'
}

// check if amp is disabled for this page
if (this.$ampMode !== false && this.$isAMP === false) {
if (!head.link.find(l => l.rel === 'amphtml' || l.hid === 'amphtml')) {
const ampPrefix = this.$ampMode === 'only' ? '' : '/amp'
head.link.push({
rel: 'amphtml',
hid: 'amphtml',
href: origin + ampPrefix + this.$route.fullPath
})
}
}

return head
}

Vue.component(AMPMustache.name, AMPMustache)
function createCustomLayout (ctx, options, isAMP) {
let layout

if (isAMP && options.ampLayout) {
layout = options.ampLayout
if (typeof layout === 'function') {
layout = layout.call(this, ctx)
}
return layout
}

layout = options.layout || 'default'
if (typeof layout === 'function') {
layout = layout.call(this, ctx)
}
return isAMP ? layout + '.amp' : layout
}
1 change: 1 addition & 0 deletions lib/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports = function (moduleOptions) {
const options = {
cdnBase: undefined,
origin: '',
mode: 'hybrid',
...this.options.amp,
...moduleOptions
}
Expand Down
2 changes: 1 addition & 1 deletion test/plugin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('Plugin', () => {
it('Detect non AMP page', () => {
Plugin.default({ route }, inject)
expect(proto.isAMP).toEqual(false)
expect(proto.ampMode).toEqual('hybrid')
expect(proto.ampMode).toEqual(false)
})

it('Detect AMP from route meta', () => {
Expand Down

0 comments on commit 0048a20

Please # to comment.