markshapiro/webpack-merge-and-include-globally

How to reference hashed merged file in ejs files?

tomas-blanarik opened this issue ยท 9 comments

Hi guys,

I am using webpack-merge-and-include-globally with 2.1.14 version and I'm merging a couple of node_modules into the one vendor.js file. I'm also using hash: true in config. The problem I'm facing now is how to render vendor-[hash].js in the .ejs file? The old solution was just to use bundled vendor.js file with no hash, but after hash is added, how to render it?

Thank you for your help!

@tomas-blanarik sorry don't know about ejs yet, but do you mean you don't know the hash when generating ejs?

Well the problem is how to add the script tag with the vendor-hash.js file. Where can I find the hash? Is it exposed somewhere globally?

Basically, can you create an example how to use this plugin with hash option enabled? I have my vendor js created with hash, but now I wanted to render it in html file or ejs file, it really doesn't matter.

@tomas-blanarik I can expose callback that will list all created files and index.js mapped to index-[hash].js, will it help?

Sure, can you then also provide an example of usage? That would be awesome :)

@tomas-blanarik
added as second parameter new MergeIntoSingle({ ... }, filesMap => { ... }); in v2.1.15
still wonder if there's proper way to receive results from webpack plugin.

!NoobAert!

I have this exact problem. I see the generated file name with the hash in the filesMap callback log statement.

How am i supposed to used this when including file in my html template ?

Hello everyone. I have solution to this problem by using additional plugins.

const MergeIntoSingleFilePlugin = require('webpack-merge-and-include-globally');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackTagsPlugin = require('html-webpack-tags-plugin');


const files = {
  'global.js': [
    './path/to/global/deps.js',
    ...
  ],
  'global.css': [
    './path/to/global/deps.css',
    ...
  ],
};

const scope = {
  filesMap: {},
};

const config = {
  ...
  plugins: [
    new MergeIntoSingleFilePlugin({
      files,
      hash: true,
    }, filesMap => scope.filesMap = filesMap),
    new HtmlWebpackPlugin({
      template: 'index.ejs',
      filename: 'index.html',
      inject: false,
    }),
    new HtmlWebpackTagsPlugin({
      tags: createTags(files),
      useHash: true,
      append: false,
      addHash: createPath,
    }),
  ],
};

function createTags(files) {
  return Object.keys(files).map(key => key);
}

function createPath(originalPath) {
  const separator = '/';
  const [fileName, ...restPath] = originalPath.split(separator).reverse();
  const withHash = scope.filesMap[fileName] || fileName;
  const path = [withHash, ...restPath].reverse().join(separator);

  return path;
}

and into index.ejs make something like that

<html>
  <head>
  % for (let css in htmlWebpackPlugin.files.css) {%>
    <link rel="stylesheet" type="text/css"  href="<%= htmlWebpackPlugin.files.css[css] %>"></link>
  <%} %>
  </head>
  <body>
  <% for (let js in htmlWebpackPlugin.files.js) {%>
    <script src="<%= htmlWebpackPlugin.files.js[js] %>"></script>
  <%} %>
  </body>
</html>

Thanks to @ atellmer's example, based on which I found a more concise way

const MergeIntoSingleFilePlugin = require('webpack-merge-and-include-globally');
const HtmlWebpackPlugin = require('html-webpack-plugin');


const files = {
  'global.js': [
    './path/to/global/deps.js',
    ...
  ],
  'global.css': [
    './path/to/global/deps.css',
    ...
  ],
};

const scope = {
  filesMap: {},
};

const config = {
  ...
  plugins: [
    new MergeIntoSingleFilePlugin({
      files,
      hash: true,
    }, filesMap => scope.filesMap = filesMap),
    new HtmlWebpackPlugin({
      template: 'index.ejs',
      filename: 'index.html',
      templateParameters: () => {
          return {
            'global_js': scope.filesMap['global.js'],
            'global_css': scope.filesMap['global.css']
          };
        }
    })
  ]
};

index.ejs

<html>
  <head>
    <link rel="stylesheet" type="text/css"  href="<%= global_css %>"></link>
  </head>
  <body>
    <script src="<%= global_js %>"></script>
  </body>
</html>