sabbelasichon / typo3_encore Goto Github PK
View Code? Open in Web Editor NEWUse Webpack Encore within TYPO3
License: Other
Use Webpack Encore within TYPO3
License: Other
I propose a different namespace for the viewhelpers by default. instead of e
use encore
.
advantages:
as those VH are not used that often in a project, the additional chars are IMO fine
Hi!
Great job!
May you post actual TYPO3 encore example?
Thanx!
I have two JavaScript entrypoints. One in the header via includeJSLibs
and one in the footer via includeJSFooter
. Both Entrypoints require runtime.js
. But this file is only included in the footer.
entrypoints.json
{
"entrypoints": {
"example1": {
"js": [
"/static/runtime.js",
"/static/example1.js"
]
},
"example2": {
"js": [
"/static/runtime.js",
"/static/example2.js"
]
}
}
}
TypoScript
page {
includeJSLibs {
example = typo3_encore:example1
example.disableCompression = 1
example.excludeFromConcatenation = 1
}
includeJSFooter {
example2 = typo3_encore:example2
example2.disableCompression = 1
example2.excludeFromConcatenation = 1
}
}
Generated HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="/static/example1.js"></script>
</head>
<body>
<script src="/static/runtime.js"></script>
<script src="/static/example2.js"></script>
</body>
</html>
This is incorrect. runtime.js
should only be included once, but in the header.
This issue is only related to dev-master.
When using $GLOBALS['TYPO3_CONF_VARS']['FE']['versionNumberInFilename'] = 'querystring'
, the frontend links assets with a version number added as query string. Since typo3-encore's middleware does not have the query string information at hand when creating the link
HTTP-header, it's missing there. Thus, after downloading the document, the browser then loads the linked resource from the document, in addition to the pushed one because it treats them as two files.
In turn, disabling TYPO3 versioning in conjunction with active webpack versioning (changing filename) leads to problems with missing assets when using long-lasting (24h) document caching policies, because assets linked in the cached document are not available anymore on the server.
So ideally TYPO3 versioning by query string should be regarded when creating the push link. Or it must be disabled but then cannot not be used in conjunction with document caching.
Since version 4 webpack-assets-manifest generate new structure:
Example:
{
"entrypoints": {
"main": {
"assets": {
"css": [
"main.css"
],
"js": [
"main.js"
]
},
"prefetch": {
"js": [
"prefetch.js"
]
},
"preload": {
"js": [
"preload.js"
]
}
}
}
}
And typo3_encore don't parse this:
page.includeJS {
main = typo3_encore:main
}
page.includeCSS {
main = typo3_encore:main
}
Dear Sebastian,
I follwed your usage instructions step by step and I was able to run the encore command, outputting the compiled files. Unfortunately, when rendering the frontend of my TYPO3 site, an exception is thrown:
The build "_default" is not configured
Ssch\Typo3Encore\Asset\UndefinedBuildException thrown in file
/var/www/html/private/typo3conf/ext/typo3_encore/Classes/Asset/EntrypointLookupCollection.php in line 57.
Where has a "build" to be created and what does a "build" look like? Is it a folder or a file? I tried configuring it in the plugin settings and referencing to a EXT:EXTENSIONNAME/Resources/Public folder, but it still said that this build is not configured.
Thanks in advance,
Christian Rohleder
Maybe it is a conceptional problem on my part, but I have the following scenario:
I use Webpack Encore + Vue in some Backend Modules - in different standalone extensions. Right now I have to resort to squashing everything into one entry file (let's say mymodule.js and render that using the Page Renderer in my BE Module and I have to include a <script> Tag for the dev-server eith HMR as the PageRenderer struggles with http:// includes).
I'd love to use typo3_encore for this, but I already use it for my Frontend Build and therefore already have an entrypoints.json somewhere.
I can't include the BE sources in this as they are basically microbuilds for every different BE module.
It would therefore be awesome if I could specify multiple entrypoint.json instead of the single one in the constants. Then I could use typo3_encore to render my specific module entrypoints/manifests..
Am I missing something or could this be a useful feature request?
If there is the TypoScript setting config.doctype = html5 we don't want to have the type 'text/javascript' in the script tags.
It works fine via TypoScript including of JS files, but not when using the ViewHelper inside Fluid templates to include scripts.
The TYPO3 extension manager shows version 3.0.4, although version 3.0.8 is installed in reality.
I guess ext_emconf.php was not updated before the release/tag.
In current dev-master, all entry point files are being pushed. However, if I use different entry points on one page, for example one which is critical and another one which is not, I would like an option to select which assets shall be pushed. Another use case is that I might want css to be pushed but not js.
So maybe an option to enable/disable pushing for an asset would be nice. This could be achieved by defining a boolean, e.g. enableHttp2Push
(which defaults to true) that can be passed as "false" to additionalParameters
in the ViewHelper to disable it.
TYPO3 version: 10.4.18
Ext. version: 3.0.9
A maybe common configuration of this ext might lead to adding "/" prefix to attribute values.
Assuming there is an encore config that writes files to the js/ directory (see example below) inside the Resources/Public folder. When there is a css class named "js-toggle", that class would become "/js-toggle".
This is because of the Ssch\Typo3Encore\Asset\TagRenderer::addAdditionalAbsRefPrefixDirectories
method.
I'm not quite sure, what this method should actually archive (except the obvious adding the relative path to additionalAbsRefPrefixDirectories) so I cannot provide a fix for this.
Steps to reproduce:
class="/js-toggle"
Example webpack configuration:
const Encore = require('@symfony/webpack-encore');
if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}
Encore
.setOutputPath('packages/site/Resources/Public')
.setPublicPath('/typo3conf/ext/site/Resources/Public')
.setManifestKeyPrefix('');
Encore.addEntry('js/app', './packages/site/Resources/Private/Build/js/app.js');
module.exports = Encore.getWebpackConfig();
Use the method setArgumentsUnderTest in all tests classes for ViewHelpers.
Currently it's not possible to use CSS files generated by TYPO3 Encore as files for RTE.
The CSS for RTE is configured in Yaml-Files:
editor:
config:
# Include custom CSS
contentsCss: "EXT:my_extension/Resources/Public/Css/rte.css"
TYPO3 Documentation for RTE
ckeditor Documentation regarding contentsCss
I would expect, that I can use typo3_encore:rte
for the entrypoint rte
. But this is not changed/processed by TYPO3 Encore.
I am not sure, if this is a bug or a feature request, because TYPO3 Encore should not be used for RTE CSS.
If it should work, I think the best way is to add a Form Data Provider, which changes the contentsCss
value:
// ext_localconf.php
$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['tcaDatabaseRecord'][\Vendor\Example\Form\FormDataProvider\RichtextEncoreConfiguration::class] = [
'depends' => [
\TYPO3\CMS\Backend\Form\FormDataProvider\TcaText::class,
],
];
The DataProvider could look like this:
<?php
declare(strict_types = 1);
namespace Vendor\Example\Form\FormDataProvider;
use Ssch\Typo3Encore\Asset\EntrypointLookupCollectionInterface;
use Ssch\Typo3Encore\Asset\EntrypointLookupInterface;
use TYPO3\CMS\Backend\Form\FormDataProviderInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Convert typo3_encore for contentCss
*/
class RichtextEncoreConfiguration implements FormDataProviderInterface {
public function __construct(EntrypointLookupCollectionInterface $entrypointLookupCollection) {
$this->entrypointLookupCollection = $entrypointLookupCollection;
}
/**
* @param array $result Given result array
* @return array Modified result array
*/
public function addData(array $result): array {
foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
if (empty($fieldConfig['config']['type']) || $fieldConfig['config']['type'] !== 'text') {
continue;
}
if (!isset($fieldConfig['config']['enableRichtext']) || (bool)$fieldConfig['config']['enableRichtext'] !== true) {
continue;
}
$rteConfiguration = $fieldConfig['config']['richtextConfiguration'];
// replace contentsCss with correct path
if ($rteConfiguration['editor']['config']['contentsCss']) {
$contentsCss = $rteConfiguration['editor']['config']['contentsCss'];
if (str_starts_with($contentsCss, 'typo3_encore:')) {
// strip prefix
$contentsCss = substr($contentsCss, strlen('typo3_encore:'));
[$buildName, $entryName] = GeneralUtility::trimExplode(':', $contentsCss, true, 2);
if (!$entryName) {
$entryName = $buildName;
$buildName = EntrypointLookupInterface::DEFAULT_BUILD;
}
$entryPointLookup = $this->entrypointLookupCollection->getEntrypointLookup($buildName);
$contentsCss = $entryPointLookup->getCssFiles($entryName);
$result['processedTca']['columns'][$fieldName]['config']['richtextConfiguration']['editor']['config']['contentsCss'] = $contentsCss;
}
}
}
return $result;
}
}
If a TYPO3 installation has bitmotion/secure-downloads installed and the file is requested to download by an user an exception is thrown.
Asset manifest file "" does not exist.
in /typo3conf/ext/typo3_encore/Classes/Asset/JsonManifestVersionStrategy.php line 79
It seems like the needed TypoScript is not included.
I would like to create preload links in my page's <head>
to preload e.g. fonts which are deeply nested within my CSS and would therefore be loaded quite late.
Example:
<link rel="preload" href="fonts/cicle_fina-webfont.woff2" as="font" type="font/woff2" crossorigin>
(taken from here)
Unfortunately when using webpack-encore in production mode, font files are versioned, so the path to the built font asset cannot be hard-coded.
That's why it would be very useful to have a ViewHelper which I could feed e.g. the original file path and then it looks up the actual path to the built font and renders the link tag dynamically.
Note: Currently, as a workaround, I disabled versioning for fonts in my webpack.config to be able to hard-code preload tags.
// disable versioning for fonts to allow preloading
.configureFilenames({
fonts: 'fonts/[name].[ext]'
})
For Dev Hotreload server i need set like this:
plugin.tx_typo3encore {
settings {
entrypointJsonPath = //dev.xxxxxx.com:8080/entrypoints.json
manifestJsonPath = //dev.xxxxxx.com:8080/manifest.json
}
}
By default this don't work.
How realize this idea?
Today iam use this hack:
[applicationContext == "Development"]
page.includeJS {
app = //dev.xxxxxx.com:8080/js/app.js
# app = typo3_encore:app
app.type = module
app.external = 1
}
page.includeCSS {
}
[end]
PHP Warning: Undefined array key "doctype" in /var/www/html/public/typo3conf/ext/typo3_encore/Classes/Asset/TagRenderer.php line 253
The Problem is already solved in dev-master, but not released.
Is there anything that should be tested for PHP 8 where I can eventually help to speed up the new version release?
config.absRefPrefix = https://domain.com/foo/
the header "This file is part of the TYPO3 CMS project." is not correct within this project
The link header is currently not passed when the page is generated from cache.
Steps to reproduce:
When I have two CSS files on a page, the order is different when the first is included via typo3_encore and the other via TYPO3.
TypoScript without typo3 encore:
page {
includeCSS {
example = EXT:example/Resources/Public/static/example1.css
example.disableCompression = 1
example.excludeFromConcatenation = 1
example2 = EXT:example/Resources/Public/static/example2.css
example2.disableCompression = 1
example2.excludeFromConcatenation = 1
}
}
Output in HTML:
<link rel="stylesheet" href="/static/example1.css?1621689390">
<link rel="stylesheet" href="/static/example2.css?1621689423">
When the first CSS is included via typo3_encore:
page {
includeCSS {
example = typo3_encore:example1
example = EXT:example/Resources/Public/static/example1.css
example.disableCompression = 1
example.excludeFromConcatenation = 1
example2 = EXT:example/Resources/Public/static/example2.css
example2.disableCompression = 1
example2.excludeFromConcatenation = 1
}
}
Now the order is different:
<link rel="stylesheet" href="/static/example2.css?1621689423">
<link rel="stylesheet" href="/static/example1.css">
This might break stuff, because the order is important.
This happens, because the PageRendererHooks::renderPreProcess
adds the files at the end of the array instead of replacing the key.
The error also occurs with JavaScript files.
The latest release is called v2.0.9 and comes with 'version' => '2.2.0',
in the ext_emconf.php file.
Also the previous version v2.0.8 doesn't match the emconf version. That's confusing. It would be great if they match in future.
some more files should be excluded like all dot files, phpstan.neon
When I try to include js/css via EXT:typo3_encore in a BackendModule I get the following error (TYPO3 8.7):
#1476107295: PHP Warning: file_get_contents(/var/www/html/htdocs/typo3/typo3temp/assets/compressed/external-77c5661ecec798f0ac007291224fa800): failed to open stream: No such file or directory in /var/www/html/vendor/typo3/cms/typo3/sysext/core/Classes/Resource/ResourceCompressor.php line 287 (More information)
Happens using any of the methods mentioned below:
<f:be.container
includeCssFiles="{0: 'typo3_encore:tx_myext_backendModule:backend-module'}"
includeJsFiles="{0: 'typo3_encore:tx_myext_backendModule:backend-module'}">
</f:be.container>
and
$pageRenderer->addJsFooterFile('typo3_encore:tx_myext_backendModule:backend-module')
If I try to include it using the ViewHelpers - nothing at all gets included:
<e:renderWebpackScriptTags entryName="backend-module" buildName="tx_myext_backendModule"></e:renderWebpackScriptTags>
TypoScript Setup (ext_typoscript_setup.txt):
module.tx_typo3encore {
settings {
builds {
tx_myext_backendModule = EXT:my_ext/Resources/Public/Build
}
}
}
It does try to look it up, when I set an invalid build name or entryPoint the extension throws an exception like expected.
Any ideas?
thanks for the extension! one thing should be highlighted in the docs is the usage of the caching framework. switching different modes like dev, hotreload, production on same environment will lead to a broken frontend because the cache will still hold the previous paths which won't exist anymore.
One option is to use
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'][\Ssch\Typo3Encore\Integration\CacheFactory::CACHE_KEY]['backend'] = \TYPO3\CMS\Core\Cache\Backend\NullBackend::class;
or maybe even remove the cache completly? as it is a filecache anyway I don't see much benefits in getting the real entrypoint file or the file from the caching framework?
hi
A question: is there a way to put some css endpoint as inline_css?
Why?
REASON 1:
The reason is the Google PageSpeed Insights test called "Preload key requests". Its telling about font preload.
I know I can use <link rel=preload>
or push the fonts with http2
headers (I use it for woff2)
Unfortunately the problem is that Google PageSpeed Insights is also requesting other font types to be preloaded like woff, ttf, eof. This has no big sense to download all this font types if browser use only one.
I noticed that if I put in <head>
a <style>
with font-face definitions then Google PageSpeed Insights no longer require to preload any fonts. That has some sense because the information what to download is on the very beginning of HTML - no css file needs to be downloaded to start to download right font file.
REASON 2:
Sometimes there is a need to have critical inline css to draw a content as fast as possible (menu, header elements) to have good score on First Contentful Paint (FCP).
btw: thank you for this nice extension.
If I am using allWrap
to wrap an entrypoint I might expect that the wrap is only generated once and wraps all script tags for a single entrypoint. That is currently not the case:
page {
includeJS {
example = typo3_encore:example1
example.disableCompression = 1
example.excludeFromConcatenation = 1
example.allWrap = <!-- Before -->|<!-- After -->
}
}
Generated HTML:
<!-- Before --><script src="/static/runtime.js"></script><!-- After -->
<!-- Before --><script src="/static/example1.js"></script><!-- After -->
Expected HTML:
<!-- Before --><script src="/static/runtime.js"></script>
<script src="/static/example1.js"></script><!-- After -->
This could be achieved, if the allWrap
is split up into two parts and the first part is applied to the first script tag and the second part is applied to the last script tag like this:
page {
includeJS {
runtime = static/runtime.js
runtime.disableCompression = 1
runtime.excludeFromConcatenation = 1
runtime.allWrap = <!-- Before -->|
example1 = static/example1.js
example1.disableCompression = 1
example1.excludeFromConcatenation = 1
example1.allWrap = |<!-- After -->
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.