Skip to content
This repository has been archived by the owner on Aug 23, 2020. It is now read-only.

Commit

Permalink
Added purify-css
Browse files Browse the repository at this point in the history
  • Loading branch information
Soner Sayakci committed Aug 28, 2018
1 parent 023c921 commit 2bf3f2d
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 0 deletions.
20 changes: 20 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Shopware 5 editor configuration normalization
# http://editorconfig.org/

# This is the top-most .editorconfig file; do not search in parent directories.
root = true

# All files.
[*]
end_of_line = lf
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[*.ini]
insert_final_newline = false
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea/
vendor
23 changes: 23 additions & 0 deletions .php_cs.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
$finder = PhpCsFixer\Finder::create()->in(__DIR__);

return PhpCsFixer\Config::create()
->setUsingCache(false)
->setRules(
[
'@PSR2' => true,
'@Symfony' => true,
'no_useless_else' => true,
'no_useless_return' => true,
'ordered_class_elements' => true,
'ordered_imports' => true,
'phpdoc_order' => true,
'phpdoc_summary' => false,
'blank_line_after_opening_tag' => false,
'concat_space' => ['spacing' => 'one'],
'array_syntax' => ['syntax' => 'short'],
'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false],
'binary_operator_spaces' => ['default' => null],
]
)
->setFinder($finder);
43 changes: 43 additions & 0 deletions Commands/PurifyCssCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace FroshPerformance\Commands;

use Shopware\Commands\ShopwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

class PurifyCssCommand extends ShopwareCommand
{
public function execute(InputInterface $input, OutputInterface $output)
{
$purify = $this->container->get('frosh_performance.components.purify_css');
$io = new SymfonyStyle($input, $output);

if (!$purify->isRunnable()) {
$io->error('Please install first purify-css');
exit(1);
}

list($before, $after) = $this->container->get('frosh_performance.components.purify_css')->purify($input->getArgument('shopId'));

$io->success(sprintf('Purified css from %s to %s', $this->humanFilesize($before), $this->humanFilesize($after)));
}

protected function configure()
{
$this
->setName('frosh:purify:css')
->setDescription('Removes unused css styles')
->addArgument('shopId', InputArgument::OPTIONAL, 'Shop id', 1);
}

private function humanFilesize($bytes, $decimals = 2)
{
$sz = 'BKMGTP';
$factor = floor((strlen($bytes) - 1) / 3);

return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
}
}
109 changes: 109 additions & 0 deletions Components/PurifyCss.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php

namespace FroshPerformance\Components;

use Shopware\Components\Model\ModelManager;
use Shopware\Components\Theme\PathResolver;
use Shopware\Components\Theme\TimestampPersistor;
use Shopware\Models\Shop\Shop;
use Symfony\Component\Process\ExecutableFinder;
use Symfony\Component\Process\Process;

class PurifyCss
{
/**
* @var string
*/
private $kernelRootDir;

/**
* @var PathResolver
*/
private $pathResolver;

/**
* @var TimestampPersistor
*/
private $timestampPersistor;

/**
* @var ModelManager
*/
private $manager;

/**
* PurifyCss constructor.
*
* @param string $kernelRootDir
* @param TimestampPersistor $timestampPersistor
* @param PathResolver $pathResolver
* @param ModelManager $manager
*/
public function __construct($kernelRootDir, TimestampPersistor $timestampPersistor, PathResolver $pathResolver, ModelManager $manager)
{
$this->kernelRootDir = rtrim($kernelRootDir, '/');
$this->timestampPersistor = $timestampPersistor;
$this->pathResolver = $pathResolver;
$this->manager = $manager;
}

/**
* @return bool
*/
public function isRunnable()
{
$finder = new ExecutableFinder();

return (bool) $finder->find('purifycss');
}

/**
* @param int $shopId
*
* @return array
*/
public function purify($shopId)
{
$finder = new ExecutableFinder();
$timestamp = $this->timestampPersistor->getCurrentTimestamp($shopId);

$shop = $this->manager->find(Shop::class, $shopId);

if (!$shop) {
throw new \RuntimeException(sprintf('Shop with id %d does not exist', $shopId));
}

$fileName = $this->pathResolver->buildTimestampName($timestamp, $shop, 'css');
$filePath = $this->kernelRootDir . '/web/cache/' . $fileName;

$beforeSize = filesize($filePath);

$arguments = [
$this->kernelRootDir . '/themes/**/*.js',
$this->kernelRootDir . '/themes/**/*.tpl',
$this->kernelRootDir . '/custom/**/*.js',
$this->kernelRootDir . '/custom/**/*.tpl',
$this->kernelRootDir . '/engine/Shopware/Plugins/**/*.tpl',
$this->kernelRootDir . '/engine/Shopware/Plugins/**/*.js',
'-m',
];

array_unshift($arguments, $filePath);
array_unshift($arguments, $finder->find('purifycss'));
array_unshift($arguments, $finder->find('node'));

$arguments[] = '-o';
$arguments[] = $filePath;

$process = new Process($arguments);
$process->run();

if ($process->getExitCode()) {
throw new \RuntimeException(sprintf('Purify failed with message %s and code %d', $process->getErrorOutput(), $process->getExitCode()));
}

$afterSize = filesize($filePath);

return [$beforeSize, $afterSize];
}
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Performance Improvments for Shopware
* Minify Html Output
* Http 2 Server Push [#1397](https://github.com/shopware/shopware/pull/1397)
* Caching of plugin configuration
* [Purify-CSS](https://github.com/purifycss/purifycss) Integration

## Requirements

Expand Down
11 changes: 11 additions & 0 deletions Resources/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,16 @@
<argument type="service" id="frosh_performance.components.cached_config_reader.inner"/>
<argument type="service" id="cache"/>
</service>

<service id="frosh_performance.commands.purify_css_command" class="FroshPerformance\Commands\PurifyCssCommand">
<tag name="console.command" command="frosh:purify:css"/>
</service>

<service id="frosh_performance.components.purify_css" class="FroshPerformance\Components\PurifyCss">
<argument>%shopware.app.rootdir%</argument>
<argument type="service" id="theme_timestamp_persistor"/>
<argument type="service" id="theme_path_resolver"/>
<argument type="service" id="models"/>
</service>
</services>
</container>

2 comments on commit 2bf3f2d

@DanielRuf
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not completely understand what purify-css does here.
Removing unused styles from CSS files can be dangerous as this command can remove things which are dynamically added eg by computed class names.

Does this also work for subshops, what about uncached, what is with plugins which have their deps and logic in vendor so they were installed with Composer?

@shyim
Copy link
Member

@shyim shyim commented on 2bf3f2d Jan 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first plugins can't be installed directly in vendor Folder. It will be every time copied to a specific folder e.g (custom/plugins, engine/Shopware.....)

But yea there could be a issue if someone changed the default paths.

You are right with computed classes, pure-css has there a option to whitelist them. This feature is more experimental and should be double checked when used :)

Please sign in to comment.