easywebpack Vue Entry Template, simplify Vue initialization without writing javascript file(.js
) init code, support client render and server side render.
When Wepback's entry configuration is directly a .vue
file, The following template code, webpack will be automatically merged with the Vue file.
import Vue from 'vue';
// .vue file
import vm from '${context.resourcePath}';
// ${codeSegment} dynamic template code template file
const data = window.__INITIAL_STATE__ || {};
const context = { state: data };
const hook = vm.hook || Vue.hook;
if (hook && hook.render) {
hook.render(context, vm);
}
const store = typeof vm.store === 'function' ? vm.store(data) : vm.store;
const router = typeof vm.router === 'function' ? vm.router() : vm.router;
const options = store && router ? {
...vm,
store,
router
} : { ...vm, data };
const app = new Vue(options);
app.$mount('#app');
import Vue from 'vue';
import { sync } from 'vuex-router-sync';
// .vue file
import vm from '${context.resourcePath}';
// ${codeSegment} dynamic template code template file
export default function(context) {
const store = typeof vm.store === 'function' ? vm.store(context.state) : vm.store;
const router = typeof vm.router === 'function' ? vm.router() : vm.router;
if (store && router) {
sync(store, router);
router.push(context.state.url);
return new Promise((resolve, reject) => {
router.onReady(() => {
const matchedComponents = router.getMatchedComponents();
if (!matchedComponents) {
return reject({ code: '404' });
}
return Promise.all(
matchedComponents.map(component => {
if (component.methods && component.methods.fetchApi) {
return component.methods.fetchApi(store);
}
return null;
})
).then(() => {
context.state = { ...store.state, ...context.state };
const hook = vm.hook || Vue.hook;
if (hook && hook.render) {
hook.render(context, vm);
}
const instanceOptions = {
...vm,
store,
router,
};
return resolve(new Vue(instanceOptions));
});
});
});
}
const VueApp = Vue.extend(vm);
const hook = vm.hook || Vue.hook;
if (hook && hook.render) {
hook.render(context, vm);
}
const instanceOptions = {
...vm,
data: context.state
};
return new VueApp(instanceOptions);
};
// ${root}/egg-vue-webpack-boilerplate/app/web/page/admin/home/home.vue
import Vue from 'vue';
import ElementUI from 'element-ui';
import VueI18n from 'vue-i18n';
import 'element-ui/lib/theme-chalk/index.css';
import createI18n from 'framework/i18n/admin';
import store from './store';
import router from './router';
Vue.use(VueI18n);
Vue.use(ElementUI);
export default {
router,
store,
components: {},
computed: {},
hook :{
render(context, vm) {
const i18n = createI18n(context.state.locale);
vm.i18n = i18n;
}
},
mounted() {},
};
module.exports = {
entry: {
app: 'app/web/page/admin/home/home.vue', // The entry will use the vue-entry-loader, not need to write the Vue initialization code
test: 'app/web/page/test/test.js' // The entry will not use the vue-entry-loader, you need to write the Vue initialization code
}
};
import codeSegment from '${templateFile}'
codeSegment(Vue);
-
Egg Project will inject the custom template code into the location above
${codeSegment}
when the fileapp/web/framework/entry/template.js
exists -
Non Egg Project will inject the custom template code into the location above
${codeSegment}
when the filesrc/framework/entry/template.js
exists -
The
entry/template.js
template file has the following constraints:- import path must be absolute path, you can use webpack alias set
- export default must return function, the argument is Vue
// import path must be absolute path, you can use webpack alias set
import Layout from 'component/layout/index';
import plugin from 'framework/plugin';
// must return function, the argument is Vue
export default function(Vue) {
Vue.use(plugin);
Vue.component(Layout.name, Layout);
}
support hook.render
method for custom logic, such common component and logic initialization
export default {
hook :{
render(context, vm) {
const i18n = createI18n(context.state.locale);
vm.i18n = i18n;
}
},
computed: {},
mounted() {},
};
dynamic create store, solve the server side render singleton problem
// store/index.js
export default function createStore(initState) {
const state = {
...initState
};
return new Vuex.Store({
state,
actions,
getters,
mutations
});
}
- Dynamic Create Router
export default function createRouter() {
return new VueRouter({
mode: 'history',
base: '/',
routes: [
{
path: '/',
component: Dashboard
},
{
path: '*', component: () => import('../view/notfound.vue')
}
]
});
}
- Vue Entry File Code
import store from './store';
import router from './router';
export default {
router, // support Object and Function
store, // support Object and Function
components: {},
computed: {},
mounted() {},
};