Idea-php-symfony2-plugin: Missing assets in Twig autocompletation when using manifest.json and Webpack-Encore versioning

Created on 13 Sep 2017  路  3Comments  路  Source: Haehnchen/idea-php-symfony2-plugin

I configured my project to use webpack encore to handle assets with versioning following this guide, but twig can't suggest me the correct file.

My configuration is this:

in config.yml I have put this:

framework:
    assets:
        json_manifest_path: '%kernel.project_dir%/web/build/manifest.json'

in my webpack.config.js I have this

.enableVersioning()

to enable versioning.

after running encore, my manifest.json become like this

{
  "build/app.js": "/build/app.177225afbc8589c7cfb4.js",
  "build/global.css": "/build/global.d41d8cd98f00b204e9800998ecf8427e.css"
}

this map my assets name to a new name with the version number. But obviously this change every time I edit my assets and run encore. Symfony knows how to handle this by reading the manifest.json file and place the mapped name of the asset (to better understand this read the guide).
But in any of my twig templates, the plugin can suggest me only the assets with the version number because they are the only who _phisically_ exist.

I think it would be useful if the plugin can understand I'm using a manifest.json and suggest me the general asset name instead of alert of a missing asset.

missingasset

let me know if you understand the problem
thank you

Lorenzo

Most helpful comment

This is how I solved:

In your main JS file (where you define all require()):

const imagesCtx = require.context('../images', true, /\.(png|jpg|jpeg|gif|ico|svg|webp)$/);
imagesCtx.keys().forEach(imagesCtx);

This isn't strictly necessary to fix your issue, but it forces Encore to copy all image files over to public/build/assets/images/ directory. Otherwise, it only handles image files linked in your JS or CSS/SCSS files.

In your webpack.config.js:

var Encore = require('@symfony/webpack-encore');

Encore
    .setOutputPath('public/build/')
    .setPublicPath('/build')
    .addEntry('app', './assets/js/app.js')
    .enableSassLoader(function(sassOptions) {}, {
        resolveUrlLoader: false
    })
    .autoProvidejQuery({
        $: 'jquery',
        jQuery: 'jquery'
    })
    .enableSourceMaps(!Encore.isProduction())
    .cleanupOutputBeforeBuild()
    .enableVersioning(Encore.isProduction())
    .enableBuildNotifications()
;

if (Encore.isProduction()) {
    Encore.configureFilenames({
        images: '[path][name].[hash:8].[ext]',
        fonts: '[path][name].[hash:8].[ext]'
    });
} else {
    Encore.configureFilenames({
        images: '[path][name].[ext]',
        fonts: '[path][name].[ext]'
    });
}

module.exports = Encore.getWebpackConfig();

The important part is the if/else:

if (Encore.isProduction()) {
    Encore.configureFilenames({
        images: '[path][name].[hash:8].[ext]',
        fonts: '[path][name].[hash:8].[ext]'
    });
} else {
    Encore.configureFilenames({
        images: '[path][name].[ext]',
        fonts: '[path][name].[ext]'
    });
}

If in dev, do not use hashes; if in prod, use hashes.

Of course make sure .enableVersioning(Encore.isProduction()) is set.

All 3 comments

Have same issue. Also there is another problem: project with remote sources by sftp, encore runned on remote server (actually docker) - and manifest.json should be downloaded on each rebuild.

Have the same problem, the issue is that the manifest file is not checked by the Symfony Plugin. On the hard drive the filename contains also the hash, so it never finds it.

This is a new feature, any plans or ETA for implementing it?

This is how I solved:

In your main JS file (where you define all require()):

const imagesCtx = require.context('../images', true, /\.(png|jpg|jpeg|gif|ico|svg|webp)$/);
imagesCtx.keys().forEach(imagesCtx);

This isn't strictly necessary to fix your issue, but it forces Encore to copy all image files over to public/build/assets/images/ directory. Otherwise, it only handles image files linked in your JS or CSS/SCSS files.

In your webpack.config.js:

var Encore = require('@symfony/webpack-encore');

Encore
    .setOutputPath('public/build/')
    .setPublicPath('/build')
    .addEntry('app', './assets/js/app.js')
    .enableSassLoader(function(sassOptions) {}, {
        resolveUrlLoader: false
    })
    .autoProvidejQuery({
        $: 'jquery',
        jQuery: 'jquery'
    })
    .enableSourceMaps(!Encore.isProduction())
    .cleanupOutputBeforeBuild()
    .enableVersioning(Encore.isProduction())
    .enableBuildNotifications()
;

if (Encore.isProduction()) {
    Encore.configureFilenames({
        images: '[path][name].[hash:8].[ext]',
        fonts: '[path][name].[hash:8].[ext]'
    });
} else {
    Encore.configureFilenames({
        images: '[path][name].[ext]',
        fonts: '[path][name].[ext]'
    });
}

module.exports = Encore.getWebpackConfig();

The important part is the if/else:

if (Encore.isProduction()) {
    Encore.configureFilenames({
        images: '[path][name].[hash:8].[ext]',
        fonts: '[path][name].[hash:8].[ext]'
    });
} else {
    Encore.configureFilenames({
        images: '[path][name].[ext]',
        fonts: '[path][name].[ext]'
    });
}

If in dev, do not use hashes; if in prod, use hashes.

Of course make sure .enableVersioning(Encore.isProduction()) is set.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

piegus picture piegus  路  3Comments

ostrolucky picture ostrolucky  路  4Comments

RikudouSage picture RikudouSage  路  6Comments

stephanvierkant picture stephanvierkant  路  3Comments

stof picture stof  路  6Comments