在一個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. [email protected]
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屬性的配置,啓動項目就可以展示不同的環境主題。