webpack-auto-inject-version icon indicating copy to clipboard operation
webpack-auto-inject-version copied to clipboard

updating packages for webpack 5 compatibility

Open raviteja9135 opened this issue 3 years ago • 5 comments

webpack 5 has a new object structure. This specific change was causing the build to fail so. Adding those changes in this PR for future use. https://webpack.js.org/contribute/writing-a-plugin/ @radswiat

raviteja9135 avatar Jun 09 '21 09:06 raviteja9135

@teodoradima or @radswiat could you merge this PR?

rcmsjr avatar Jul 19 '21 22:07 rcmsjr

@radswiat please merge this PR

raviteja9135 avatar Jul 28 '21 04:07 raviteja9135

@raviteja9135 I have a fork that works with webpack 5. However, I only tested inject by tag. See the repo here: https://github.com/teodoradima/webpack-auto-inject-version

teodoradima avatar Jul 29 '21 06:07 teodoradima

Can't use your fork since you did not build the changes so /dist is not patched. I do use patch package instead: npm i patch-package

webpack-auto-inject-version+1.2.2.patch:

diff --git a/node_modules/webpack-auto-inject-version/dist/WebpackAutoInjectVersion.js b/node_modules/webpack-auto-inject-version/dist/WebpackAutoInjectVersion.js
index 7f672ae..b6fca30 100644
--- a/node_modules/webpack-auto-inject-version/dist/WebpackAutoInjectVersion.js
+++ b/node_modules/webpack-auto-inject-version/dist/WebpackAutoInjectVersion.js
@@ -3066,7 +3066,7 @@ var AutoIncreaseVersion = function () {
       // we have to register AutoIncreaseVersion instead of firing it straight away
       if (_config2.default.componentsOptions.AutoIncreaseVersion.runInWatchMode) {
         if (this.context.compiler) {
-          this.context.compiler.plugin('emit', function (compilation, cb) {
+          this.context.compiler.hooks.emit.tapAsync('emit', function (compilation, cb) {
             _this.start();
             cb();
           });
@@ -3276,7 +3276,7 @@ var InjectAsComment = function () {
       var _this = this;
 
       // bind into emit hook
-      this.context.compiler.plugin('emit', function (compilation, cb) {
+      this.context.compiler.hooks.emit.tapAsync('emit', function (compilation, cb) {
         // iterate over all assets file in compilation
         for (var basename in compilation.assets) {
           // bug fix, extname is not able to handle chunk file params index.js?random123
@@ -3508,7 +3508,7 @@ var InjectByTag = function () {
     value: function apply() {
       var _this = this;
 
-      this.context.compiler.plugin('emit', function (compilation, cb) {
+      this.context.compiler.hooks.emit.tapAsync('emit', function (compilation, cb) {
         // for every output file
         for (var basename in compilation.assets) {
           // only if match regex

bumbummen99 avatar Oct 19 '21 15:10 bumbummen99

Hey folks, a bit late to the party, but, I hit this and tried to help out in 2 ways:

  1. I submitted a PR against @teodoradima fork with and update to lazily add the InjectAsComment support to combine with his/her quick fixes for InjectFromTag approach. https://github.com/teodoradima/webpack-auto-inject-version/pull/1.

I can try to fixup any small issues as I mostly just tested it around my immediate usage needs, but fundamentally it seems to work. I don't intend to update tests or other build framework at this time as I just don't have time to do the updates necessary to the repo to get it all working.

  1. In an effort of further troubleshooting (unrelated to the plug-in above), I (again lazily) took much of the logic from the original plugin source and hard-coded a plug-in that can be dropped in a standalone file in your local repository to do the InjectAsComment approach. See below if this may help you.
const fs = require('fs');
const path = require('path');
const webpackSources = require('webpack-sources');

const pluginComponentName = 'WebpackVersionInject';
const endOfLine = require('os').EOL;

const validTags = {
   version: (options) => {
      return options.version;
   },
   date: () => {
      return new Date().toUTCString();
   }
};


/**
   * Handle asset file
   * - call suitable inject based on file extension
   * @param ext
   * @param asset
   * @private
   * @return {ReplaceSource}
   */
const _handleAssetFile = (ext, asset, options) => {
   switch (ext) {
      case '.js': {
         return injectIntoJs(asset, options);
      }
      case '.html': {
         return injectIntoHtml(asset, options);
      }
      case '.css': {
         return injectIntoCss(asset, options);
      }
      default:
         return null;
   }
};

/**
   * Parse tags
   * - parse inject tags eg {version}, {date}
   * @private
   *
   * @param baseOpen
   * @param baseClose
   *
   * @return {string}
   */
const parseTags = (baseOpen, baseClose, options) => {
   let tagPattern = options.componentsOptions.InjectAsComment.tag;
   tagPattern = tagPattern.replace(/(\{([a-zA-Z]+)\})/g, tag => {
      const tagName = tag.replace(/(\{|\})/g, '');
      if (typeof validTags[tagName] === 'function') {
         return validTags[tagName](options);
      }
      log.error(`unsupported tag in componentsOptions.InjectAsComment.tag [${tagName}]`);
      return tag;
   });
   return `${baseOpen} ${tagPattern} ${baseClose}`;
};

/**
   * Inject into css
   * - inject tag comment into css asset file
   * - format: / ** .... ** /
   * @private
   *
   * @param asset
   *
   * @return {ReplaceSource}
   */
const injectIntoCss = (asset, options) => {
   asset.insert(0, `${parseTags(`/** [${options.SHORT}] `, ' **/ ', options)}${endOfLine}`);
   return asset;
};

/**
   * Inject into html
   * - inject tag comment into html asset file
   * - format: <!-- ... -->
   * @private
   *
   * @param asset
   *
   * @return {ReplaceSource}
   */
const injectIntoHtml = (asset, options) => {
   asset.insert(0, `${parseTags(`<!-- [${options.SHORT}] `, ' --> ', options)}${endOfLine}`);
   return asset;
};

/**
   * Inject into JS
   * - inject tag comment into JS asset file
   * - format: // ...
   * @private
   *
   * @param asset
   *
   * @return {ReplaceSource}
   */
const injectIntoJs = (asset, options) => {
   asset.insert(0,
      options.componentsOptions.InjectAsComment.multiLineCommentType ?
         `${parseTags(`/*! [${options.SHORT}] `, '*/ ', options)}${endOfLine}` :
         `${parseTags(`// [${options.SHORT}] `, ' ', options)}${endOfLine}`
   );
   return asset;
};

// the date formatting is somewhat nerfed from original and just hardcodes new Date().toUTCString() to reduce
// dependencies for the project
module.exports = class WebpackVersionInjectPlugin {
    // many of these options dont do anything with this plugin
    static defaultOptions = {
      SHORT: '[AIV_SHORT]',
      SILENT: false,
      PACKAGE_JSON_PATH: './package.json',
      PACKAGE_JSON_INDENT: 4,
      components: {
         InjectAsComment: true
      },
      componentsOptions: {
         AutoIncreaseVersion: {
            runInWatchMode: false
         },
         InjectAsComment: {
            tag: 'Build version: {version} - {date}',
            multiLineCommentType: false
         }
      },
      LOGS_TEXT: {
         AIS_START: 'Auto inject version started'
      }
   };

    constructor(options = {}) {
       this.options = { ...WebpackVersionInjectPlugin.defaultOptions, ...options };
        const packageFile = JSON.parse(
            fs.readFileSync(path.resolve(this.options.PACKAGE_JSON_PATH), 'utf8')
        );
       // we inject version as a runtime generated value, allowing the user to override it optionally
       this.options.version = this.options.version ?? packageFile.version;
    }

    apply(compiler) {
      compiler.hooks.compilation.tap(pluginComponentName, compilation => {
         compilation.hooks.processAssets.tap({ name: pluginComponentName, stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS }, assets => {
            for (let a in assets) {
               const asset = compilation.getAsset(a);  // <- standardized version of asset object
               // bug fix, extname is not able to handle chunk file params index.js?random123
               const ext = path.extname(a).replace(/(\?)(.){0,}/, '');
               const contents = asset.source.source();
               if (!contents.substring) {
                  console.log(`skipping asset with no source content ${JSON.stringify(a)} ${typeof contents}`);
                  continue;
               }
               const newSource = new webpackSources.ReplaceSource(asset.source);
               _handleAssetFile(ext, newSource, this.options);
               // eslint-disable-next-line no-console
               console.log(`InjectAsComment : match : ${a} : injected : ${this.options.version}`);
               compilation.updateAsset(a, new webpackSources.RawSource(newSource.source()));
            };
         });
      });
      return Promise.resolve();
   }
}

Usage (in webpack.config.js):

// path to the file containing the code above
const WebpackVersionInjectPlugin = require('./webpack.versionInject.plugin.js');
...

new WebpackVersionInjectPlugin({
            SHORT: 'MyApplication',
            components: {
               AutoIncreaseVersion: false,
               InjectAsComment: true
            },
            componentsOptions: {
               InjectAsComment: {
                  tag: '|  Version: {version}  |  {date}',
                  multiLineCommentType: true
               }
            }
         })

lanfear avatar May 18 '22 17:05 lanfear