webpack-encore icon indicating copy to clipboard operation
webpack-encore copied to clipboard

versioned icons not found in the manifest.json in PWA configuration using .configureManifestPlugin

Open MarlonAEC opened this issue 4 years ago • 5 comments

Hi I have active the .enableVersioning() option in my webpack.config.js file and I also configured the seed key/values for my PWA using .configureManifestPlugin like this:

var Encore = require('@symfony/webpack-encore');
var ManifestPlugin = require('webpack-manifest-plugin');
var OfflinePlugin = require('offline-plugin');
const CopyPlugin = require('copy-webpack-plugin');

if (!Encore.isRuntimeEnvironmentConfigured()) {
    Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}

Encore
    // directory where compiled assets will be stored
    .setOutputPath('public/build/')
    // public path used by the web server to access the output path
    .setPublicPath('/build')
    // only needed for CDN's or sub-directory deploy
    //.setManifestKeyPrefix('build/')

    .addEntry('app', './assets/js/app.js')
    .addEntry('sw', './assets/js/serviceWorker.js')

    .splitEntryChunks()

    .disableSingleRuntimeChunk()

    .cleanupOutputBeforeBuild()
    .enableBuildNotifications()
    .enableSourceMaps(!Encore.isProduction())

//ENABLING VERSIONING HERE
    .enableVersioning(Encore.isProduction())

    .configureBabelPresetEnv((config) => {
        config.useBuiltIns = 'usage';
        config.corejs = 3;
    })
    .configureBabel(function(babelConfig){
        babelConfig.plugins.push("@babel/plugin-proposal-class-properties");
    })
    .enableSassLoader()

    .autoProvidejQuery()
    .enableReactPreset()

//COPYING THE HASHED ICONS TO THE PUBLIC FOLDER I REALLY DON'T KNOW IF THERE IS ANOTHER WAY TO DO THIS
    .copyFiles(
        {
            from: './assets/img/icons',
            to: 'images/icons/[path][name].[hash:8].[ext]',
            pattern: /\.(png|jpg|jpeg)$/
        }
    )
//ADDING PWD KEYS TO MANIFEST.JSON
    .configureManifestPlugin( (options) =>{
        options.seed = {
            "name": "bla bla bla",
            "short_name": "bla",
            "display": "standalone",
            "start_url": ".",
            "background_color": "#fff",
            "theme_color": "#1c97b0",
            "orientation": "portrait-primary",
            "icons": [
                {
                    "src": "/build/images/icons/icon-512x512.png", //IS THIS THE CORRECT URL???????
                    "type": "image/png",
                    "sizes": "512x512"
                },
                {
                    "src": "/build/images/icons/icon-192x192.png", //IS THIS THE CORRECT URL???????
                    "type": "image/png",
                    "sizes": "192x192"
                }
            ]
          }        
    })
   
    var config = Encore.getWebpackConfig();
 
    config.plugins.push(new OfflinePlugin({
        "strategy": "changed",
        "responseStrategy": "cache-first",
        "publicPath": "/build/",
        "caches": {
            "main": [
                '*.json',
                '*.css', 
                '*.js',
                'img/*'
            ]
        },
        "ServiceWorker": {
            "events": !Encore.isProduction(),
            "entry": "./assets/js/serviceWorker.js",
            "cacheName": "Reysis",
            "navigateFallbackURL": '/',
            "minify": !Encore.isProduction(),
            "output": "./../sw.js",
            "scope": "/"
        },
        "AppCache": null
    }));
;

module.exports = Encore.getWebpackConfig();

my final manifest.json is this

{
  "name": "bla bla bla",
  "short_name": "bla",
  "display": "standalone",
  "start_url": ".",
  "background_color": "#fff",
  "theme_color": "#1c97b0",
  "orientation": "portrait-primary",
  "icons": [
    {
      "src": "/build/images/icons/icon-512x512.png",
      "type": "image/png",
      "sizes": "512x512"
    },
    {
      "src": "/build/images/icons/icon-192x192.png",
      "type": "image/png",
      "sizes": "192x192"
    }
  ],
  "build/app.css": "/build/app.css",
  "build/app.js": "/build/app.js",
  "build/sw.js": "/build/sw.js",
  "build/vendors~app.css": "/build/vendors~app.css",
  "build/vendors~app.js": "/build/vendors~app.js",
  "build/vendors~app~sw.js": "/build/vendors~app~sw.js",
  "build/images/icons/icon-192x192.png": "/build/images/icons/icon-192x192.3d157c59.png",
  "build/images/icons/icon-512x512.png": "/build/images/icons/icon-512x512.b6511709.png"
}

but I got a not found icon in the browser when trying to load icons from the manifest,... My question is: Is this the correct way to add my PWA settings to the manifest.json? or ... Is it necessary to add the hash to the icons inside the .configManifestPlugin in the seed option? I am a little new using Encore, maybe I am doing something wrong, sorry for the inconvenience and thanks in advance...

I'm using Reactjs for the Frontend

MarlonAEC avatar Jul 02 '20 15:07 MarlonAEC

Hi,

You are confusing the manifest.json from Webpack Manifest Plugin and the manifest.json for PWA. They don't have the same goals and can not be "merged" in a single manifest.json file.

As a workaround, you can configure the manifest.json filename used by Webpack:

Encore.
  .configureManifestPlugin(options => {
    options.fileName = 'webpack-manifest.json';
  })

If you are using Symfony with the Symfony Webpack Encore Bundle, you will have to configure framework.assets.json_manifest_path to target the new webpack-manifest.json file.


The URL you use in your manifest.json file is not correct, you should not use build/images/icons/icon-192x192.png but /build/images/icons/icon-192x192.3d157c59.png.

But the hash 3d157c59 is not predictable, so you can't use a raw value here.

You can disable the hash for images by using Encore.configureFilenames():

Encore
  .configureFilenames({
    images: 'images/[name].[ext]'
  })

I'm not a big fan, a better solution would be to generate your PWA's manifest.json after Webpack has built entries (or resolved entries names). This way you will be able to use something like this:

Encore.addPlugin(MyPlugin([
  {
    name: 'manifest.json',
    content(webpackEntries) {
      const json = {
        // ...
        'icons': [
          {
            'src': webpackEntries['build/images/icons/icon-512x512.png'], // should resolve to /build/images/icons/icon-512x512.b6511709.png
            'type': 'image/png',
            'sizes': '512x512',
          },
          {
            'src': webpackEntries['build/images/icons/icon-192x192.png'], // should resolve to /build/images/icons/icon-192x192.3d157c59.png
            'type': 'image/png',
            'sizes': '192x192',
          },
        ],
      };

      return JSON.stringify(json, null, 2);
    },
  },
]);

I don't think such a plugin exists, but you can create your own I guess.

Kocal avatar Jul 02 '20 15:07 Kocal

@Kocal Thanks for the answer it help me a lot to understand the differences between the both manifest and I solve the first part of the problem.... the second part well... is there some place where I can read more about how to solve it?? also I was inspecting using the dev tools and I saw that in the Sources tab, the images folder is not there... but if I check the public path it is beeing copied to that location due the .copyFile() function in the webpack.config.js file... is this normal?? could this be part of the problem?? Cheers!!

MarlonAEC avatar Jul 02 '20 17:07 MarlonAEC

Ah! Sorry, I didn't see you used .copyFiles!

Then you can use instead:

Encore
    .copyFiles(
        {
            from: './assets/img/icons',
            to: 'images/icons/[path][name].[ext]',
            pattern: /\.(png|jpg|jpeg)$/
        }
    )

Kocal avatar Jul 02 '20 19:07 Kocal

Project made with TypeScript, react.Js, React-native. Recycling day design

https://github.com/Rodrigo001-de/Projeto-Ecoleta-advanced

Rodrigo001-dev avatar Jul 03 '20 01:07 Rodrigo001-dev

Other solution to copy manifest.json PWA into build folder :

Encore
.addPlugin(new CopyWebpackPlugin({
        patterns: [
            { from: './assets/icon_pwa', to: 'icon_pwa' },
            { from: './assets/manifest.json', to: path.resolve(__dirname, 'public/build', 'manifest.json') }
        ],
    }))

FlorianLeMenn avatar Feb 03 '22 08:02 FlorianLeMenn