webpack-merge-and-include-globally icon indicating copy to clipboard operation
webpack-merge-and-include-globally copied to clipboard

How to reference hashed merged file in ejs files?

Open tomas-blanarik-visma opened this issue 6 years ago • 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-visma avatar Mar 04 '19 11:03 tomas-blanarik-visma

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

markshapiro avatar Mar 04 '19 17:03 markshapiro

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?

tomas-blanarik-visma avatar Mar 04 '19 17:03 tomas-blanarik-visma

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-visma avatar Mar 04 '19 18:03 tomas-blanarik-visma

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

markshapiro avatar Mar 04 '19 18:03 markshapiro

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

tomas-blanarik-visma avatar Mar 04 '19 18:03 tomas-blanarik-visma

@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.

markshapiro avatar Mar 04 '19 20:03 markshapiro

!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 ?

spidergears avatar Jun 26 '19 09:06 spidergears

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>

atellmer avatar May 29 '20 17:05 atellmer

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>

yicone avatar Nov 12 '22 02:11 yicone