Warm tip: This article is reproduced from serverfault.com, please click

Webpack

发布于 2020-12-02 13:04:03

Context

I am actually managing some dependencies via npm. Then I wrote a webpack.config.js to handle my imports :

  1. Bundle Jquery + popper + Bootstrap.js
  2. Bundle codemirror with my modules needs (xml autocomplete and so on)
  3. ...
  4. Collect fonts from the fontawesome node_module

I am using django, so there is a collectstatic command which is helping me to collect all scripts, fonts, styles etc. to the folder I want. Everything is working great :

  • My bundled scripts are available
  • And for style sheets, I'm using relative imports to the 'vendor' node_module.

I am capable to get fonts to node_modules, and deliver it to the correct folder as expected.

Problem

I'm new to webpack world, and for sure I'm not using it as it should be, but it's working.
However when I run to compile my stuffs, an extra file is generated fontawesome.js in my fonts folder, is it possible to avoid this unexpected behavior.
What am I missing ?

It is not a big deal as long as I'm not importing this file, but I don't want to pollute my repo.

Edit

I updated the code of my webpack config.
Well, I figured out that the js file was generated from the filename in my entry point. But I don't want this file :)

wepback.config.js

"webpack": "^5.6.0",

var path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // Extract css in its own file
const webpack = require('webpack');

const path_modules = path.resolve(__dirname, 'node_modules');
const base_path = path.resolve(__dirname, 'src');
const dist_static = path.resolve(__dirname, 'webpacked_src');

module.exports = {
    entry: {
        bootstrap: {
            import: [
                base_path + '/bootstrap/bootstrap-bundle.js',
                //base_path + '/bootstrap/test.scss'
            ],
            filename: 'js_packed/[name].js',
        },
        fontawesome: {
            import: [
                path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot',
                //path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-brands-400.svg',
                path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf',
                path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff',
                path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2',
                path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot',
                //path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg',
                path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf',
                path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff',
                path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2',
                path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot',
                //path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg',
                path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf',
                path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff',
                path_modules + '/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2',
            ],
            filename: 'fonts/[name].js'
        },
        codemirror: {
            import: [
                base_path + '/codemirror/code-mirror.js',
                path_modules + '/codemirror/lib/codemirror.css',
                path_modules + '/codemirror/theme/monokai.css', // Import the theme style --> Little selection midnight / material-darker / material-ocean / monokai (sublimetext)
                path_modules + '/codemirror/addon/hint/show-hint.css',
            ],
            filename: 'js_packed/[name].js',
        },
        vue: {
            import: [
                base_path + '/vue/vue.js',
            ],
            filename: 'js_packed/[name].js',
        },
    },
    output: {
        path: dist_static
    },
    plugins: [
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery'
        }),
        autoprefixer = require('autoprefixer'),
        new MiniCssExtractPlugin({
            filename: "css_packed/[name].css", // change this RELATIVE to the output.path
        }),
    ],
    module: {
        rules: [
            {
                test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name].[ext]',
                            outputPath: 'fonts/'
                        }
                    }
                ]
            },
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader, // instead of style-loader
                    'css-loader'
                ]
            },
            {
                test: /\.scss$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {outputPath: 'css/', name: '[name].min.css'}
                    },
                    'sass-loader'
                ]
            }
        ],
    },
};

fontawesome.js

And the content of the generated file, if it can help webpack experts :

(() => {
    "use strict";
    var t = {};
    t.g = function () {
        if ("object" == typeof globalThis) return globalThis;
        try {
            return this || new Function("return this")()
        } catch (t) {
            if ("object" == typeof window) return window
        }
    }(), (() => {
        var r;
        t.g.importScripts && (r = t.g.location + "");
        var e = t.g.document;
        if (!r && e && (e.currentScript && (r = e.currentScript.src), !r)) {
            var p = e.getElementsByTagName("script");
            p.length && (r = p[p.length - 1].src)
        }
        if (!r) throw new Error("Automatic publicPath is not supported in this browser");
        r = r.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/"), t.p = r + "../"
    })(), t.p, t.p, t.p, t.p, t.p, t.p, t.p, t.p, t.p, t.p, t.p, t.p
})();
Questioner
Devart
Viewed
0
Mike Post 2021-01-09 00:39:32

Unfortunately, this is a bug in webpack: https://github.com/webpack/webpack/issues/11671

In the meantime, it's straight forward to add a custom webpack plugin that will remove these files. Here's what I'm using to delete all JS files (because I'm using a CSS file as my entry):

plugins: [
    {
      // Delete empty JS files; work around for https://github.com/webpack/webpack/issues/11671
      apply: (compiler) => {
        compiler.hooks.afterEmit.tap('DeleteJSFilesPlugin', (compilation) => {
          const iter = compilation.emittedAssets.entries();
          for (const [key] of iter) {
            if (key.match(/.*\.js$/)) {
              fs.unlinkSync(path.join(compilation.outputOptions.path, key));
            }
          }
        });
      }
    }
  ]