csswebpacksasswebpack-style-loader

webpack not bundling scss when using import instead of require


Simple webpack setup, when I use import to load my scss it is completely missing from the bundle. The line where the import should be is simply missing. When I use require instead, it works.

optimization: {usedExports: true} is not the problem, I tried with and without

mini-css-extract-plugin also did not work.

when I put a typo in the scss it complains, so it is parsed but simply not bundled in the end?

index.js

require("./scss/style.scss");
//import "./scss/style.scss" <--- not working

import { createApp } from 'vue';
import App from './components/App.vue';

const el = document.getElementById('app');
createApp(App).mount(el);

webpack config

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');
const { DefinePlugin } = require('webpack');

const dist = path.resolve(__dirname, "dist");

module.exports = env => {
    const mode = env.production == true ? "production" : "development";
    const devtool = mode == "production" ? false : "inline-source-map";

    return {
        mode: mode,
        entry: './web/index.js',
        output: {
            filename: 'bundle.js',
            path: dist
        },
        optimization: {
            usedExports: true,
        },
        devServer: {
            static: {
                directory: dist
            },
            port: 8888
        },
        module: {
            rules: [{
                test: /\.(sa|sc|c)ss$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'sass-loader',
                ],
            }, {
                test: /\.(ttf|eot|woff|woff2|svg)$/,
                use: {
                    loader: 'file-loader',
                    options: {
                        name: '[name].[ext]',
                        outputPath: 'fonts/'
                    },
                },
            }, {
                test: /\.vue$/,
                loader: 'vue-loader'
            }]
        },
        plugins: [
            new CleanWebpackPlugin(),
            new DefinePlugin({
                __VUE_OPTIONS_API__: false,
                __VUE_PROD_DEVTOOLS__: false,
            }),
            new HtmlWebpackPlugin({
                template: path.resolve("./web/index.html")
            }),
            new VueLoaderPlugin()
        ],
        resolve: {
            extensions: ['.js'],
            alias: {
                "@": path.resolve(__dirname, 'web')
            }
        },
        devtool
    };
};

Solution

  • I found the problem but I don't understand why webpack drops it.

    Quote from https://webpack.js.org/guides/tree-shaking/

    Note that any imported file is subject to tree shaking. This means if you use something like css-loader in your project and import a CSS file, it needs to be added to the side effect list so it will not be unintentionally dropped in production mode:

    In my package.json I put

    "sideEffects": false,
    

    to be able to use treeshaking.
    But I had to disable it in the loader rule

    {
      test: /\.(sa|sc|c)ss$/,
      use: ['style-loader','css-loader','sass-loader'],
      sideEffects: true <----
    }