Wordpressor
Wordpressor

Reputation: 7543

Webpack - outputting different file extensions?

I have this kind of input and output in my web pack file:

entry: {
  "logic": './foo/logic.js',
  "logic.min": './foo/logic.js',
  "style.min": './foo/style.scss'
},
watch: true,
devtool: 'source-map',
output: {
  path: path.resolve(__dirname, '/dist'),
  filename: '[name].js'
},

Then I run some rules to make sure proper files are handled properly:

module: {
        rules: [
            {
                test: /\.jsx?$/i,
                loader: 'babel-loader',
                options: {
                    presets: ['es2015'],
                    minified: true
                }
            },
            {
                test: /\.scss|css$/,
                use: extractSass.extract({
                    use: [{loader: "css-loader", options: { minimize: true }}, { loader: "sass-loader" }],

                    fallback: "style-loader"
                })
            },
        ],
    },

As far as I understand webpack the code above should output:

logic.js
logic.min.js
style.min.css

and source map files.

Unfortunately there's one thing that I can't figure out. I'm getting a file called:

style.min.css.js

Why is this file even generated? I tried outputting [file].[ext] but it returned literally [ext] for JS files extensions...

Upvotes: 2

Views: 1533

Answers (2)

Christian4423
Christian4423

Reputation: 1796

Try adding [ext] to the plugin filename key.

Why are you trying to render the minified file and the unminified file at the same time?

Run webpack for unminified files. Run webpack -p for minified files.

Rules

module: {
    rules: [
        {
            test: /\.jsx?$/,
            exclude: [
                path.resolve(__dirname, "node_modules")
            ],                
            loader: "babel-loader",
            options: {
                presets: ['react', 'env', 'stage-0'],
                plugins: ['react-html-attrs', 'transform-class-properties', 'transform-decorators-legacy'],
            }
        },
        {
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: "css-loader"
            })
        },            
        {
            test: /\.(scss|sass)$/,
            use: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: [
                    "css-loader",
                    "sass-loader"
                ]
            })
        }
    ]
 }

Plugins

plugins: [
    new ExtractTextPlugin({
        filename: "./css/bundle.[ext]",
        disable: false,
        allChunks: true
    }),
    new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery",
        "window.jQuery": "jquery"
    })
]

Upvotes: 1

Steven Scaffidi
Steven Scaffidi

Reputation: 2307

Unfortunately, this is simply the way webpack works right now. You can take a look at this issue https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/518. You can write a small plugin to stop the plugin from emitting js files. Here is a simple plugin that works:

module.exports = class CleanupAssetsAndFiles {

    constructor (options = {}) {

        this.paths = options.paths || [ 'styles/' ];
        this.extensions = options.extensions || [ 'js', 'js.map' ];

    }

    isInvalidExtension (asset) {

        return (
            this.extensions.reduce((validAssets, e) => {

                if (asset.endsWith(e)) {

                    validAssets.push(e);

                }
                return validAssets;

            }, []).length > 0
        );

    }

    apply (compiler) {

        compiler.plugin('should-emit', (compilation) => {

            compilation.assets = Object.keys(compilation.assets).reduce((assets, a) => {

                if (!this.isInvalidExtension(a) || !this.paths.some((path) => a.startsWith(path))) {

                    assets[a] = compilation.assets[a];

                }

                return assets;

            }, {});

            return true;

        });

    }

};

I wrote this plugin for webpack 3 but I believe it still works in webpack 4. Basically, it looks at the extensions and paths that you pass it and stops emitting those files for those paths. This plugin worked for my use-case, but you can tweak it to work for yours if it's not the same. There is a pending PR to add full support for CSS https://github.com/webpack/webpack/pull/6448. Hope this helps.

Upvotes: 1

Related Questions