UNPKG

webpack-remove-empty-scripts

Version:

Webpack plugin removes empty JavaScript files generated when using styles.

395 lines (333 loc) 14.3 kB
<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](https://img.shields.io/npm/v/webpack-remove-empty-scripts?logo=npm&color=brightgreen "npm package")](https://www.npmjs.com/package/webpack-remove-empty-scripts "download npm package") [![node](https://img.shields.io/node/v/webpack-remove-empty-scripts)](https://nodejs.org) [![node](https://img.shields.io/github/package-json/dependency-version/webdiscus/webpack-remove-empty-scripts/peer/webpack)](https://webpack.js.org/) [![Test](https://github.com/webdiscus/webpack-remove-empty-scripts/actions/workflows/test.yml/badge.svg)](https://github.com/webdiscus/webpack-remove-empty-scripts/actions/workflows/test.yml) [![codecov](https://codecov.io/gh/webdiscus/webpack-remove-empty-scripts/branch/master/graph/badge.svg)](https://codecov.io/gh/webdiscus/webpack-remove-empty-scripts) [![node](https://img.shields.io/npm/dm/webpack-remove-empty-scripts)](https://www.npmjs.com/package/webpack-remove-empty-scripts) ## 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: ```js 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 `Emergency Crutch` 🩼 for the [mini-css-extract-plugin issue](https://github.com/webpack-contrib/mini-css-extract-plugin/issues/151).\ > 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](https://github.com/fqborges/webpack-fix-style-only-entries). ## Install ```console npm install webpack-remove-empty-scripts --save-dev ``` ## Usage with mini-css-extract-plugin The example of webpack.config.js: ```javascript 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](#options). --- ## Usage with html-webpack-plugin > ✅ It is recommended to use the new powerful [html-bundler-webpack-plugin][html-bundler-webpack-plugin] instead of: > > - html-webpack-plugin > - mini-css-extract-plugin > - webpack-remove-empty-scripts ### Highlights of html-bundler-webpack-plugin - **Prevents generating unexpected empty JS files.** - An [entry point](https://github.com/webdiscus/html-bundler-webpack-plugin#option-entry) can be an HTML template. - Source **scripts** and **styles** can be specified directly in HTML using `<script>` and `<link>`. - Extracts JS and CSS from their sources specified in HTML. - Resolving [source](https://github.com/webdiscus/html-bundler-webpack-plugin#loader-option-sources) assets specified in standard attributes `href` `src` `srcset` etc. - Inline [JS](https://github.com/webdiscus/html-bundler-webpack-plugin#recipe-inline-js), [CSS](https://github.com/webdiscus/html-bundler-webpack-plugin#recipe-inline-css), [SVG](https://github.com/webdiscus/html-bundler-webpack-plugin#recipe-inline-image), [PNG](https://github.com/webdiscus/html-bundler-webpack-plugin#recipe-inline-image) without additional plugins and loaders. - Support for [template engines](https://github.com/webdiscus/html-bundler-webpack-plugin#recipe-template-engine) such as Eta, EJS, Handlebars, Nunjucks, LiquidJS and others. ### Simple usage example Add source scripts and styles directly to HTML: ```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 <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: ```js 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: - `RemoveEmptyScriptsPlugin.STAGE_BEFORE_PROCESS_PLUGINS` (default)\ Remove empty scripts `before` processing other plugins.\ For example, exact this stage needs for properly work of the `webpack-manifest-plugin`. - `RemoveEmptyScriptsPlugin.STAGE_AFTER_PROCESS_PLUGINS`\ Remove empty scripts `after` processing all other plugins.\ For example, exact this stage needs for properly work of the `@wordpress/dependency-extraction-webpack-plugin`. 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](#usage-stage-optoion). > **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 ```js const isProduction = process.env.NODE_ENV === 'production'; new RemoveEmptyScriptsPlugin({ verbose: isProduction !== true }) ``` ### Disable plugin by development to improve performance ```js 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. ```js 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 ```js new RemoveEmptyScriptsPlugin({ extensions: /\.(foo|bar)$/ }) ``` ### Usage a javascript entry to styles Give an especial extension to your file, for example `.css.js`: ```js new RemoveEmptyScriptsPlugin({ extensions: /\.(css.js)$/ }) ``` ### Remove generated scripts `*.js` `*.mjs` except `*.rem.js` `*.rem.mjs` ```js new RemoveEmptyScriptsPlugin({ remove: /(?<!\.rem)\.(js|mjs)$/ }) ``` ### Recursive ignore all js files from directory, for example `my-workers/` ```js new RemoveEmptyScriptsPlugin({ ignore: [ /my-workers\/.+\.js$/, ] }) ``` ### Usage webpack-hot-middleware ```js new RemoveEmptyScriptsPlugin({ ignore: [ 'webpack-hot-middleware', ] }) ``` [See the test case](https://github.com/webdiscus/webpack-remove-empty-scripts/blob/master/test/cases/css-entry-with-ignored-hmr/webpack.config.js). ## 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/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://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/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/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 - [ansis][ansis] - The Node.js library for ANSI color styling of text in terminal. - [html-bundler-webpack-plugin][html-bundler-webpack-plugin] - HTML bundler plugin for webpack handels a template as an entry point, extracts CSS and JS from their sources specified in HTML, supports template engines like Eta, EJS, Handlebars, Nunjucks and others "out of the box". - [pug-plugin][pug-plugin] - plugin for Webpack compiles Pug files to HTML, extracts CSS and JS from their sources specified in Pug. - [pug-loader][pug-loader] - loader for Webpack renders Pug to HTML or template function. Optimized for using with Vue. ## License [ISC](https://github.com/webdiscus/webpack-remove-empty-scripts/blob/master/LICENSE) <!-- prettier-ignore-start --> [ansis]: https://github.com/webdiscus/ansis [pug-plugin]: https://github.com/webdiscus/pug-plugin [pug-loader]: https://github.com/webdiscus/pug-loader [html-bundler-webpack-plugin]: https://github.com/webdiscus/html-bundler-webpack-plugin <!-- prettier-ignore-end -->