在一个web app应用中,需要有多个运行环境,并且每个运行环境主题也是不一样。
本项目解决方案
import()
http://es6.ruanyifeng.com/#docs/module#import ES6 import() 可以动态加载,可以利用环境变量导入不同文件,
缺点:import() 是异步加载, 加载时,首先同步加载加载 import... from..., 然后加载 import(), 所以加载页面是会突然从一个样式跳到另一个样式。
通过 sass-loader 定义环境变量
https://www.npmjs.com/package/sass-loader 通过环境变量 设置一些共有属性
缺点: 如果样式完全不一样,需要定义的变量太多。
sass-resources-loader
https://www.npmjs.com/package/sass-resources-loader 目的: 所有的sass 文件都会自动@import 公共的样式和变量,方法等。
preprocess-loader 进行webpack 打包预处理
https://www.npmjs.com/package/preprocess-loader
本项目有interviewed-qa和simplyhired-qa两种环境,各个环境主题也是不一样的。
先安装相应插件:
"preprocess-loader": "^0.3.0",
"sass-loader": "^7.1.0",
"sass-resources-loader": "^2.0.0",
新建一个style.js文件
const path = require('path');
const rootPath = path.resolve(__dirname, './../');
const whiteLabel = process.env.WHITE_LABEL === 'simplyhired' ? process.env.WHITE_LABEL : 'default';
module.exports = path.join(rootPath, `frontend/App/Common/Config/Config.${whiteLabel}.scss`);
在App/Common/Config目录下面,新建两个文件,分别配置两种环境的属性值:
default.scss文件
$font-family: "Roboto" !default;
$font-family-url: "Roboto" !default;
$bg-color: #f0f2f5 !default;
$fg-color: white !default;
$border-color: #dfe2e9 !default;
$nprogress-color: #488EFF !default;
$hover-color: #1497FF !default;
$background-light-color: #f2f7ff !default;
...
simplyhired.scss文件
$font-family: "Source Sans Pro" !default;
$font-family-url: "Source+Sans+Pro" !default;
$bg-color: #F3F3F3 !default;
$fg-color: white !default;
$border-color: #D8D8D8 !default;
$active-color: #0275d8 !default;
$nprogress-color: #ff6600 !default;
$hover-color: #ff8822 !default;
$background-light-color: #fff5ef !default;
...
在webpack.common.js中加上:
...
const styleConfig = require('./style.js');
...
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
use: [
{
loader: 'babel-loader'
},{
loader: 'preprocess-loader',
options: {
SIMPLY_HIRED: process.env.WHITE_LABEL,
ppOptions: {
type: ['jsx', 'js']
}
}
}
]
},
...
{
test: /\.s?css$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader"
}, {
loader: "postcss-loader",
options: {
plugins: function() {
return [
require('precss'),
require('autoprefixer')
]
}
}
}, {
loader: "sass-loader" // compiles Sass to CSS
},{
loader: "sass-resources-loader",
options: {
resources: styleConfig,
}
},
]
},
]
}
在env文件中加上:
SITE_NAME=the site name
# uncomment it if whitelabel to simple hired
# WHITE_LABEL=simplyhired
WHITE_LABEL=simplyhired
# one of SITE_DOMAIN and EMAIL should be defined
SITE_DOMAIN=interviewed.com
# EMAIL_FROM
# default: employer+ {organization.name} @ {SITE_DOMAIN}
# e.g. employer+indeed@interviewed.com
EMAIL_FROM=employer.simplyhired.com
在App/Common/WhiteLabeled目录下,新建你一下文件:
Index.js
import './Common.base.scss';
// @ifdef SIMPLY_HIRED
import './Common.simplyhired.scss';
// @endif
Common.base.scss
@import url("https://fonts.googleapis.com/css?family=#{$font-family-url}");
body {
background: $bg-color;
min-width: 1180px;
color: #2e3033;
#app {
font-family: $font-family !important;
}
}
.ant-spin-container:after {
position: relative !important;
}
...
Common.simplyhired.scss
@import url("https://fonts.googleapis.com/css?family=#{$font-family-url}");
body {
font-family: $font-family, "HelveticaNeue", "Arial", sans-serif;
}
.ant-tooltip,
.ant-dropdown,
.ant-select,
.ant-select-dropdown,
.ant-form,
.ant-modal,
.ant-checkbox-wrapper,
.ant-form-item,
.ant-input,
.ant-table,
.ant-tabs {
font-family: $font-family, "Chinese Quote", -apple-system, BlinkMacSystemFont,
"Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
"Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol" !important;
}
.ant-layout {
background: $bg-color !important;
}
...
在各个组件的源头导入App/Common/WhiteLabeled,比如:
import React from 'react';
import { Route } from 'react-router-dom';
import withTracker from 'App/Common/HigherComponents/GoogleAnalyticsRoute';
import 'App/Common/WhiteLabeled';
const App = () => (
<div>
<Route exact path="/account/sign-in" component={withTracker(LoginApp)} />
/>
);
export default App;
根据siteName属性的配置,启动项目就可以展示不同的环境主题。