Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何使用配置? #14

Open
nonocast opened this issue Mar 8, 2020 · 0 comments
Open

如何使用配置? #14

nonocast opened this issue Mar 8, 2020 · 0 comments

Comments

@nonocast
Copy link
Owner

@nonocast nonocast commented Mar 8, 2020

Node

这个和传统Java, C#应用程序基本一致,

- config
  - default.yaml
  - development.yaml
  - production.yaml
  - test.yaml
- src
- test
- .env
- .env.production
- .env.test

index.js

require('dotenv').config(); // 这句后续应交由dotenv-cli来实现
const config = require('config');

config是用来做常规设置,而dotenv区别config主要有2个因素:

  1. dotenv写到process的环境变量,比如说NODE_ENV, DEBUG的这些和process.env强绑定的设置
  2. 用户名密码之类不对外公开的信息,如果放在config则一并上传到了git repo,如果是公开的repo则公开了用户名密码,所以一般.env是不用来上传的

注:

  • 整个加载过程是层叠覆盖式的,比如当NODE_ENV=production时,会先加载.env,然后再加载.env.production覆盖 (dotenv-cli -e则不会显式层叠加载)

对应的webpack.config.js

const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const _externals = require('externals-dependencies');

module.exports = {
  mode: 'production',
  target: 'node',
  entry: './src/index.js',
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: [
          /test/,
          /node_modules/
        ],
        loader: 'babel-loader'
      }
    ]
  },
  node: {
    __filename: false,
    __dirname: false
  },
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'bundle.js'
  },
  optimization: {
    minimizer: [new TerserPlugin()]
    // minimizer: []
  },
  plugins: [
        new CopyWebpackPlugin(['config', '.env*', 'package.json'])
  ],
  externals: _externals()
};

在运行build的时候还是需要先制定NODE_ENV

NODE_ENV=production node bundle.js

再来看dotenv-cli, 这样可以去掉require('dotenv').config(),然后在运行时选择NODE_ENV,

.env

NODE_ENV=development
DEBUG=app*

.env.production

NODE_ENV=production

ok, 然后配置运行指令,

dotenv -e .env node app
dotenv -e .env.prodcution node app

这样就比较有一致性了。

最后补充一下pm2的情况,pm2的环境变量建议还是直接在ecosystem.config.js中设置,不要混dotenv。

最终可以整理如下:

"scripts": {
  "start": "node src/index",
  "start:prod": "cross-env NODE_ENV=production node src/index",
  "build": "webpack --mode production --progress --display-modules --colors --display-reasons"
},

参考:

React

React的配置比Node会受限一些,主要是因为它运行在浏览器中,刚刚的config都是运行时,但React的配置则基本是编译时,因为.env的内容直接hard code到最终编译的js, 所以和Node是不同的,遵循create-react-app的要求,可以采用.env和.env.production等支持多环境,在加载.env.production时会先加载.env。

如果需要运行时,就比如build以后需要做配置,则需要在HTML中引入js,

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>React App</title>

    <script type="text/javascript">
      window.RUNTIME = {
        SERVICE: "http://xyz.api"
      };
    </script>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

然后在页面获取,

function App() {
  return (
    <div className="App">
      {window.RUNTIM && window.RUNTIME.SERVICE &&
        <h1>{window.RUNTIME.SERVICE}</h1>
      }
      <h1>{process.env.REACT_APP_MESSAGE}</h1>
    </div>
  );
}

此外,yarn start时NODE_ENV=development, yarn build后则NODE_ENV=production

现在需求来了,

  • 在本地运行时,默认连接本地的服务,但可以手动设置采用其他服务地址
  • 编译后, 则默认使用云端地址, 可手动修改服务地址

config.js

import Debug from 'debug';

const debug = Debug('app:config');

class Config {
  constructor() {
    debug(`NODE_ENV: ${process.env.NODE_ENV}`);

    if (window.RUNTIME && window.RUNTIME.SERVICE) {
      this.service = window.RUNTIME.SERVICE;
    } else {
      if (process.env.REACT_APP_SERVICE) {
        this.service = process.env.REACT_APP_SERVICE;
      } else {
        throw new Error("Missing service configration");
      }
    }
  }

}

export default new Config();

在index.js中直接可以import './config', 然后在app.js就可以消费了,

function App() {
  return (
    <div className="App">
      <h1>{config.service}</h1>
    </div>
  );
}

最后补充一下env,

.env

REACT_APP_SERVICE=http://localhost:9007

.env

REACT_APP_SERVICE=https://api.space365.live

如果在HTML设置了service,则无视.env

<script type="text/javascript">
  window.RUNTIME = { SERVICE: "http://xyz.api" };
</script>

上述代码可以在这里获取。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant
You can’t perform that action at this time.