css - 基于环境的 Sass 动态导入
问题描述
我正在尝试根据环境切换 sass 导入 URL。我已经回顾了许多其他问题和答案,这一直在与我作斗争。@import 不允许动态字符串,因此我尝试对每个字符串使用 mixin,并基于环境变量使用 @if/@else,但是我无法从其他 sass 文件访问根环境变量。
webpack.config.js
const scssRule = config.module.rules.find(rule => rule.test.test(".scss"));
const scssLoaderConfig = scssRule.use.find(({loader}) => loader === "sass-loader");
scssLoaderConfig.options = scssLoaderConfig.options || {};
scssLoaderConfig.options["implementation"] = require("sass"); //dart-sass
scssLoaderConfig.options["additionalData"] = `$env:"${env}";`; //Pass env to sass
主题.scss
//NOTE: This $env line is not actually in the file. It gets injected by webpack via sass-loader additionalData
$env: "preprod";
@forward "icons" as icon_*;
//More @forward directives such as colors
_icons.scss
@mixin importIconsPreprod {
@import "https://preprod.example.com/icons.css";
}
@mixin importIconsProd {
@import "https://example.com/icons.css";
}
@mixin importIcons() {
//SassError: Undefined variable.
@if $env == "preprod" {
@include importIconsPreprod;
} @else {
@include importIconsProd;
}
//More styles here
}
期望的实现
@use "theme-package" as theme;
//Import icons from theme.icon namespace
@include theme.icon_importIcons;
解决方案
一段时间后,我找到了解决方案。我最终生成了一个文件 _env.scss 作为 webpack 的一部分。该文件包含指示环境的 $env sass 变量,并由 _icons.scss 加载。下面的代码:
webpack.config.js
const writeEnvScss = require("./scripts/write-env-scss.js");
//Write _env.scss, default to "prod"
writeEnvScss("./packages/Theme/src/Component/includes/_env.scss", "prod");
_env.scss 作为构建的一部分生成
$env:"preprod";
_icons.scss
//"env" file is created as part of webpack.config.js
@use "includes/env" as *;
@mixin importIconsPreprod {
@import "https://preprod.example.com/icons.css";
}
@mixin importIconsProd {
@import "https://example.com/icons.css";
}
@mixin importIcons() {
@if $env == "preprod" {
@include importIconsPreprod;
} @else {
@include importIconsProd;
}
}
写-env-scss.js
const fs = require("fs");
const path = require("path");
//looks for optional --env cli param or NODE_ENV environment variable
module.exports = function(scssPath, envDefault) {
scssPath = scssPath || null;
if (!scssPath) {
throw new Error("scss path required");
}
envDefault = envDefault || "local";
//Determine env
let env = getArg("--env") || process.env.NODE_ENV || null;
switch (env) {
case "development":
case "local":
env = "local";
break;
case "preprod":
break;
case "production":
case "prod":
env = "prod";
break;
default:
env = envDefault;
break;
}
console.log("ENV =>", env);
//Write _env.scss to Theme
fs.writeFileSync(path.resolve(scssPath), `$env:"${env}";`);
};
function getArg(key) {
var index = process.argv.indexOf(key);
var next = process.argv[index + 1];
return index < 0 ? null : !next || next[0] === "-" ? true : next;
}
推荐阅读
- python - 无法通过 pipenv 安装 html 或 re
- javascript - 如果组件道具类型无效,如何防止构建应用程序?
- php - 显示预加载器图标 - 直到页面完全加载
- shell - 这是否意味着易受攻击的功能如果我通过程序执行 shell 代码
- java - 使用 Spring Data JpaRepositories 通过 ElementCollections 中的值查询实体
- python - 选择多个标准
- shell - 无法扩展 cURL 命令中使用的变量
- yaml - Bitbucket 管道配置问题
- python - 如何在等待 API 返回值时等待并显示进度信息
- xaml - 如何在选择项目后让自动完成框变大