Skip to content

Commit 38c3974

Browse files
Mikko TiihonenMikko Tiihonen
authored andcommitted
Precompress and optimize static files during build and serve them to the browsers.
- optimize png images with pngquant (quality 95) and advpng - optimize svg images with svgo - create precompressed variants of js, css, svg files: gz using zopfli and br using brotli Currently using forked versions of expressjs/send/negotiator while waiting for the PRs to go through: - jshttp/negotiator#49 - pillarjs/send#108
1 parent aeb1502 commit 38c3974

File tree

5 files changed

+96
-5
lines changed

5 files changed

+96
-5
lines changed

Dockerfile

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,36 @@ ADD . ${WORK}
2727
# Build and set permissions for arbitary non-root users in OpenShift
2828
# (https://docs.openshift.org/latest/creating_images/guidelines.html#openshift-specific-guidelines)
2929
RUN \
30+
echo "deb http://ftp.de.debian.org/debian/ stretch main contrib non-free\ndeb-src http://ftp.de.debian.org/debian/ stretch main contrib non-free" | tee /etc/apt/sources.list.d/stretch.list && \
31+
apt-get update && \
32+
apt-get install -y --no-install-recommends \
33+
brotli \
34+
zopfli \
35+
advancecomp \
36+
pngquant && \
3037
npm install && \
3138
npm rebuild node-sass && \
3239
npm run build && \
3340
rm -rf static docs test /tmp/* && \
3441
npm prune --production && \
3542
npm cache clean && \
43+
apt-get purge --auto-remove -y \
44+
brotli \
45+
zopfli \
46+
advancecomp \
47+
pngquant \
48+
# also remove packages that native node module compilations required \
49+
g++ \
50+
cpp \
51+
gcc \
52+
make \
53+
autoconf \
54+
automake \
55+
libtool \
56+
lib*-dev && \
57+
apt-get autoremove -y && \
58+
apt-get clean && \
59+
rm -rf /var/lib/apt/lists/* && \
3660
chmod -R a+rwX . && \
3761
chown -R 9999:9999 ${WORK}
3862

package.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@
2323
"test-visual-update": "gemini update test/visual/",
2424
"es-lint": "eslint .",
2525
"lint": "npm run es-lint",
26-
"build": "NODE_ENV=production webpack --progress --color --display-error-details",
27-
"win-build": "set NODE_ENV=production&& webpack --progress --color",
26+
"build": "npm run webpack && npm run precompress",
27+
"win-build": "npm run win-webpack",
28+
"webpack": "NODE_ENV=production webpack --progress --color --display-error-details",
29+
"win-webpack": "set NODE_ENV=production&& webpack --progress --color",
2830
"start": "NODE_ENV=production node --harmony server/server",
29-
"win-start": "set NODE_ENV=production&& set CONFIG=hsl&& node --harmony server/server.js"
31+
"win-start": "set NODE_ENV=production&& set CONFIG=hsl&& node --harmony server/server.js",
32+
"precompress": "./precompress.sh _static"
3033
},
3134
"main": "server.js",
3235
"repository": {
@@ -59,7 +62,7 @@
5962
"csscolorparser": "1.0.3",
6063
"debug": "2.3.3",
6164
"element-resize-detector": "1.1.9",
62-
"express": "4.14.0",
65+
"express": "gmokki/express#6eeb054",
6366
"fluxible": "1.2.0",
6467
"fluxible-action-utils": "0.2.4",
6568
"fluxible-addons-react": "0.2.8",

precompress-file.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/bin/bash
2+
set -e
3+
4+
if [ -x "$(command -v brotli)" ]; then
5+
BROTLI=brotli
6+
elif [ -x "$(command -v bro)" ]; then
7+
BROTLI=bro
8+
fi
9+
if [ -x "$(command -v zopfli)" ]; then
10+
ZOPFLI=zopfli
11+
fi
12+
if [ -x "$(command -v advpng)" ]; then
13+
ADVPNG=advpng
14+
fi
15+
16+
# settings
17+
ZOPFLI_ITERATIONS=15
18+
BROTLI_LEVEL=20
19+
PNG_QUALITY=95
20+
PNG_ZOPFLI_ITERATIONS=15
21+
SKIP_COMPRESS_REGEXP="\.map$"
22+
23+
[ -f "$1" ] || exit 1
24+
25+
[[ "$1" =~ $SKIP_COMPRESS_REGEXP ]] && exit 0
26+
27+
TMPDIR="$(mktemp -d /tmp/precompress-XXXXXXXXXX)"
28+
function cleanup {
29+
rm -rf "$TMPDIR"
30+
}
31+
trap cleanup EXIT
32+
33+
if [[ "$1" =~ \.png$ ]]; then
34+
TMPFILE="$TMPDIR/image.png"
35+
if pngquant --speed 1 --quality $PNG_QUALITY - < "$1" > "$TMPFILE"; then :; else
36+
[[ $? != 99 ]] && exit 1
37+
fi
38+
[ -n "$ADVPNG" ] && $ADVPNG --recompress --shrink-insane --iter=$PNG_ZOPFLI_ITERATIONS --quiet "$TMPFILE" || exit 1
39+
mv "$TMPFILE" "$1" || exit 2
40+
else
41+
if [[ "$1" =~ \.svg$ ]]; then
42+
export PATH+=:$(dirname "$0")/node_modules/.bin
43+
svgo --multipass --disable removeUselessDefs --disable=cleanupIDs --config '{"useShortTags":false}' --output "$TMPDIR/file.svg" "$1" &&
44+
mv "$TMPDIR/file.svg" "$1" || exit 3
45+
fi
46+
[ -n "$ZOPFLI" ] && $ZOPFLI -i$ZOPFLI_ITERATIONS "$1" -c > "$TMPDIR/file.gz" && mv "$TMPDIR/file.gz" "$1.gz" || exit 4
47+
[ -n "$BROTLI" ] && $BROTLI --quality $BROTLI_LEVEL --input "$1" --output "$TMPDIR/file.br" && mv "$TMPDIR/file.br" "$1.br" || exit 5
48+
fi
49+
50+
exit 0

precompress.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
set -e
3+
4+
if [ ! -d "$1" ]; then
5+
exit 1
6+
fi
7+
8+
if [ $(uname) == Linux ]; then
9+
NUMCPUS=$(grep -c "^processor" /proc/cpuinfo)
10+
else
11+
NUMCPUS=$(sysctl -n hw.ncpu)
12+
fi
13+
14+
find "$1" -type f -and -not -name "*.gz" -and -not -name "*.br" -print0 | xargs -0 -n1 -P$NUMCPUS nice ./precompress-file.sh

server/server.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const app = express();
4242
function setUpStaticFolders() {
4343
const staticFolder = path.join(process.cwd(), '_static');
4444
// Sert cache for 1 week
45-
app.use(config.APP_PATH, express.static(staticFolder, { maxAge: 604800000 }));
45+
app.use(config.APP_PATH, express.static(staticFolder, { maxAge: 604800000, precompressed: [{encoding: 'br', extension: '.br'}, {encoding: 'gzip', extension: '.gz'}]}));
4646
}
4747

4848
function setUpMiddleware() {

0 commit comments

Comments
 (0)