react/vue中引入scss全局变量

2019-04-13 · xiejiahe

应用场景

当我们在scss样式文件中想使用其他已经声明好的scss变量文件,通常会这么做:

// style.scss
@import "variables.scss";

body {
  color: $theme-color;
}

随着项目越来越大,每个样式文件都需要用到全局定义好的变量,这时就变得非常的笨重,弊端就暴露出来了。

下面来看看怎么去解决这个问题

安装sass-resouces-loader

npm i sass-resources-loader -D

sass-resources-loader 是什么? 官方是这么解释的:

这个加载器将 @import 您的SASS资源放入每个required SASS模块中。因此,您可以在所有SASS样式中使用共享变量和mixin,而无需在每个文件中手动导入它们。使用CSS模块!

可以这么去理解,当你新建了一个scss文件,这个loader会自动在顶部引入您指定的变量文件,这就能解决上述问题了。

react配置

如果使用的是官方提供的脚手架create-react-app 那就再好不过了,配置方式如下:

1、打开 config/webpack.config.js

2、找到如下代码

{
  test: sassRegex,
  exclude: sassModuleRegex,
  use: getStyleLoaders(
    {
      importLoaders: 2,
      sourceMap: isEnvProduction && shouldUseSourceMap,
    },
    'sass-loader'
  ),
  // Don't consider CSS imports dead code even if the
  // containing package claims to have no side effects.
  // Remove this when webpack adds a warning or an error for this.
  // See https://github.com/webpack/webpack/issues/6571
  sideEffects: true,
},

3、修改成如下

{
  test: sassRegex,
  exclude: sassModuleRegex,
  // 看源码可以看出来 getStyleLoaders 返回的是一个数组,所以我们可以用 concat把他合并
  use: getStyleLoaders(
    {
      importLoaders: 2,
      sourceMap: isEnvProduction && shouldUseSourceMap,
    },
    'sass-loader'
  ).concat({
    // 这行的意思是引入加载器 sass-resources-loader
    loader: 'sass-resources-loader',
    options: {
      // 这里是需要引入全局的资源文件,它可以是一个字符串或者是一个数组, 通常用数组去代替。
      resources: ['./src/assets/scss/_variables.scss', './src/assets/scss/mixins.scss']
    }
  }),
  // Don't consider CSS imports dead code even if the
  // containing package claims to have no side effects.
  // Remove this when webpack adds a warning or an error for this.
  // See https://github.com/webpack/webpack/issues/6571
  sideEffects: true,
},

4、启动项目即可


vue配置

vue配置就要分脚手架版本了,目前有 2.x和3.x, 大部分项目都陆续升级到3.x了,建议升级下。

vue-cli 2.x配置

1、打开 build/utils.js

2、找到 generateLoaders 函数, 大概是这样子

function generateLoaders (loader, loaderOptions) {
  const loaders = [cssLoader]
  if (loader) {
    loaders.push({
      loader: loader + '-loader',
      options: Object.assign({}, loaderOptions, {
        sourceMap: options.sourceMap
      })
    })
  }

  // Extract CSS when that option is specified
  // (which is the case during production build)
  if (options.extract) {
    return ExtractTextPlugin.extract({
      use: loaders,
      fallback: 'vue-style-loader'
    })
  } else {
    return ['vue-style-loader'].concat(loaders)
  }
}

3、修改成如下

function generateLoaders (loader, loaderOptions) {
  const loaders = [cssLoader]
  if (loader) {
    loaders.push({
      loader: loader + '-loader',
      options: Object.assign({}, loaderOptions, {
        sourceMap: options.sourceMap
      })
    })
  }

  if (loader === 'sass') {
    loaders.push({
      loader: 'sass-resources-loader',
      options: {
        // 注意这里是引入全局变量
        resources: ['./src/assets/scss/_variables.scss', './src/assets/scss/mixins.scss']
      },
    });
  }

  // Extract CSS when that option is specified
  // (which is the case during production build)
  if (options.extract) {
    return ExtractTextPlugin.extract({
      use: loaders,
      fallback: 'vue-style-loader'
    })
  } else {
    return ['vue-style-loader'].concat(loaders)
  }
}

vue-cli 3.x配置

我认为cli 3.x的配置会更人性化一些,统一配置在根项目的 vue.config.js 中,升级会变得更容易。

配置如下

// vue.config.js

const path = require('path');

module.exports = {
  chainWebpack: config => {
    const oneOfsMap = config.module.rule('scss').oneOfs.store
    oneOfsMap.forEach(item => {
      item
        .use('sass-resources-loader')
        .loader('sass-resources-loader')
        .options({
          resources: [path.resolve(__dirname, './src/assets/scss/variables.scss'), path.resolve(__dirname, './src/assets/scss/mixins.scss')]
        })
        .end()
    })
  }
}

总结

在中大型的项目中,sass-resources-loader是必不可少的,或者是其他的方法,这将大大的减少项目中的代码量,使得维护变得更容易。

Vue.jsReact
原创文章,转载请注明出处。