From 8c18e9bfbf6347e9fd6922693878d8a736d04510 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 2 Jun 2020 16:14:23 +0200 Subject: [PATCH] :sparkles: Improve cache handling. And make the devenv http server behave similar to a production environment (related to cache handling). --- docker/devenv/Dockerfile | 1 + docker/devenv/docker-compose.yaml | 1 + docker/devenv/files/init.sh | 3 + docker/devenv/files/nginx.conf | 95 +++++++++++++++++++++ frontend/deps.edn | 2 +- frontend/gulpfile.js | 46 +++++++++- frontend/package-lock.json | 5 ++ frontend/package.json | 1 + frontend/resources/templates/index.mustache | 6 +- frontend/scripts/build-app.sh | 4 +- frontend/shadow-cljs.edn | 2 +- frontend/src/uxbox/config.cljs | 2 +- 12 files changed, 160 insertions(+), 8 deletions(-) create mode 100644 docker/devenv/files/nginx.conf diff --git a/docker/devenv/Dockerfile b/docker/devenv/Dockerfile index 8caf8e9061..469892ecb9 100644 --- a/docker/devenv/Dockerfile +++ b/docker/devenv/Dockerfile @@ -31,6 +31,7 @@ RUN set -ex; \ build-essential \ imagemagick \ webp \ + nginx \ jq \ redis-tools \ ; \ diff --git a/docker/devenv/docker-compose.yaml b/docker/devenv/docker-compose.yaml index cfbcc2985a..03f2fe6044 100644 --- a/docker/devenv/docker-compose.yaml +++ b/docker/devenv/docker-compose.yaml @@ -29,6 +29,7 @@ services: - "user_data:/home/uxbox/local" - "${HOME}/.m2:/home/uxbox/.m2" - "${PWD}:/home/uxbox/uxbox" + - ./files/nginx.conf:/etc/nginx/nginx.conf ports: - 3447:3447 diff --git a/docker/devenv/files/init.sh b/docker/devenv/files/init.sh index c87dd9f384..2ecd72657f 100755 --- a/docker/devenv/files/init.sh +++ b/docker/devenv/files/init.sh @@ -3,6 +3,9 @@ set -e; source ~/.zshrc +echo "[init.sh] Start nginx." +sudo nginx + echo "[init.sh] Setting up local permissions." sudo chown -R uxbox /home/uxbox/local diff --git a/docker/devenv/files/nginx.conf b/docker/devenv/files/nginx.conf new file mode 100644 index 0000000000..7732fb64cd --- /dev/null +++ b/docker/devenv/files/nginx.conf @@ -0,0 +1,95 @@ +user www-data; +worker_processes auto; +pid /run/nginx.pid; +include /etc/nginx/modules-enabled/*.conf; + +events { + worker_connections 768; + # multi_accept on; +} + +http { + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + # server_tokens off; + + # server_names_hash_bucket_size 64; + # server_name_in_redirect off; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + gzip on; + + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + + gzip_types text/plain text/css text/javascript application/javascript application/json application/transit+json; + + map $http_upgrade $connection_upgrade { + default upgrade; + '' close; + } + + include /etc/nginx/sites-enabled/*; + + + server { + listen 3449 default_server; + server_name _; + + client_max_body_size 5M; + charset utf-8; + + proxy_http_version 1.1; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Scheme $scheme; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + root /home/uxbox/uxbox/frontend/resources/public; + # root /home/uxbox/uxbox/frontend/target/dist; + etag off; + + + location ~* \.(js|css).*$ { + add_header Cache-Control "max-age=86400" always; # 24 hours + } + + location = /index.html { + add_header Cache-Control "no-cache, max-age=0"; + } + + location / { + try_files $uri /index.html; + } + + location /api { + proxy_pass http://127.0.0.1:6060/api; + } + + location /ws/notifications { + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_pass http://127.0.0.1:6060/ws/notifications; + } + + location /media { + alias /var/www/app/media; + } + + location /static { + alias /var/www/app/backend/resources/public/static; + } + } +} diff --git a/frontend/deps.edn b/frontend/deps.edn index eb597d0ebb..5749c14fe9 100644 --- a/frontend/deps.edn +++ b/frontend/deps.edn @@ -31,7 +31,7 @@ funcool/datoteka {:mvn/version "1.2.0"} binaryage/devtools {:mvn/version "RELEASE"} - thheller/shadow-cljs {:mvn/version "2.8.110"} + thheller/shadow-cljs {:mvn/version "2.9.10"} lambdaisland/uri {:mvn/version "1.3.45" :exclusions [org.clojure/data.json]} diff --git a/frontend/gulpfile.js b/frontend/gulpfile.js index 1f720a3871..404bc44447 100644 --- a/frontend/gulpfile.js +++ b/frontend/gulpfile.js @@ -17,6 +17,9 @@ const sass = require("sass"); const autoprefixer = require("autoprefixer") const postcss = require("postcss") +const mapStream = require("map-stream"); + + const paths = {}; paths.resources = "./resources/"; paths.output = "./resources/public/"; @@ -130,6 +133,42 @@ function readConfig(data) { return JSON.stringify(cfg); } +const defaultManifest = { + "main": "/js/main.js", + "shared": "/js/shared.js", + "worker": "js/worker.js" +}; + +function readManifest() { + try { + const path = __dirname + "/resources/public/js/manifest.json"; + const content = JSON.parse(fs.readFileSync(path, {encoding: "utf8"})); + + const index = {}; + for (let item of content) { + index[item.name] = "/js/" + item["output-name"]; + }; + + return index; + } catch (e) { + console.error("Error on reading manifest, using default."); + return defaultManifest; + } +} + +function touch() { + return mapStream(function(file, cb) { + if (file.isNull()) { + return cb(null, file); + } + + // Update file modification and access time + return fs.utimes(file.path, new Date(), new Date(), () => { + cb(null, file) + }); + }); +} + function templatePipeline(options) { return function() { const input = options.input; @@ -140,11 +179,13 @@ function templatePipeline(options) { const themes = ["default"]; const locales = readLocales(); - const config = readConfig({themes}); + const manifest = readManifest(); + const config = readConfig({themes, manifest}); const tmpl = mustache({ ts: ts, th: th, + manifest: manifest, config: JSON.stringify(config), translations: JSON.stringify(locales), themes: JSON.stringify(themes), @@ -153,7 +194,8 @@ function templatePipeline(options) { return gulp.src(input) .pipe(tmpl) .pipe(rename("index.html")) - .pipe(gulp.dest(output)); + .pipe(gulp.dest(output)) + .pipe(touch()); }; } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 37a1e50de0..45415ff2be 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -3340,6 +3340,11 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, + "map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" + }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 0855a243d9..5d22775244 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -29,6 +29,7 @@ }, "dependencies": { "date-fns": "^2.13.0", + "map-stream": "0.0.7", "mousetrap": "^1.6.5", "randomcolor": "^0.5.4", "react": "^16.13.1", diff --git a/frontend/resources/templates/index.mustache b/frontend/resources/templates/index.mustache index 99d48366f7..2c17e8417c 100644 --- a/frontend/resources/templates/index.mustache +++ b/frontend/resources/templates/index.mustache @@ -16,7 +16,9 @@ window.uxboxTranslations = JSON.parse({{& translations }}); window.uxboxThemes = {{& themes }}; - - + {{# manifest}} + + + {{/manifest}} diff --git a/frontend/scripts/build-app.sh b/frontend/scripts/build-app.sh index 02e1a5e673..20c20c6e11 100755 --- a/frontend/scripts/build-app.sh +++ b/frontend/scripts/build-app.sh @@ -3,6 +3,8 @@ source ~/.bashrc set -ex +TAG=`git log -n 1 --pretty=format:%H -- ./` + npm ci export NODE_ENV=production; @@ -10,7 +12,7 @@ export NODE_ENV=production; # Clean the output directory npx gulp clean || exit 1; -shadow-cljs release main +shadow-cljs release main --config-merge "{:release-version \"${TAG}\"}" npx gulp build || exit 1; npx gulp dist:clean || exit 1; npx gulp dist:copy || exit 1; diff --git a/frontend/shadow-cljs.edn b/frontend/shadow-cljs.edn index d6afa16cad..0f3c921432 100644 --- a/frontend/shadow-cljs.edn +++ b/frontend/shadow-cljs.edn @@ -1,5 +1,4 @@ {:deps {:aliases [:dev]} - :dev-http {3449 "classpath:public"} :http {:port 3448} :nrepl {:port 3447} @@ -10,6 +9,7 @@ :asset-path "/js" :devtools {:browser-inject :main} :build-options {:manifest-name "manifest.json"} + :modules {:shared {:entries []} :main {:entries [uxbox.main] diff --git a/frontend/src/uxbox/config.cljs b/frontend/src/uxbox/config.cljs index c7246e394c..7b1ef9543d 100644 --- a/frontend/src/uxbox/config.cljs +++ b/frontend/src/uxbox/config.cljs @@ -13,7 +13,7 @@ (this-as global (let [config (obj/get global "uxboxConfig") puri (obj/get config "publicURI" "http://localhost:3449") - buri (obj/get config "backendURI" "http://localhost:6060") + buri (obj/get config "backendURI" "http://localhost:3449") gcid (obj/get config "googleClientID" true) warn (obj/get config "demoWarning" true)] (def default-language "en")