Skip to content

artembatura/modify-source-webpack-plugin

Repository files navigation

npm version npm version npm version npm version npm version npm version

Webpack plugin for modifying modules source.

Compatibility

Webpack Version Plugin version Status
^5.0.0 ^4.0.0

âś…

^4.37.0 ^4.0.0

âś…

Migration guide from version 3

Installation

NPM

npm i -D modify-source-webpack-plugin

Yarn

yarn add -D modify-source-webpack-plugin

Import

ES6/TypeScript

import { ModifySourcePlugin } from 'modify-source-webpack-plugin';

CJS

const { ModifySourcePlugin } = require('modify-source-webpack-plugin');

Usage

webpack.config.js

module.exports = {
  plugins: [new ModifySourcePlugin(options)]
};

Options

rules[].test

Type: RegExp | ((module: webpack.NormalModule) => boolean)

Required

test is RegExp or function, which used to determinate which modules should be modified.

RegExp will be applied to full module path (based on userRequest).

function will be applied to NormalModule.

Example with RegExp

plugins: [
  new ModifySourcePlugin({
    rules: [
      {
        test: /index\.js$/
      }
    ]
  })
];

Example with Function

plugins: [
  new ModifySourcePlugin({
    rules: [
      {
        test: module =>
          module.source().source().includes('my-secret-module-marker')
      }
    ]
  })
];

rules[].operations

Type: AbstractOperation[] (supported ConcatOperation, ReplaceOperation)

Required

List of operations which describes how modules should be modified.

⚠️ Operations should make syntax compatible changes. For example all unsupported syntax will break your build or create errors in runtime.

Example with concat operation

import {
  ModifySourcePlugin,
  ConcatOperation
} from 'modify-source-webpack-plugin';

module.exports = {
  plugins: [
    new ModifySourcePlugin({
      rules: [
        {
          test: /my-file\.js$/,
          operations: [
            new ConcatOperation(
              'start',
              '// Proprietary and confidential.\n\n'
            ),
            new ConcatOperation(
              'end',
              '\n\n// File is written by me, January 2022'
            )
          ]
        }
      ]
    })
  ]
};

Example with replace operation

import {
  ModifySourcePlugin,
  ReplaceOperation
} from 'modify-source-webpack-plugin';

module.exports = {
  plugins: [
    new ModifySourcePlugin({
      rules: [
        {
          test: /my-file\.js$/,
          operations: [
            new ReplaceOperation('once', 'searchValue', 'replaceValue'),
            new ReplaceOperation('all', 'searchValue', 'replaceValue')
          ]
        }
      ]
    })
  ]
};

Bad example

module.exports = {
  plugins: [
    new ModifySourcePlugin({
      rules: [
        {
          test: /my-file\.js$/,
          operations: [
            new ConcatOperation('start', 'Haha I break your build LOL')
          ]
        }
      ]
    })
  ]
};

debug

Type: boolean

For easier debugging. Print some logs in the console.

Advanced Usage

Compile-time constants

Constants related to information about files that we change.

Constant Description
$FILE_PATH Path to file
$FILE_NAME File name
plugins: [
  new ModifySourcePlugin({
    rules: [
      {
        test: /my-file\.js$/,
        operations: [
          new ConcatOperation(
            'end',
            '\n\n // This file is on the path - $FILE_PATH and filename - $FILE_NAME'
          )
        ]
      }
    ]
  })
];

Put content before and after file contents

my-file.js (clickable)
console.log('Hello world!');

webpack.config.js

plugins: [
  new ModifySourcePlugin({
    rules: [
      {
        test: /my-file\.js$/,
        operations: [
          new ConcatOperation('start', '// Something before file contents.\n'),
          new ConcatOperation('end', '\n// Something after file contents.')
        ]
      }
    ]
  })
];
Result my-file.js (clickable)
// Something before file contents.
console.log('Hello world!');
// Something after file contents.

Replace plug with a content

my-component.jsx (clickable)
function HelloMessage(props) {
  return (
    <div>
      Hello, $NAME
      <button
        onClick={() => {
          props.userLogout();
          alert('Goodbye, $NAME!');
        }}
      >
        $EXIT_LABEL
      </button>
    </div>
  );
}

webpack.config.js

plugins: [
  new ModifySourcePlugin({
    rules: [
      {
        test: /my-component\.jsx$/,
        operations: [
          new ReplaceOperation('all', '$NAME', 'Artem Batura'),
          new ReplaceOperation('once', '$EXIT_LABEL', 'Exit')
          // new ReplaceOperation('once', '$EXIT_LABEL', 'Leave')
        ]
      }
    ]
  })
];
Result my-component.jsx (clickable)
function HelloMessage(props) {
  return (
    <div>
      Hello, Artem Batura
      <button
        onClick={() => {
          props.userLogout();

          alert('Goodbye, Artem Batura!');
        }}
      >
        Exit
      </button>
    </div>
  );
}

Place code/text fragment in required position

my-component.jsx (clickable)
function HelloMessage(props) {
  $MY_DEBUG_CODE;

  return (
    <div>
      Hello, user! $MY_USER_COMPONENT
      <button onClick={() => props.userLogout()}>Exit</button>
    </div>
  );
}

webpack.config.js

plugins: [
  new ModifySourcePlugin({
    rules: [
      {
        test: /my-component\.js$/,
        operations: [
          new ReplaceOperation(
            'once',
            '$MY_DEBUG_CODE',
            'console.log("props", props)'
          ),
          new ReplaceOperation(
            'once',
            '$MY_USER_COMPONENT',
            '<div>compilation-time markup</div>'
          )
        ]
      }
    ]
  })
];
Result my-component.jsx (clickable)
function HelloMessage(props) {
  console.log('props', props);

  return (
    <div>
      Hello, user!
      <div>compilation-time markup</div>
      <button onClick={() => props.userLogout()}>Exit</button>
    </div>
  );
}