diff options
author | dizzy <diosmosis@users.noreply.github.com> | 2021-09-28 12:07:16 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-28 12:07:16 +0300 |
commit | 2ac2bc1aeaf8efce6bb9af92506311da99e1757f (patch) | |
tree | 532874be8120221d30307680b2a437cc361d2a70 /plugins/CoreConsole | |
parent | 1bc9fdf55352b61c278d298e9935451394230355 (diff) |
[Vue] Introduce Vue + Workflow commands (#17940)
* adding vue
* adding webpack config + example vue library project
* forgot to add base tsconfig.json
* Add build command that allows building all plugins + watching for changes.
* autodetect umd bundles
* initial externals detection
* integrate vue CLI
* add externals config via vue config
* explain regenerator issue
* remove ie11
* Build polyfills in separate library.
* add command to quickly compute total asset size (minified + gzipped)
* output tweak for --exclude-angular
* Explicitly disable support for ie11 since Vue 3 does not support it.
* rebuild and add option to clear webpack cache to build commands
* Add example vue component that compiles w/ vue 3.
* get example vue component to display
* include tslib via polyfills so it is not compiled in each library
* get async component loading to work
* some tweaks and tests
* Add generate vue component command and run to generate activity indicator template.
* switch to using composition api since that is apparently better supported, and get activity indicator adapter to bind data properly
* remove vue-class-component npm package
* eslint changes
* rever tracking JS change
* tweak
* Remove CoreVue vue dir which was just there for testing.
* Update vue.config.js
* apply some review feedback
* add plugin to compute js asset size command
* use local script to build
* update changelog and apply review feedback
* fix bower component mapping
* update expected screenshots
* update screenshot
* Update and rename 4.5.0-b2.php to 4.6.0-b1.php
* Update Version.php
* update expected screenshot
* updates expected UI test files
Co-authored-by: sgiehl <stefan@matomo.org>
Diffstat (limited to 'plugins/CoreConsole')
-rw-r--r-- | plugins/CoreConsole/Commands/ComputeJsAssetSize.php | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/plugins/CoreConsole/Commands/ComputeJsAssetSize.php b/plugins/CoreConsole/Commands/ComputeJsAssetSize.php new file mode 100644 index 0000000000..9b0bd310ef --- /dev/null +++ b/plugins/CoreConsole/Commands/ComputeJsAssetSize.php @@ -0,0 +1,253 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +namespace Piwik\Plugins\CoreConsole\Commands; + +use Piwik\AssetManager; +use Piwik\Common; +use Piwik\Development; +use Piwik\Metrics\Formatter; +use Piwik\Piwik; +use Piwik\Plugin; +use Piwik\Plugin\ConsoleCommand; +use Piwik\Plugin\Manager; +use Piwik\ProxyHttp; +use Piwik\SettingsPiwik; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class ComputeJsAssetSize extends ConsoleCommand +{ + protected function configure() + { + $this->setName('development:compute-js-asset-size'); + $this->setDescription('Generates production assets and computes the size of the resulting code.'); + $this->addOption('exclude-angular', null, InputOption::VALUE_NONE); + $this->addOption('no-delete', null, InputOption::VALUE_NONE, 'Do not delete files after creating them.'); + } + + public function isEnabled() + { + return SettingsPiwik::isGitDeployment(); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $excludeAngular = $input->getOption('exclude-angular'); + $noDelete = $input->getOption('no-delete'); + + $this->checkDevelopmentModeDisabled(); + $this->ensureThirdPartyPluginsActivated(); + + $output->writeln("Building and printing sizes of built JS assets..."); + + if ($excludeAngular) { + $this->excludeAngular($output); + } + + $this->deleteMergedAssets(); + $this->buildAssets(); + + $output->writeln(""); + $this->printCurrentGitHashAndBranch($output, $excludeAngular); + + $output->writeln(""); + $this->printFilesizes($output); + + if (!$noDelete) { + $this->deleteMergedAssets(); + } + } + + private function ensureThirdPartyPluginsActivated() + { + $expectedPluginsLoadedAndActivated = [ + "CorePluginsAdmin", + "CoreAdminHome", + "CoreHome", + "WebsiteMeasurable", + "IntranetMeasurable", + "Diagnostics", + "CoreVisualizations", + "Proxy", + "API", + "Widgetize", + "Transitions", + "LanguagesManager", + "Actions", + "Dashboard", + "MultiSites", + "Referrers", + "UserLanguage", + "DevicesDetection", + "Goals", + "Ecommerce", + "SEO", + "Events", + "UserCountry", + "GeoIp2", + "VisitsSummary", + "VisitFrequency", + "VisitTime", + "VisitorInterest", + "RssWidget", + "Feedback", + "Monolog", + "Login", + "TwoFactorAuth", + "UsersManager", + "SitesManager", + "Installation", + "CoreUpdater", + "CoreConsole", + "ScheduledReports", + "UserCountryMap", + "Live", + "PrivacyManager", + "ImageGraph", + "Annotations", + "MobileMessaging", + "Overlay", + "SegmentEditor", + "Insights", + "Morpheus", + "Contents", + "TestRunner", + "BulkTracking", + "Resolution", + "DevicePlugins", + "Heartbeat", + "Intl", + "UserId", + "CustomJsTracker", + "Tour", + "PagePerformance", + "CustomDimensions", + "TagManager", + "AbTesting", + "ActivityLog", + "Bandwidth", + "Cohorts", + "CustomAlerts", + "CustomReports", + "CustomVariables", + "DeviceDetectorCache", + "FormAnalytics", + "Funnels", + "GoogleAnalyticsImporter", + "InvalidateReports", + "MarketingCampaignsReporting", + "MediaAnalytics", + "MultiChannelConversionAttribution", + "QueuedTracking", + "RollUpReporting", + "SearchEngineKeywordsPerformance", + "UsersFlow", + "VisitorGenerator", + "WhiteLabel", + "WooCommerceAnalytics", + "AdvertisingConversionExport", + ]; + + if (is_file(PIWIK_INCLUDE_PATH . '/plugins/CoreVue/plugin.json')) { + $expectedPluginsLoadedAndActivated[] = "CoreVue"; + } + + $pluginsLoadedAndActivated = Manager::getInstance()->getPluginsLoadedAndActivated(); + $pluginsLoadedAndActivated = array_map(function (Plugin $p) { return $p->getPluginName(); }, $pluginsLoadedAndActivated); + + $missingPlugins = array_diff($expectedPluginsLoadedAndActivated, $pluginsLoadedAndActivated); + if (!empty($missingPlugins)) { + throw new \Exception("Activate the following plugins before running this command: " . implode(", ", $missingPlugins)); + } + } + + private function excludeAngular(OutputInterface $output) + { + Piwik::addAction('AssetManager.getJavaScriptFiles', function (&$files) use ($output) { + $newFiles = []; + foreach ($files as $filePath) { + if (strpos($filePath, 'node_modules/angular') !== false) { + if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) { + $output->writeln("<comment> Excluding angular file $filePath.</comment>"); + } + continue; + } + + $newFiles[] = $filePath; + } + $files = $newFiles; + }); + } + + private function buildAssets() + { + AssetManager::getInstance()->getMergedCoreJavaScript(); + AssetManager::getInstance()->getMergedNonCoreJavaScript(); + } + + private function deleteMergedAssets() + { + AssetManager::getInstance()->removeMergedAssets(); + } + + private function printFilesizes(OutputInterface $output) + { + $fileSizes = []; + + $mergedCore = AssetManager::getInstance()->getMergedCoreJavaScript(); + $fileSizes[] = [$mergedCore->getRelativeLocation(), $this->getFileSize($mergedCore->getAbsoluteLocation()), $this->getGzippedFileSize($mergedCore->getAbsoluteLocation())]; + + $mergedNonCore = AssetManager::getInstance()->getMergedNonCoreJavaScript(); + $fileSizes[] = [$mergedNonCore->getRelativeLocation(), $this->getFileSize($mergedNonCore->getAbsoluteLocation()), $this->getGzippedFileSize($mergedNonCore->getAbsoluteLocation())]; + + $table = new Table($output); + $table->setHeaders(['File', 'Size', 'Size (gzipped)'])->setRows($fileSizes); + $table->render(); + } + + private function getFileSize($fileLocation) + { + $formatter = new Formatter(); + + $size = filesize($fileLocation); + $size = $formatter->getPrettySizeFromBytes($size, 'K', 2); + return $size; + } + + private function checkDevelopmentModeDisabled() + { + if (Development::isEnabled()) { + throw new \Exception("This command is to estimate production build sizes, so development mode must be disabled for it."); + } + } + + private function getGzippedFileSize($path) + { + $data = file_get_contents($path); + $data = ProxyHttp::gzencode($data); + + if (false === $data) { + throw new \Exception('compressing file '.$path.' failed'); + } + + $compressedPath = dirname($path) . '/' . basename($path) . '.gz'; + file_put_contents($compressedPath, $data); + return $this->getFileSize($compressedPath); + } + + private function printCurrentGitHashAndBranch(OutputInterface $output, $excludeAngular) + { + $branchName = trim(`git rev-parse --abbrev-ref HEAD`); + $lastCommit = trim(`git log --pretty=format:'%h' -n 1`); + + $output->writeln("<info>$branchName ($lastCommit)</info> <comment>" . ($excludeAngular ? '(without angularjs)' : '') . "</comment>"); + } +} |