【问题标题】:Theme system for laravel applicationlaravel 应用的主题系统
【发布时间】:2019-12-09 18:57:59
【问题描述】:

我正在开发一个小众游戏服务器的控制面板。我想要我的应用程序的基本主题系统,目标是将主题资产(js/css/images)与视图保持在一起。我不希望将资源目录中的视图和公共目录中的资产分开。

考虑到这一点;这就是我想出的。

这样组织的主题(视图和资产) - 即删除默认的 views 目录:

新的config/site.php

<?php

return [
    'theme' => 'default',
];

修改config/views.php

<?php

return [

    'paths' => [
        resource_path('themes/' . config('site.theme')),
    ],

    ...

新路线routes/web.php

Route::get('theme/{file?}', 'ThemeController@serve')
    ->where('file', '[a-zA-Z0-9\.\-\/]+');

新控制器app/Http/Controllers/ThemeController.php

<?php

namespace App\Http\Controllers;

use Carbon\Carbon;
use Illuminate\Support\Facades\File;

class ThemeController extends Controller
{
    /**
     * @param $file
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function serve($file)
    {
        $siteConfig = config('site');

        $filePath = resource_path("themes/{$siteConfig['theme']}/{$file}");

        if (!file_exists($filePath)) {
            header("HTTP/1.0 404 Not Found");
            exit;
        }

        $fileLastModified = Carbon::createFromTimestamp(filemtime($filePath))->format('D, j M Y H:i:s');
        $fileEtag = md5_file($filePath);
        $requestFileEtag = request()->getETags()[0] ?? null;

        if (!empty($requestFileEtag) && strcmp($fileEtag, $requestFileEtag) === 0) {
            header("Last-Modified: {$fileLastModified}");
            header("Etag: {$fileEtag}");
            header("HTTP/1.1 304 Not Modified");
            exit;
        }

        return response()->file($filePath, [
            'Cache-Control' => 'public, max-age=' . ($siteConfig['themeFilesCacheForMinutes'] * 60),
            'Etag' => $fileEtag,
            'Last-Modified' => $fileLastModified,
            'Content-Type' => $this->guessMimeType($filePath)
        ]);
    }

    /**
     * @param $filePath
     * @return false|string
     */
    private function guessMimeType($filePath) {
        $ext = pathinfo($filePath, PATHINFO_EXTENSION);
        switch ($ext) {
            case 'css':
                return 'text/css; charset=UTF-8';
            case 'js':
                return 'text/javascript; charset=UTF-8';
            default:
                return File::mimeType($filePath);
        }
    }
}

使用该设置;如果我想包含我的主题中的资产,例如css/sb-admin-2.min.css&lt;head&gt;...&lt;/head&gt; 的主布局中,这就是我所做的:

<link href="{{ url('theme/css/sb-admin-2.min.css') }}" rel="stylesheet">

因此,使用这种技术,我可以将视图和资产保持在一起,并使用 php 来提供具有缓存功能的静态资产(通过 headers + etag)。

我在本地对此进行了测试,它可以正常工作,初始加载大约需要 900 毫秒,一旦缓存预热,它会在 500 毫秒以下加载页面。

我的问题;这是一个不好的方法吗?即使用 php 提供静态文件?有没有更好的方法来做到这一点?

【问题讨论】:

  • 你正在占用所有使用浏览器和服务器的缓存系统......所有页面的加载时间都会很长,如果你把所有的 css 放在一起,而不仅仅是第一个页面跨度>
  • 使用 Laravel Mix (laravel.com/docs/6.x/mix),您可以在处理资源目录的同时将资产编译到公共目录。这样就无需使用控制器来提供文件。

标签: php laravel themes laravel-6


【解决方案1】:

如果您想将刀片和静态资源打包为单独的可替换主题,只需为每个主题创建一个包,然后使用依赖注入选择所需的主题。在每个主题的 ServiceProvider 中,将您的资产发布到公共目录。

【讨论】:

    猜你喜欢
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    • 2013-11-15
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多