jhthorsen / mojolicious-plugin-webpack

Integrate your mojo app with webpack
13 stars 7 forks source link

Consider adding asset like capabilities to handle images #12

Closed dmanto closed 3 years ago

dmanto commented 3 years ago

As per our Mojo IRC chat conversation, I prepared a minimal setup to work with, it is based on the webpack example of the M::P::Webpack distribution.

I think we need as a minimum a way to handle all assets handled by Assetpack, and that the migration be as automatic as possible.

As you explained at #mojo IRC, there are many ways for webpack to handle static files. So I made several cases, and prepared a github repo with some working and non-working branches here.

There are 4 cases:

1) master branch. A naive approach just using a 'assets/image/xxxxx.jpg' url for src attribute. Obviously it doesn't work, because there is no mechanism to actually copy the asset from the assets directory to the public one.

2) "using-copy-webpack-plugin" branch. That works, just need to know the place where the asset will go, but nothing complicated. Good luck with the caching gotcha although, as if you edit the image for some reason it will be difficult to reset all the cached old versions of an asset with the same name.

3) "use-hashed-name-on-images" branch. So if you include the [contenthash] as part of your asset url everything should work, except that it doesn't because you don't actually know the new name of the generated url's asset.

4) "parsing-stats-file" branch: I remember taking a look on the code, and it is based on DOM parsing the html file generated by the html-webpack-plugin.

Instead of that, I propose to parse the .json file with the stats object generated by Webpack at compilation. I use it only to extract url information on copied assets, please take a look on this branch and let me know what you think.

jhthorsen commented 3 years ago

I've gone a completely new direction with this project, since I've been wanting to clean up this code for a long time. The upcoming version can be found in #13. I would very much like some feedback.

The PR fixes this issue by parsing the stats file.

jhthorsen commented 3 years ago

Sorry for the long delay. For some reason, I find it harder to find time to do open source these days 😞

Anyway, this is fixed in 1.00 by simply not using any json or html parser at all, but rather just look at the filenames that exists in ./public/asset. I chose this solution, since it seems like that is the "hack" rollupjs uses in many of its plugins.

heikojansen commented 5 months ago

The following might be useful for other people who, like me, are struggling to understand just how (image) asset management and referencing could be made to work:

Following https://webpack.js.org/guides/asset-management/#loading-images I added

  config.module.rules.push({
    test: /\.(png|svg|jpg|jpeg|gif)$/i,
    type: 'asset/resource'
  });

and following https://webpack.js.org/guides/asset-modules/#resource-assets I added

config.output.assetModuleFilename = '[name].[hash][ext]';

to the webpack configuration.

Then I created [APP_ROOT]/assets/img/my.svg and added import './img/my.svg'; to [APP_ROOT]/assets/index.js.

Now when running webpack the SVG file got picked up and written to [APP_ROOT]/public/asset/my.[CHECKSUM].svg.

Also my SASS asset contains background-image: url('./img/my.svg'); and the generated CSS in the browser shows background-image: url('my.[CHECKSUM].svg');.

Dumping the asset_map in a Mojolicious template shows that an entry like this exists:

  "my.svg" => {
    "ext" => "svg",
    "helper" => "image",
    "mode" => "production",
    "mtime" => 1711099616,
    "name" => "my.svg",
    "path" => bless( do{\(my $o = "/[PATH_TO_APP_ROOT]/public/asset/my.[CHECKSUM].svg")}, 'Mojo::File' ),
    "rel_name" => "my.[CHECKSUM].svg"
  },

Now I could add %= asset 'my.svg' to my Mojolicious template and in the HTML delivered to the browser found <img src="/asset/my.a6eb8bea2d1367117b16.svg">.

It`s not quite perfect yet (e.g, what about the 'img' subdir?), but it looks like I might be on my way towards a viable solution.

If I failed to understand that there's some even easier way to work with (static) assets please share your knowledge since it took me quite a while to come up with the solution described above ...

Best Heiko