Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: entry files can now be async #174

Merged
merged 1 commit into from
Mar 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/@averjs/vue-app/templates/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ axios.interceptors.response.use((response) => {
return Promise.reject(error);
});

export function createApp(ssrContext) {
export async function createApp(ssrContext) {
const i18n = createI18n(ssrContext);
const router = createRouter({ i18n });
const store = createStore(ssrContext);
Expand Down Expand Up @@ -68,7 +68,8 @@ export function createApp(ssrContext) {

for(const entry of entries) {
const mixin = entry.default;
if(typeof mixin === 'function') userReturns = merge(userReturns, mixin({ ...ssrContext, appOptions }));
const returns = await mixin({ ...ssrContext, appOptions });
if(typeof mixin === 'function') userReturns = merge(userReturns, returns);
}

const app = new Vue(appOptions);
Expand Down
192 changes: 97 additions & 95 deletions packages/@averjs/vue-app/templates/entry-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,109 +2,111 @@ import { createApp } from './app';
import Vue from 'vue';
import axios from 'axios';
import { composeComponentOptions } from './utils';
const { app, router, store, userReturns } = createApp({ isServer: false });

// eslint-disable-next-line no-unused-vars
class ClientEntry {
constructor() {
this.addMobileCheck();
<% if (config.csrf) { %> this.configureCSRF(); <% } %>
this.setRouterMixins();
this.initMixin();
(async () => {
const { app, router, store, userReturns } = await createApp({ isServer: false });

router.onReady(() => {
router.beforeResolve(async (to, from, next) => {
const matched = router.getMatchedComponents(to);
const prevMatched = router.getMatchedComponents(from);
let diffed = false;
const activated = matched.filter((c, i) => diffed || (diffed = (prevMatched[i] !== c)));
const asyncDataHooks = activated.map(c => {
const { asyncData } = composeComponentOptions(c);
if (typeof asyncData === 'function' && asyncData) return asyncData
else return false;
}).filter(_ => _);

if (!asyncDataHooks.length) return next();

try {
await Promise.all(asyncDataHooks.map(hook => hook({ store, route: { to, from }, isServer: false })))
next();
} catch(err) {
next(err);
}
class ClientEntry {
async init() {
this.addMobileCheck();
<% if (config.csrf) { %> this.configureCSRF(); <% } %>
this.setRouterMixins();
await this.initMixin();

router.onReady(() => {
router.beforeResolve(async (to, from, next) => {
const matched = router.getMatchedComponents(to);
const prevMatched = router.getMatchedComponents(from);
let diffed = false;
const activated = matched.filter((c, i) => diffed || (diffed = (prevMatched[i] !== c)));
const asyncDataHooks = activated.map(c => {
const { asyncData } = composeComponentOptions(c);
if (typeof asyncData === 'function' && asyncData) return asyncData
else return false;
}).filter(_ => _);

if (!asyncDataHooks.length) return next();

try {
await Promise.all(asyncDataHooks.map(hook => hook({ store, route: { to, from }, isServer: false })))
next();
} catch(err) {
next(err);
}
});

app.$mount('#app');
});

app.$mount('#app');
});
}

initMixin() {
const entries = [
<%
if(typeof config.entries !== 'undefined' && typeof config.entries.client !== 'undefined') {
for(const entry of config.entries.client) {
print(`require('${entry}'),`);
}

async initMixin() {
const entries = [
<%
if(typeof config.entries !== 'undefined' && typeof config.entries.client !== 'undefined') {
for(const entry of config.entries.client) {
print(`require('${entry}'),`);
}
}
}
%>
];
const mixinContext = require.context('@/', false, /^\.\/entry-client\.js$/i);
for(const key of mixinContext.keys()) entries.push(mixinContext(key));

for(const entry of entries) {
const mixin = entry.default;
if(typeof mixin === 'function') mixin({ userReturns });
%>
];
const mixinContext = require.context('@/', false, /^\.\/entry-client\.js$/i);
for(const key of mixinContext.keys()) entries.push(mixinContext(key));

for(const entry of entries) {
const mixin = entry.default;
if(typeof mixin === 'function') await mixin({ userReturns });
}
}
}

addMobileCheck() {
Vue.prototype.$isMobile = () => {
let check = false;
((a) => {
// eslint-disable-next-line no-useless-escape
if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) {
check = true;
}
})(navigator.userAgent || navigator.vendor || window.opera);
return check;
};
}

<% if (config.csrf) { %>
configureCSRF() {
let token = document.querySelector('meta[name="csrf-token"]');

if (token) {
axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
Vue.prototype.$csrf = token.content;
} else {
console.error('CSRF token not found');

addMobileCheck() {
Vue.prototype.$isMobile = () => {
let check = false;
((a) => {
// eslint-disable-next-line no-useless-escape
if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) {
check = true;
}
})(navigator.userAgent || navigator.vendor || window.opera);
return check;
};
}
}
<% } %>

setRouterMixins() {
Vue.mixin({
async beforeRouteUpdate(to, from, next) {
const { asyncData } = this.$options;
if (asyncData) {
try {
await asyncData({
store: this.$store,
route: { to, from },
isServer: false
});

<% if (config.csrf) { %>
configureCSRF() {
let token = document.querySelector('meta[name="csrf-token"]');

if (token) {
axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
Vue.prototype.$csrf = token.content;
} else {
console.error('CSRF token not found');
}
}
<% } %>

setRouterMixins() {
Vue.mixin({
async beforeRouteUpdate(to, from, next) {
const { asyncData } = this.$options;
if (asyncData) {
try {
await asyncData({
store: this.$store,
route: { to, from },
isServer: false
});
next();
} catch(err) {
next(err);
}
} else {
next();
} catch(err) {
next(err);
}
} else {
next();
}
}
});
});
}
}
}

// eslint-disable-next-line no-unused-vars
const clientEntry = new ClientEntry();
const clientEntry = new ClientEntry();
await clientEntry.init();
})();
4 changes: 2 additions & 2 deletions packages/@averjs/vue-app/templates/entry-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default async context => {
const contextRendered = fn => {
if(typeof fn === 'function') renderedFns.push(fn);
}
const { app, router, store, userReturns } = createApp({ isServer: true, context });
const { app, router, store, userReturns } = await createApp({ isServer: true, context });
const { url } = context;
const meta = app.$meta();

Expand All @@ -44,7 +44,7 @@ export default async context => {

for(const entry of entries) {
const mixin = entry.default;
if(typeof mixin === 'function') mixin({...context, userReturns, contextRendered});
if(typeof mixin === 'function') await mixin({...context, userReturns, contextRendered});
}

for (const [key] of Object.entries(store._actions)) {
Expand Down