Skip to content

Commit

Permalink
Add Vite Support
Browse files Browse the repository at this point in the history
  • Loading branch information
lcharette committed Jul 3, 2024
1 parent 192e6b9 commit 2e8066a
Show file tree
Hide file tree
Showing 15 changed files with 669 additions and 31 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [5.2.0](https://github.com/userfrosting/sprinkle-core/compare/5.1.0...5.2.0)
- [New Feature] Add [Vite](https://vitejs.dev) support :
- New Vite Bakery command, `assets:vite`. This command can be used to
- Add [Vite](https://vitejs.dev) Twig function : `vite_js`, `vite_css` and `vite_preload` to include Vite entrypoints into any Twig template.
- The default bundler (Webpack or Vite) used by `assets:build` command can be defined using the `assets.bundler` config, or `ASSETS_BUNDLER` env variable. Webpack is used by default.
- Added `assets.vite` config array in `app/config/default.php` to configure Twig integration.
- `assets.vite.dev` (bool) : Indicates whether the application is running in development mode (i.e. using vite server). Defaults to false. Tied to `VITE_DEV_ENABLED` env variable by default too.
- `assets.vite.base` (string) : Public base path from which Vite's published assets are served. The assets paths will be relative to the `outDir` in your vite configuration.
- `assets.vite.server` (string) : The vite server url, including port.
- [Bakery] The default sub commands in `AssetsBuildCommand` are now in `AssetsBuildCommandListener`
- [Bakery] Added the server option to `assets:webpack` to run HMR server (`npm run webpack:server`) plus use new npm command syntax.
- [Bakery] `AbstractAggregateCommandEvent` construction is now optional. Added `addCommands` and `prependCommands`. All setters methods return `$this`.

## [5.1.1](https://github.com/userfrosting/sprinkle-core/compare/5.1.0...5.1.1)
- Fix issue with sprunje using multiple listable fetched from database ([Chat Reference](https://chat.userfrosting.com/channel/support?msg=sgMq8sbAjsCN2ZGXj))
Expand Down
16 changes: 16 additions & 0 deletions app/config/default.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@
'key' => 'site.alerts', // the key to use to store flash messages
],

/*
* ----------------------------------------------------------------------
* Asset bundler Config
* ----------------------------------------------------------------------
* Frontend assets can be handle either by Vite or Webpack. This section
* is used to define which bundler is used, and their configuration.
*/
'assets' => [
'bundler' => env('ASSETS_BUNDLER'), // Either 'vite' or 'webpack'
'vite' => [
'dev' => env('VITE_DEV_ENABLED'),
'base' => '',
'server' => 'http://[::1]:3000/'
]
],

/*
* ----------------------------------------------------------------------
* Bakery Config
Expand Down
14 changes: 3 additions & 11 deletions app/src/Bakery/AssetsBuildCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,6 @@ final class AssetsBuildCommand extends Command
{
use WithSymfonyStyle;

/**
* @var string[] Commands to run
*/
protected array $commands = [
'assets:install',
'assets:webpack',
];

/**
* @param \UserFrosting\Event\EventDispatcher $eventDispatcher
*/
Expand All @@ -53,9 +45,9 @@ protected function configure(): void
$list = implode(', ', $this->aggregateCommands());

$this->setName('assets:build')
->setDescription('Build the assets using npm and Webpack Encore')
->setDescription('Build the assets using npm and Webpack Encore or Vite')
->addOption('production', 'p', InputOption::VALUE_NONE, 'Create a production build')
->addOption('watch', 'w', InputOption::VALUE_NONE, 'Watch for changes and recompile automatically')
->addOption('watch', 'w', InputOption::VALUE_NONE, 'Watch for changes and recompile automatically (Webpack only)')
->setHelp("This command combine the following commands : <comment>{$list}</comment>. For more info, see <comment>https://learn.userfrosting.com/asset-management</comment>.")
->setAliases(['build-assets', 'webpack']);
}
Expand Down Expand Up @@ -87,7 +79,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
*/
protected function aggregateCommands(): array
{
$event = new AssetsBuildCommandEvent($this->commands);
$event = new AssetsBuildCommandEvent();
$event = $this->eventDispatcher->dispatch($event);

return $event->getCommands();
Expand Down
114 changes: 114 additions & 0 deletions app/src/Bakery/AssetsViteCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php

declare(strict_types=1);

/*
* UserFrosting Core Sprinkle (http://www.userfrosting.com)
*
* @link https://github.com/userfrosting/sprinkle-core
* @copyright Copyright (c) 2013-2024 Alexander Weissman & Louis Charette
* @license https://github.com/userfrosting/sprinkle-core/blob/master/LICENSE.md (MIT License)
*/

namespace UserFrosting\Sprinkle\Core\Bakery;

use DI\Attribute\Inject;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use UserFrosting\Bakery\WithSymfonyStyle;
use UserFrosting\Sprinkle\Core\Bakery\Helper\ShellCommandHelper;
use UserFrosting\Sprinkle\Core\Exceptions\VersionCompareException;
use UserFrosting\Sprinkle\Core\Validators\NodeVersionValidator;
use UserFrosting\Sprinkle\Core\Validators\NpmVersionValidator;

/**
* Alias for `npm run vite:dev` and `npm run vite:build` commands.
*/
final class AssetsViteCommand extends Command
{
use WithSymfonyStyle;
use ShellCommandHelper;

#[Inject]
protected NodeVersionValidator $nodeVersionValidator;

#[Inject]
protected NpmVersionValidator $npmVersionValidator;

#[Inject('UF_MODE')]
protected string $envMode;

/**
* {@inheritdoc}
*/
protected function configure(): void
{
$help = [
'This command run <info>Vite</info>, using the config defined in <info>vite.config.js</info>.',
'It will automatically compile the frontend dependencies in the <info>public/assets/</info> directory, or use the Vite development server',
'Everything will be executed in the same dir the bakery command is executed.',
'For more info, see <comment>https://learn.userfrosting.com/asset-management</comment>',
];

$this->setName('assets:vite')
->setDescription('Alias for `npm run vite:dev` or `npm run vite:build` commands.')
->addOption('production', 'p', InputOption::VALUE_NONE, 'Force the creation of a production build using `vite:build`')
->setHelp(implode(' ', $help));
}

/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->io->title('Running Vite');

// Get options
$production = (bool) $input->getOption('production');

// Validate dependencies
try {
$this->nodeVersionValidator->validate();
$this->npmVersionValidator->validate();
} catch (VersionCompareException $e) {
$this->io->error($e->getMessage());

return self::FAILURE;
}

// Get path
$path = getcwd();
if ($path === false) {
$this->io->error('Error getting working directory');

return self::FAILURE;
}

// Execute Vite
if (!file_exists($path . '/vite.config.js') && !file_exists($path . '/vite.config.ts')) {
$this->io->warning('Vite config not found. Skipping.');

return self::SUCCESS;
}

// Select command based on command arguments
$command = match (true) {
($production || $this->envMode === 'production') => 'npm run vite:build',
default => 'npm run vite:dev',
};

$this->io->info("Running command: $command");
if ($this->executeCommand($command) !== 0) {
$this->io->error('Vite command has failed');

return self::FAILURE;
}

// If all went well and there's no fatal errors, we are successful
$this->io->success('Vite command completed');

return self::SUCCESS;
}
}
12 changes: 8 additions & 4 deletions app/src/Bakery/AssetsWebpackCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
use UserFrosting\Sprinkle\Core\Validators\NpmVersionValidator;

/**
* Alias for `npm run dev`, `npm run build` and `npm run watch` commands.
* Alias for `npm run webpack:dev`, `npm run webpack:build`,
* `npm run webpack:server` and `npm run webpack:watch` commands.
*/
final class AssetsWebpackCommand extends Command
{
Expand Down Expand Up @@ -56,6 +57,7 @@ protected function configure(): void
->setDescription('Alias for `npm run dev`, `npm run build` or `npm run dev` command')
->addOption('production', 'p', InputOption::VALUE_NONE, 'Create a production build')
->addOption('watch', 'w', InputOption::VALUE_NONE, 'Watch for changes and recompile automatically')
->addOption('server', 's', InputOption::VALUE_NONE, 'Run the development server with Hot Module Replacement (HMR)')
->setHelp(implode(' ', $help));
}

Expand All @@ -69,6 +71,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
// Get options
$production = (bool) $input->getOption('production');
$watch = (bool) $input->getOption('watch');
$server = (bool) $input->getOption('server');

// Validate dependencies
try {
Expand Down Expand Up @@ -98,9 +101,10 @@ protected function execute(InputInterface $input, OutputInterface $output)

// Select command based on command arguments
$command = match (true) {
($production || $this->envMode === 'production') => 'npm run build',
$watch => 'npm run watch',
default => 'npm run dev',
($production || $this->envMode === 'production') => 'npm run webpack:build',
$server => 'npm run webpack:server',
$watch => 'npm run webpack:watch',
default => 'npm run webpack:dev',
};

$this->io->info("Running command: $command");
Expand Down
44 changes: 40 additions & 4 deletions app/src/Bakery/Event/AbstractAggregateCommandEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ abstract class AbstractAggregateCommandEvent
/**
* @param string[] $commands
*/
public function __construct(protected array $commands)
public function __construct(protected array $commands = [])
{
}

Expand All @@ -37,25 +37,61 @@ public function getCommands(): array

/**
* @param string[] $commands
*
* @return self
*/
public function setCommands(array $commands): void
public function setCommands(array $commands): self
{
$this->commands = $commands;

return $this;
}

/**
* @param string $command
*
* @return self
*/
public function addCommand(string $command): void
public function addCommand(string $command): self
{
$this->commands[] = $command;

return $this;
}

/**
* @param string[] $commands
*
* @return self
*/
public function addCommands(array $commands): self
{
$this->commands = array_merge($this->commands, $commands);

return $this;
}

/**
* @param string $command
*
* @return self
*/
public function prependCommand(string $command): void
public function prependCommand(string $command): self
{
array_unshift($this->commands, $command);

return $this;
}

/**
* @param string[] $commands
*
* @return self
*/
public function prependCommands(array $commands): self
{
$this->commands = array_merge($commands, $this->commands);

return $this;
}
}
7 changes: 7 additions & 0 deletions app/src/Core.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use UserFrosting\Sprinkle\Core\Bakery\AssetsBuildCommand;
use UserFrosting\Sprinkle\Core\Bakery\AssetsInstallCommand;
use UserFrosting\Sprinkle\Core\Bakery\AssetsUpdateCommand;
use UserFrosting\Sprinkle\Core\Bakery\AssetsViteCommand;
use UserFrosting\Sprinkle\Core\Bakery\AssetsWebpackCommand;
use UserFrosting\Sprinkle\Core\Bakery\BakeCommand;
use UserFrosting\Sprinkle\Core\Bakery\ClearCacheCommand;
Expand All @@ -32,6 +33,7 @@
use UserFrosting\Sprinkle\Core\Bakery\DebugMailCommand;
use UserFrosting\Sprinkle\Core\Bakery\DebugTwigCommand;
use UserFrosting\Sprinkle\Core\Bakery\DebugVersionCommand;
use UserFrosting\Sprinkle\Core\Bakery\Event\AssetsBuildCommandEvent;
use UserFrosting\Sprinkle\Core\Bakery\LocaleCompareCommand;
use UserFrosting\Sprinkle\Core\Bakery\LocaleDictionaryCommand;
use UserFrosting\Sprinkle\Core\Bakery\LocaleInfoCommand;
Expand All @@ -58,6 +60,7 @@
use UserFrosting\Sprinkle\Core\Error\ExceptionHandlerMiddleware;
use UserFrosting\Sprinkle\Core\Error\RegisterShutdownHandler;
use UserFrosting\Sprinkle\Core\Event\ResourceLocatorInitiatedEvent;
use UserFrosting\Sprinkle\Core\Listeners\AssetsBuildCommandListener;
use UserFrosting\Sprinkle\Core\Listeners\ModelInitiated;
use UserFrosting\Sprinkle\Core\Listeners\ResourceLocatorInitiated;
use UserFrosting\Sprinkle\Core\Listeners\SetRouteCaching;
Expand Down Expand Up @@ -136,6 +139,7 @@ public function getBakeryCommands(): array
AssetsUpdateCommand::class,
AssetsInstallCommand::class,
AssetsWebpackCommand::class,
AssetsViteCommand::class,
BakeCommand::class,
ClearCacheCommand::class,
DebugCommand::class,
Expand Down Expand Up @@ -288,6 +292,9 @@ public function getEventListeners(): array
ResourceLocatorInitiatedEvent::class => [
ResourceLocatorInitiated::class,
],
AssetsBuildCommandEvent::class => [
AssetsBuildCommandListener::class,
],
];
}
}
Loading

0 comments on commit 2e8066a

Please sign in to comment.