前言
專案環境
- 後端框架:Phalcon
- 前端框架:Bootstrap + jQuery
什麼是前後端分離?
傳統專案大多數是 MVC 架構,直接使用 PHP 等後端語言渲染 HTML 模板,返回給瀏覽器
現在,前後端分離不需要後端渲染模板,而是交由瀏覽器 Javascript 渲染,後端只需要返回前端渲染所需要的資料即可
前後端分離的本質:
- 路由分離
- 模板分離
前後端偽分離?
傳統 MVC 專案直接升級到前後端分離需要大量的時間與人力,在業務多變的階段並不適合,所以便有了本文的過渡方案探索
- 路由先不分離,仍然採用 PHP 提供的路由
- 模板部分分離,在原 PHP 模板中,引入 Vue 編譯後的模板,為此需要約定
示例
新建控制器 TestController.php
<?php
namespace App\Controller;
class TestController
{
public function indexAction() { }
}
新建模板 test/index.volt
<div id="app">
<!-- 約定 一個頁面對應一個 Vue 元件 -->
<index-view></index-view>
</div>
<!-- 約定 一個頁面對應一個前端控制器 -->
<script src="/mix/dist/js/test/index.js?v={{ time() }}"></script>
暫時找不到很好解決快取的方案,所以統一不快取
新建前端控制器 public/mix/resources/js/test/index.js
import Vue from 'vue';
import ElementUI from 'element-ui';
import IndexView from '@views/test/index.vue';
import Mixin from '@utils/mixin';
Vue.use(ElementUI);
Vue.use(Mixin); // 全域性元件、方法、計算屬性等
new Vue({
el: '#app',
components: { IndexView },
});
新建 Vue 元件 public/mix/resources/views/test/index.vue
<template>
<div>
Hello Vue!
</div>
</template>
<script>
export default {
components: {},
props: {},
data() {
return {};
},
beforeCreate() {
},
created() {
console.log('Created');
},
beforeMount() {
},
mounted() {
},
beforeUpdate() {
},
updated() {
},
beforeDestroy() {
},
destroyed() {
},
watch: {},
computed: {},
methods: {},
};
</script>
<style lang="scss" scoped>
</style>
前後端偽分離
- 後端框架:Phalcon + Hyperf
- 前端框架:Bootstrap + jQuery + Vue
前端編譯使用 Laravel Mix 工具,這會節省大量前端配置時間
根目錄新建檔案 webpack.mix.js
const fs = require('fs');
const mix = require('laravel-mix');
const rs_root = 'public/mix/resources'; // 資源 源目錄
const rs_output = 'public/mix/dist'; // 資源 打包目錄
const js_entry = `${ rs_root }/js`; // js 源目錄
const js_output = `${ rs_output }/js`; // js 打包目錄
const css_entry = `${ rs_root }/css`; // css 源目錄
const css_output = `${ rs_output }/css`; // css 打包目錄
mix.webpackConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, rs_root),
'@api': path.resolve(__dirname, `${ rs_root }/api`),
'@components': path.resolve(__dirname, `${ rs_root }/components`),
'@utils': path.resolve(__dirname, `${ rs_root }/utils`),
'@views': path.resolve(__dirname, `${ rs_root }/views`),
},
},
});
// 按照約定,編譯對應的資源
fs.readdirSync(path.resolve(__dirname, js_entry)).forEach(dir => {
fs.readdirSync(path.resolve(__dirname, `${ js_entry }/${ dir }`)).forEach(file => {
mix.js(`${ js_entry }/${ dir }/${ file }`, `${ js_output }/${ dir }/${ file }`);
});
});
mix.sass(`${ css_entry }/app.scss`, `${ css_output }/app.css`); // 公共 CSS
mix.setPublicPath(rs_output);
mix.setResourceRoot('/mix/dist/');
流程
- 按照示例配置一個頁面
- Yarn 安裝前端依賴
- Yarn 前端編譯,此時,PHP 模板中已正確引入 Vue
- 訪問路由,PHP 渲染模板,返回給瀏覽器
- 瀏覽器載入 Vue,交由 Vue 渲染頁面
侷限
- 不能做到全域性自動載入元件
- 編譯後的檔案大小可能會很大
優勢
- 可以更好地編寫複雜的頁面
- 更好的維護性
後記
目前仍在不斷地探索中