Middleman and Webpack: Is there a way to get the chunkhash of generated bundles?

Hello,

I’m planning to build a static website using Middleman. So far I’ve seen it’s awesome. I’ve decided to use Webpack in order to manage the assets, like javascript, css, etc. Among other things, Webpack has a really cool feature that allows to add an unique hash in the filename for each chunk generated, so that you can just cache the assets for a really long time without worring that the cache would get stale when you update the site, because in that new version filename would be different.

Here is the problem: is there a way to reference the generated filename in the Middleman template files so that I could include them?

Thanks in advance.

Hi @dorellang, if you use the asset helpers in the layout it’ll have access to the hashed assets when a build is run. The documentation has more here: https://middlemanapp.com/basics/helper_methods/#asset-helpers.

Thank you, that’s enough for me :slight_smile:

Cheers.

Did this answer your query?

As far as the question you seemed to want to create hashes inside Webpack

i.e. filename: ‘assets/stylesheets/all.bundle.[hash].css’,

and then call these back into Middleman…

I dont believe the asset helpers can achieve this - please provide code to resolve this question if acheived.

Hello,

It’s been a while, but in the meantime I think I’ve found a fairly elegant way to solve this. It’s not rocket science…actually I’m just ripping off the idea from this project.

So this is what you do:

  • Install the webpack-stats-plugin. If you’re using NPM, do: npm i webpack-stats-plugin. Naturally if using Yarn, just do yarn add webpackstats-plugin instead.

  • Import the plugin in the webpack.config.js file and add it to the plugin list:

    var StatsWriterPlugin = require("webpack-stats-plugin").StatsWriterPlugin
    ...
    module.exports = {
    ...
      plugins = [
        new StatsWriterPlugin(),
        ...
      ],
    ...
    }
    

    This will create Webpack stats.json file in the output path. This file contains a list with all the generated chunks.

  • Let’s say you’ve configured Webpack and Middleman to use the ‘.tmp/dist’ output, then this helper would do the trick. Create the helpers/webpack_stats_loader.rb file with the following content:

    require 'json'
    
    module WebpackStatsLoader
    
      def webpack_stats
        return @webpack_stats if @webpack_stats
        File.open('.tmp/dist/stats.json') do |stats_file|
          stats = JSON.load(stats_file)
          @webpack_stats = stats
        end
      end
    
      def link_webpack_css_chunk(chunkname)
        output = StringIO.new
        [*webpack_stats["assetsByChunkName"][chunkname]].each do |assets|
          css_assets = [*assets].select { |filename| filename =~ /.css$/ }
          css_assets.each do |filename|
            output << "<link rel='stylesheet' href='/#{filename}'>"
          end
        end
        output.string
      end
    
      def link_webpack_js_chunk(chunkname)
        output = StringIO.new
        [*webpack_stats["assetsByChunkName"][chunkname]].each do |assets|
          js_assets = [*assets].select { |filename| filename =~ /.js$/ }
          js_assets.each do |filename|
            output << "<script src='/#{filename}'></script>"
          end
        end
        output.string
      end
    
    end
    
  • Finally to include a Webpack chunk in your layout just call the link_webpack_css_chunk or the link_webpack_js_chunk method in the template:

    <!-- this will output a <script> tag -->
    <%= link_webpack_js_chunk 'entry_name' %>
    
    <!-- while this will output a <link rel="stylesheet"...> tag -->
    <%= link_webpack_css_chunk %>
    

That’s it! Hope it helps someone :smiley: