Novices Performing Miracles

    vue-style-variables-loader

    1.0.2 • Public • Published

    vue-style-variables-loader

    这个基于 webpack 的 loader 试图解决使用 Vue 开发中的两个问题:

    1. 在 Vue 单文件中自动引入变量文件
    2. 选用了一个 UI 框架并使用了框架提供的主题解决方案,在组件中想使用这些主题变量,但又不想使用框架指定的预处理器

    下面让我们分别看下这两个问题。

    问题1:在 Vue 单文件中引入变量文件

    通常我们的项目中包含一个定义了常用变量的文件,以开发选择的预处理器格式存在。 使用时,在每个 Vue 单文件组件的 style 块中都需要手动引入这个变量文件。虽然使用 webpack alias 之后不用考虑路径问题,但如果能自动引入将方便很多。

    // Component.vue
     
    <style lang="scss">
        // 引入变量文件
        @import "@/styles/variables.scss";
        // 开始使用变量
    </style>

    有人针对这个问题向 vue-loader 提出了相关 issue。而 vue-loader 认为这个工作应该交给各个预处理器 loader 完成。

    例如使用 sass 时,可以使用 sass-resources-loader

    {
        loader: 'sass-resources-loader',
        options: {
            resources: 'variables.scss'
        }
    }

    或者使用 sass-loader的注入环境变量功能。keen-ui就采用了这种方式支持用户覆盖预定义的主题变量

    plugins: [
        new webpack.LoaderOptionsPlugin({
            options: {
                sassLoader: {
                    data: '@import "src/styles/variables.scss";',
                    includePaths: 'src/styles'
                },
                context: path.resolve(__dirname) // your project root
            }
        })
    ]

    而在 stylus-loader 中,可以使用import达到引入全局变量的目的。

    plugins: [
        new webpack.LoaderOptionsPlugin({
            test: /\.styl$/,
            stylus: {
                use: [require('nib')()],
                import: ['~nib/lib/nib/index.styl']
            }
        })
    ]

    less-loader 中并没有找到解决方法,似乎只能每次手动引入了。

    可以看出,各个预处理器 loader 都有自己的方式解决这个问题。而且就算是手动引入,代价也并不高,让我们继续来看第二个问题。

    问题2:选用和 UI 框架不同的预处理器开发

    各个 UI 框架都有自己的主题解决方案,例如:

    可以看出在使用变量文件覆盖的方案中,主题变量必须使用框架指定的预处理器定义。 例如选择了 vuetify,那开发者自定义的变量文件就必须使用 stylus 来写。这样在实际组件开发中,如果选择 less,就无法使用 stylus 定义的这些变量了。

    // Component.vue
     
    <style lang="less">
        // 引入变量文件
        @import "@/styles/variables.styl";
        // 出错了,less 并不认识 stylus 定义的变量 $bg-color
        background: @bg-color;
    </style>

    所以在上述场景中,我们需要将文件中使用 stylus 定义的每一个主题变量都转换成 less 变量,然后注入.vue文件的<style>块中。 如果能实现这一点,其实第一个问题也就顺便解决了。

    实现思路

    首先,开发者使用所选 UI 框架的主题解决方案,使用框架指定的预处理器创建一个变量文件,由于该文件只包含变量,对于开发者而言,学习特定预处理器语法的成本并不高。

    然后,使用 loader 处理每一个.vue文件。该 loader 接受之前的变量文件作为输入,在每个.vue文件的每个<style>块中,根据当前<style>块指定的预处理器语言,将包含的所有变量进行转换并注入。这样开发者就可以直接使用自己熟悉的预处理器语法开发了。

    并不需要做类似stylus,less,sass之间全部语法的互相转换。只需要转换变量声明语句。例如我们选用了 vuetify,会使用 stylus 编写一个文件theme.styl,里面包含了 stylus hash 类型的主题变量:

    // theme.styl
     
    $theme := {
        primary: white
        secondary: #fff
    }

    经过 loader 对theme.styl文件内容的解析, 在开发者的组件中,不需要添加任何额外语句,就可以直接使用 less 的语法访问这些变量:

    // Component.vue
     
    <style lang="less">
    .selector {
        background: @theme-primary;
        color: @theme-secondary;
    }
    </style>
     
    <style lang="sass">
    .selector
        background: $theme-primary
        color: $theme-secondary
    </style>

    要注意 less 和 sass 中变量名称中不能包含.,所以我使用了-。所以需要通过@theme-primary而非@theme.primary这样的形式访问 hash 变量。

    最后,对于问题一,由于在 less,stylus 和 sass 中,都支持使用@import "foo.scss";这样的语句引入文件。对于不需要不同预处理器间的语法转换,只想自动批量引入多个变量文件的场景,loader 不会对这些文件的内容进行解析,只会简单的把这些@import语句插入<style>块中。

    使用方法

    安装

    npm install vue-style-variables-loader --save-dev

    在 webpack 中配置规则,处理项目中每一个.vue文件,要注意配置include/exclude规则,使 loader 只作用于开发者项目内的文件,不包含第三方文件。

    {
        test: /\.vue$/,
        use: [
            {
                loader: 'vue-loader',
                options: vueLoaderConfig
            },
            {
                loader: 'vue-style-variables-loader',
                options: {
                    variablesFiles: [
                        resolve('./src/styles/theme-variables.styl')
                    ],
                    importStatements: [
                        '@import "~@/styles/other-variables.less";'
                    ]
                }
            }
        ],
        include: [resolve('src')]
    },
    {
        test: /\.vue$/,
        use: [
            {
                loader: 'vue-loader',
                options: vueLoaderConfig
            }
        ],
        exclude: [resolve('src')]
    },

    参数说明

    两个参数:

    • variablesFiles 变量文件路径,Array 类型。指定主题变量文件。
    • importStatements import 语句,Array 类型。需要插入.vue文件<style>块头部的@import语句。在这里可以引入其他项目中使用的变量文件,要注意 loader 不会对这些文件做任何解析工作,只是简单的添加而已。

    参数注意事项

    使用variablesFiles时,传入的变量文件只允许包含定义变量语法。诸如 mixin,@import语句等都不能使用。

    使用importStatements有两点需要注意:

    1. 由于 css-loader 中认为@import路径是相对当前路径,所以需要加上~前缀使 webpack alias 生效。例如上面使用示例中:'@import "~@/styles/other-variables.less";'相关ISSUE
    2. 需要加上预处理器后缀名,原因是 loader 需要知道@import语句中文件的后缀,才能正确插入对应的<style>块中。例如'@import "~@/styles/other-variables.less";'就不会插入<style lang="styl">中。

    参考资料

    the-super-tiny-compiler

    Keywords

    none

    Install

    npm i vue-style-variables-loader

    DownloadsWeekly Downloads

    6

    Version

    1.0.2

    License

    ISC

    Last publish

    Collaborators

    • panyuqi