12要素のアプリケーションマニフェストはWebアプリケーションの開発と運用に大きく貢献しましたが、これは主にバックエンドに影響を与え、フロントエンドをバイパスしました。マニフェストのほとんどの句は、フロントエンドに適用できないか、単独で実行されますが、3番目の構成(構成)には疑問があります。
元のマニフェストには、「実行時に構成を保持する」と記載されていました。実際には、これは、構成をソースコードまたは最終的なアーティファクト内に保存できないことを意味します。起動時にアプリケーションに渡す必要があります。このルールには実用的なアプリケーションがあります。ここにいくつかあります。
異なる環境のアプリケーションは、異なるバックエンドにアクセスする必要があります。本番環境(本番API)、ステージング(APIステージング)、および統合テストの実行時(特別なモックサーバー)。
e2eテストでは、ユーザーの反応を待つ時間を短縮する必要があります。たとえば、非アクティブ状態が10分間続いた後にサイトで何かが発生した場合、テストシナリオでは、この間隔を1分に減らすことができます。
SSR
フロントエンドアプリケーションにSSRが含まれている場合、タスクは少し簡単になります。構成は環境変数としてサーバー上のアプリケーションに渡されます。レンダリングされる<script>
と、ページの最初で宣言されたグローバル変数としてクライアントへの応答に入ります。クライアントでは、これらの変数をグローバルスコープから取得して使用するだけで十分です。
最近、Aviasalesで、サイトの一部のサーバーレンダリングのアプリケーションを作成し、この問題に直面しました。結果は私のチームメイトzaopensorsil-- isomorphic-env-webpack-pluginです。
美しいNext.jsはこれを箱から出して実行します。特別なことをする必要はありません。
CSR
, — . , , . , .
:
–
config.js
, . , . — -, -, — -. — PR .
.
DefinePlugin
Webpack. — . — , . , , . .
.
-
- :
nginx, nginx -. nginx .
, — API.
— , nginx . /user-api/path
https://user.my-service.io/path
, /auth-api/path
https://auth.other-service.io/path
.
nginx Docker-
1.19 Docker- nginx . .template
/etc/nginx/templates
. , .
nginx SPA :
server {
listen 8080;
root /srv/www;
index index.html;
server_name _;
location /user-api {
proxy_pass ${USER_API_URL};
}
location /auth-api {
proxy_pass ${AUTH_API_URL};
}
location / {
try_files $uri /index.html;
}
}
Dockerfile :
FROM node:14.15.0-alpine as build
WORKDIR /app
#
# ...
FROM nginx:1.19-alpine
COPY ./default.conf.template /etc/nginx/templates/default.conf.template
COPY --from=build /app/public /srv/www
EXPOSE 8080
, nginx .
, , .
API, - .
-, . , .
JS-:
window.__ENV__ = {
USER_API_URL: 'https://user.my-service.io/',
AUTH_API_URL: 'https://auth.other-service.io/',
};
, . . <script>
HTML- .
nginx Docker-
, , — API, . , , env.dict
:
BACK_URL
GOOGLE_CLIENT_ID
Bash- generate_env.sh
JS-:
#!/bin/bash
filename='/etc/nginx/env.dict'
# JS-
config_str="window._env_ = { "
# JS-
while read line; do
variable_str="${line}: \"${!line}\""
config_str="${config_str}${variable_str}, "
done < $filename
# JS-
config_str="${config_str} };"
#
echo "Creating config-file with content: \"${config_str}\""
echo "${config_str}" >> /srv/www/config.env.js
# <script> HTML-
sed -i '/<\/body><\/html>/ i <script src="/confit.env.js"></script>' *.html
Bash, . , .
nginx , nginx. cmd.sh
, :
#!/bin/bash
bash /etc/nginx/generate_env.sh
nginx -g "daemon off;"
Dockerfile:
FROM node:14.15.0-alpine as build
WORKDIR /app
#
# ...
FROM nginx:1.19-alpine
# Alpine Bash,
RUN apk add bash
COPY ./default.conf /etc/nginx/conf.d/
COPY --from=build /app/public /srv/www
COPY ./cmd.sh /etc/nginx/cmd.sh
COPY ./generate_env.sh /etc/nginx/generate_env.sh
COPY ./env.dict /etc/nginx/env.dict
EXPOSE 8080
CMD ["bash", "/etc/nginx/cmd.sh"]
— env.dict
.
, , SSR . isomorphic-env-webpack-plugin, : HTML.
このスキームにはもう1つの小さなエッジケースがあります。通常、コンテンツハッシュはリソースを含むファイルの名前に追加されるため、ブラウザではすべてのファイルを名前で問題なく永久にキャッシュできます。この場合、変数を含むファイルを生成するためのスクリプトを少し複雑にし、内容をハッシュして、結果をファイル名に追加する必要があります。
結論
フロントエンドアプリケーションのパラメーターを正しく操作することで、信頼性が高く使いやすいシステムを作成できます。チームメンバーの快適さを根本的に改善し、潜在的なエラーを減らすには、構成をアプリケーションから切り離してランタイムに移動するだけで十分です。
どのように構成をクライアントアプリケーションに渡しますか?