Giter Club home page Giter Club logo

modify-source-webpack-plugin's Introduction

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>
  );
}

modify-source-webpack-plugin's People

Contributors

artembatura avatar dependabot[bot] avatar renovate-bot avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

modify-source-webpack-plugin's Issues

Incompatibility with webpack v >= 5.66.0

[DEP_WEBPACK_COMPILATION_NORMAL_MODULE_LOADER_HOOK] DeprecationWarning: Compilation.hooks.normalModuleLoader was moved to NormalModule.getCompilationHooks(compilation).loader (Use node --trace-deprecation ...` to show where the warning was created)
c:\sources\xxx\node_modules\webpack\lib\NormalModule.js:207
throw new TypeError(
^

TypeError: The 'compilation' argument must be an instance of Compilation
at Function.getCompilationHooks (c:\sources\xxx\node_modules\webpack\lib\NormalModule.js:207:10)
at c:\sources\xxx\node_modules\modify-source-webpack-plugin\build\ModifySourcePlugin.js:80:40
at Hook.eval [as call] (eval at create (c:\sources\xxx\node_modules\tapable\lib\HookCodeFactory.js:19:10), :238:1)
at Hook.CALL_DELEGATE [as _call] (c:\sources\xxx\node_modules\tapable\lib\Hook.js:14:14)
at Compiler.newCompilation (c:\sources\xxx\node_modules@angular-devkit\build-angular\node_modules\webpack\lib\Compiler.js:1055:26)
at c:\sources\xxx\node_modules@angular-devkit\build-angular\node_modules\webpack\lib\Compiler.js:1099:29
at eval (eval at create (c:\sources\xxx\node_modules\tapable\lib\HookCodeFactory.js:33:10), :31:1)
`

crash when build again

version: 3.0.0-rc.0

webpack version: 4.46.0

When i use this plugin, the first time build is successful, but if i modify some source code and run build again (with node_modules/.cache), it will throw error. Here is output:

 error  in ./src/views/Home.vue?vue&type=script&lang=ts&

Syntax Error: Thread Loader (Worker 0)
Modify function at index 0 is not defined in global space.


 @ ./src/views/Home.vue?vue&type=script&lang=ts& 1:0-560 1:576-579 1:581-1138 1:581-1138
 @ ./src/views/Home.vue
 @ ./src/views lazy ^\.\/.*$ namespace object
 @ ./src/router/index.ts
 @ ./src/main.ts
 @ multi ./src/main.ts

I think it's caused by cache. If i remove node_modules/.cache, it can build successfully again.

I am using a new template project (Vue 2) created buy vue-cli. Here is my vue.config.js:

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

module.exports = {
  configureWebpack: {
    plugins: [
      new ModifySourcePlugin({
        debug: true,
        rules: [
          {
            test: /\.vue\?vue&type=script.*/,
            modify: (src, path) => {
              console.log('modify');
              var s = '\n\n';
              return src + s;
            },
          },
        ],
      }),
    ],
  },
};

How used the plugin in custom webpack plugin?

apply = (compiler) => {
    new ModifySourcePlugin({
      debug: true,
      rules: [
        {
          test: /mutations\.js/,
          modify: (src, filename) => {
            return `${src}\n\n// This file (${filename}) is written by me. All rights reserved`;
          },
        },
      ],
    });
  }

The usage is not worked!

Feature request: add ability to dynamically determine inserted contents based on current file path

Before version 4 it was possible to analyze the contents of the file being processed (and its path) and generate inserted content dynamically based on the current file data.

Starting from version 4, it seems to be impossible to analyze file data during modification.

Here is an example of how we used version 3 of the plugin:

new ModifySourcePlugin({
  rules: [
    {
      test: /antd\/[^/]+(\/[^/]+)?\/style\/[^/]+\.less/,
      modify: (src, filePath) => {
        const directoryPath = path.dirname(filePath);

        const variablesRelativePath = path.relative(
          directoryPath,
          'src/styles/common/variables.less',
        );

        const filePathMatch = filePath.match(
          /antd\/[^/]+\/([^/]+)\/style\/[^/]+\.less$/,
        );
        let overridesImport;

        if (!filePathMatch) {
          overridesImport = '';
        } else {
          const [, componentName] = filePathMatch;
          const overridesPath = `src/styles/ant/${componentName}.less`;
          const overridesRelativePath = path.relative(
            directoryPath,
            overridesPath,
          );
          overridesImport = existsSync(overridesPath)
            ? `@import '${overridesRelativePath}';${EOL}`
            : '';
        }

        return `${src}${EOL}@import '${variablesRelativePath}';${EOL}${overridesImport}`;
      },
    },
  ],
})

I thought that we needed to write a custom operation for it, but it seems like there is no way to get current file info inside the operation.

Is it possible to get the same behaviour with version 4?

Supported file types?

I want to replace the whole source of my .vue file before it's picked for compilation. Will your plugin help with any type of resource (or) is it only for JS? I did notice a closed issue w.r.t support for css file, but it didn't answer if your plugin was later updated to be agnostic to the resource type.

Thanks a lot for this plugin!

Does it support css files

Hi,
Thank you for the plugins, it looks very promising for my use case!
It looks like this plugin prepends a loader to do the modification.
In that case, I am wonder does the plugin work for a .css file (I think css files are also NormalModule)?

Doesn't run when using Watch

I've setup this plugin in my webpack config to re-write sass url's

It works brilliantly when running webpack directly, but if I use set the watch option to true; the re-written urls are lost if any changes are made to the sass files while watching.

Is this expected; can it me made to work?

Thanks,
Ben.

how to use this plugin in vue2.0

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

module.exports = {
configureWebpack: {
plugins: [
new ModifySourcePlugin({
include: [/App.vue?vue.*/],
exclude: ['node_modules'],
patterns: [{
reg: /Welcome/g,
newStr: '2323',
}],
},
),
],
},
};

it can't run
there aren't any error

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.