{"id":26671233,"url":"https://github.com/lavas-project/vue-style-variables-loader","last_synced_at":"2025-04-12T04:13:49.184Z","repository":{"id":57158857,"uuid":"98421987","full_name":"lavas-project/vue-style-variables-loader","owner":"lavas-project","description":"Webpack loader for loading global variable.less/styl/sass files in every vue component","archived":false,"fork":false,"pushed_at":"2017-11-27T06:08:42.000Z","size":85,"stargazers_count":15,"open_issues_count":2,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-12T04:13:44.427Z","etag":null,"topics":["loader","style","variables","webpack"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lavas-project.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-26T12:47:33.000Z","updated_at":"2022-08-26T08:20:01.000Z","dependencies_parsed_at":"2022-09-03T07:40:12.726Z","dependency_job_id":null,"html_url":"https://github.com/lavas-project/vue-style-variables-loader","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lavas-project%2Fvue-style-variables-loader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lavas-project%2Fvue-style-variables-loader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lavas-project%2Fvue-style-variables-loader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lavas-project%2Fvue-style-variables-loader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lavas-project","download_url":"https://codeload.github.com/lavas-project/vue-style-variables-loader/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248514201,"owners_count":21116903,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["loader","style","variables","webpack"],"created_at":"2025-03-25T23:49:45.122Z","updated_at":"2025-04-12T04:13:49.154Z","avatar_url":"https://github.com/lavas-project.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vue-style-variables-loader\n\n[![npm version](https://badge.fury.io/js/vue-style-variables-loader.svg)](https://badge.fury.io/js/vue-style-variables-loader)\n[![Build Status](https://travis-ci.org/lavas-project/vue-style-variables-loader.svg?branch=master)](https://travis-ci.org/lavas-project/vue-style-variables-loader)\n\n[![NPM](https://nodei.co/npm/vue-style-variables-loader.png?downloads=true\u0026downloadRank=true\u0026stars=true)](https://nodei.co/npm/vue-style-variables-loader/)\n\n\n这个基于 webpack 的 loader 试图解决使用 Vue 开发中的两个问题：\n1. 在 Vue 单文件中自动引入变量文件\n2. 选用了一个 UI 框架并使用了框架提供的主题解决方案，在组件中想使用这些主题变量，但又不想使用框架指定的预处理器\n\n下面让我们分别看下这两个问题。\n\n## 问题1：在 Vue 单文件中引入变量文件\n\n通常我们的项目中包含一个定义了常用变量的文件，以开发选择的预处理器格式存在。\n使用时，在每个 Vue 单文件组件的 style 块中都需要手动引入这个变量文件。虽然使用 webpack alias 之后不用考虑路径问题，但如果能自动引入将方便很多。\n``` vue\n// Component.vue\n\n\u003cstyle lang=\"scss\"\u003e\n    // 引入变量文件\n    @import \"@/styles/variables.scss\";\n    // 开始使用变量\n\u003c/style\u003e\n```\n\n有人针对这个问题向 vue-loader 提出了[相关 issue](https://github.com/vuejs/vue-loader/issues/328)。而 vue-loader 认为这个工作应该交给各个预处理器 loader 完成。\n\n例如使用 sass 时，可以[使用 sass-resources-loader](https://vue-loader.vuejs.org/en/configurations/pre-processors.html)\n``` javascript\n{\n    loader: 'sass-resources-loader',\n    options: {\n        resources: 'variables.scss'\n    }\n}\n```\n\n或者[使用 sass-loader](https://github.com/webpack-contrib/sass-loader#environment-variables)的注入环境变量功能。[keen-ui就采用了这种方式支持用户覆盖预定义的主题变量](https://github.com/JosephusPaye/Keen-UI/blob/master/Customization.md#customization)\n``` javascript\nplugins: [\n    new webpack.LoaderOptionsPlugin({\n        options: {\n            sassLoader: {\n                data: '@import \"src/styles/variables.scss\";',\n                includePaths: 'src/styles'\n            },\n            context: path.resolve(__dirname) // your project root\n        }\n    })\n]\n```\n\n而在 stylus-loader 中，可以使用[import](https://github.com/shama/stylus-loader#using-nib-with-stylus)达到引入全局变量的目的。\n``` javascript\nplugins: [\n    new webpack.LoaderOptionsPlugin({\n        test: /\\.styl$/,\n        stylus: {\n            use: [require('nib')()],\n            import: ['~nib/lib/nib/index.styl']\n        }\n    })\n]\n```\n\nless-loader 中并没有找到解决方法，似乎只能每次手动引入了。\n\n可以看出，各个预处理器 loader 都有自己的方式解决这个问题。而且就算是手动引入，代价也并不高，让我们继续来看第二个问题。\n\n## 问题2：选用和 UI 框架不同的预处理器开发\n\n各个 UI 框架都有自己的主题解决方案，例如：\n* vuetify [使用 stylus hash 变量](https://vuetifyjs.com/style/theme)覆盖[预定义的变量列表](https://github.com/vuetifyjs/vuetify/blob/dev/src/stylus/settings/_theme.styl)。\n* keen-ui [使用用户自定义的 sass 变量文件](https://github.com/JosephusPaye/Keen-UI/blob/master/Customization.md#customization)覆盖[预定义的变量列表](https://github.com/JosephusPaye/Keen-UI/blob/master/src/styles/variables.scss)\n* vux 通过 vux-loader [使用用户自定义的 less 变量文件](https://vux.li/#/?id=%E9%A2%9C%E8%89%B2%E9%85%8D%E7%BD%AE)覆盖[预定义的变量列表](https://github.com/airyland/vux/blob/v2/src/styles/variable.less)\n* [vue-material](https://github.com/vuematerial/vue-material)和以上框架都不同，使用了[编程式方式设置主题](http://vuematerial.io/#/themes/configuration)。\n\n可以看出在使用变量文件覆盖的方案中，主题变量必须使用框架指定的预处理器定义。\n例如选择了 vuetify，那开发者自定义的变量文件就必须使用 stylus 来写。这样在实际组件开发中，如果选择 less，就无法使用 stylus 定义的这些变量了。\n``` vue\n// Component.vue\n\n\u003cstyle lang=\"less\"\u003e\n    // 引入变量文件\n    @import \"@/styles/variables.styl\";\n    // 出错了，less 并不认识 stylus 定义的变量 $bg-color\n    background: @bg-color;\n\u003c/style\u003e\n```\n\n所以在上述场景中，我们需要将文件中使用 stylus 定义的每一个主题变量都转换成 less 变量，然后注入`.vue`文件的`\u003cstyle\u003e`块中。\n如果能实现这一点，其实第一个问题也就顺便解决了。\n\n## 实现思路\n\n首先，开发者使用所选 UI 框架的主题解决方案，使用框架指定的预处理器创建一个变量文件，由于该文件只包含变量，对于开发者而言，学习特定预处理器语法的成本并不高。\n\n然后，使用 loader 处理每一个`.vue`文件。该 loader 接受之前的变量文件作为输入，在每个`.vue`文件的每个`\u003cstyle\u003e`块中，根据当前`\u003cstyle\u003e`块指定的预处理器语言，将包含的所有变量进行转换并注入。这样开发者就可以直接使用自己熟悉的预处理器语法开发了。\n\n并不需要做类似[stylus，less，sass之间全部语法的互相转换](http://csspre.com/convert/)。只需要转换变量声明语句。例如我们选用了 vuetify，会使用 stylus 编写一个文件`theme.styl`，里面包含了 stylus hash 类型的主题变量：\n``` stylus\n// theme.styl\n\n$theme := {\n    primary: white\n    secondary: #fff\n}\n```\n\n经过 loader 对`theme.styl`文件内容的解析，\n在开发者的组件中，不需要添加任何额外语句，就可以直接使用 less 的语法访问这些变量：\n``` vue\n// Component.vue\n\n\u003cstyle lang=\"less\"\u003e\n.selector {\n    background: @theme-primary;\n    color: @theme-secondary;\n}\n\u003c/style\u003e\n\n\u003cstyle lang=\"sass\"\u003e\n.selector\n    background: $theme-primary\n    color: $theme-secondary\n\u003c/style\u003e\n```\n\n\u003e 要注意 less 和 sass 中变量名称中不能包含`.`，所以我使用了`-`。所以需要通过`@theme-primary`而非`@theme.primary`这样的形式访问 hash 变量。\n\n最后，对于问题一，由于在 less，stylus 和 sass 中，都支持使用`@import \"foo.scss\";`这样的语句引入文件。对于不需要不同预处理器间的语法转换，只想自动批量引入多个变量文件的场景，loader 不会对这些文件的内容进行解析，只会简单的把这些`@import`语句插入`\u003cstyle\u003e`块中。\n\n## 使用方法\n\n安装\n```bash\nnpm install vue-style-variables-loader --save-dev\n```\n\n在 webpack 中配置规则，处理项目中每一个`.vue`文件，要注意配置`include/exclude`规则，使 loader 只作用于开发者项目内的文件，不包含第三方文件。\n```javascript\n{\n    test: /\\.vue$/,\n    use: [\n        {\n            loader: 'vue-loader',\n            options: vueLoaderConfig\n        },\n        {\n            loader: 'vue-style-variables-loader',\n            options: {\n                variablesFiles: [\n                    resolve('./src/styles/theme-variables.styl')\n                ],\n                importStatements: [\n                    '@import \"~@/styles/other-variables.less\";'\n                ]\n            }\n        }\n    ],\n    include: [resolve('src')]\n},\n{\n    test: /\\.vue$/,\n    use: [\n        {\n            loader: 'vue-loader',\n            options: vueLoaderConfig\n        }\n    ],\n    exclude: [resolve('src')]\n},\n```\n\n## 参数说明\n\n两个参数：\n* `variablesFiles` 变量文件路径，Array 类型。指定主题变量文件。\n* `importStatements` import 语句，Array 类型。需要插入`.vue`文件`\u003cstyle\u003e`块头部的`@import`语句。在这里可以引入其他项目中使用的变量文件，要注意 loader 不会对这些文件做任何解析工作，只是简单的添加而已。\n\n### 参数注意事项\n\n使用`variablesFiles`时，传入的变量文件只允许包含定义变量语法。诸如 mixin，`@import`语句等都不能使用。\n\n使用`importStatements`有两点需要注意：\n1. 由于 css-loader 中认为`@import`路径是相对当前路径，所以需要加上`~`前缀使 webpack alias 生效。例如上面使用示例中：`'@import \"~@/styles/other-variables.less\";'`。[相关ISSUE](https://github.com/webpack-contrib/css-loader/issues/12)。\n2. 需要加上预处理器后缀名，原因是 loader 需要知道`@import`语句中文件的后缀，才能正确插入对应的`\u003cstyle\u003e`块中。例如`'@import \"~@/styles/other-variables.less\";'`就不会插入`\u003cstyle lang=\"styl\"\u003e`中。\n\n## 参考资料\n\n[the-super-tiny-compiler](https://github.com/thejameskyle/the-super-tiny-compiler/blob/master/the-super-tiny-compiler.js)\n[vue-loader 相关 issue](https://github.com/vuejs/vue-loader/issues/328)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flavas-project%2Fvue-style-variables-loader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flavas-project%2Fvue-style-variables-loader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flavas-project%2Fvue-style-variables-loader/lists"}