Fampiharana pejy tokana (SPA) dia fitambarana rakitra JavaScript sy HTML static, ary koa sary sy loharano hafa. Satria tsy miova izy ireo, dia tena mora ny famoahana azy ireo amin'ny Internet. Betsaka ny serivisy mora sy maimaim-poana ho an'izany, manomboka amin'ny Pejy GitHub tsotra (ary ho an'ny sasany aza narod.ru) ary mifarana amin'ny CDN toa an'i Amazon S3. Nila zavatra hafa anefa aho.
Nila sary Docker miaraka amin'ny SPA aho mba ho mora atomboka amin'ny famokarana ho ampahany amin'ny cluster Kubernetes, ary amin'ny masinin'ny mpamorona back-end izay tsy mahafantatra ny atao hoe SPA.
Nofaritako ho an'ny tenako ireto fepetra takiana manaraka ireto:
- mora ampiasaina (fa tsy fivoriambe);
- haben'ny kely indrindra na amin'ny lafin'ny kapila sy ny RAM;
- fanamafisam-peo amin'ny alΓ lan'ny fari-piainan'ny tontolo iainana mba ahafahan'ny sary ampiasaina amin'ny tontolo samihafa;
- ny fizarana rakitra mahomby indrindra.
Anio aho dia hilaza aminao ny fomba:
- gut nginx;
- manangana brotli avy amin'ny loharano;
- ampianaro ny rakitra static mba hahafantarana ny fari-piainan'ny tontolo iainana;
- ary mazava ho azy ny fomba hanangonana sary Docker avy amin'izany rehetra izany.
Ny tanjon'ity lahatsoratra ity dia ny hizara ny traikefako sy ny fihantsiana ireo mpikambana efa za-draharaha amin'ny fiaraha-monina amin'ny tsikera manorina.
Manangana sary ho an'ny fivoriambe
Mba hahatonga ny sary Docker farany ho kely habe, dia mila manaraka fitsipika roa ianao: sosona kely indrindra ary sary fototra minimalista. Iray amin'ireo sary fototra kely indrindra ny sary Alpine Linux, ka izay no hofidiko. Mety hisy hilaza fa tsy mety amin'ny famokarana ny Alpine, ary mety ho marina izany. Fa izaho manokana dia tsy mbola nanana olana taminy ary tsy misy ady hevitra momba azy.
Mba hananan'ny sosona vitsy kokoa dia hanangona ny sary amin'ny dingana 2 aho. Ny voalohany dia drafitra; ny fitaovana fanampiny rehetra sy ny rakitra vonjimaika dia hijanona ao. Ary amin'ny dingana farany dia hosoratako fotsiny ny dikan-teny farany amin'ny fampiharana.
Andeha isika hanomboka amin'ny sary fanampiny.
Mba hanangonana rindranasa SPA dia matetika mila node.js ianao. Haka ny sary ofisialy aho, izay miaraka amin'ireo mpitantana fonosana npm sy yarn. Amin'ny anaran'ny tenako dia hanampy node-gyp aho, izay ilaina hanamboarana fonosana npm sasany, ary ny compressor Brotli avy amin'ny Google, izay mahasoa antsika any aoriana.
Dockerfile misy fanehoan-kevitra.
# ΠΠ°Π·ΠΎΠ²ΡΠΉ ΠΎΠ±ΡΠ°Π·
FROM node:12-alpine
LABEL maintainer="Aleksey Maydokin <[email protected]>"
ENV BROTLI_VERSION 1.0.7
# ΠΠ°ΠΊΠ΅ΡΡ, ΠΊΠΎΡΠΎΡΡΠ΅ Π½ΡΠΆΠ½Ρ, ΡΡΠΎΠ±Ρ ΡΠΎΠ±ΡΠ°ΡΡ ΠΈΠ· ΠΈΡΡ
ΠΎΠ΄Π½ΠΈΠΊΠΎΠ² Brotli
RUN apk add --no-cache --virtual .build-deps
bash
gcc
libc-dev
make
linux-headers
cmake
curl
&& mkdir -p /usr/src
# ΠΡΡ
ΠΎΠ΄Π½ΠΈΠΊΠΈ Brotli ΡΠΊΠ°ΡΠΈΠ²Π°Π΅ΠΌ ΠΈΠ· ΠΎΡΠΈΡΠΈΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΡ
&& curl -LSs https://github.com/google/brotli/archive/v$BROTLI_VERSION.tar.gz | tar xzf - -C /usr/src
&& cd /usr/src/brotli-$BROTLI_VERSION
# ΠΠΎΠΌΠΏΠΈΠ»ΠΈΡΡΠ΅ΠΌ Brotli
&& ./configure-cmake --disable-debug && make -j$(getconf _NPROCESSORS_ONLN) && make install
# ΠΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ node-gyp
&& yarn global add node-gyp
# Π£Π±ΠΈΡΠ°Π΅ΠΌ Π·Π° ΡΠΎΠ±ΠΎΠΉ ΠΌΡΡΠΎΡ
&& apk del .build-deps && yarn cache clean && rm -rf /usr/src
Efa eto aho miady amin'ny minimalism, ka ny sary dia natambatra tamin'ny ekipa lehibe iray.
Ny sary vita dia azo jerena eto:
nginx
Afaka mampiasa mpizara tranonkala rehetra ianao mba hizara votoaty static. Efa zatra miasa amin'ny nginx aho ka hampiasa azy izao.
Nginx dia manana sary Docker ofisialy, saingy manana mΓ΄dely be loatra ho an'ny fizarana static tsotra. Iza amin'ireo no tafiditra amin'ny fandefasana dia azo jerena amin'ny ekipa manokana na ao amin'ny Dockerfile ofisialy.
$ docker run --rm nginx:1-alpine nginx -V
nginx version: nginx/1.17.9
built by gcc 8.3.0 (Alpine 8.3.0)
built with OpenSSL 1.1.1d 10 Sep 2019
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --with-perl_modules_path=/usr/lib/perl5/vendor_perl --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-Os -fomit-frame-pointer' --with-ld-opt=-Wl,--as-needed
Hampiasa ny Dockerfile ho fototra aho, fa izay ilaina ihany no avelako hizarana votoaty static. Ny kinovako dia tsy afaka miasa amin'ny HTTPS, tsy hanohana fanomezan-dΓ lana, sy ny maro hafa. Fa ny dikan-ko dia afaka mizara rakitra voaporitra amin'ny algorithm Brotli, izay mahomby kokoa noho ny gzip. Indray mandeha isika dia hanery rakitra; tsy ilaina ny manao izany amin'ny lalitra.
Ity no Dockerfile niafarako. Ny fanehoan-kevitra amin'ny teny Rosiana dia ahy, amin'ny teny anglisy - avy amin'ny tany am-boalohany.
dockerfile
# ΠΠ°Π·ΠΎΠ²ΡΠΉ ΠΎΠ±ΡΠ°Π· ΡΠ½ΠΎΠ²Π° Alpine
FROM alpine:3.9
LABEL maintainer="Aleksey Maydokin <[email protected]>"
ENV NGINX_VERSION 1.16.0
ENV NGX_BROTLI_VERSION 0.1.2
ENV BROTLI_VERSION 1.0.7
RUN set -x
&& addgroup -S nginx
&& adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx nginx
# Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΠΏΠ°ΠΊΠ΅ΡΡ, ΠΊΠΎΡΠΎΡΡΠ΅ Π½ΡΠΆΠ½Ρ ΡΡΠΎΠ±Ρ ΡΠΎΠ±ΡΠ°ΡΡ nginx ΠΈ ΠΌΠΎΠ΄ΡΠ»Ρ ngx_brotli ΠΊ Π½Π΅ΠΌΡ
&& apk add --no-cache --virtual .build-deps
gcc
libc-dev
make
linux-headers
curl
&& mkdir -p /usr/src
# Π‘ΠΊΠ°ΡΠΈΠ²Π°Π΅ΠΌ ΠΈΡΡ
ΠΎΠ΄Π½ΠΈΠΊΠΈ
&& curl -LSs https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz | tar xzf - -C /usr/src
&& curl -LSs https://github.com/eustas/ngx_brotli/archive/v$NGX_BROTLI_VERSION.tar.gz | tar xzf - -C /usr/src
&& curl -LSs https://github.com/google/brotli/archive/v$BROTLI_VERSION.tar.gz | tar xzf - -C /usr/src
&& rm -rf /usr/src/ngx_brotli-$NGX_BROTLI_VERSION/deps/brotli/
&& ln -s /usr/src/brotli-$BROTLI_VERSION /usr/src/ngx_brotli-$NGX_BROTLI_VERSION/deps/brotli
&& cd /usr/src/nginx-$NGINX_VERSION
&& CNF="
--prefix=/etc/nginx
--sbin-path=/usr/sbin/nginx
--modules-path=/usr/lib/nginx/modules
--conf-path=/etc/nginx/nginx.conf
--error-log-path=/var/log/nginx/error.log
--http-log-path=/var/log/nginx/access.log
--pid-path=/var/run/nginx.pid
--lock-path=/var/run/nginx.lock
--http-client-body-temp-path=/var/cache/nginx/client_temp
--http-proxy-temp-path=/var/cache/nginx/proxy_temp
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp
--http-scgi-temp-path=/var/cache/nginx/scgi_temp
--user=nginx
--group=nginx
--without-http_ssi_module
--without-http_userid_module
--without-http_access_module
--without-http_auth_basic_module
--without-http_mirror_module
--without-http_autoindex_module
--without-http_geo_module
--without-http_split_clients_module
--without-http_referer_module
--without-http_rewrite_module
--without-http_proxy_module
--without-http_fastcgi_module
--without-http_uwsgi_module
--without-http_scgi_module
--without-http_grpc_module
--without-http_memcached_module
--without-http_limit_conn_module
--without-http_limit_req_module
--without-http_empty_gif_module
--without-http_browser_module
--without-http_upstream_hash_module
--without-http_upstream_ip_hash_module
--without-http_upstream_least_conn_module
--without-http_upstream_keepalive_module
--without-http_upstream_zone_module
--without-http_gzip_module
--with-http_gzip_static_module
--with-threads
--with-compat
--with-file-aio
--add-dynamic-module=/usr/src/ngx_brotli-$NGX_BROTLI_VERSION
"
# Π‘ΠΎΠ±ΠΈΡΠ°Π΅ΠΌ
&& ./configure $CNF
&& make -j$(getconf _NPROCESSORS_ONLN)
&& make install
&& rm -rf /usr/src/
# Π£Π΄Π°Π»ΡΠ΅ΠΌ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΈΠΉ brotli ΠΌΠΎΠ΄ΡΠ»Ρ, ΠΎΡΡΠ°Π²Π»ΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ
&& rm /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so
&& sed -i '$ d' /etc/apk/repositories
# Bring in gettext so we can get `envsubst`, then throw
# the rest away. To do this, we need to install `gettext`
# then move `envsubst` out of the way so `gettext` can
# be deleted completely, then move `envsubst` back.
&& apk add --no-cache --virtual .gettext gettext
&& mv /usr/bin/envsubst /tmp/
&& runDeps="$(
scanelf --needed --nobanner /usr/sbin/nginx /usr/lib/nginx/modules/*.so /tmp/envsubst
| awk '{ gsub(/,/, "nso:", $2); print "so:" $2 }'
| sort -u
| xargs -r apk info --installed
| sort -u
)"
&& apk add --no-cache $runDeps
&& apk del .build-deps
&& apk del .gettext
&& mv /tmp/envsubst /usr/local/bin/
# Bring in tzdata so users could set the timezones through the environment
# variables
&& apk add --no-cache tzdata
# forward request and error logs to docker log collector
&& ln -sf /dev/stdout /var/log/nginx/access.log
&& ln -sf /dev/stderr /var/log/nginx/error.log
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]
Hamboariko avy hatrany ny nginx.conf mba hahafahan'ny gzip sy brotli amin'ny alΓ lan'ny default. Hampiditra lohapejy caching koa aho, satria tsy hiova static mihitsy isika. Ary ny fikitihana farany dia ny hamerenana ny fangatahana 404 rehetra mankany amin'ny index.html, ilaina amin'ny fitetezana ao amin'ny SPA izany.
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
load_module /usr/lib/nginx/modules/ngx_http_brotli_static_module.so;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
gzip_static on;
brotli_static on;
server {
listen 80;
server_name localhost;
charset utf-8;
location / {
root html;
try_files $uri /index.html;
etag on;
expires max;
add_header Cache-Control public;
location = /index.html {
expires 0;
add_header Cache-Control "no-cache, public, must-revalidate, proxy-revalidate";
}
}
}
}
Azonao alaina eto ny sary vita:
Fampianarana statika mba hahatakarana ny fari-piainan'ny tontolo iainana
Nahoana no ilaina ny fanovana ao amin'ny SPA? Ohatra, mba hamaritana izay API RESTful ampiasaina. Amin'ny ankapobeny, afindra any amin'ny SPA ny fanovana ho an'ny tontolo irina amin'ny dingana fananganana. Raha mila manova zavatra ianao dia tsy maintsy manangana indray ny fampiharana. Tsy tiako izany. Tiako haorina indray mandeha eo amin'ny sehatra CI ny fampiharana, ary amboarina araka izay ilaina amin'ny sehatra CD amin'ny fampiasana ny fari-piainan'ny tontolo iainana.
Mazava ho azy fa ny rakitra static ny tenany dia tsy mahatakatra ny fari-piainan'ny tontolo iainana. Noho izany dia tsy maintsy mampiasa fitaka ianao. Amin'ny sary farany dia tsy hanomboka ny nginx aho, fa script shell manokana izay hamaky ny fari-piainan'ny tontolo iainana, soraty amin'ny rakitra static, manindry azy ireo, ary avy eo mamindra ny fanaraha-maso amin'ny nginx.
Ho an'ity tanjona ity, ny Dockerfile dia manome ny parameter ENTRYPOINT. Andeha homentsika azy ity script manaraka ity (mampiasa Angular ho ohatra):
docker-entrypoint.sh
#!/bin/sh set -e FLAG_FILE="/configured" TARGET_DIR="/etc/nginx/html" replace_vars () { ENV_VARS='$(awk 'BEGIN{for(v in ENVIRON) print "
quot;v}')'
# Π Angular ΠΈΡΠ΅ΠΌ ΠΏΠ»Π΅ΠΉΡΡ ΠΎΠ»Π΄Π΅ΡΡ Π² main-ΡΠ°ΠΉΠ»Π°Ρ
for f in "$TARGET_DIR"/main*.js; do
# envsubst Π·Π°ΠΌΠ΅Π½ΡΠ΅Ρ Π² ΡΠ°ΠΉΠ»Π°Ρ ΠΏΠ»Π΅ΠΉΡΡ ΠΎΠ»Π΄Π΅ΡΡ Π½Π° Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΈΠ· ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ
echo "$(envsubst "$ENV_VARS" < "$f")" > "$f"
done
}
compress () {
for i in $(find "$TARGET_DIR" | grep -E ".css$|.html$|.js$|.svg$|.txt$|.ttf
quot;); do
# ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΡΡ ΡΡΠ΅ΠΏΠ΅Π½Ρ ΡΠΆΠ°ΡΠΈΡ
gzip -9kf "$i" && brotli -fZ "$i"
done
}
if [ "$1" = 'nginx' ]; then
# Π€Π»Π°Π³ Π½ΡΠΆΠ΅Π½, ΡΡΠΎΠ±Ρ Π²ΡΠΏΠΎΠ»Π½ΠΈΡΡ ΡΠΊΡΠΈΠΏΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΈ ΡΠ°ΠΌΠΎΠΌ ΠΏΠ΅ΡΠ²ΠΎΠΌ Π·Π°ΠΏΡΡΠΊΠ΅
if [ ! -e "$FLAG_FILE" ]; then
echo "Running init script"
echo "Replacing env vars"
replace_vars
echo "Compressing files"
compress
touch $FLAG_FILE
echo "Done"
fi
fi
exec "$@"
Mba hahavitan'ny script ny asany dia tsy maintsy soratana ao amin'ny rakitra js amin'ity endrika ity ny fika:${API_URL}
.Tsara ny manamarika fa ny ankamaroan'ny SPA maoderina dia manampy hashes amin'ny rakitra rehefa manorina. Ilaina izany mba ahafahan'ny navigateur afaka mitahiry ny rakitra mandritra ny fotoana maharitra. Raha miova ny rakitra dia hiova ny hash-ny, izay hanery ny navigateur hisintona indray ilay rakitra.
Indrisy anefa, amin'ny fombako, ny fanovana ny fanovana amin'ny alΓ lan'ny fari-piainan'ny tontolo iainana dia tsy mitondra fiovana amin'ny hash rakitra, izay midika fa ny cache navigateur dia tsy maintsy ho foana amin'ny fomba hafa. Tsy manana an'io olana io aho satria ny fanamafisana samihafa dia apetraka amin'ny tontolo samihafa.
Manambatra ny sary farany
Farany.
dockerfile
# ΠΠ΅ΡΠ²ΡΠΉ Π±Π°Π·ΠΎΠ²ΡΠΉ ΠΎΠ±ΡΠ°Π· Π΄Π»Ρ ΡΠ±ΠΎΡΠΊΠΈ FROM alexxxnf/spa-builder as builder # Π§ΡΠΎΠ±Ρ ΡΡΡΠΊΡΠΈΠ²Π½Π΅Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΊΡΡ Docker-Π°, ΡΠ½Π°ΡΠ°Π»Π° ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΡΠΎΠ»ΡΠΊΠΎ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ COPY ./package.json ./package-lock.json /app/ RUN cd /app && npm ci --no-audit # ΠΠΎΡΠΎΠΌ ΡΠΎΠ±ΠΈΡΠ°Π΅ΠΌ ΡΠ°ΠΌΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ COPY . /app RUN cd /app && npm run build -- --prod --configuration=docker # ΠΡΠΎΡΠΎΠΉ Π±Π°Π·ΠΎΠ²ΡΠΉ ΠΎΠ±ΡΠ°Π· Π΄Π»Ρ ΡΠ°Π·Π΄Π°ΡΠΈ FROM alexxxnf/nginx-spa # ΠΠ°Π±ΠΈΡΠ°Π΅ΠΌ ΠΈΠ· ΠΏΠ΅ΡΠ²ΠΎΠ³ΠΎ ΠΎΠ±ΡΠ°Π·Π° ΡΠ½Π°ΡΠ°Π»Π° ΠΊΠΎΠΌΠΏΡΠ΅ΡΡΠΎΡ COPY --from=builder /usr/local/bin/brotli /usr/local/bin # ΠΠΎΡΠΎΠΌ Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ ΡΡΠ΄ΠΎ-ΡΠΊΡΠΈΠΏΡ COPY ./docker/docker-entrypoint.sh /docker-entrypoint.sh # Π Π² ΠΊΠΎΠ½ΡΠ΅ Π·Π°Π±ΠΈΡΠ°Π΅ΠΌ ΡΠ°ΠΌΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ COPY --from=builder /app/dist/app /etc/nginx/html/ ENTRYPOINT ["/docker-entrypoint.sh"] CMD ["nginx", "-g", "daemon off;"]
Ankehitriny dia azo angonina sy ampiasaina na aiza na aiza ny sary azo.
Source: www.habr.com