Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use Bootstrap 4 and Sass (and jQuery) #215

Closed
alvipeo opened this issue Jan 11, 2016 · 31 comments
Closed

How to use Bootstrap 4 and Sass (and jQuery) #215

alvipeo opened this issue Jan 11, 2016 · 31 comments

Comments

@alvipeo
Copy link

alvipeo commented Jan 11, 2016

ok, I'm not a pro neither in webpack nor any of these new shiny 0.x.x version tech YET, so... But just in case someone would need it, here's how I got Bootstrap 4 (alpha now) + sass working:

  1. npm install bootstrap-loader --save
  2. npm install jquery --save
  3. npm install bootstrap@4.0.0-alpha.2 --save
  4. npm install css-loader node-sass resolve-url-loader sass-loader style-loader url-loader --save-dev
  5. Added autoprefixer to web.config.js (to use with postcss - optional):
    const autoprefixer = require('autoprefixer');

    postcss: [autoprefixer],  // this is inside module.exports object
  1. Add loaders to webpack.config.js:
        { test: /\.scss$/, loaders: ['style', 'css', 'postcss', 'sass'] },
        { test: /\.(woff2?|ttf|eot|svg)$/, loader: 'url?limit=10000' },
        // Bootstrap 4
        { test: /bootstrap\/dist\/js\/umd\//, loader: 'imports?jQuery=jquery' }

  1. Add jQuery plugin to webpack.config.js (to plugins array):
        new ProvidePlugin({
            jQuery: 'jquery',
            $: 'jquery',
            jquery: 'jquery'
        })
  1. Add to the end of vendor.ts:
    import 'jquery';
    import 'bootstrap-loader';
  1. Add some Bootstrap markup to your home.html to see that it works

Resulting webpack.config.js:

// @AngularClass

/*
 * Helper: root(), and rootDir() are defined at the bottom
 */
var path = require('path');
// Webpack Plugins
var ProvidePlugin = require('webpack/lib/ProvidePlugin');
var DefinePlugin = require('webpack/lib/DefinePlugin');
var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ENV = process.env.ENV = process.env.NODE_ENV = 'development';
const autoprefixer = require('autoprefixer');

var metadata = {
    title: 'IlgGallery UI',
    baseUrl: '/',
    host: '192.168.1.2',
    port: 3000,
    ENV: ENV
};
/*
 * Config
 */
module.exports = {
    // static data for index.html
    metadata: metadata,
    // for faster builds use 'eval'
    devtool: 'source-map',
    debug: true,

    entry: {
        'vendor': './src/vendor.ts',
        'main': './src/main.ts' // our angular app
    },

    // Config for our build files
    output: {
        path: root('dist'),
        filename: '[name].bundle.js',
        sourceMapFilename: '[name].map',
        chunkFilename: '[id].chunk.js'
    },

    resolve: {
        // ensure loader extensions match
        extensions: ['', '.ts', '.js', '.json', '.css', '.html']
    },

    module: {
        preLoaders: [{ test: /\.ts$/, loader: 'tslint-loader', exclude: [/node_modules/] }],
        loaders: [
            // Support for .ts files.
            {
                test: /\.ts$/,
                loader: 'ts-loader',
                query: {
                    'ignoreDiagnostics': [
                        2403, // 2403 -> Subsequent variable declarations
                        2300, // 2300 -> Duplicate identifier
                        2374, // 2374 -> Duplicate number index signature
                        2375  // 2375 -> Duplicate string index signature
                    ]
                },
                exclude: [/\.(spec|e2e)\.ts$/, /node_modules\/(?!(ng2-.+))/]
            },

            // Support for *.json files.
            { test: /\.json$/, loader: 'json-loader' },

            // Support for CSS as raw text
            { test: /\.css$/, loader: 'raw-loader' },

            // support for .html as raw text
            { test: /\.html$/, loader: 'raw-loader' },

            // if you add a loader include the resolve file extension above

            { test: /\.scss$/, loaders: ['style', 'css', 'postcss', 'sass'] },
            { test: /\.(woff2?|ttf|eot|svg)$/, loader: 'url?limit=10000' },
            // Bootstrap 4
            { test: /bootstrap\/dist\/js\/umd\//, loader: 'imports?jQuery=jquery' }
        ]
    },

    // sassResources: path.resolve(__dirname, "./node_modules/bootstrap/scss"),

    postcss: [autoprefixer],

    plugins: [
        new CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.bundle.js', minChunks: Infinity }),
        // static assets
        new CopyWebpackPlugin([{ from: 'src/assets', to: 'assets' }]),
        // generating html
        new HtmlWebpackPlugin({ template: 'src/index.html', inject: false }),
        // replace
        new DefinePlugin({
            'process.env': {
                'ENV': JSON.stringify(metadata.ENV),
                'NODE_ENV': JSON.stringify(metadata.ENV)
            }
        }),
        new ProvidePlugin({
            jQuery: 'jquery',
            $: 'jquery',
            jquery: 'jquery'
        })
    ],

    // Other module loader config
    tslint: {
        emitErrors: false,
        failOnHint: false
    },
    // our Webpack Development Server config
    devServer: {
        port: metadata.port,
        host: metadata.host,
        historyApiFallback: true,
        watchOptions: { aggregateTimeout: 300, poll: 1000 }
    },
    // we need this due to problems with es6-shim
    node: { global: 'window', progress: false, crypto: 'empty', module: false, clearImmediate: false, setImmediate: false }
};

// Helper functions

function root(args) {
    args = Array.prototype.slice.call(arguments, 0);
    return path.join.apply(path, [__dirname].concat(args));
}

function rootNode(args) {
    args = Array.prototype.slice.call(arguments, 0);
    return root.apply(path, ['node_modules'].concat(args));
}

I haven't changed webpack.prod.config.js so authors could help us out here please.

@alvipeo alvipeo changed the title How to use Bootstrap 4 and Sass How to use Bootstrap 4 and Sass (and jQuery) Jan 11, 2016
@PatrickJS
Copy link
Owner

@ackzell
Copy link

ackzell commented Jan 20, 2016

Hey @alvipeo, thanks a lot for sharing how to do this.

I noticed something (and maybe is that I'm just tired) with a couple of the classes I'm trying to apply, namely btn-success-outline and pull-xs-right, these don't seem to get applied to the elements I am working with. Do you happen to have gone through this as well?

@ackzell
Copy link

ackzell commented Jan 21, 2016

I figured it out, it is loading Bootstrap version 3, not 4 as I intended.

From https://github.com/shakacode/bootstrap-loader/

You need to have a .bootstraprc that explicitly uses version 4, like so:

https://github.com/shakacode/bootstrap-loader/blob/master/.bootstraprc-4-default

This fixed it for me.

@rvalimaki
Copy link

I'm quite sure that I carefully replicated all above steps, and still the production build fails:

c:\path\to\angular2-webpack-starter\node_modules\webpack-md5-hash\plugin\webpack_md5_hash.js:27
var source = chunk.modules.sort(compareModules).map(getModuleSource).reduce(concatenateSource);
^

TypeError: Reduce of empty array with no initial value
at Array.reduce (native)
at Compilation. (C:\fastems\MMS5\MMS_NG\angular2-webpack-starter\node_modules\webpack-md5-hash\plugin\webpack_md5_hash.js:27:82)
at Compilation.applyPlugins (C:\fastems\MMS5\MMS_NG\angular2-webpack-starter\node_modules\webpack\node_modules\tapable\lib\Tapable.js:26:37)

Debug build is working fine, as well as production build without jQuery, SASS & bootstrap.

EDIT: that particular problem was due to missing empty line at the end of vendors.ts file

@Znow
Copy link

Znow commented Jan 21, 2016

When following the above guidelines, im getting:

ERROR in Cannot find module 'babel/polyfill'
 @ ./~/bootstrap-loader/loader.js 1:0-44

Tried googling like hell, looking through issues etc, nothing.

@ollwenjones
Copy link

@Znow I'm not using this setup, but boostrap 4 is written in ES6, so I'm guessing the babel is a dependency of the bootsrap-loader. You have it npm installed as a dev dependency?

@ackzell
Copy link

ackzell commented Jan 21, 2016

What version of node are you using @Znow ? I think I upgraded my node version and that fixed it. (you could use something like nvm if you are able to so you avoid the risk of breaking something by upgrading your node)

@Znow
Copy link

Znow commented Jan 21, 2016

@ackzell Just updated node to latest, now I get another error:

image

Along with this in Chrome DevTools:

image

@ackzell
Copy link

ackzell commented Jan 21, 2016

@Znow I didn't encounter that, sorry. Maybe removing the node_modules folder and $ npm install again?

@PatrickJS
Copy link
Owner

Cannot find module is a typescript error where you should provide type definitions for the module. you can also declare the module it as type any. I should probably add a note about this

@PatrickJS
Copy link
Owner

when you see the error Cannot find module x you need to include the type definition. see https://github.com/AngularClass/angular2-webpack-starter/blob/master/src/custom_typings.d.ts

@manavsehgal
Copy link

Referencing in #199, consolidating UI/style related issues.

@jgrannas
Copy link

So I set this up without postcss, but what is the proper way to pull in scss files into my components?

In my component:
@Component({ selector: 'about', templateUrl: 'app/components/about/about.html', styles: [require('./about.scss')], providers: [Mockable], directives: [MockableList, ROUTER_DIRECTIVES], pipes: [] })

In my webpack.config.js in loaders array:
{ test: /\.scss$/, loaders: ['style', 'css', 'sass'] },

I am getting an error

EXCEPTION: TypeError: s.replace is not a function

So I tried to change the loader to this:
{ test: /\.scss$/, loader: 'raw-loader!sass-loader' },

Which got rid of the error, but my css is rendered with encapsulation and looks like my component is not encapsulated:
body.test[_ngcontent-gpk-3] { background: red; } body.test[_ngcontent-gpk-3] h3[_ngcontent-gpk-3] { color: #FFF; } body.test[_ngcontent-gpk-3] a[_ngcontent-gpk-3] { color: #FFF; }

So what would be the best way to have a "global" scss stylesheet, and then use component scss stylesheets together? I think I have gotten the global part, by turning off viewEncapsulation on the root app, but then do I need to turn it on for every single component inside the app to get the styles to work properly?

I guess basically I am asking how to overwrite the css for the body tag from a component stylesheet.

@kahboom
Copy link

kahboom commented Mar 30, 2016

@jgrannas - Not sure if this is what you're referring to, but I have it set up to use a global main.scss file located in a separate directory called /assets/scss. That main SCSS file is referenced in the main/top-level AppComponent. It can then import other SCSS files like _common.scss. Even though viewEncapsulation is turned off for the primary component I can still require SCSS files for specific components and it works fine.

Try using the following for the loaders in your webpack.config.js:
loaders: ['raw-loader', 'sass-loader']

See what I have and maybe it will help:

pietro909 pushed a commit to pietro909/angular2-webpack-playground that referenced this issue May 30, 2016
@lpalli
Copy link

lpalli commented Jun 2, 2016

Using loaders: ['raw-loader', 'sass-loader'] instead of loaders: ['style', 'css', 'postcss', 'sass'] solved my problems using scss in the current webpack.

@IAMtheIAM
Copy link

If you use style-loader, then you can't put your scss inside the Angular2 @component decorator. It has to go above/outside of it, the non-angular way.

@lpalli
Copy link

lpalli commented Jun 7, 2016

I used loaders: ['raw-loader', 'sass-loader'] and I can put the scss in the @component decorator:

@Component({
  selector: 'app',
  directives: [ RouterActive ],
  styles: [ require('./app.scss') ],
  template: require('./app.html'),
  ...
})

@opsxcq
Copy link

opsxcq commented Jul 14, 2016

This guide is a little bit outdated, can anyone update it ?

@kjartanvalur
Copy link

Can anyone update this?

@lpalli
Copy link

lpalli commented Sep 9, 2016

Yesterday I was able to integrate Boostrap 4, Sass and jQuery using the informations on this "issue" on the "last" commit of the master branch. Maybe I can update the information on this issue or it's best to make a new one?

@kjartanvalur
Copy link

@lpalli Can you please share your info on this. e.g. do you use require('bootstrap-loader') or do you somehow reference in webpack.config?

@lhammond
Copy link

@lpalli @kjartanvalur I'm also curious about this.

@kahboom
Copy link

kahboom commented Sep 12, 2016

@kjartanvalur @lhammond - Not sure if you're asking how to load the styles within the Angular 2 Component decorator, in which case my solution won't help. Also not sure if this is how @lpalli did it or was what he referring to, but I was able to integrate jQuery, Bootstrap 4, and Sass without using the bootstrap-loader, instead using the sass-loader and raw-loader as dev dependencies installed with npm, since I was also using Sass for each component. I added the following to the config/webpack.common.js file, under module.exports[module][loaders]:

// File loader for supporting images, for example, in CSS files.
{
  test: /\.(jpg|png|gif)$/,
  loader: 'file'
},

// SCSS Loader
{
test: /\.scss$/,
loaders: ['style', 'css', 'sass']
//loaders: ['raw-loader', 'sass-loader']
},

// Fonts
{
test: /\.(woff2?|ttf|eot|svg)$/,
loader: 'url?limit=10000'
},

// Bootstrap 4
{
test: /bootstrap\/dist\/js\/umd\//,
loader: 'imports?jQuery=jquery'
}

Then under module.exports[plugins] I added the following (I needed c3 and d3, but you could leave those out):

// Plugin: jQuery
new ProvidePlugin({
    jQuery: 'jquery',
    $: 'jquery',
    jquery: 'jquery',
    c3: 'c3',
    d3: 'd3',
    'Tether': 'tether',
    'window.Tether': 'tether'
}),

And then would reference SCSS files from the component (ie src/app/dashboard/dashboard.component.ts) like this:

declare var $: any;

require('./dashboard.scss');

@Component({
    selector: 'dashboard',
    providers: [
        Title
    ],
    templateUrl: './dashboard.html'
})

The bad thing about this is that you lose the benefits of Angular 2's ViewEncapsulation, which means I have to require() each SCSS file within the component at the top of the file instead of within the Component decorator (using ViewEncapsulation) as of Webpack 2. I'm okay with that, as I don't see the huge benefit yet, but am still looking at other solutions to keep things the "Angular way". I'm also biased toward Node.js and am used to just require()ing things. Global SCSS files (if you have one or two) can be resolved by adding it to the loader chain with require('!!style!css!sass!./example.scss'), for example, but that's a whole other issue.

If you're interested in a working reference, you can see the repo I'm working on with the changes here, or just my personal fork that gets updated a bit more frequently here. It uses the latest changes in angular2-webpack-starter with Webpack 2, no Angular Material, just Bootstrap and a pattern library that uses Bootstrap under the covers called PatternFly (optional). Just my preference because I personally dislike Angular Material. To try it out:

git clone git@github.com:hawtio/hawtio-ipaas.git
cd hawtio-ipaas
npm install
npm start

Hope this helps someone!

@kahboom
Copy link

kahboom commented Sep 14, 2016

...aand actually the guide has been updated since I last checked, and instructions are working for me (including both global styles and referencing Sass within Angular's Component decorator, using ViewEncapsulation). So you can just install Bootstrap 4 with npm install bootstrap@4.0.0-alpha.4 and follow this guide: https://github.com/AngularClass/angular2-webpack-starter/wiki/How-to-include-SCSS-in-components

@alissonrayan
Copy link

To install bootstrap 3.

npm install bootstrap-loader
npm install --save-dev bootstrap-sass
npm install --save-dev css-loader node-sass resolve-url-loader sass-loader style-loader url-loader

In src/vendor.browser.ts add the following line:
import 'bootstrap-loader';

In config/webpack.common.js add the following loaders:

{ test:/bootstrap-sass[\/\\]assets[\/\\]javascripts[\/\\]/, loader: 'imports?jQuery=jquery' },
{ test: /\.(woff2?|svg)$/, loader: 'url?limit=10000' },
{ test: /\.(ttf|eot)$/, loader: 'file' },
{ test: /\.scss$/, loaders: ['style', 'css', 'postcss', 'sass'] }

It works fine for me.

@d-campion
Copy link

Hello, I follow the post https://github.com/AngularClass/angular2-webpack-starter/wiki/How-to-use-Bootstrap-4-and-Sass-(and-jQuery)

But I have one big problem :(

image

If, you have any solution ?

Thanks

@dhoffi
Copy link

dhoffi commented Dec 19, 2016

I did anything I found (not only from here) but did not succeed in getting bootstrap integrated with webpack starter.
Where I am so far can be found at git@gitlab.com:hoffi_examples/angular2-spring-boot.git

still get:

ERROR in ./~/bootstrap-loader/lib/bootstrap.loader.js!./~/bootstrap-loader/no-op.js
Module not found: Error: Can't resolve 'style' in '/Users/hoffmd9/DBs/git/examples/angular2/angular2-spring-boot/angular2-spring-boot-frontend/node_modules/bootstrap-loader'
BREAKING CHANGE: It's no longer allowed to omit the '-loader' prefix when using loaders.
                 You need to specify 'style-loader' instead of 'style'.
 @ ./~/bootstrap-loader/lib/bootstrap.loader.js!./~/bootstrap-loader/no-op.js 1:21-1267
 @ ./~/bootstrap-loader/loader.js
 @ multi bootstrap-loader

and things are not bootstrap on html yet sigh

anybody?

@d-campion
Copy link

Hello, I think you can try this :
if you have install "style"
uninstall "style" on your project and try this : npm install "style-loader" --save-dev

And, if is not working what is your version of webpack ?

@dhoffi
Copy link

dhoffi commented Dec 19, 2016

no, already had "style-loader": "^0.13.1" in package.json and no "style" anywhere.

├─┬ assets-webpack-plugin@3.5.0
├─┬ copy-webpack-plugin@4.0.1
├─┬ extract-text-webpack-plugin@1.0.1
│ └─┬ webpack-sources@0.1.3
├─┬ html-webpack-plugin@2.24.1
├─┬ karma-webpack@1.8.0
├── script-ext-html-webpack-plugin@1.3.4
├── v8-lazy-parse-webpack-plugin@0.3.0
├─┬ UNMET PEER DEPENDENCY webpack@2.1.0-beta.27
├─┬ webpack-dev-middleware@1.9.0
├─┬ webpack-dev-server@2.1.0-beta.11
├─┬ webpack-md5-hash@0.0.5
├─┬ webpack-merge@1.0.2

@pnowy
Copy link

pnowy commented Feb 2, 2017

What I did to make it work (Bootstrap3):

npm install --save-dev bootstrap-sass

On the webpack.common.js I've added the following loaders:

{test:/bootstrap-sass[\/\\]assets[\/\\]javascripts[\/\\]/, loader: 'imports?jQuery=jquery' },
{test: /\.woff(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000" },
{test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" }

and on the end I've put on the styles.scss:

$bootstrap-sass-asset-helper: true;
@import "~bootstrap-sass/assets/stylesheets/bootstrap";

For the JS components I've used the ng2-bootstrap.

@syed-haroon
Copy link

This is for someone who is looking for VUE.JS 2 and Bootstrap 4 solution:
Stack overflow: http://stackoverflow.com/a/43383449/1292050
Git setup https://github.com/syed-haroon/vue-js-2-basic-setup

I also encourage you to take look at this URL for more sophisticate work setup https://github.com/prograhammer/example-vue-project

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests