在项目中,我们常会用到css预处理器 ,如sass,less, stylus,书写css变得非常便捷;项目中一般会建立公共样式文件,存放公共样式、公共变量、项目主题、基础样式混合方法,但是在项目中使用这些变量的时候通常都要在每个页面style标签内用@import引入,繁琐,所以需要使用webpack的相关配置全局注入公共文件
sass 全局变量注入
为了使用sass,我们需要安装sass的依赖包
npm install --save-dev sass-loader
npm install --save-dev node-sass //sass-loader依赖于node-sass
1、使用sass-resources-loader工具引入
- 添加依赖
npm install sass-resources-loader --save-dev
- 在项目build文件夹里找到utils.js ,定位到下边代码
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
将scss: generateLoaders('sass')进行修改
sass: generateLoaders('sass', {
indentedSyntax: true,
}),
scss: generateLoaders('sass').concat(
{
loader: 'sass-resources-loader',
options: {
//这里按照你的文件路径填写;多个文件时用数组的形式传入,如resources: [path.resolve(__dirname, '../src/styles/base/_variables.scss')]
resources: path.resolve(__dirname, '../src/styles/base/_variables.scss')
}
}),
当然也可以直接修改generateLoaders方法
function generateLoaders(loader, loaderOptions) {
const loaders = []
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
// loaders.push(MiniCssExtractPlugin.loader)
loaders.push({
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../../'
}
})
} else {
loaders.push('vue-style-loader')
}
loaders.push(cssLoader)
if (options.usePostCSS) {
loaders.push(postcssLoader)
}
if (loader) {
// 修改这一块,当使用sass-resources时也需要引入'sass-loader'
if (loader === 'sass-resources') {
loaders.push({
loader: 'sass-loader'
})
}
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
return loaders
}
// 全局文件引入 当然只想编译一个文件的话可以省去这个函数
function resolveResource(name) {
return path.resolve(__dirname, '../src/styles/base/' + name);
}
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass-resources', {
resources: [resolveResource('_variables.scss')]
}),
scss: generateLoaders('sass-resources', {
resources: [resolveResource('_variables.scss')]
}),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
2、向预处理器 Loader 传递选项实现全局变量注入
- 可以直接在vue.config.js中进行配置;可参考Vue CLI官方文档
// vue.config.js;这个方法我没有实践过,哈哈,但是官方文档应该还是很可信的
module.exports = {
css: {
loaderOptions: {
// 给 sass-loader 传递选项
sass: {
// @/ 是 src/ 的别名
// 所以这里假设你有 `src/variables.sass` 这个文件
// 注意:在 sass-loader v7 中,这个选项名是 "data"
prependData: `@import "~@/variables.sass"`
},
// 默认情况下 `sass` 选项会同时对 `sass` 和 `scss` 语法同时生效
// 因为 `scss` 语法在内部也是由 sass-loader 处理的
// 但是在配置 `data` 选项的时候
// `scss` 语法会要求语句结尾必须有分号,`sass` 则要求必须没有分号
// 在这种情况下,我们可以使用 `scss` 选项,对 `scss` 语法进行单独配置
scss: {
prependData: `@import "~@/variables.scss";`
},
// 给 less-loader 传递 Less.js 相关选项
less:{
// http://lesscss.org/usage/#less-options-strict-units `Global Variables`
// `primary` is global variables fields name
globalVars: {
primary: '#fff'
}
}
}
}
}
也可以直接在对应Loader 中的 loaderOptions 配置
//在项目build文件夹里找到utils.js
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
// @/ 是 src/ 的别名,使用的时候要加上~
// 注意:在 sass-loader v7 中,prependData这个选项名要改成 "data",我用的是v7,所以使用的data,要导入多个文件时,就直接import多个就行,如 : data: `
@import "~@/styles/base/_variables.scss";
@import "~@/styles/base/_mixins.scss"
`
// 默认情况下 `sass` 选项会同时对 `sass` 和 `scss` 语法同时生效,因为 `scss` 语法在内部也是由 sass-loader 处理的,但是在配置 `data` 选项的时候,`scss` 语法会要求语句结尾必须有分号,`sass` 则要求必须没有分号,在这种情况下,我们可以使用 `scss` 选项,对 `scss` 语法进行单独配置
sass: generateLoaders('sass', {
indentedSyntax: true,
data: `
@import "~@/styles/base/_variables.scss"`
}),
scss: generateLoaders('sass',{
data: `
@import "~@/styles/base/_variables.scss";`
}),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
less 全局变量注入
为了使用less,我们需要安装less的依赖包
npm install less less-loader --save-dev
1、使用sass-resources-loader工具引入
方法同sass引入方法,将sass-loader 改为 less-loader即可
2、使用style-resources-loader工具引入
安装依赖
npm i style-resources-loader -D
在项目build文件夹里找到utils.js
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less').concat({
loader: 'style-resources-loader',
options: {
patterns: path.resolve(__dirname, '../src/assets/styles/variables.less'),
injector: 'append'
}
}),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
3、可以为less-loader在加载时使用globalVars注入全局变量。
此选项定义文件可以引用的变量。实际上,该声明放置在基本Less文件的顶部,这意味着可以使用该声明,但是如果在文件中定义了此变量,也可以覆盖该声明。
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less',{
globalVars : {
@primary : #F97A73
}
}),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
或者处理对应less文件,获取所有的变量值;但是如果变量文件中出现引用关系的时候就会报错,例如 @primary : #F97A73;@button-primary-background-color: @primary;
//在项目build文件夹里找到utils.js
const fs = require('fs'); //使用时需要导入
// 读取less全局变量文件
function getLessVariables(file) {
var themeContent = fs.readFileSync(file, 'utf-8')
var variables = {}
themeContent.split('\n').forEach(function (item) {
if (item.indexOf('//') > -1 || item.indexOf('/*') > -1) { return }
var _pair = item.split(':')
if (_pair.length < 2) return;
var key = _pair[0].replace('\r', '').replace('@', '')
if (!key) return;
var value = _pair[1].replace(';', '').replace('\r', '').replace(/^\s+|\s+$/g, '')
variables[key] = value
})
console.info(variables);
return variables
}
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less', {
globalVars: getLessVariables(path.join(__dirname, "../src/assets/styles/variables.less"))// 读取less全局变量文件
}),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
4、可以为less-loader在加载时使用modifyVars注入全局变量。
与全局变量选项相反,这会将声明放在基本文件的末尾,这意味着它将覆盖Less文件中定义的所有内容。
//在项目build文件夹里找到utils.js
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less',{
modifyVars: {
// 直接覆盖变量
'text-color': '#333',
'hack': `true;
// 或者可以通过 less 文件覆盖(文件路径为绝对路径)
@import "${path.join(__dirname,'../src/assets/styles/variables')}";`
}
}),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
stylus全局变量注入
为了使用stylus的安装包,我们需要安装stylus的依赖
npm install stylus-loader stylus --save-dev
1、使用style-resources-loader工具引入
方法同less引入方法一致
2、可以为stylus-loader的传递选项实现全局变量注入
//在项目build文件夹里找到utils.js中的cssLoaders函数中
const stylusOptions = {
import: [
path.join(__dirname, "../src/assets/style/mk_variables.styl")
],
paths: [
path.join(__dirname, '../src/assets'),
path.join(__dirname, '../')
]
}
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus',stylusOptions),
styl: generateLoaders('stylus',stylusOptions)
}