Skip to content

Commit

Permalink
Merge branch 'release/1.0.11' into v1
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Welch committed Aug 10, 2021
2 parents 3bba9f9 + 668fb10 commit 642fb48
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 47 deletions.
16 changes: 10 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
# Plugin Vite Changelog

## 1.0.11 - 2021.08.10
### Added
* Added [Preload Directives Generation](https://vitejs.dev/guide/features.html#preload-directives-generation) that will automatically generate `<link rel="modulepreload">` directives for entry chunks and their direct imports ([PR#2](https://github.com/nystudio107/craft-plugin-vite/pull/2))

## 1.0.10 - 2021.07.14
### Added
* Added a `craft.vite.devServerRunning()` method to allow you to determine if the Vite dev server is running or not from your Twig templates (https://github.com/nystudio107/craft-vite/issues/10)
* Added a `craft.vite.devServerRunning()` method to allow you to determine if the Vite dev server is running or not from your Twig templates ([#10](https://github.com/nystudio107/craft-vite/issues/10))

## 1.0.9 - 2021.07.14
### Changed
* Switched the `checkDevServer` test file to `@vite/client` to accommodate with the change in Vite `^2.4.0` to use the `.mjs` extension (https://github.com/nystudio107/craft-vite/issues/11)
* Switched the `checkDevServer` test file to `@vite/client` to accommodate with the change in Vite `^2.4.0` to use the `.mjs` extension ([#11](https://github.com/nystudio107/craft-vite/issues/11))

## 1.0.8 - 2021.06.29
### Changed
* Roll back the automatic inclusion of `@vite/client.js` (https://github.com/nystudio107/craft-vite/issues/9)
* Roll back the automatic inclusion of `@vite/client.js` ([#9](https://github.com/nystudio107/craft-vite/issues/9))

## 1.0.7 - 2021.06.28
### Changed
* Always include the `@vite/client.js` script if the dev server is running (https://github.com/nystudio107/craft-vite/issues/9)
* Always include the `@vite/client.js` script if the dev server is running ([#9](https://github.com/nystudio107/craft-vite/issues/9))

## 1.0.6 - 2021.05.21
### Added
* Added a `includeReactRefreshShim` setting that will automatically include the required [shim for `react-refresh`](https://vitejs.dev/guide/backend-integration.html#backend-integration) when the Vite dev server is running (https://github.com/nystudio107/craft-vite/issues/5)
* Added a `includeReactRefreshShim` setting that will automatically include the required [shim for `react-refresh`](https://vitejs.dev/guide/backend-integration.html#backend-integration) when the Vite dev server is running ([#5](https://github.com/nystudio107/craft-vite/issues/5))

### Changed
* Removed custom user/agent header that was a holdover from `curl`
Expand All @@ -43,7 +47,7 @@

## 1.0.3 - 2021.05.08
### Added
* Added the `devServerInternal` setting back in, along with `checkDevServer` for people who want the fallback behavior (https://github.com/nystudio107/craft-vite/issues/2)
* Added the `devServerInternal` setting back in, along with `checkDevServer` for people who want the fallback behavior ([#2](https://github.com/nystudio107/craft-vite/issues/2))

### Changed
* Refactored `extractCssFiles()` to be simpler
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "nystudio107/craft-plugin-vite",
"description": "Plugin Vite is the conduit between Craft CMS plugins and Vite, with manifest.json & HMR support",
"version": "1.0.10",
"version": "1.0.11",
"keywords": [
"craftcms",
"plugin",
Expand Down
41 changes: 40 additions & 1 deletion src/helpers/ManifestHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,25 @@ public static function extractManifestTags(string $path, bool $asyncCss = true,
continue;
}
// Include the entry script
$tagOptions = array_merge($scriptOptions, $scriptTagAttrs);
$tags[] = [
'type' => 'file',
'url' => $entry['file'],
'options' => array_merge($scriptOptions, $scriptTagAttrs)
'options' => $tagOptions
];
// Include any imports
$importFiles = [];
// Only include import tags for the non-legacy scripts
if (!$legacy) {
self::extractImportFiles(self::$manifest, $manifestKey, $importFiles);
foreach ($importFiles as $importFile) {
$tags[] = [
'crossorigin' => $tagOptions['crossorigin'] ?? true,
'type' => 'import',
'url' => $importFile,
];
}
}
// Include any CSS tags
$cssFiles = [];
self::extractCssFiles(self::$manifest, $manifestKey, $cssFiles);
Expand All @@ -167,6 +181,31 @@ public static function extractManifestTags(string $path, bool $asyncCss = true,
return $tags;
}

/**
* Extract any import files from entries recursively
*
* @param array $manifest
* @param string $manifestKey
* @param array $importFiles
*
* @return array
*/
protected static function extractImportFiles(array $manifest, string $manifestKey, array &$importFiles): array
{
$entry = $manifest[$manifestKey] ?? null;
if (!$entry) {
return [];
}

$imports = $entry['imports'] ?? [];
foreach ($imports as $import) {
$importFiles[] = $manifest[$import]['file'];
self::extractImportFiles($manifest, $import, $importFiles);
}

return $importFiles;
}

/**
* Extract any CSS files from entries recursively
*
Expand Down
145 changes: 106 additions & 39 deletions src/services/ViteService.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ class ViteService extends Component
*/
public $includeReactRefreshShim = false;

/**
* @var bool Whether the modulepreload-polyfill shim should be included
*/
public $includeModulePreloadShim = true;

// Protected Properties
// =========================================================================

Expand Down Expand Up @@ -160,7 +165,7 @@ public function devServerScript(string $path, array $scriptTagAttrs = []): strin
// Replace the hard-coded dev server URL with whatever they have theirs set to
$script = str_replace(
'http://localhost:3000/',
rtrim($this->devServerPublic, '/').'/',
rtrim($this->devServerPublic, '/') . '/',
$script
);
$lines[] = HtmlHelper::script(
Expand Down Expand Up @@ -199,6 +204,13 @@ public function manifestScript(string $path, bool $asyncCss = true, array $scrip
$legacyTags = ManifestHelper::legacyManifestTags($path, $asyncCss, $scriptTagAttrs, $cssTagAttrs);
// Include any manifest shims
if (!$this->manifestShimsIncluded) {
// Handle the modulepreload-polyfill shim
if ($this->includeModulePreloadShim) {
$lines[] = HtmlHelper::script(
FileHelper::fetchScript('modulepreload-polyfill.min.js', $this->cacheKeySuffix),
['type' => 'module']
);
}
// Handle any legacy polyfills
if (!empty($legacyTags)) {
$lines[] = HtmlHelper::script(
Expand All @@ -210,21 +222,7 @@ public function manifestScript(string $path, bool $asyncCss = true, array $scrip
}
$this->manifestShimsIncluded = true;
}
foreach(array_merge($tags, $legacyTags) as $tag) {
if (!empty($tag)) {
$url = FileHelper::createUrl($this->serverPublic, $tag['url']);
switch ($tag['type']) {
case 'file':
$lines[] = HtmlHelper::jsFile($url, $tag['options']);
break;
case 'css':
$lines[] = HtmlHelper::cssFile($url, $tag['options']);
break;
default:
break;
}
}
}
$lines = array_merge($lines, $this->manifestScriptTags($tags, $legacyTags));

return implode("\r\n", $lines);
}
Expand Down Expand Up @@ -272,7 +270,7 @@ public function devServerRegister(string $path, array $scriptTagAttrs = [])
// Replace the hard-coded dev server URL with whatever they have theirs set to
$script = str_replace(
'http://localhost:3000/',
rtrim($this->devServerPublic, '/').'/',
rtrim($this->devServerPublic, '/') . '/',
$script
);
$view->registerScript(
Expand Down Expand Up @@ -314,6 +312,15 @@ public function manifestRegister(string $path, bool $asyncCss = true, array $scr
$legacyTags = ManifestHelper::legacyManifestTags($path, $asyncCss, $scriptTagAttrs, $cssTagAttrs);
// Include any manifest shims
if (!$this->manifestShimsIncluded) {
// Handle the modulepreload-polyfill shim
if ($this->includeModulePreloadShim) {
$view->registerScript(
FileHelper::fetchScript('modulepreload-polyfill.min.js', $this->cacheKeySuffix),
$view::POS_HEAD,
['type' => 'module'],
'MODULEPRELOAD_POLYFILL'
);
}
// Handle any legacy polyfills
if (!empty($legacyTags)) {
$view->registerScript(
Expand All @@ -327,28 +334,7 @@ public function manifestRegister(string $path, bool $asyncCss = true, array $scr
}
$this->manifestShimsIncluded = true;
}
foreach(array_merge($tags, $legacyTags) as $tag) {
if (!empty($tag)) {
$url = FileHelper::createUrl($this->serverPublic, $tag['url']);
switch ($tag['type']) {
case 'file':
$view->registerJsFile(
$url,
$tag['options'],
md5($url . JsonHelper::encode($tag['options']))
);
break;
case 'css':
$view->registerCssFile(
$url,
$tag['options']
);
break;
default:
break;
}
}
}
$this->manifestRegisterTags($tags, $legacyTags);
}

/**
Expand Down Expand Up @@ -435,4 +421,85 @@ protected function injectErrorEntry()
// That's okay, Vite will have already logged the error
}
}


/**
* Iterate through all the tags, and return them
*
* @param array $tags
* @param array $legacyTags
* @return array
*/
protected function manifestScriptTags(array $tags, array $legacyTags): array
{
$lines = [];
foreach (array_merge($tags, $legacyTags) as $tag) {
if (!empty($tag)) {
$url = FileHelper::createUrl($this->serverPublic, $tag['url']);
switch ($tag['type']) {
case 'file':
$lines[] = HtmlHelper::jsFile($url, $tag['options']);
break;
case 'css':
$lines[] = HtmlHelper::cssFile($url, $tag['options']);
break;
case 'import':
$lines[] = HtmlHelper::tag('link', '', [
'crossorigin' => $tag['crossorigin'],
'href' => $url,
'rel' => 'modulepreload',
]);
break;
default:
break;
}
}
}

return $lines;
}

/**
* Iterate through all the tags, and register them
*
* @param array $tags
* @param array $legacyTags
* @throws InvalidConfigException
*/
protected function manifestRegisterTags(array $tags, array $legacyTags)
{
$view = Craft::$app->getView();
foreach (array_merge($tags, $legacyTags) as $tag) {
if (!empty($tag)) {
$url = FileHelper::createUrl($this->serverPublic, $tag['url']);
switch ($tag['type']) {
case 'file':
$view->registerJsFile(
$url,
$tag['options'],
md5($url . JsonHelper::encode($tag['options']))
);
break;
case 'css':
$view->registerCssFile(
$url,
$tag['options']
);
break;
case 'import':
$view->registerLinkTag(
[
'crossorigin' => $tag['crossorigin'],
'href' => $url,
'rel' => 'modulepreload',
],
md5($url)
);
break;
default:
break;
}
}
}
}
}
1 change: 1 addition & 0 deletions src/web/assets/dist/modulepreload-polyfill.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 72 additions & 0 deletions src/web/assets/src/modulepreload-polyfill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
The following polyfill function is meant to run in the browser and adapted from
https://github.com/guybedford/es-module-shims
MIT License
Copyright (C) 2018-2021 Guy Bedford
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*/

(function() {
const relList = document.createElement('link').relList;
if (relList && relList.supports && relList.supports('modulepreload')) {
return;
}

for (const link of document.querySelectorAll('link[rel="modulepreload"]')) {
processPreload(link);
}

new MutationObserver(mutations => {
for (const mutation of mutations) {
if (mutation.type !== 'childList') continue;
for (const node of mutation.addedNodes) {
if (node.tagName === 'LINK' && node.rel === 'modulepreload')
processPreload(node);
else if (node.querySelectorAll) {
for (const link of node.querySelectorAll('link[rel=modulepreload]')) {
processPreload(link);
}
}
}
}
}).observe(document, { childList: true, subtree: true });

function getFetchOpts (script) {
const fetchOpts = {};
if (script.integrity)
fetchOpts.integrity = script.integrity;
if (script.referrerpolicy)
fetchOpts.referrerPolicy = script.referrerpolicy;
if (script.crossorigin === 'use-credentials')
fetchOpts.credentials = 'include';
else if (script.crossorigin === 'anonymous')
fetchOpts.credentials = 'omit';
else
fetchOpts.credentials = 'same-origin';
return fetchOpts;
}

function processPreload(script) {
if (script.ep) {
// ep marker = processed
return;
}
script.ep = true;
// prepopulate the load record
const fetchOpts = getFetchOpts(script);
fetch(script.href, fetchOpts);
}
}());

0 comments on commit 642fb48

Please sign in to comment.