0

I'm attempting to output a css file from bootstrap 4.0.0 beta scss using webpack. I've successfully handled scss with an inline style injection as per: https://getbootstrap.com/docs/4.0/getting-started/webpack/ . There are issues related to having the style injected into the head of the document.

here's my package.json:

{
  "name": "testproject",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/knockout": "^3.4.46",
    "bootstrap": "^4.0.0-beta",
    "css-loader": "^0.28.7",
    "extract-text-webpack-plugin": "^3.0.1",
    "html-webpack-plugin": "^2.30.1",
    "jquery": "^3.2.1",
    "knockout": "^3.4.2",
    "node-sass": "^4.5.3",
    "popper.js": "^1.12.5",
    "postcss-loader": "^2.0.8",
    "precss": "^2.0.0",
    "sass-loader": "^6.0.6",
    "style-loader": "^0.19.0",
    "ts-loader": "^3.0.2",
    "typescript": "^2.5.3",
    "url-loader": "^0.6.2",
    "webpack": "^3.7.1",
    "webpack-notifier": "^1.5.0"
  },
  "-vs-binding": {
    "BeforeBuild": [
      "build"
    ]
  },
  "dependencies": {}
}

and my webpack.config.js (updated):

var path = require('path');
var webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const extractScss = new ExtractTextPlugin({
    filename: 'dist/[name].[hash].css',
    allChunks: true,
});

module.exports = {
    entry: {
        site: [
            './wwwroot/js/site.js',
            './Script/testkoviewmodel.ts'],
    },
    output: {
        publicPath: "/dist/",
        path: path.join(__dirname, '/wwwroot/dist/'),
        filename: '[name].[hash].build.js',
    },
    plugins: [
        extractScss,
        new webpack.optimize.UglifyJsPlugin({
            minimize: true,
            compress: {
                warnings: false
            },
        }),
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery',
            Popper: ['popper.js', 'default'],
        }),
        new HtmlWebpackPlugin({
            inject: false,
            template: 'Views/Shared/_LayoutTemplate.cshtml',
            filename: '../../Views/Shared/_Layout.cshtml',
        }),        
    ],
    devtool: 'source-map',
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: 'ts-loader',
                exclude: /node_modules/,
            },
            { test: /\.css$/, loader: "style-loader!css-loader" },
            {
                test: /\.scss$/,
                use: extractScss.extract({
                    fallback: 'style-loader',
                    use: ['css-loader', 'sass-loader']
                }),
                exclude: /node_modules/,
            },
            { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
            { test: /\.(woff|woff2)$/, loader: "url?prefix=font/&limit=5000" },
            { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
            { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml" },
        ]
    },
    resolve: {
        extensions: ['.ts', '.tsx', '.js', '.scss'],
    }
};

I've tried all manner of modifications to the webpack config as per many many posts of people all having the same or related issue. So far I've obviously been unsuccessful.

**EDIT !important : The entire problem is the exclude properties should be QUOTED as they are not regex but strings in this case. Thanks to BudHead!

billy jean
  • 1,399
  • 4
  • 25
  • 45

1 Answers1

1

Assuming you are importing bootstrap 4 like so in your entry js:

import 'bootstrap/scss/bootstrap.scss';

...try the following plugin setup:

const extractScss = new ExtractTextPlugin({
  filename: 'assets/css/[name].[contenthash].css',
  allChunks: true
});

... add the above to your plugins array:

plugins: [extractScss]

... and then in your rules:

{
  test: /\.scss$/,
  use: extractScss.extract({
    fallback: 'style-loader',
    //resolve-url-loader may be chained before sass-loader if necessary
    use: ['css-loader', 'sass-loader']
  })
}

So it's important to construct your ExtracTextPlugin, here I have mine set to the

const extractScss = new ExtractTextPlugin(...)

That way later on in your rules configuration you are passing the same object. In your code above you are using the imported instance of ExtractTextPlugin not the new one you created in your plugins array (which has no options set).

You'll probably have to adjust the filename in the plugin options, mine is set to go to something like assets/css/main.awef32fq23faf23aasdf.css

Budhead2004
  • 579
  • 4
  • 10
  • This is the solution. Thanks for pointing out the scope issue! I'm no longer getting the error. I am however, unable to actually generate the css file. Do i need to add .scss and .css to my resolve declaration? – billy jean Oct 18 '17 at 15:02
  • The extractTextPlugin with css and sass loader should extract everything to it's own .css file. There may be something else wrong. Verify the filename property in the extractTextPlugin matches what you have in your output object. – Budhead2004 Oct 18 '17 at 15:42
  • Are you sure i only need to import 'bootstrap'; No reference to the bootstrap.scss needed? Also, where in the output would the css file need to be defined? I'm starting to wonder if the reason i am not getting the error about the @ is because nothing is being processed? – billy jean Oct 18 '17 at 15:56
  • You are correct I have updated the import statement above to include the .scss file. My bad, I am using a custom theme, so I import my theme: import("./assets/scss/theme.scss"); and in that theme file I have a reference to boostrap.scss (@import "~bootstrap/scss/bootstrap";) – Budhead2004 Oct 18 '17 at 16:02
  • So now I'm back to the original error: ERROR in ./node_modules/bootstrap/scss/bootstrap.scss Module parse failed: D:\ProjectSourceCode\SupplyChainIQ\SupplyChainIQ\node_modules\bootstrap\scss\bootstrap.scss Unexpected character '@' (8:0) – billy jean Oct 18 '17 at 16:39
  • @billyjean Can you update your code to your current webpack.config.js? – Budhead2004 Oct 18 '17 at 17:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/157020/discussion-between-budhead2004-and-billy-jean). – Budhead2004 Oct 18 '17 at 17:18