Client Fixes (#9064)

* fix loading of payments scripts

* improve loading times
This commit is contained in:
Matteo Pagliazzi
2017-09-22 13:29:08 +02:00
committed by GitHub
parent 744090e652
commit f128f3d3cd
7 changed files with 80 additions and 37 deletions

View File

@@ -75,6 +75,7 @@ import * as Analytics from 'client/libs/analytics';
import BuyModal from './components/shops/buyModal.vue'; import BuyModal from './components/shops/buyModal.vue';
import SelectMembersModal from 'client/components/selectMembersModal.vue'; import SelectMembersModal from 'client/components/selectMembersModal.vue';
import notifications from 'client/mixins/notifications'; import notifications from 'client/mixins/notifications';
import { setup as setupPayments } from 'client/libs/payments';
export default { export default {
mixins: [notifications], mixins: [notifications],
@@ -205,6 +206,12 @@ export default {
'preferences.timezoneOffset': this.browserTimezoneOffset, 'preferences.timezoneOffset': this.browserTimezoneOffset,
}); });
} }
this.$nextTick(() => {
// Load external scripts after the app has been rendered
setupPayments();
Analytics.load();
});
}).catch((err) => { }).catch((err) => {
console.error('Impossible to fetch user. Clean up localStorage and refresh.', err); // eslint-disable-line no-console console.error('Impossible to fetch user. Clean up localStorage and refresh.', err); // eslint-disable-line no-console
}); });

View File

@@ -19,7 +19,6 @@
<script> <script>
import axios from 'axios'; import axios from 'axios';
import { mapState } from 'client/libs/store'; import { mapState } from 'client/libs/store';
import bModal from 'bootstrap-vue/lib/components/modal'; import bModal from 'bootstrap-vue/lib/components/modal';
const AMAZON_PAYMENTS = process.env.AMAZON_PAYMENTS; // eslint-disable-line const AMAZON_PAYMENTS = process.env.AMAZON_PAYMENTS; // eslint-disable-line
@@ -32,7 +31,7 @@ export default {
data () { data () {
return { return {
OffAmazonPayments: {}, OffAmazonPayments: {},
isAmazonReady: false, isAmazonSetup: false,
amazonButtonEnabled: false, amazonButtonEnabled: false,
amazonPaymentsbillingAgreementId: '', amazonPaymentsbillingAgreementId: '',
amazonPaymentspaymentSelected: false, amazonPaymentspaymentSelected: false,
@@ -41,16 +40,22 @@ export default {
}, },
computed: { computed: {
...mapState({user: 'user.data'}), ...mapState({user: 'user.data'}),
...mapState(['isAmazonReady']),
}, },
mounted () { mounted () {
window.onAmazonLoginReady = () => { if (this.isAmazonReady) return this.setupAmazon();
window.amazon.Login.setClientId(AMAZON_PAYMENTS.CLIENT_ID);
this.OffAmazonPayments = window.OffAmazonPayments; this.$store.watch(state => state.isAmazonReady, (isAmazonReady) => {
this.isAmazonReady = true; if (isAmazonReady) return this.setupAmazon();
this.showButton(); });
};
}, },
methods: { methods: {
setupAmazon () {
if (this.isAmazonSetup) return false;
this.isAmazonSetup = true;
this.OffAmazonPayments = window.OffAmazonPayments;
this.showButton();
},
showButton () { showButton () {
// @TODO: prevent modal close form clicking outside // @TODO: prevent modal close form clicking outside
let amazonButton = this.OffAmazonPayments.Button( // eslint-disable-line let amazonButton = this.OffAmazonPayments.Button( // eslint-disable-line

View File

@@ -19,8 +19,5 @@
<!-- Translations --> <!-- Translations -->
<script type='text/javascript' src='/api/v3/i18n/browser-script'></script> <script type='text/javascript' src='/api/v3/i18n/browser-script'></script>
<script async type='text/javascript' src='https://static-na.payments-amazon.com/OffAmazonPayments/us/sandbox/js/Widgets.js'></script>
<script async type='text/javascript' src="https://checkout.stripe.com/v2/checkout.js"></script>
</body> </body>
</html> </html>

View File

@@ -5,6 +5,10 @@ import includes from 'lodash/includes';
import getStore from 'client/store'; import getStore from 'client/store';
import Vue from 'vue'; import Vue from 'vue';
const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
const AMPLITUDE_KEY = process.env.AMPLITUDE_KEY; // eslint-disable-line no-process-env
const GA_ID = process.env.GA_ID; // eslint-disable-line no-process-env
let REQUIRED_FIELDS = ['hitType', 'eventCategory', 'eventAction']; let REQUIRED_FIELDS = ['hitType', 'eventCategory', 'eventAction'];
let ALLOWED_HIT_TYPES = [ let ALLOWED_HIT_TYPES = [
'pageview', 'pageview',
@@ -93,12 +97,7 @@ export function updateUser (properties) {
}); });
} }
export function setup () { export function setup () {
const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
const AMPLITUDE_KEY = process.env.AMPLITUDE_KEY; // eslint-disable-line no-process-env
const GA_ID = process.env.GA_ID; // eslint-disable-line no-process-env
// Setup queues until the real scripts are loaded // Setup queues until the real scripts are loaded
/* eslint-disable */ /* eslint-disable */
@@ -119,12 +118,12 @@ export function setup () {
}, window['ga'].l = 1 * new Date(); }, window['ga'].l = 1 * new Date();
ga('create', GA_ID); ga('create', GA_ID);
/* eslint-enable */ /* eslint-enable */
}
export function load () {
// Load real scripts // Load real scripts
if (!IS_PRODUCTION) return; if (!IS_PRODUCTION) return;
Vue.nextTick(() => {
// Amplitude // Amplitude
const amplitudeScript = document.createElement('script'); const amplitudeScript = document.createElement('script');
let firstScript = document.getElementsByTagName('script')[0]; let firstScript = document.getElementsByTagName('script')[0];
@@ -139,5 +138,4 @@ export function setup () {
gaScript.async = 1; gaScript.async = 1;
gaScript.src = '//www.google-analytics.com/analytics.js'; gaScript.src = '//www.google-analytics.com/analytics.js';
firstScript.parentNode.insertBefore(gaScript, firstScript); firstScript.parentNode.insertBefore(gaScript, firstScript);
});
} }

View File

@@ -0,0 +1,32 @@
import getStore from 'client/store';
const AMAZON_PAYMENTS = process.env.AMAZON_PAYMENTS; // eslint-disable-line
const NODE_ENV = process.env.NODE_ENV; // eslint-disable-line
export function setup () {
const store = getStore();
// Set Amazon Payments as ready in the store,
// Added here to make sure the listener is registered before the script can be executed
window.onAmazonLoginReady = () => {
store.state.isAmazonReady = true;
window.amazon.Login.setClientId(AMAZON_PAYMENTS.CLIENT_ID);
};
// Load the scripts
// Amazon Payments
const amazonScript = document.createElement('script');
let firstScript = document.getElementsByTagName('script')[0];
amazonScript.type = 'text/javascript';
amazonScript.async = true;
amazonScript.src = `https://static-na.payments-amazon.com/OffAmazonPayments/us/${(NODE_ENV === 'production' ? '' : 'sandbox/')}js/Widgets.js`;
firstScript.parentNode.insertBefore(amazonScript, firstScript);
// Stripe
const stripeScript = document.createElement('script');
firstScript = document.getElementsByTagName('script')[0];
stripeScript.async = true;
stripeScript.src = '//checkout.stripe.com/v2/checkout.js';
firstScript.parentNode.insertBefore(stripeScript, firstScript);
}

View File

@@ -4,7 +4,9 @@ require('babel-polyfill');
import Vue from 'vue'; import Vue from 'vue';
import AppComponent from './app'; import AppComponent from './app';
import { setup as setupAnalytics } from 'client/libs/analytics'; import {
setup as setupAnalytics,
} from 'client/libs/analytics';
import router from './router'; import router from './router';
import getStore from './store'; import getStore from './store';
import StoreModule from './libs/store'; import StoreModule from './libs/store';
@@ -27,11 +29,12 @@ Vue.config.productionTip = IS_PRODUCTION;
Vue.use(i18n, {i18nData: window && window['habitica-i18n']}); Vue.use(i18n, {i18nData: window && window['habitica-i18n']});
Vue.use(StoreModule); Vue.use(StoreModule);
setupAnalytics(); setupAnalytics(); // just create queues for analytics, no scripts loaded at this time
const store = getStore();
export default new Vue({ export default new Vue({
el: '#app', el: '#app',
router, router,
store: getStore(), store,
render: h => h(AppComponent), render: h => h(AppComponent),
}); });

View File

@@ -55,6 +55,7 @@ export default function () {
title: 'Habitica', title: 'Habitica',
isUserLoggedIn, isUserLoggedIn,
isUserLoaded: false, // Means the user and the user's tasks are ready isUserLoaded: false, // Means the user and the user's tasks are ready
isAmazonReady: false, // Whether the Amazon Payments lib can be used
user: asyncResourceFactory(), user: asyncResourceFactory(),
credentials: AUTH_SETTINGS ? { credentials: AUTH_SETTINGS ? {
API_ID: AUTH_SETTINGS.auth.apiId, API_ID: AUTH_SETTINGS.auth.apiId,
@@ -95,9 +96,9 @@ export default function () {
cloning: false, cloning: false,
tasksToClone: {}, tasksToClone: {},
}, },
editingGroup: {}, // TODO move to local state editingGroup: {}, // @TODO move to local state
// content data, frozen to prevent Vue from modifying it since it's static and never changes // content data, frozen to prevent Vue from modifying it since it's static and never changes
// TODO apply freezing to the entire codebase (the server) and not only to the client side? // @TODO apply freezing to the entire codebase (the server) and not only to the client side?
// NOTE this takes about 10-15ms on a fast computer // NOTE this takes about 10-15ms on a fast computer
content: deepFreeze(content), content: deepFreeze(content),
constants: deepFreeze({...commonConstants, DAY_MAPPING}), constants: deepFreeze({...commonConstants, DAY_MAPPING}),