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

Bourbon Sass Mixin Library with vue-loader #95

Closed
tikiatua opened this issue Dec 7, 2015 · 8 comments
Closed

Bourbon Sass Mixin Library with vue-loader #95

tikiatua opened this issue Dec 7, 2015 · 8 comments

Comments

@tikiatua
Copy link

tikiatua commented Dec 7, 2015

Hi there,
Thank you for the amazing vue-loader. I have been looking for something similar for quite some time and really love the approach of keeping style, template and javascript of a component in a single file.

Is it at all possible to use the bourbon sass mixin library with the vue-loader? I did include it in the webpack setup in different ways but have not been able to use bourbon functions in my styles (i.e. the very handy tint-function).

Any help would be greatly appreciated.

var path = require('path');
var webpack = require('webpack');

var node_modules = path.resolve(__dirname, 'node_modules');
var pathToBourbon = require('node-bourbon').includePaths;

module.exports = {
    entry: {
        public: [path.resolve(__dirname, 'app/public/main.js')],
    },
    output: {
        path: path.resolve(__dirname, 'build/assets'),
        filename: '[name].bundle.js',
        publicPath: '/assets/'
    },
    module: {
        loaders: [
            {
                // parse vue components
                test: /\.vue$/,
                loader: 'vue',
                exclude: node_modules
            }, {
                // edit this for additional asset file types
                test: /\.(png|jpg|gif)$/,
                loader: 'file?name=[name].[ext]?[hash]',
                exclude: node_modules
            }, {
                // parse css styles
                test: /\.css$/,
                loader: 'style!css',
                exclude: node_modules
            }, {
                // parse scss styles
                test: /\.scss$/,
                loader: 'style!css!sass?includePaths[]=' + pathToBourbon
            }, {
                // parse javascript styles
                test: /\.js$/,
                loader: 'babel',
                exclude: node_modules
            }
        ],
    },
    vue: {
        loaders: {
            // scss loader-statement is required to make scss syntax work
            // however, includePaths do not seem to import the tint-function or any mixins
            scss: 'style!css!sass?includePaths[]=' + pathToBourbon
        }
    },
    sassLoader: {
        includePaths: [pathToBourbon]
    },
    babel: {
        presets: ['es2015', 'stage-0'],
        plugins: ['transform-runtime']
    }
};

if (process.env.NODE_ENV === 'production') {
  module.exports.plugins = [
    new webpack.DefinePlugin({
        'process.env': {
            NODE_ENV: '"production"'
        }
    }),
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        }
    }),
    new webpack.optimize.OccurenceOrderPlugin()
    ]
} else {
    module.exports.devtool = '#source-map'
}

Example component

<style lang="scss">
$custom-red: red;
.header {
    color: $custom-red;
    border: 1px solid tint($custom-red, 20%);
}
</style>

<template>
    <div class="header">
        <h1>Custom header content</h1>
    </div>
</template>

<script>
    module.exports = {}
</script>
``
@yyx990803
Copy link
Member

You still need to @import "bourbon" because each file is compiled individually.

@tikiatua
Copy link
Author

tikiatua commented Dec 8, 2015

Brilliant! Could have thought of that myself. Thank you very much for your help.

For all those that need a working example:

// webpack.config.js
var path = require('path');
var webpack = require('webpack');

var node_modules = path.resolve(__dirname, 'node_modules');
var pathToBourbon = require('node-bourbon').includePaths;

module.exports = {
    entry: {
        public: [path.resolve(__dirname, 'app/public/main.js')],
    },
    output: {
        path: path.resolve(__dirname, 'build/assets'),
        filename: '[name].bundle.js',
        publicPath: '/assets/'
    },
    module: {
        loaders: [
            {
                // parse vue components
                test: /\.vue$/,
                loader: 'vue',
                exclude: node_modules
            }, {
                // edit this for additional asset file types
                test: /\.(png|jpg|gif)$/,
                loader: 'file?name=[name].[ext]?[hash]',
                exclude: node_modules
            }, {
                // parse css styles
                test: /\.css$/,
                loader: 'style!css',
                exclude: node_modules
            }, {
                // parse scss styles
                test: /\.scss$/,
                loader: 'style!css!sass',
                exclude: node_modules
            }, {
                // parse javascript styles
                test: /\.js$/,
                loader: 'babel',
                exclude: node_modules
            }
        ],
    },
    vue: {
        loaders: {
            scss: 'style!css!sass',
            exclude: node_modules
        }
    },
    sassLoader: {
        includePaths: [pathToBourbon]
    },
    babel: {
        presets: ['es2015', 'stage-0'],
        plugins: ['transform-runtime']
    }
};

if (process.env.NODE_ENV === 'production') {
  module.exports.plugins = [
    new webpack.DefinePlugin({
        'process.env': {
            NODE_ENV: '"production"'
        }
    }),
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        }
    }),
    new webpack.optimize.OccurenceOrderPlugin()
    ]
} else {
    module.exports.devtool = '#source-map'
}

// vue component
<style lang="scss">
@import "bourbon";
$custom-red: red;
.header {
    color: $custom-red;
    border: 1px solid tint($custom-red, 20%);
}
</style>

<template>
    <div class="header">
        <h1>Custom header content</h1>
    </div>
</template>

<script>
    module.exports = {}
</script>

// extract from package.json (assuming that compiled files are in /build directory)
{
  "scripts": {
    "dev": "webpack-dev-server --content-base build/ --inline --hot --quiet",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
  }
}

// running in console with  "npm run dev"

@ryandeussing
Copy link

And if you want bourbon + neat:

npm install --save-dev node-neat

var sassPaths = require("node-neat").includePaths.map(function(sassPath) {
  return "includePaths[]=" + sassPath;
}).join("&");
...
...
...
sassLoader: {
  includePaths: [sassPaths] 
},
@import "~bourbon";
@import "~bourbon-neat";

@dolbex
Copy link

dolbex commented Mar 16, 2016

Thanks so much for the help on this thread. Saved my rear.

@gregorskii
Copy link

I am doing something similar to this with Concise.css, but this results in the concise.css included multiple times in the output sass file when using the ExtractTextPlugin to create a single css file. Although, even if it was multiple files each file would include all the css from Concise or Bourbon in it. Which seems to be a waste correct?

Should the SASS loader not create a commons chunk with Bourbon/Concise load that first, as commons.css then use the same mixins from Bourbon/Concise on the other chunks?

Thanks

--- think this is covered here:
#110

@ericcirone
Copy link

ericcirone commented Sep 20, 2016

@gregorskii I'm hitting the same issue. I'm getting Foundation 6 to work with Vue and Vue-Loader. I have it all working as scss files outside of loader. But when I want to use sass variables inside vue-loader <style> blocks, I have to @import in each <style> block which, while using ExtractTextPlugin, will put foundation repeated in my output .css file. Is there any way to get vue-loader to have some common code loaded for the <style> block?

@ryandeussing
Copy link

@ericcirone see this thread: #110 - you can remove all the duplicate styles in your production build.

@billwing
Copy link

How to solved the error, pls?
File to import not found or unreadable: bourbon

App.vue

<style lang="scss">
  @import "bourbon";

  $custom-red: red;
  .header {
    color: $custom-red;
    border: 1px solid tint($custom-red, 20%);
  }
</style>

webpack.base.config.js

const path = require('path')
const vueConfig = require('./vue-loader.config')

module.exports = {
  devtool: '#source-map',
  entry: {
    app: './src/client-entry.js',
    vendor: ['vue', 'vue-router', 'vuex', 'firebase', 'lru-cache', 'es6-promise']
  },
  output: {
    path: path.resolve(__dirname, '../dist'),
    publicPath: '/dist/',
    filename: 'client-bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue',
        options: vueConfig
      },
      {
        test: /\.js$/,
        loader: 'babel',
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'url',
        options: {
          limit: 10000,
          name: '[name].[ext]?[hash]'
        }
      },
      {
        test: /\.scss$/,
        loader: 'style!css!sass',
        exclude: /node_modules/
      }
    ]
  }
}

vue-loader.config.js

const ExtractTextPlugin = require('extract-text-webpack-plugin')
const pathToBourbon = require('bourbon').includePaths

module.exports = {
  postcss: [
    require('autoprefixer')({
      browsers: ['last 3 versions']
    })
  ],
  sassLoader: {
    includePaths: [pathToBourbon]
  },
  loaders: {
    scss: 'style!css!sass',
    exclude: /node_modules/
  }
}

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

7 participants