Skip to content
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## v3.0.0

The new version changes the plugin architecture and requires some modifications. It's highly recommended to check the
README.md

* Updated the plugin's configuration array
* The methods `$this->ViteScripts->pluginScript($pluginName)` and `pluginCss()` were removed
* The `$this->ViteScripts->css()` and `$this->ViteScripts->script()` were updated
* The running environment MUST be defined explicitly or a detector should be used

## v2.3.0

### Changed
Expand Down
180 changes: 99 additions & 81 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 @@ -17,12 +17,13 @@ You can install this plugin into your CakePHP application using [composer](https

### CakePHP Version Map

| CakePHP version | Plugin Version | Branch | min. PHP Version |
|-----------------|----------------|--------|------------------|
| ^3.10 | / | cake3 | ^7.4 |
| ^4.2 | 0.x | master | ^7.4 |
| ^4.2 | 1.x | master | ^8.0 |
| ^5.0 | 2.x | cake5 | ^8.1 |
| CakePHP version | Plugin Version | Branch | min. PHP Version |
|-----------------|----------------|-------------|------------------|
| ^3.10 | / | cake3 | ^7.4 |
| ^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-next | ^8.3 |

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,121 +80,138 @@ 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
],
'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
'builds' => [
[
'plugin' => null, // the plugin name or null if it doesn't exist. Default: null
'outputDirectory' => 'build', // the output directory relative to `webroot`. Default: 'build'
'manifest' => 'build' . DS . '.vite' . DS . 'manifest.json', // the relative path to the manifest file. Default: 'build' . DS . '.vite' . DS . 'manifest.json'
'environment' => \ViteHelper\Enum\Environment::PRODUCTION, // the forced environment, all files what 'falls' in this manifest file will be rendered this way. Default: the globally set environment
],
],
],
```

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
]);
```

Example:
Since every build option has a default value:

```php
return [
'ViteHelper' => [
'forceProductionMode' => 1,
'development' => [
'hostNeedles' => ['.dev'], // if you don't use one of the defaults
'url' => 'https://192.168.0.88:3000',
],
'ViteHelper' => [
'environment' => \ViteHelper\Enum\Environment::DEVELOPMENT, // available options PRODUCTION, DEVELOPMENT, FROM_DETECTOR
'development' => [
'url' => 'http://localhost:3000', // url of the vite dev server
],
'builds' => [
[],
['plugin' => 'MyAwesomePlugin', 'environment' => 'prod']
],
];
],
```

## Helper method usage with options
These are valid builds. Assets from `MyAwesomePlugin` will be loaded like in production, the assets from root in development mode.

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()`.
## 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
$this->ViteScripts->script([

// 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.
$this->request->addDetector(
\ViteHelper\View\Helper\ViteScriptsHelper::VITESCRIPT_DETECTOR_NAME,
function ($serverRequest) {
// your logic goes here
// return true for prod, false for dev
}
);
```

// files that are entry files during development and that should be served during production
'files' => [
'webroot_src/main.ts',
],
In the development mode the plugins adds the necessary tags for development, in production this isn't happening.

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

// "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 */ }
]);
```
The options are the same for `::script()` and `::css()`.

**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.
### Example

It depends on your project and use case how you define entries. If you don't use `prodFilter` or `files`, the plugin
will serve all your entry files which might just be the case you want. So don't overconfigure it ;)
```php
$this->ViteScripts->script(
files: ['resource/file1.js', 'resource/file2.js'], // Files as array/file as string
block: null, // name of the view block to render the scripts in. Default: null
plugin: null, // Plugin's name. Default: null

// 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,
);
```

## Opt out of global config + Plugin development
## Performance

You can use the helper methods with multiple configurations through the `$config` argument.
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`.

> **New in version 2.3:** You can pass a config key instead of a config instance to the helper. The default config key
> is `ViteHelper`.
```php
$this->loadHelper('ViteHelper.ViteScripts', [
'render_mode' => \ViteHelper\Enum\RenderMode::MANUAL
]);
```

This might be useful when using plugin scripts or when developing plugins:
In your php-layout, right before the `viewBlocks` you should manually call the `::render()` method or dispatch
the `Vite.render` event.

```php
<?php $this->ViteScripts->pluginScript('MyPlugin', devMode: true, config: 'MyPlugin.ViteConfig'); ?>
$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

The example above uses a convenience method to load plugin scripts for `MyPlugin`. DevMode is enabled and the helper
will use a CakePHP config under the key `MyPlugin.ViteConfig`. In this way, you can scope your App's and your plugin's
config.

It is assumed that the `manifest.json` is available directly in your plugin's `webroot`. If this is not the case, you
should define the absolute path throuh the `build.manifest` config option.
```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') ?>
```

## Vite JS bundler / Dev server

Expand All @@ -215,9 +233,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
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"type": "cakephp-plugin",
"license": "MIT",
"require": {
"php": ">=8.1",
"php": ">=8.3",
"cakephp/cakephp": "^5.0"
},
"require-dev": {
Expand Down 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
30 changes: 14 additions & 16 deletions config/app_vite.php
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
<?php

use \ViteHelper\Utilities\ConfigDefaults;

return [
'ViteHelper' => [
'build' => [
'outDirectory' => ConfigDefaults::BUILD_OUT_DIRECTORY,
'manifest' => ConfigDefaults::BUILD_MANIFEST,
],
// the running environment
'environment' => \ViteHelper\Enum\Environment::PRODUCTION,
// development settings
'development' => [
'scriptEntries' => ConfigDefaults::DEVELOPMENT_SCRIPT_ENTRIES,
'styleEntries' => ConfigDefaults::DEVELOPMENT_STYLE_ENTRIES,
'hostNeedles' => ConfigDefaults::DEVELOPMENT_HOST_NEEDLES,
'url' => ConfigDefaults::DEVELOPMENT_URL,
'url' => 'http://localhost:3000',
],
'forceProductionMode' => ConfigDefaults::FORCE_PRODUCTION_MODE,
'plugin' => false,
'productionHint' => ConfigDefaults::PRODUCTION_HINT,
'viewBlocks' => [
'css' => ConfigDefaults::VIEW_BLOCK_CSS,
'script' => ConfigDefaults::VIEW_BLOCK_SCRIPT,
// list of builds
'builds' => [
[
// the plugin name or null if it doesn't exist
'plugin' => null,
// the output directory relative to `webroot`
'outputDirectory' => 'build',
// the relative path to the manifest file
'manifest' => 'build' . DS . '.vite' . DS . 'manifest.json',
],
],
],
];
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
Loading
Loading