symfony / webpack-encore

A simple but powerful API for processing & compiling assets built around Webpack
https://symfony.com/doc/current/frontend.html
MIT License
2.23k stars 200 forks source link

Import global scss rules in vue components #807

Open jwillp opened 4 years ago

jwillp commented 4 years ago

Hi all, How can one import scss files globally for vue components: Similar to how it is done with vue-cli:

// vue.config.js
const path = require('path')

module.exports = {
    pluginOptions: {
        'style-resources-loader': {
            preProcessor: 'scss',
            patterns: [
                path.resolve(__dirname, './assets/css/_variables.scss'),
                path.resolve(__dirname, './assets/css/_responsive-utilities.mixins.scss'),
            ]
        }
    },
}

I looked everywhere I could, but did not manage to find a solution.

Kocal commented 4 years ago

You can use sass-loader's additionalData option.

This should work:

Encore.enableSassLoader(options => {
  options.additionalData = `
@import "${path.resolve(__dirname, './assets/css/_variables.scss')}";
@import "${path.resolve(__dirname, './assets/css/_responsive-utilities.mixins.scss')}";
`
});
jwillp commented 4 years ago

Thank you for your answer, unfortunately it does not work. Vue Components complain about the variables not being defined

Kocal commented 4 years ago

Surely because vue-style-loader is not used, see https://vue-loader.vuejs.org/guide/pre-processors.html#sharing-global-variables.

Encore use style-loader and not vue-style-loader, when CSS extraction is disabled, see https://github.com/symfony/webpack-encore/blob/a7d76ee0661ddeac35e241e1f48962dbf6123906/lib/loaders/css-extract.js#L32.

You can try to play with Encore.configureLoaderRule('css', option => {}) to use vue-style-loader instead, see https://symfony.com/doc/current/frontend/encore/advanced-config.html#having-the-full-control-on-loaders-rules and https://github.com/symfony/webpack-encore/blob/master/test/config-generator.js#L1169-L1370 for more information.

jwillp commented 4 years ago

Thank you again for this, however, I can't seem to wrap my head around what I am supposed to do. Given that I don't really know the internals of webpack-encore:

I tried the following:

    .configureLoaderRule('scss', (loaderRule) => {
        loaderRule.use = {
            loader: require.resolve('vue-style-loader'),
            options: {
                additionalData: `
                    @import "${path.resolve(__dirname, './assets/css/_variables.scss')}";
                    @import "${path.resolve(__dirname, './assets/css/_responsive-utilities.mixins.scss')}";
                `
            }
        }
    })

    .configureLoaderRule('css', (loaderRule) => {
        loaderRule.use = {
            loader: require.resolve('vue-style-loader'),
            options: {}
        }
    })
jwillp commented 4 years ago

I finally managed to do it using the sass-resources-loader with the following configuration:

    .configureLoaderRule('scss', (loaderRule) => {
        loaderRule.oneOf.forEach((rule) => {
            rule.use.push({
                loader: 'sass-resources-loader',
                options: {
                    // Provide path to the file with resources
                    // Or array of paths
                    resources: [
                        path.resolve(__dirname, './assets/css/_variables.scss'),
                        path.resolve(__dirname, './assets/css/_responsive-utilities.mixins.scss'),
                    ]
                },
            })
        })

However, I do think that an official configuration method could be a nice addition as this is, in my opinion, a pretty common use case when working with vue.js.

dimti commented 4 years ago

I finally managed to do it using the sass-resources-loader with the following configuration:

    .configureLoaderRule('scss', (loaderRule) => {
        loaderRule.oneOf.forEach((rule) => {
            rule.use.push({
                loader: 'sass-resources-loader',
                options: {
                    // Provide path to the file with resources
                    // Or array of paths
                    resources: [
                        path.resolve(__dirname, './assets/css/_variables.scss'),
                        path.resolve(__dirname, './assets/css/_responsive-utilities.mixins.scss'),
                    ]
                },
            })
        })

However, I do think that an official configuration method could be a nice addition as this is, in my opinion, a pretty common use case when working with vue.js.

Does not work for me.

Default scss files - accept that shared variables But scss style in vue-component - not.

I need to customize vue-library https://github.com/JosephusPaye/Keen-UI/blob/master/Customization.md#customization But unable to it with configureLoaderRule