关于loader:styleresourcesloader-应用

17次阅读

共计 5020 个字符,预计需要花费 13 分钟才能阅读完成。

style-resources-loader 利用

此 loader 将款式资源(例如变量、mixin)注入到 sass、scss、less、stylus 等模块中


通过在工作中的利用场景,来介绍此 loader 用法和一些发散的点

场景需要

我的项目构造如下:

  ├─views             
  ├─componets              组件目录    
  |     ├─brand1           组件 1
  |            ├─cmp.vue
  |            ├─...
  |     └─brand2           组件 2
  |            ├─cmp.vue
  |            ├─...
  ├─theme                  主题目录
  (每个主题中色彩变量可能会反复)
  |     ├─brand1.less      组件 1 主题色彩变量
  |     └─brand2.less      组件 2 主题色彩变量
  |     └─other.less       其余主题色彩变量
  └─...     

需要:

  • 组件目录应用对应的主题色彩变量,其余目录应用主题 3 色彩变量
  • 应用主题色彩变量时不须要每次独自 @import ‘@/theme/brandx.less’

解决方案

module: {
        rules: [
            {
                test: /\.less$/i,
                use: [MiniCssExtractPlugin.loader, "css-loader", 'less-loader'],
            },
            {
                test: /components\\brand1.*\.less$/i,
                use: [{
                    loader: 'style-resources-loader',
                    options: {patterns: [path.resolve(__dirname, 'src/theme/brand1.less')]
                    },
                }],
            },
            {
                test: /components\\brand2.*\.less$/i,
                use: [{
                    loader: 'style-resources-loader',
                    options: {patterns: [path.resolve(__dirname, 'src/theme/brand2.less')]
                    },
                }],
            },
            {test: /[^components\\].*\.less$/i,
                use: [{
                    loader: 'style-resources-loader',
                    options: {patterns: [path.resolve(__dirname, 'src/theme/brand3.less')]
                    },
                }],
            },
        ]
    },

发散点

loader 匹配规定

loader 会把非 js 的文件转换为 js 文件,不同类型的文件依据定义的 rules 中不同 test 去匹配相应的 loader 进行解决,这里对 vue 组件中款式文件的解决其实是先通过了 vue-loader 将.vue 文件中的 <style lang="less"> 局部转换为 less 文件后,再由其余匹配此规定的 loader 进行解决

loader 程序

在之前应用 loader 的过程中,我只晓得 use 中的 loader 程序是从右向左(或者说是从下到上,这个是看书写的习惯),例如上面,执行程序是 less-loader->css-loader->MiniCssExtractPlugin.loader

{
    test: /\.less$/i,
    use: [MiniCssExtractPlugin.loader, "css-loader", 'less-loader'],
},

其实在 rules 中对于雷同类型文件的匹配程序也是一样;例如咱们把下面的 rules 程序换一下,此时所有的 less 文件在第一个规定中曾经全副转换为 css,无奈匹配第二个规定执行 style-resources-loader,导致其 less 变量并未注入从而引起报错

// error code
module: {
        rules: [
            {
                test: /components\\brand1.*\.less$/i,
                use: [{
                    loader: 'style-resources-loader',
                    options: {patterns: [path.resolve(__dirname, 'src/theme/brand1.less')]
                    },
                }],
            },
            {
                test: /\.less$/i,
                use: [MiniCssExtractPlugin.loader, "css-loader", 'less-loader'],
            },
        ]
      }

同时也能够依据 build 信息看到具体的 loader 执行程序

扩大:在很多材料中有介绍 loader 的 pitch 概念
https://webpack.docschina.org/api/loaders/#pitching-loader

这边能够本人写一个例子去感受一下

//src/loaders/a.js
module.exports = function(source) {
      // this.data 为在 pitch 阶段和 normal 阶段之间共享的 data 对象。console.log('a-loader',this.data);
      return source;
};

module.exports.pitch = function(remainingRequest, precedingRequest, data) {console.log('a-pitch**************************');
      console.log(remainingRequest);
      console.log(precedingRequest);
      console.log(data);
      data.value = 'a-pitch-value';
}

//src/loaders/b.js
module.exports = function(source) {console.log('b-loader', this.data);
      return source;
};

module.exports.pitch = function(remainingRequest, precedingRequest, data) {console.log('b-pitch**************************');
      console.log(remainingRequest);
      console.log(precedingRequest);
      console.log(data);
      data.value = 'b-pitch-value';
}

//src/loaders/c.js
module.exports = function(source) {console.log('c-loader',this.data);
      return source;
};

module.exports.pitch = function(remainingRequest, precedingRequest, data) {console.log('c-pitch**************************');
      console.log(remainingRequest);
      console.log(precedingRequest);
      console.log(data);
      data.value = 'c-pitch-value';
}

//webpack.config.js
module: {
        rules: [
            {
                use: [path.join(__dirname, 'src/loaders/a.js'),
                    path.join(__dirname, 'src/loaders/b.js'),
                    path.join(__dirname, 'src/loaders/c.js'),
                ],
            },
        ]
    },

后果如下:

这个办法如同用的不是很多,目前就在 mini-css-extract-plugin 中看到

调试 loader


而后抉择 node.js,我的项目外面会多一个.vscode 的文件夹

配置 launch.json 文件

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "pwa-node",
            "request": "launch",
            "name": "webpack",
            "program": "D:\\webpack-test\\node_modules\\webpack-cli\\bin\\cli.js",
            //"args": [
            //    "dev"
            //]
        }
    ]
}

次要是配置 program,此为你执行文件的地位,args 为你执行命令时的参数,我这边只是用 webpack 打包,所以不须要此参数,这里等价于让 vscode 自带的 node 调试性能去帮你执行 webpack 这条命令

配置好了之后,就能够间接在 node_modules 外面找到相应的 loader 代码,而后打上断点,按 F5 开始进行调试

style-resources-loader 的 injector 属性

第一次看这个属性的时候可能会看不懂,然而如果会调试了 loader 的话,间接去源码外面去打个断点就晓得怎么用的了

Name Type Default Description
injector Function
‘prepend’
‘append’
‘prepend’ Controls the resources injection precisely

此属性为 准确管制资源注入

例如:

//a.less
@primary-color: red;
.text-color {color: @primary-color;}
//var.less
@primary-color: black;

injectorprepend

//a.css
.text-color {color: red;}

injectorappend

//a.css
.text-color {color: black;}

从例子能够看进去,管制咱们的变量是否会笼罩原文件中的变量

injector 为回调函数时,官网给的例子是

module.exports = {
    // ...
    module: {
        rules: [{
            test: /\.styl$/,
            use: ['style-loader', 'css-loader', 'stylus-loader', {
                loader: 'style-resources-loader',
                options: {
                    patterns: [path.resolve(__dirname, 'path/to/stylus/variables/*.styl'),
                        path.resolve(__dirname, 'path/to/stylus/mixins/*.styl')
                    ],
                    injector: (source, resources) => {
                        const combineAll = type => resources
                            .filter(({file}) => file.includes(type))
                            .map(({content}) => content)
                            .join('');
 
                        return combineAll('variables') + combineAll('mixins') + source;
                    }
                }
            }]
        }]
    },
    // ...
}

意思就是让咱们本人管制注入的变量内容是来自于哪个文件(variables、mixins)

source 为源文件内容字符串

resources 为注入文件的对象数组,对象蕴含 file 和 content 属性

  • file 为该文件的绝对路径
  • content 为该文件的文件内容字符串

源码:

const normalizeInjector = (injector: StyleResourcesLoaderOptions['injector']): StyleResourcesNormalizedInjector => {if (typeof injector === 'undefined' || injector === 'prepend') {return (source, resources) => resources.map(getResourceContent).join('') + source;
    }

    if (injector === 'append') {return (source, resources) => source + resources.map(getResourceContent).join('');
    }

    return injector;
};

正文完
 0