Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cake5 - Next #19

Open
wants to merge 11 commits into
base: cake5
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 92 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ reloading.
In production mode, the Helper loads the bundled files. `@vitejs/plugin-legacy` is supported, which will
insert `nomodule`-tags for older browsers, e.g. older iOS devices, which do not support js modules.

> This readme is for **version 1.x.** If you are migrating from 0.x and something is unclear, read the Migration guide
> This readme is for **version 3.x.** If you are migrating from 0.x and something is unclear, read the Migration guide
> under `/docs`. Feel free to open an issue if you run into problems.

## Installation
Expand All @@ -23,6 +23,7 @@ You can install this plugin into your CakePHP application using [composer](https
| ^4.2 | 0.x | master | ^7.4 |
| ^4.2 | 1.x | master | ^8.0 |
| ^5.0 | 2.x | cake5 | ^8.1 |
| ^5.0 | 3.x | cake5 | ^8.1 |

The recommended way to install the plugin is:

Expand Down Expand Up @@ -62,13 +63,13 @@ These are the default view blocks in CakePHP.
In your php-template or in layout you can import javascript files with:

```php
<?php $this->ViteScripts->script($options) ?>
<?php $this->ViteScripts->script('resources/main.ts') ?>
```

… or by using this shortcut for a single entrypoint:
… or multiple files

```php
<?php $this->ViteScripts->script('webroot_src/main.ts') ?>
<?php $this->ViteScripts->script(['resources/main.ts', 'resources/main2.ts', 'resources/main3.ts']) ?>
```

If you imported CSS files inside your JavaScript files, this method automatically
Expand All @@ -79,95 +80,130 @@ appends your css tags to the css view block.
In your php-template you can import css files with:

```php
<?php $this->ViteScripts->css($options) ?>
<?php $this->ViteScripts->css('resources/style.css') ?>
```

… or by using this shortcut for a single entrypoint:
… or multiple files

```php
<?php $this->ViteScripts->css('webroot_src/style.css') ?>
<?php $this->ViteScripts->css(['resources/style.css', 'resources/style2.css', 'resources/style3.css']) ?>
```

## Configuration

The plugin comes with some default configuration. You may need to change it depending on your setup. Or you might not
need any config at all.

You can override some of these config settings through the `$options` of the helper methods. Or you can pass
your own instance of `ViteHelperConfig` to a helper method as a second parameter.
The default configuration is:

```php
'ViteHelper' => [
'build' => [
'outDirectory' => false, // output directory of build assets. string (e.g. 'dist') or false.
'manifest' => WWW_ROOT . 'manifest.json', // absolute path to manifest
],
'plugin' => false, // or string 'MyPlugin' to serve plugin build assets
'render_mode' => \ViteHelper\Enum\RenderMode::AUTO, // how/when the styles and scripts should be added to view blocks. available options AUTO, MANUAL
'environment' => \ViteHelper\Enum\Environment::PRODUCTION, // available options PRODUCTION, DEVELOPMENT, FROM_DETECTOR
'development' => [
'scriptEntries' => ['someFolder/myScriptEntry.ts'], // relative to project root
'styleEntries' => ['someFolder/myStyleEntry.scss'], // relative to project root. Unnecessary when using css-in-js.
'hostNeedles' => ['.test', '.local'], // to check if the app is running locally
'url' => 'http://localhost:3000', // url of the vite dev server
],
'forceProductionMode' => false, // or true to always serve build assets
'plugin' => false, // or string 'MyPlugin' to serve plugin build assets
'productionHint' => 'vprod', // can be a true-ish cookie or url-param to serve build assets without changing the forceProductionMode config
'viewBlocks' => [
'css' => 'css', // name of the css view block
'script' => 'script', // name of the script view block
'build' => [
'outDirectory' => 'build', // output directory of build assets. string (e.g. 'dist') or false.
'manifest' => WWW_ROOT . 'build' . DS . '.vite' . DS . 'manifest.json', // absolute path to manifest
],
],
```

You can override the defaults in your `app.php`, `app_local.php`, or `app_vite.php`.
You can override the defaults in your `app.php`, `app_local.php`, or `app_vite.php`, also you can override in
`AppView.php` when you are loading the helper.

See the plugin's [app_vite.php](https://github.com/brandcom/cakephp-vite/blob/master/config/app_vite.php) for reference.
```php
$this->loadHelper('ViteHelper.ViteScripts', [
// ...your config goes here
]);
```

## Environment

Example:
The plugin MUST accurately determine whether you are in development or production mode. You must explicitly set in the
config that you are in either `\ViteHelper\Enum\Environment::PRODUCTION` or `\ViteHelper\Enum\Environment::DEVELOPMENT`.
To enhance the flexibility of the plugin, you can utilize `\ViteHelper\Enum\Environment::FROM_DETECTOR`. This setting
will employ a [detector](https://book.cakephp.org/5/en/controllers/request-response.html#Cake\Http\ServerRequest::is)
to automatically detect the environment.

```php
return [
'ViteHelper' => [
'forceProductionMode' => 1,
'development' => [
'hostNeedles' => ['.dev'], // if you don't use one of the defaults
'url' => 'https://192.168.0.88:3000',
],
],
];
$this->request->addDetector(
\ViteHelper\View\Helper\ViteScriptsHelper::VITESCRIPT_DETECTOR_NAME,
function ($serverRequest) {
// your logic goes here
// return true for prod, false for dev
}
);
```

## Helper method usage with options

You can pass an `$options` array to override config or to completely skip the necessity to have a ViteHelper config.

The options are mostly the same for `::script()` and `::css()`.
The options are the same for `::script()` and `::css()`.

### Example

```php
$this->ViteScripts->script([
$this->ViteScripts->script(
// files for the block
files: ['resource/file1.js', 'resource/file2.js'], // can be also a string

// filter for environment
// default: null
// in case of null the file(s) will be rendered both on prod and dev
// possible values: \ViteHelper\Enum\Environment::PRODUCTION, \ViteHelper\Enum\Environment::DEVELOPMENT, null
environment: null,

// name of the view block to render the scripts in
// default null
// on null uses `css` for style, `script` for javascript files
block: null,

// plugin prefix
// default null
// on null uses the plugin used in default config
plugin: null,
);
```

// this would append both the scripts and the css to a block named 'myCustomBlock'
// don't forget to use the block through $this->fetch('myCustomBlock')
'block' => 'myCustomBlock',
'cssBlock' => 'myCustomBlock', // for ::script() only – if you use css imports inside js.
## Performance

// files that are entry files during development and that should be served during production
'files' => [
'webroot_src/main.ts',
],
In production, it's possible that the manifest.json file is too large. If the default render mode is set to `AUTO`,
every `::script()` and `::css()` call automatically and instantly adds the HTML tag to the block. You can disable this
feature by setting render mode `MANUAL`.

// "devEntries" is like "files". If you set "files", it will override both "devEntries" and "prodFilters"
'devEntries' => ['webroot_src/main.ts']

// "prodFilter" filters the entry files. Useful for code-splitting if you don't use dynamic imports
'prodFilter' => 'webroot_src/main.ts' // as string if there's only one option
'prodFilter' => 'main.ts' // also works - only looks for parts of the string
'prodFilter' => ['main.ts'] // as array - same as above with multiple files
'prodFilter' => function (ManifestRecord $record) { /* do something with the record and return true or false */ }
```php
$this->loadHelper('ViteHelper.ViteScripts', [
'render_mode' => \ViteHelper\Enum\RenderMode::MANUAL
]);
```

In your php-layout, right before the `viewBlocks` you should manually call the `::render()` method or dispatch
the `Vite.render` event.

```php
$this->ViteScripts->script('resource/myscript1.js');
$this->ViteScripts->script('resource/myscript2.js');
// ... + a lot of script
$this->ViteScripts->script('resource/myscriptN.js');
$this->ViteScripts->render();
<?= $this->fetch('css') ?>
```
or

```php
$this->ViteScripts->script('resource/myscript1.js');
$this->ViteScripts->script('resource/myscript2.js');
// ... + a lot of script
$this->ViteScripts->script('resource/myscriptN.js');
// dispatch 'Vite.render' event
$this->getEventManager()->dispatch('Vite.render');
<?= $this->fetch('css') ?>
```

// TODO pluginScript should be removed, devEntries and prodFilter makes no-sense anymore

**Note:** You need to set `devEntries` when running the dev server. They have to either be set in the config or
through the helper method. In contrast, you only need `files` or `prodFilter` if you are interested in php-side
code-splitting and don't use dynamic imports in js.
Expand Down Expand Up @@ -215,9 +251,9 @@ yarn add -D @vitejs/plugin-legacy
### Configuration

After installing, you will need to refactor the files a bit to make sense of it in a php project. The default config of
this plugin assumes that you put your js, ts, scss etc. in `/webroot_src`.
this plugin assumes that you put your js, ts, scss etc. in `/resources`.

The build files will end up in `/webroot/assets` by default. Your `vite.config.js or *.ts` file for vite stays in the
The build files will end up in `/webroot/build` by default. Your `vite.config.js or *.ts` file for vite stays in the
project root.

> Wanted: Examples for vite/plugin configs and directory structures. Feel free to contribute with a PR to show how your
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
},
"scripts": {
"test": "phpunit",
"cs-check": "phpcs --colors --parallel=16 -p src/",
"cs-fix": "phpcbf --colors --parallel=16 -p src/",
"cs-check": "phpcs --colors -p src/",
"cs-fix": "phpcbf --colors -p src/",
"stan": "phpstan analyse",
"stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^1.7.0 && mv composer.backup composer.json",
"lowest-setup": "composer update --prefer-lowest --prefer-stable --prefer-dist --no-interaction && cp composer.json composer.backup && composer require --dev dereuromark/composer-prefer-lowest && mv composer.backup composer.json"
Expand Down
21 changes: 6 additions & 15 deletions config/app_vite.php
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
<?php

use \ViteHelper\Utilities\ConfigDefaults;

return [
'ViteHelper' => [
'plugin' => false,
'render_mode' => \ViteHelper\Enum\RenderMode::AUTO,
'environment' => \ViteHelper\Enum\Environment::PRODUCTION,
'build' => [
'outDirectory' => ConfigDefaults::BUILD_OUT_DIRECTORY,
'manifest' => ConfigDefaults::BUILD_MANIFEST,
'outDirectory' => 'build',
'manifest' => WWW_ROOT . 'build' . DS . '.vite' . DS . 'manifest.json',
],
'development' => [
'scriptEntries' => ConfigDefaults::DEVELOPMENT_SCRIPT_ENTRIES,
'styleEntries' => ConfigDefaults::DEVELOPMENT_STYLE_ENTRIES,
'hostNeedles' => ConfigDefaults::DEVELOPMENT_HOST_NEEDLES,
'url' => ConfigDefaults::DEVELOPMENT_URL,
],
'forceProductionMode' => ConfigDefaults::FORCE_PRODUCTION_MODE,
'plugin' => false,
'productionHint' => ConfigDefaults::PRODUCTION_HINT,
'viewBlocks' => [
'css' => ConfigDefaults::VIEW_BLOCK_CSS,
'script' => ConfigDefaults::VIEW_BLOCK_SCRIPT,
'url' => 'http://localhost:3000',
],
],
];
19 changes: 13 additions & 6 deletions etc/vite.config.ts.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import basicSsl from '@vitejs/plugin-basic-ssl'

// https://vitejs.dev/config/
export default defineConfig({
root: '',
publicDir: 'resources/assets',
plugins: [
basicSsl(),
vue(),
Expand All @@ -26,23 +28,28 @@ export default defineConfig({
protocol: 'wss',
},
watch: {
ignored: [/bin/, /config/, /plugins/, /resources/, /tests/, /vendor/, /logs/, /tmp/],
depth: 5,
ignored: [/bin/, /config/, /plugins/, /tests/, /vendor/, /logs/, /tmp/],
depth: 15,
}
},
build: {
emptyOutDir: true,
outDir: './webroot/build',
assetsDir: 'assets',
assetsDir: './assets',
manifest: true,
rollupOptions: {
input: [
'./webroot_src/js/main.js',
'./webroot_src/js/timetables.js',
'./webroot_src/scss/style.scss',
'./resources/js/main.js',
'./resources/js/timetables.js',
'./resources/scss/style.scss',
],
output: {
entryFileNames: '[name].[hash].min.js',
manualChunks(id) {
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
}
}
}
},
Expand Down
14 changes: 14 additions & 0 deletions src/Enum/Environment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);

namespace ViteHelper\Enum;

/**
* The plugin environment mode
*/
enum Environment: string
{
case PRODUCTION = 'prod';
case DEVELOPMENT = 'dev';
case FROM_DETECTOR = 'detector';
}
11 changes: 11 additions & 0 deletions src/Enum/RecordType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);

namespace ViteHelper\Enum;

enum RecordType: string
{
case STYLE = 'style';

case SCRIPT = 'script';
}
11 changes: 11 additions & 0 deletions src/Enum/RenderMode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);

namespace ViteHelper\Enum;

enum RenderMode: int
{
case AUTO = 1;

case MANUAL = 2;
}
8 changes: 0 additions & 8 deletions src/Exception/InvalidArgumentException.php

This file was deleted.

31 changes: 31 additions & 0 deletions src/Model/Entity/Record.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);

namespace ViteHelper\Model\Entity;

use ViteHelper\Enum\RecordType;

abstract class Record
{
protected RecordType $type;

/**
* Default constructor
*
* @param \ViteHelper\Enum\RecordType $type
*/
public function __construct(RecordType $type)
{
$this->type = $type;
}

/**
* returns the record type
*
* @return \ViteHelper\Enum\RecordType
*/
public function getType(): RecordType
{
return $this->type;
}
}
Loading
Loading