Home

Awesome

<div align="center"> <img width="120" height="120" src="https://cdn.worldvectorlogo.com/logos/logo-javascript.svg"> <a href="https://webpack.js.org/"> <img width="120" height="120" vspace="" hspace="25" src="https://cdn.rawgit.com/webpack/media/e7485eb2/logo/icon-square-big.svg"> </a> <h1><a href="https://github.com/webdiscus/webpack-remove-empty-scripts">webpack-remove-empty-scripts</a></h1> <div>The Webpack plugin removes empty JavaScript files generated when using styles.</div> </div>

npm node node Test codecov node

The problem this plugin solves

Webpack generates a JS file for each resource defined in the entry option.

For example, you have a style file in the entry option:

module.exports = {
  entry: {
    styles: './styles.scss',
  },
}

The following files are generated in the output directory:

dist/styles.css
dist/styles.js // <= unexpected empty JS file

This plugin removes generated empty JS files.

Warning

This plugin is the Crutch 🩼 for the mini-css-extract-plugin issue.
The mini-css-extract-plugin extract CSS, but not eliminate a generated empty JS file.

Note

This plugin is compatible with Webpack 5. For Webpack 4 use webpack-fix-style-only-entries.

Install

npm install webpack-remove-empty-scripts --save-dev

Usage with mini-css-extract-plugin

The example of webpack.config.js:

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const RemoveEmptyScriptsPlugin = require('webpack-remove-empty-scripts');

module.exports = {
  entry: {
    'main' : './app/main.js',
    'styles': ['./common/styles.css', './app/styles.css']
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ]
      },
    ]
  },
  plugins: [
    // removes the empty `.js` files generated by webpack
    new RemoveEmptyScriptsPlugin(),
    new MiniCssExtractPlugin({
      filename: '[name].[chunkhash:8].css',
    }),
  ],
};

See the plugin options.


Usage with html-webpack-plugin

✅ It is recommended to use the new powerful html-bundler-webpack-plugin instead of:

Highlights of html-bundler-webpack-plugin

Simple usage example

Add source scripts and styles directly to HTML:

<html>
<head>
  <!-- specify source styles -->
  <link href="./style.scss" rel="stylesheet">
  <!-- specify source scripts here and/or in body -->
  <script src="./main.js" defer="defer"></script>
</head>
<body>
  <h1>Hello World!</h1>
  <!-- specify source images -->
  <img src="./logo.png">
</body>
</html>

The generated HTML contains the output filenames of the processed assets:

<html>
<head>
  <link href="assets/css/style.05e4dd86.css" rel="stylesheet">
  <script src="assets/js/main.f4b855d8.js" defer="defer"></script>
</head>
<body>
  <h1>Hello World!</h1>
  <img src="assets/img/logo.58b43bd8.png">
</body>
</html>

Add the HTML templates in the entry option:

const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');

module.exports = {
  plugins: [
    new HtmlBundlerPlugin({
      // define a relative or absolute path to template pages
      entry: 'src/views/',
      // OR define templates manually
      entry: {
        index: 'src/views/home.html', // => dist/index.html
        'news/sport': 'src/views/news/sport/index.html', // => dist/news/sport.html
      },
    }),
  ],
  // ... loaders for styles, images, etc.
};

<a id="options" name="options" href="#options"></a>

Options

enabled

Type: boolean Default: true<br> Enable / disable the plugin. Tip: Use disable for development to improve performance.

stage

Type: number<br> Values:

Webpack plugins use different stages for their functionality. For properly work other plugins can be specified the stage when should be removed empty scripts: before or after processing of other Webpack plugins.

See usage example.

Warning

Because webpack-manifest-plugin and @wordpress/dependency-extraction-webpack-plugin needs different stages both plugins can't be used together with RemoveEmptyScriptsPlugin at one configuration.

extensions

Type: RegExp Default: /\.(css|scss|sass|less|styl)([?].*)?$/ Note: the Regexp should have the query part at end ([?].*)?$ to match assets like style.css?key=val <br> Type: string[] Default: ['css', 'scss', 'sass', 'less', 'styl']. It is automatically converted to type RegExp.
Search for empty js files in source files only with these extensions.

ignore

Type: string | RegExp | string[] | RegExp[] Default: null<br> Ignore source files.

remove

Type: RegExp Default: /\.(js|mjs)$/<br> Remove generated scripts.

verbose

Type: boolean Default: false<br> Show process information.

Recipes

Show logs to console by development

const isProduction = process.env.NODE_ENV === 'production';
new RemoveEmptyScriptsPlugin({ verbose: isProduction !== true })

Disable plugin by development to improve performance

const isProduction = process.env.NODE_ENV === 'production';
new RemoveEmptyScriptsPlugin({ enabled: isProduction === true })

<a id="usage-stage-optoion" name="usage-stage-optoion" href="#usage-stage-optoion"></a>

Specify stage for properly work some plugins

For example, using @wordpress/dependency-extraction-webpack-plugin the empty scripts must be removed after processing all plugins.

const path = require('path');
const DependencyExtractionWebpackPlugin = require('@wordpress/dependency-extraction-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const RemoveEmptyScriptsPlugin = require('webpack-remove-empty-scripts');

module.exports = {
  output: {
    path: path.join(__dirname, 'public'),
  },
  entry: {
    'main': './src/sass/main.scss',
  },
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin(),
    new DependencyExtractionWebpackPlugin(),
    new RemoveEmptyScriptsPlugin({
      stage: RemoveEmptyScriptsPlugin.STAGE_AFTER_PROCESS_PLUGINS, // <- use this option
    }),
  ],
};

Identify only .foo and .bar extensions as styles

new RemoveEmptyScriptsPlugin({ extensions: /\.(foo|bar)$/ })

Usage a javascript entry to styles

Give an especial extension to your file, for example .css.js:

new RemoveEmptyScriptsPlugin({ extensions: /\.(css.js)$/ })

Remove generated scripts *.js *.mjs except *.rem.js *.rem.mjs

new RemoveEmptyScriptsPlugin({ remove: /(?<!\.rem)\.(js|mjs)$/ })

Recursive ignore all js files from directory, for example my-workers/

new RemoveEmptyScriptsPlugin({
  ignore: [
    /my-workers\/.+\.js$/,
  ]
})

Usage webpack-hot-middleware

new RemoveEmptyScriptsPlugin({
  ignore: [
    'webpack-hot-middleware',
  ]
})

See the test case.

Testing

npm run test will run the unit and integration tests.
npm run test:coverage will run the tests with coverage.

Who use this plugin

<a href='https://github.com/mozilla'> <img src='https://avatars.githubusercontent.com/u/131524?s=42&v=4' title='Mozilla'> </a> <a href='https://github.com/mozmeao'> <img src='https://avatars.githubusercontent.com/u/17653958?s=42&v=4' title='Mozilla Marketing'> </a> <a href='https://github.com/OpenSourceOrg'> <img src="https://avatars.githubusercontent.com/u/5924333?s=42&v=4" title='Open Source Org'> </a> <a href='https://github.com/pypi/warehouse'> <img src="https://avatars.githubusercontent.com/u/2964877?s=42&v=4" title='PyPi'> </a> <a href='https://github.com/preactjs'> <img src="https://avatars.githubusercontent.com/u/26872990?s=42&v=4" title='Preact'> </a> <a href='https://github.com/rails/jsbundling-rails/blob/main/docs/switch_from_webpacker.md'> <img src="https://avatars.githubusercontent.com/u/4223?s=42&v=4" title='Rails'> </a> <a href='https://www.cisco.com/c/dam/en_us/about/doing_business/open_source/docs/slido-test-2206-1655452418.pdf'> <img src='https://avatars.githubusercontent.com/u/1376999?s=42&v=4' title='Cisco'> </a> <a href='https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/webpack.config.js'> <img src='https://avatars.githubusercontent.com/u/22105643?s=42&v=4' title='Cisco'> </a> <a href='https://github.com/jenkinsci'> <img src='https://avatars.githubusercontent.com/u/107424?s=42&v=4' title='Jenkins'> </a> <a href='https://github.com/coinbase'> <img src='https://avatars.githubusercontent.com/u/1885080?s=42&v=4' title='Coinbase'> </a> <a href='https://github.com/PrestaShop'> <img src='https://avatars.githubusercontent.com/u/2815696?s=42&v=4' title='PrestaShop'> </a> <a href='https://github.com/getsentry'> <img src='https://avatars.githubusercontent.com/u/1396951?s=42&v=4' title='Sentry'> </a> <a href='https://github.com/wikimedia'> <img src='https://avatars.githubusercontent.com/u/56668?s=42&v=4' title='Wikimedia'> </a> <a href='https://github.com/TYPO3GmbH'> <img src='https://avatars.githubusercontent.com/u/24472665?s=42&v=4' title='TYPO3 GmbH'> </a> <a href='https://github.com/woocommerce'> <img src='https://avatars.githubusercontent.com/u/473596?s=42&v=4' title='WooCommerce'> </a> <a href='https://github.com/plentymarkets'> <img src='https://avatars.githubusercontent.com/u/3379035?s=42&v=4' title='plentymarkets'> </a> <a href='https://github.com/standardnotes'> <img src='https://avatars.githubusercontent.com/u/24537496?s=42&v=4' title='Standard Notes'> </a> <a href='https://github.com/roots'> <img src='https://avatars.githubusercontent.com/u/4986074?s=42&v=4' title='Roots'> </a> <a href='https://github.com/ampproject'> <img src='https://avatars.githubusercontent.com/u/14114390?s=42&v=4' title='AMP'> </a> <a href='https://github.com/awesomemotive'> <img src='https://avatars.githubusercontent.com/u/8514352?s=42&v=4' title='Awesome Motive'> </a> <a href='https://github.com/10up'> <img src='https://avatars.githubusercontent.com/u/3358927?s=42&v=4' title='10up'> </a> <a href='https://github.com/collab-project'> <img src='https://avatars.githubusercontent.com/u/347599?s=42&v=4' title='Collab project'> </a> <a href='https://github.com/jspsych'> <img src='https://avatars.githubusercontent.com/u/16901698?s=42&v=4' title='jsPsych'> </a> <a href='https://github.com/grandnode'> <img src='https://avatars.githubusercontent.com/u/16118376?s=42&v=4' title='GrandNode'> </a> <a href='https://github.com/TheOdinProject'> <img src='https://avatars.githubusercontent.com/u/4441966?s=42&v=4' title='The Odin Project'> </a> <a href='https://github.com/ministryofjustice'> <img src='https://avatars.githubusercontent.com/u/2203574?s=42&v=4' title='Ministry of Justice, London'> </a> <a href='https://github.com/helsingborg-stad'> <img src='https://avatars.githubusercontent.com/u/12846276?s=42&v=4' title='Helsingborg Stad'> </a> <a href='https://github.com/City-of-Helsinki'> <img src='https://avatars.githubusercontent.com/u/1875564?s=42&v=4' title='City of Helsinki'> </a>

Also See

License

ISC

<!-- prettier-ignore-start --> <!-- prettier-ignore-end -->