From 0048a20007586fe5ff6daff15d7c59ecf43f3893 Mon Sep 17 00:00:00 2001 From: Ahad Birang Date: Mon, 16 Sep 2019 00:56:58 +0430 Subject: [PATCH] feat(global-amp-mode): configurable global default ampMode BREAKING CHANGE: module does not provide middleware anymore --- example/nuxt.config.js | 5 -- lib/amp/components.js | 17 ++++++ lib/amp/middleware.js | 124 ---------------------------------------- lib/amp/plugin.js | 126 +++++++++++++++++++++++++++++++++++------ lib/module.js | 1 + test/plugin.test.js | 2 +- 6 files changed, 127 insertions(+), 148 deletions(-) create mode 100644 lib/amp/components.js delete mode 100644 lib/amp/middleware.js diff --git a/example/nuxt.config.js b/example/nuxt.config.js index 7941c45c..93eb78bd 100644 --- a/example/nuxt.config.js +++ b/example/nuxt.config.js @@ -12,10 +12,5 @@ module.exports = { ], amp: { origin: 'http://localhost:3000' - }, - router: { - middleware: [ - 'amp' - ] } } diff --git a/lib/amp/components.js b/lib/amp/components.js new file mode 100644 index 00000000..40d50842 --- /dev/null +++ b/lib/amp/components.js @@ -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) diff --git a/lib/amp/middleware.js b/lib/amp/middleware.js deleted file mode 100644 index 89046f9c..00000000 --- a/lib/amp/middleware.js +++ /dev/null @@ -1,124 +0,0 @@ -import VueMeta from 'vue-meta' -import { stringify } from 'qs' -import Middleware from '../middleware' - -const [vueMetaMajor] = VueMeta.version.split('.') - -function ensureKey (obj, key, d) { - if (!obj[key]) { - obj[key] = d - } -} - -function stringifyQuery (query) { - if (!Object.keys(query).length) { - return '' - } - return '?' + stringify(query) -} - -Middleware.amp = function ({ route, req, app }) { - if (!route.matched[0]) { - return - } - - const { options } = route.matched[0].components.default - - if (options.amp === false) { - return - } - - if (!options._amp) { - options.head = createCustomHead(options.head) - options.layout = createCustomLayout(options.layout) - options._amp = true - } -} - -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', []) - - const { amp, ...query } = this.$route.query - - if (origin && !head.link.find(l => l.rel === 'canonical' || l.hid === 'canonical')) { - const path = this.$isAMP && this.$ampMode !== 'only' - ? this.$route.path.replace(/^\/amp(\/.*)?/, '$1') - : this.$route.path - - head.link.push({ - rel: 'canonical', - hid: 'canonical', - href: origin + path + stringifyQuery(query) - }) - } - - /** - * 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.path + stringifyQuery(query) - }) - } - } - - return head -} - -const createCustomLayout = originalLayout => function customLayout (ctx) { - let layout - - switch (typeof originalLayout) { - case 'function': - layout = originalLayout.call(this, ctx) - break - case 'string': - layout = { ...originalLayout } - break - default: - layout = 'default' - break - } - return ctx.app.$isAMP ? layout + '.amp' : layout -} diff --git a/lib/amp/plugin.js b/lib/amp/plugin.js index 20401198..77f96c63 100644 --- a/lib/amp/plugin.js +++ b/lib/amp/plugin.js @@ -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) { @@ -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 @@ -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 } @@ -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 +} diff --git a/lib/module.js b/lib/module.js index a7774033..81523654 100644 --- a/lib/module.js +++ b/lib/module.js @@ -16,6 +16,7 @@ module.exports = function (moduleOptions) { const options = { cdnBase: undefined, origin: '', + mode: 'hybrid', ...this.options.amp, ...moduleOptions } diff --git a/test/plugin.test.js b/test/plugin.test.js index 569106e7..4d6f280e 100644 --- a/test/plugin.test.js +++ b/test/plugin.test.js @@ -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', () => {