2
votes

Currently, I am trying to load my scss files and font-awesome with Webpack3.

Here is my webpack.config.js

const autoprefixer = require('autoprefixer');
const path = require('path');
const webpack = require('webpack');
const precss = require('precss');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
    entry: [
        './Scripts/app.ts',
        './Scripts/scss/main.scss',
        //'font-awesome/scss/font-awesome.scss',
        'tether'
    ],
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, './Scripts/dist')
    },
    module: {
        rules: [
            {
                loader: 'ts-loader',
                test: /\.ts$/,
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'postcss-loader'
                ]
            },
            {
                test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                use: 'url-loader?limit=10000'
            },
            {
                test: /\.(ttf|eot|svg)(\?[\s\S]+)?$/,
                use: 'file-loader'
            },
            {
                test: /\.(jpe?g|png|gif|svg)$/i,
                use: [
                    'file-loader?name=images/[name].[ext]',
                    'image-webpack-loader?bypassOnDebug'
                ]
            },
            // font-awesome
            {
                test: /font-awesome\.config\.js/,
                use: [
                    { loader: 'style-loader' },
                    { loader: 'font-awesome-loader' }
                ]
            },
            // Bootstrap 4
            {
                test: /bootstrap\/dist\/js\/umd\//,
                use: 'imports-loader?jQuery=jquery'
            },
            // SCSS pre-processing
            {
                test: /\.(scss)$/,
                //use: ExtractTextPlugin.extract({
                //    fallback: 'style-loader',
                //    use: [
                //        // the order of the loaders cannot be changed
                //        {
                //            loader: 'css-loader',
                //            options: { minimize: false } // minifize css file
                //        }, // translates CSS into CommonJS modules
                //        {
                //            loader: 'postcss-loader', // Run post css actions
                //            options: {
                //                // post css plugins, can be exported to postcss.config.js
                //                plugins() {
                //                    return [precss, autoprefixer];
                //                }
                //            }
                //        },
                //        { loader: 'sass-loader' } // compiles SASS to CSS
                //    ]
                //})

                use: [{
                    loader: 'style-loader' // creates style nodes from JS strings
                }, {
                    loader: 'css-loader' // translates CSS into CommonJS
                }, {
                    loader: 'sass-loader' // compiles Sass to CSS
                }]
            }
        ]
    },
    resolve: {
        extensions: ['.ts', '.js']
    },
    plugins: [
        new ExtractTextPlugin('main.css', {
            allChunks: true
        }),
        // minify the bundled js files
        new webpack.optimize.UglifyJsPlugin({
            include: /\.js$/,
            minimize: true,
            sourceMap: true
        }),
        new webpack.ProvidePlugin({
            jQuery: 'jquery',
            jquery: 'jquery',
            $: 'jquery',
            tether: 'tether',
            Tether: 'tether',
            Popper: ['popper.js', 'default'],
            Alert: 'exports-loader?Alert!bootstrap/js/dist/alert',
            Button: 'exports-loader?Button!bootstrap/js/dist/button',
            Carousel: 'exports-loader?Carousel!bootstrap/js/dist/carousel',
            Collapse: 'exports-loader?Collapse!bootstrap/js/dist/collapse',
            Dropdown: 'exports-loader?Dropdown!bootstrap/js/dist/dropdown',
            Modal: 'exports-loader?Modal!bootstrap/js/dist/modal',
            Popover: 'exports-loader?Popover!bootstrap/js/dist/popover',
            Scrollspy: 'exports-loader?Scrollspy!bootstrap/js/dist/scrollspy',
            Tab: 'exports-loader?Tab!bootstrap/js/dist/tab',
            Tooltip: "exports-loader?Tooltip!bootstrap/js/dist/tooltip",
            Util: 'exports-loader?Util!bootstrap/js/dist/util'
        })
    ],
    devtool: 'source-map'
};

More details (based on the rules for .scss):

  1. I import the font-awesome scss in my main.scss using:
$fa-font-path: "~/node_modules/font-awesome/fonts";
@import '~font-awesome/scss/font-awesome.scss';
  1. the font and icons are reference to the packages in "node_moduldes" (which is not what I want in production)

  2. the build artifact would be just bundle.js

If I run webpack, it seems everything works. However, once we move to production, I am assuming that the icon/font links to the node_module would be broken.

here is my scss:

enter image description here

If I use the code that is commented out, font-awesome can be loaded properly but not my scss files.

details:

  • all the svg/ttf/eot files can be produced
  • the scss can be processed to css file, but when I load the pages, they look horrible.

My Question:

Is there any way I can load font-awesome with all the artifact and load my scss component properly(like production) with Webpack 3?

Thanks in advance.

1
I also faced the same issue, in lack of finding any solution i ended up writing a gulp task to move font-awesome related files to destination folder to be served to client.Deepak Kumar
Thanks @DeepakKumar It could be a temporary solution. However, I don't wanna introduce another tool to our build pipeline. It would be great if we can handle it well with webpack.Terence

1 Answers

1
votes

I spent some time diligently searching for a better solution. Here is my approach and it works as expected:

I reference to two resources:

  1. Using FontAwesome with Sass
  2. sass-loader: https://github.com/webpack-contrib/sass-loader

couple things I would love to emphasis:

  • how we "import" package. I move the import css file from my TypeScript file to main.scss. Everything works like a charm.
  • another important thing is that the sass-loader has rules for @import

webpack provides an advanced mechanism to resolve files. The sass-loader uses node-sass' custom importer feature to pass all queries to the webpack resolving engine. Thus you can import your Sass modules from node_modules. Just prepend them with a ~ to tell webpack that this is not a relative import:

@import "~bootstrap/dist/css/bootstrap";

It's important to only prepend it with ~, because ~/ resolves to the home directory. webpack needs to distinguish between bootstrap and ~bootstrap because CSS and Sass files have no special syntax for importing relative files. Writing @import "file" is the same as @import "./file";

from https://github.com/webpack-contrib/sass-loader

so here is my main.scss file:

@import '~bootstrap/dist/css/bootstrap.min.css';
@import '~inputmask/css/inputmask.css';

$fa-font-path: "~font-awesome/fonts";
@import '~font-awesome/scss/font-awesome.scss';

// import partials
@import "variables";
@import "mixins";

@import "accordion";
@import "buttons";
@import "cards";
@import "container";
@import "errors";
@import "fonts";
@import "form";
@import "headers";
@import "hyperlinks";
@import "tables";
@import "warnings";
@import "wcb-footer";
@import "wcb-header";

@import "asmt-report"; // optional