[IT 鐵人賽] 簡易的後端輸出與 Hybrid 模式 Day 20

昨天提到了後端與前端的混和( Hybrid )模式,我們今天就會提出比較完整的例子,來說明一下我自己目前比較喜歡的方式。由於 Phalcon 實在有點冷門,所以我今天會用一個更冷門的 Slim PHP Framework 來介紹( 你是故意的嗎 )。

對了,今天也會有 Docker 會分享給各位,方便大家不用處理環境問題。


後端的設計

我們昨天有提到後端的作法,今天我們來實作一些關於後端的操作方式。首先,我們需要準備一些需要的工具:

  • PHP 7.3 with PHP-FPM
  • Nginx
  • Slim PHP Framework

我們這邊用 PHP 來舉例,所以倘若你不是使用 PHP 的話,你要換成其他的後端語言也是可以。昨天我們有說了,後端也是需要一些 Router 來接收前端來的狀況,所以,對於路由的部分,我們還是需要做設定。

<?php

use DI\Container;
use Middlewares\TrailingSlash;
use Slim\Factory\AppFactory;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;

require __DIR__ . '/vendor/autoload.php';

// Create Container using PHP-DI
$container = new Container();
AppFactory::setContainer($container);
$container->set('view', function () {
    return new Twig(__DIR__ . '/view');
});

// Set container to create App with on AppFactory
$app = AppFactory::create();

$app->addRoutingMiddleware();

// Add Twig-View Middleware
$app->add(TwigMiddleware::createFromContainer($app));

// Add trailing slash
$app->add(new TrailingSlash());

// Add two routes
$app->get('/', \Ithomeironman2019\Controller\HomeController::class . ':index');
$app->get('/hello', \Ithomeironman2019\Controller\HomeController::class . ':hello');

// Run application
$app->run();

我們就簡單設定兩組路由就好了,然後我們是交給 HomeController 來做,這個地方就跟昨天說的一樣,你可以準備 TDK, JSON-LD 與要交給前端的資料。至於 API 什麼的我這邊就不額外在提,資料來源我不多做著墨,就直接使用固定資料來當作範例。

<?php

namespace Ithomeironman2019\Controller;

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Container\ContainerInterface;

class HomeController
{
     protected $container;
     protected $view;
     protected $templateData = [];

     // constructor receives container instance
     public function __construct(ContainerInterface $container)
     {
          $this->container = $container;
          $this->view = $container->get('view');
     }

     public function index(Request $request, Response $response, $args)
     {
          return $this->view->render($response, 'index.twig', $this->templateData);
     }

     public function contact(Request $request, Response $response, $args)
     {
          return $this->view->render($response, 'hello.twig', $this->templateData);
     }
}

前端的設計

前端的部分,其實就是把 Vue 拆開來,然後改一下設定。不過,老實說 Vue CLI 3.0 之後,設定改了一狗票,如果要回頭搭配 Webpack 的話,其實很麻煩。但是,原先的 3.0 的 vue-cli-service 運作方式,個人覺得挺難用的。

然後,你其實可以用 Vue CLI 來把跟 Webpack 相關的資料輸出:

vue inspect > webpack.txt

這樣你就可以拿到跟 Webpack 有關的設定,然後你想要用那個部分,就從這邊把他拿出去用。不過多少還是會遇到一點問題,

"Cannot assign to read only property 'exports' of object '#<Object>'"
Cannot assign to read only property 'exports' of object '#<Object>'
Local NPM Module causes "Cannot assign to read only property 'exports' of object"

然後呢,我還是建議你們使用 concurrently 或是 gulp-shell 的方式,來把前後端的 Watch 接起來,因為 Webpack 要套到 Vue CLI 3.0 還要能正常運作,實在有點太浪費時間。我大概花了 20 個小時卡在套件相依,然後卡在 ES5, ES6, Webpack, Vue CLI 使用 JavaScript 的版本衝突,各種 module 操作衝突等等。

真心覺得累。

其實這樣就好了:

"serve": "concurrently \"gulp\" \"vue-cli-service build --watch\""

上面大概就是開發模式跑起來的狀況,底下是監看整個 PHP/Vue 的部分,左上角是簡單的啟動一個 Web Server 的服務,右上角是目前資料夾。主要的開發還是以 Vue CLI 3.0 為主。


混合模式

上述就是簡單的混合模式的基本架構。最後我們在 build 的時候,他會統一建立到 dist 底下,大概會類似這個樣子:

然後你只要把 dist 部屬到遠端,然後把 Nginx/Apache 指向 public/index.php 就好了。剩下的大概就是 TDK, JSON-LD 由後端幫你出,然後前端由 Vue 那邊幫你產生。

以上是最終執行結果。由於我在整理 Docker 耗費太多時間,今天的文章實在沒有心力交代太多過程。就容許我先這樣子結束這一回合吧。


小結

那個說好的 醬汁 Dockfile 嘛,由於我還沒調整好,所以我應該明天在給大家(哈哈哈哈)。

ITHome 鐵人賽同步刊登 簡易的後端輸出與 Hybrid 模式 Day 20

Hina Chen
偏執與強迫症的患者,算不上是無可救藥,只是我已經遇上我的良醫了。
Taipei