Skip to content

Commit

Permalink
Added assets hashing after build, added favicon
Browse files Browse the repository at this point in the history
  • Loading branch information
MyIgel committed Apr 29, 2022
1 parent 59e54fc commit b842466
Show file tree
Hide file tree
Showing 14 changed files with 2,407 additions and 2,249 deletions.
3 changes: 2 additions & 1 deletion config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
\Engelsystem\Http\ResponseServiceProvider::class,
\Engelsystem\Http\Psr7ServiceProvider::class,
\Engelsystem\Helpers\AuthenticatorServiceProvider::class,
\Engelsystem\Helpers\AssetsServiceProvider::class,
\Engelsystem\Renderer\TwigServiceProvider::class,
\Engelsystem\Middleware\RouteDispatcherServiceProvider::class,
\Engelsystem\Middleware\RequestHandlerServiceProvider::class,
Expand All @@ -33,7 +34,7 @@
\Engelsystem\Helpers\VersionServiceProvider::class,
\Engelsystem\Mail\MailerServiceProvider::class,
\Engelsystem\Http\HttpClientServiceProvider::class,
\Engelsystem\Helpers\DumpServerServiceProvider::class
\Engelsystem\Helpers\DumpServerServiceProvider::class,
],

// Application middleware
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"style-loader": "^3.3.1",
"terser-webpack-plugin": "^5.1.2",
"webpack": "^5.37.1",
"webpack-cli": "^4.7.0"
"webpack-cli": "^4.7.0",
"webpack-manifest-plugin": "^5.0.0"
}
}
1 change: 1 addition & 0 deletions resources/views/layouts/app.twig
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">

<link rel="icon" href="{{ asset('assets/angel.svg') }}">
<link rel="stylesheet" type="text/css" href="{{ asset('assets/theme' ~ themeId ~ '.css') }}"/>
<script type="text/javascript" src="{{ asset('assets/vendor.js') }}"></script>

Expand Down
2 changes: 2 additions & 0 deletions src/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ protected function registerPaths()
$this->instance('path', $appPath);
$this->instance('path.config', $appPath . DIRECTORY_SEPARATOR . 'config');
$this->instance('path.resources', $appPath . DIRECTORY_SEPARATOR . 'resources');
$this->instance('path.public', $appPath . DIRECTORY_SEPARATOR . 'public');
$this->instance('path.assets', $this->get('path.resources') . DIRECTORY_SEPARATOR . 'assets');
$this->instance('path.assets.public', $this->get('path.public') . DIRECTORY_SEPARATOR . 'assets');
$this->instance('path.lang', $this->get('path.resources') . DIRECTORY_SEPARATOR . 'lang');
$this->instance('path.views', $this->get('path.resources') . DIRECTORY_SEPARATOR . 'views');
$this->instance('path.storage', $appPath . DIRECTORY_SEPARATOR . 'storage');
Expand Down
38 changes: 38 additions & 0 deletions src/Helpers/Assets.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace Engelsystem\Helpers;

class Assets
{
/** @var string */
protected string $assetsPath;

/** @var string */
protected string $manifestFile = 'manifest.json';

/**
* @param string $assetsPath Directory containing assets
*/
public function __construct(string $assetsPath)
{
$this->assetsPath = $assetsPath;
}

/**
* @param string $asset
* @return string
*/
public function getAssetPath(string $asset): string
{
$manifest = $this->assetsPath . DIRECTORY_SEPARATOR . $this->manifestFile;
if (is_readable($manifest)) {
$manifest = json_decode(file_get_contents($manifest), true);

if (isset($manifest[$asset])) {
$asset = $manifest[$asset];
}
}

return $asset;
}
}
15 changes: 15 additions & 0 deletions src/Helpers/AssetsServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Engelsystem\Helpers;

use Engelsystem\Container\ServiceProvider;

class AssetsServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->when(Assets::class)
->needs('$assetsPath')
->give($this->app->get('path.assets.public'));
}
}
13 changes: 12 additions & 1 deletion src/Renderer/Twig/Extensions/Assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,27 @@

namespace Engelsystem\Renderer\Twig\Extensions;

use Engelsystem\Helpers\Assets as AssetsProvider;
use Engelsystem\Http\UrlGeneratorInterface;
use Illuminate\Support\Str;
use Twig\Extension\AbstractExtension as TwigExtension;
use Twig\TwigFunction;

class Assets extends TwigExtension
{
/** @var AssetsProvider */
protected $assets;

/** @var UrlGeneratorInterface */
protected $urlGenerator;

/**
* @param AssetsProvider $assets
* @param UrlGeneratorInterface $urlGenerator
*/
public function __construct(UrlGeneratorInterface $urlGenerator)
public function __construct(AssetsProvider $assets, UrlGeneratorInterface $urlGenerator)
{
$this->assets = $assets;
$this->urlGenerator = $urlGenerator;
}

Expand All @@ -36,6 +43,10 @@ public function getFunctions(): array
public function getAsset(string $path): string
{
$path = ltrim($path, '/');
if (Str::startsWith($path, 'assets/')) {
$asset = Str::replaceFirst('assets/', '', $path);
$path = 'assets/' . $this->assets->getAssetPath($asset);
}

return $this->urlGenerator->to('/' . $path);
}
Expand Down
2 changes: 2 additions & 0 deletions tests/Unit/ApplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public function testAppPath()
$this->assertTrue($app->has('path.cache'));
$this->assertTrue($app->has('path.cache.routes'));
$this->assertTrue($app->has('path.cache.views'));
$this->assertTrue($app->has('path.public'));
$this->assertTrue($app->has('path.assets.public'));

$this->assertEquals(realpath('.'), $app->path());
$this->assertEquals(realpath('.') . '/config', $app->get('path.config'));
Expand Down
25 changes: 25 additions & 0 deletions tests/Unit/Helpers/AssetsServiceProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Engelsystem\Test\Unit\Helpers;

use Engelsystem\Application;
use Engelsystem\Helpers\Assets;
use Engelsystem\Helpers\AssetsServiceProvider;
use Engelsystem\Test\Unit\ServiceProviderTest;

class AssetsServiceProviderTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Helpers\AssetsServiceProvider::register
*/
public function testRegister()
{
$app = new Application();
$app->instance('path.assets.public', '/tmp');

$serviceProvider = new AssetsServiceProvider($app);
$serviceProvider->register();

$this->assertArrayHasKey(Assets::class, $app->contextual);
}
}
23 changes: 23 additions & 0 deletions tests/Unit/Helpers/AssetsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Engelsystem\Test\Unit\Helpers;

use Engelsystem\Helpers\Assets;
use Engelsystem\Test\Unit\TestCase;

class AssetsTest extends TestCase
{
/**
* @covers \Engelsystem\Helpers\Assets::__construct
* @covers \Engelsystem\Helpers\Assets::getAssetPath
*/
public function testGetAssetPath()
{
$assets = new Assets('/foo/bar');
$this->assertEquals('lorem.bar', $assets->getAssetPath('lorem.bar'));

$assets = new Assets(__DIR__ . '/Stub/files');
$this->assertEquals('something.xyz', $assets->getAssetPath('something.xyz'));
$this->assertEquals('lorem-hashed.ipsum', $assets->getAssetPath('foo.bar'));
}
}
3 changes: 3 additions & 0 deletions tests/Unit/Helpers/Stub/files/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"foo.bar": "lorem-hashed.ipsum"
}
36 changes: 27 additions & 9 deletions tests/Unit/Renderer/Twig/Extensions/AssetsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Engelsystem\Test\Unit\Renderer\Twig\Extensions;

use Engelsystem\Helpers\Assets as AssetsProvider;
use Engelsystem\Http\UrlGenerator;
use Engelsystem\Renderer\Twig\Extensions\Assets;
use PHPUnit\Framework\MockObject\MockObject;
Expand All @@ -14,10 +15,12 @@ class AssetsTest extends ExtensionTest
*/
public function testGetFunctions()
{
/** @var UrlGenerator|MockObject $urlGenerator */
/** @var UrlGenerator&MockObject $urlGenerator */
$urlGenerator = $this->createMock(UrlGenerator::class);
/** @var AssetsProvider&MockObject $assets */
$assets = $this->createMock(AssetsProvider::class);

$extension = new Assets($urlGenerator);
$extension = new Assets($assets, $urlGenerator);
$functions = $extension->getFunctions();

$this->assertExtensionExists('asset', [$extension, 'getAsset'], $functions);
Expand All @@ -28,20 +31,35 @@ public function testGetFunctions()
*/
public function testGetAsset()
{
/** @var UrlGenerator|MockObject $urlGenerator */
/** @var UrlGenerator&MockObject $urlGenerator */
$urlGenerator = $this->createMock(UrlGenerator::class);
/** @var AssetsProvider&MockObject $assets */
$assets = $this->createMock(AssetsProvider::class);

$urlGenerator->expects($this->exactly(2))
$urlGenerator->expects($this->exactly(4))
->method('to')
->with('/assets/foo.css')
->willReturn('https://foo.bar/project/assets/foo.css');
->withConsecutive(['/test.png'], ['/assets/foo.css'], ['/assets/bar.css'], ['/assets/lorem-hashed.js'])
->willReturnCallback(function ($path) {
return 'https://foo.bar/project' . $path;
});

$extension = new Assets($urlGenerator);
$assets->expects($this->exactly(3))
->method('getAssetPath')
->withConsecutive(['foo.css'], ['bar.css'], ['lorem.js'])
->willReturnOnConsecutiveCalls('foo.css', 'bar.css', 'lorem-hashed.js');

$extension = new Assets($assets, $urlGenerator);

$return = $extension->getAsset('test.png');
$this->assertEquals('https://foo.bar/project/test.png', $return);

$return = $extension->getAsset('assets/foo.css');
$this->assertEquals('https://foo.bar/project/assets/foo.css', $return);

$return = $extension->getAsset('/assets/foo.css');
$this->assertEquals('https://foo.bar/project/assets/foo.css', $return);
$return = $extension->getAsset('/assets/bar.css');
$this->assertEquals('https://foo.bar/project/assets/bar.css', $return);

$return = $extension->getAsset('assets/lorem.js');
$this->assertEquals('https://foo.bar/project/assets/lorem-hashed.js', $return);
}
}
8 changes: 5 additions & 3 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const nodeEnv = (process.env.NODE_ENV || 'development').trim();
const {WebpackManifestPlugin} = require('webpack-manifest-plugin');
const fs = require('fs');

// eslint-disable-next-line
Expand All @@ -18,9 +19,10 @@ const plugins = [
},
}),
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id]-[hash].css',
filename: '[name]-[contenthash].css',
chunkFilename: '[id]-[contenthash].css',
}),
new WebpackManifestPlugin({}),
];

let themeFileNameRegex = /theme\d+/;
Expand Down Expand Up @@ -50,7 +52,7 @@ module.exports = {
},
output: {
path: path.resolve('public/assets'),
filename: '[name].js',
filename: '[name]-[contenthash].js',
publicPath: '',
clean: true,
},
Expand Down
Loading

0 comments on commit b842466

Please sign in to comment.