sabbelasichon / typo3_encore

Use Webpack Encore within TYPO3
Other
106 stars 19 forks source link

Add cache buster parameter for the SVG Viewhelper #174

Open sabbelasichon opened 1 year ago

sabbelasichon commented 1 year ago

Relates: https://github.com/sabbelasichon/typo3_encore/pull/169

georgringer commented 1 year ago

some more input here:

sabbelasichon commented 1 year ago

Thanks. I would say if you are using the asset viewhelper encore knows about the versioned svg. If you are using the SvgViewhelper as it is the parameter can be useful in either way.

kszymukowicz commented 1 year ago

For me following config works. The sprite have hash and TYPO3 is using this hash.

Encore.addLoader({
  test: /\.svg$/,
  loader: 'svg-sprite-loader',
  options: {
      extract: true,
      spriteFilename: "sprite.[hash].svg",
  }
}).addPlugin(new SpritePlugin())
kszymukowicz commented 1 year ago

Sorry. Actually my test was a bit wrong because I tested on my modified version of code. In SvgViewHelper I have modification. I am not sure it nice version but at least this works well with:

  1. watch mode for svg-sprite-loader
  2. build mode with hash in filename of sprite.svg (spriteFilename: "sprite.[hash].svg")
try {
            $image = $this->imageService->getImage($this->arguments['src'], null, false);
            $imageUri = $this->imageService->getImageUri($image, (bool)$this->arguments['absolute']);
            $imageContents = $image->getContents();
        } catch (FolderDoesNotExistException $folderDoesNotExistException) {
            $imageUri = GeneralUtility::makeInstance(PackageFactory::class)->getPackage(EntrypointLookupInterface::DEFAULT_BUILD)->getUrl($this->arguments['src']);
            if (filter_var($imageUri, FILTER_VALIDATE_URL)) {
                $imageContents = GeneralUtility::getUrl($imageUri);
            } else {
                $imageContents = $this->filesystem->get(Environment::getPublicPath() . $imageUri);
            }
        }
sabbelasichon commented 1 year ago

@kszymukowicz Would you like to create a PR for this?

kszymukowicz commented 1 year ago

@sabbelasichon

As far as I remember I finally had no 100% working solution. I started to doubt that anyone really use this svg-sprite-loader with TYPO3 Encore ;)

The two main drawbacks that makes this solution unusable are:

  1. I could not make the svg sprite to be used in scss
  2. The use of svg in watch mode was forbidden because it the svg url there is different port and because of that we have browser error "Unsafe attempt to load URL URL/TO/SVG.svg. Domains, protocols and ports must match.". I made some fast hack for this and put some PHP wrapper that reads the svg on the same port but that needs a special php file and htaccess/vhost modification only for watch mode. I am not sure such hack can be part of final solution.

I think a svg-sprite replace could be to inline the svg in css file with base64. Sure base64 makes the svg to take more space inside css file but there are some packages like this https://github.com/bhovhannes/svg-url-loader that makes possible to not use base64 and still have svg in css file.

I did not tested that yet fully but I think I will use it over svg-sprite-loader which makes too much problems - at least for me.

kszymukowicz commented 1 year ago

I just investigated a bit. So when someone would consider using inline svg (data:image/svg+xml) instead of some svg-sprite then here are two working configurations:

1) when using pure encore add just

     .configureImageRule({
         type: 'asset',
     })

It will inline all assets (like gif, jpg, svg) smaller than 4kB to CSS using base64.

2) or install npm install svg-url-loader --save-dev and code below. This will inline only svg and utf-8 instead of base64.

     .addRule({
       test: /\.svg$/,
       use: [
        {
          loader: 'svg-url-loader',
        },
       ],
       type: 'javascript/auto',
      })

You can also use both settings together. Then for svg the 'svg-url-loader' will be used and standard webpack for rest assets. Tested with @symfony/webpack-encore v4.2.0.