mariusbalcytis / webpack-bundle

Bundle to Integrate Webpack into Symfony
MIT License
122 stars 36 forks source link

Loading Images #7

Closed jorge-marques closed 7 years ago

jorge-marques commented 8 years ago

Can the webpack_asset function be used to load images?

mariusbalcytis commented 8 years ago

No, not out of the box.

The issue is that every webpack module is javascript file by default. So either you require('image.png') or put image.png as an entry point (read "inside webpack_asset function"), webpack generates javascript file with module.exports = 'file_path.png'; somewhere in it (and javascript is not valid picture file).

It could be possible if using additional plugins like extract-text-webpack-plugin (see this issue for discussion). It's already configured for css files in this bundle (see example in readme) - same story would go for images. I played a little with this idea - unfortulatelly, it looks like plug-in doesn't support binary content.

So, to make it work, one would need to:

  1. Make extract-text-webpack-plugin work with binary content
  2. Configure app/config/webpack.config.js to use it for images (possibly few instances of plugin may be needed - for images and css files)
  3. Pass second argument to webpack_asset to take correct file (not default JS one)

On the other hand, webpack is really brilliant when you are making single-page application. If that's the case, you can still use image loading with require inside your javascript files and add them dynamically when needed.

jorge-marques commented 8 years ago

Thank you for the quick reply. Yeah I did try and got a .js file as a result. I'm new to the whole symfony ecosystem. I am actually not working on an SPA, so i can't really require the image files. Do have any tips regarding the images? Ideally I'd like to keep them next to my other assets in /app/Resources/assets.

jorge-marques commented 8 years ago

This might be achievable with the copy-webpack-plugin. I'm unsure if the manifest plugin would pick up on these files though.

mariusbalcytis commented 8 years ago

No, as it's a plug-in, not a loader - it does not interfere with entry point loading, requiring other assets or handling webpack modules.

But it could be used - as it copies files, you could just point src to needed URL statically. This would mean hard-coded URLs, so you would not get automatic cache-busting.

maryo commented 8 years ago

I've created a loader+plugin to handle this scenario. https://github.com/vaniocz/entry-file-loader

It could be probably improved further (I couldn't find how to automatically get if it's an "entry asset". If it was possible then the PR would not be needed for this case). If this PR was merged https://github.com/mariusbalcytis/webpack-bundle/pull/11 then it would be possible to load images using {{ webpack_asset('entry-file!@admin/img/blank-avatar.png', 'png') }}

Maybe another twig function could be created for this purpose.

maryo commented 8 years ago

I've added two new functions to my fork. https://github.com/maryo/webpack-bundle/commit/a6ee447cebe2344aed9a4247215e89d52a8e7c13

webpack_css_asset for easier linking of css assets so you don't need a condition in template. it should by improved to support media attribute {{ webpack_css_asset('@admin/index.js') }}

webpack_file_asset for easier linking of images and other file assets using the mentiond loader, the webpack config template and package.json would need to change also <img src="{{ webpack_file_asset('@admin/images/blank-avatar.png') }}">

Let me know what you think. I'd add few tests and send a PR if interested.

mariusbalcytis commented 8 years ago

11 was merged - thanks for that, didn't realized that filters can be also applied to entry point files.

As I understand, loading images via webpack is needed for cache-busting? Or is there another use case?

They could also be optimized by some filter like image-webpack-loader - is !! really needed?

If it's common use-case, you could give a PR. I'd have some minor comments on it if you'd give it though.

maryo commented 8 years ago

Cache busting is one example. Possible usage of filters like image-loader is another good example. Very good example is that you can link to files from node_modules using this approach.

But the primary reason for me was that I simply didn't want to split the images into two folders - assets for CSS and public for HTML (when both relate to design of my site) or to have all images in public folder when the images linked from CSS using file-loader are then copied to compiled folder so they are public just for no purpose. Sometimes you want to even use the same asset like image once from CSS as a background and once from HTML. But in case of webpack and CSS you need to use a loader for the assets. Like file-loader which copies the files thus at the end the CSS uses different assets (copies) than those linked from HTML. It's actually not a problem in 95% of cases but it just feels weird :)

Another solution is to create a loader which would not use copies but it would somehow need to consider the directory structure change like ../../public/images -> ../bundles/xxx/images (probably different for dev-server) or something like this. The loader could be a part of this bundle since it would not have usage outside of it.

!! is needed because when file-loader is usually registered on png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot then it is invoked twice and this seemed like the easiest solution. Maybe it's not ideal though.

ehough commented 8 years ago

Just chiming in to express my support for this idea. I have a working configuration using the currently-published versions of both this bundle and entry-file-loader.

In my Twig templates I have:

<img src="{{ webpack_asset('@app/img/logo.png', 'png') }}" alt="logo">

and in my webpack config:

loaders: [
  {
    test: /\.(png|jpg|jpeg|gif)$/,
    loader: 'entry-file'
  }
  ...

This setup works perfectly: free cache busting and the possibility to insert additional loaders to the images if I want. I would image that the same procedure would work for non-image files, too.

maryo commented 8 years ago

It should work but I'm not sure it is the best approach to set the loader for all image files. The loader is then invoked for every image linked even from CSS/JS. But actually... maybe it's not a problem at all if you didn't encounter any performance issue (or simmilar).