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

Patterns deployment cache #1088

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ FROM node:19.8.1-alpine as builder
COPY . /frontend-shared
RUN cd /frontend-shared && \
yarn install --frozen-lockfile && \
yarn build-pattern-lib
NODE_ENV=production yarn build-pattern-lib
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot set ENV NODE_ENV=production for the whole docker stage, because then yarn install does not install dev dependencies, which are needed for bundling.



FROM nginx:1.24.0-alpine

RUN rm -r /usr/share/nginx/html && rm /etc/nginx/conf.d/default.conf
# Copy pattern library static assets, and put them in nginx document root folder
COPY --from=builder /frontend-shared/build /usr/share/nginx/html
COPY ./templates/index.html /usr/share/nginx/html/index.html
COPY --from=builder /frontend-shared/templates/index.html /usr/share/nginx/html/index.html
COPY ./images /usr/share/nginx/html/images
COPY conf/nginx.conf /etc/nginx/conf.d/default.conf

Expand Down
16 changes: 15 additions & 1 deletion conf/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ server {
return 200 'Success!';
}

# JS and CSS files can be saved for a year, as they include a hash.
location ~* \.(?:css|js)$ {
expires 1y;
add_header Cache-Control "public";
}
# TODO Decide on a sensible cache period for images
location ~* \.(?:jpg|gif|png|ico|svg)$ {
expires 1M;
add_header Cache-Control "public";
}

# When requesting static paths with an extension, try them, and return a 404 if not found
location ~* .+\..+ {
try_files $uri $uri/ =404;
Expand All @@ -18,6 +29,9 @@ server {
# When requesting a path without extension, try it, and return the index if not found
# This allows for client-side route handling
location / {
try_files $uri $uri/ /index.html$is_args$args;
# The index file references CSS and JS bundles, so we need to make sure it's always up to date
# TODO It would also be ok to cache it for a short period of time, like 5 minutes
expires -1;
try_files $uri $uri/ /index.html;
}
}
27 changes: 27 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { buildCSS, runTests, watchJS } from '@hypothesis/frontend-build';
import * as fs from 'fs';
import gulp from 'gulp';

import { servePatternLibrary } from './scripts/serve-pattern-library.js';
Expand Down Expand Up @@ -60,3 +61,29 @@ gulp.task(
})
)
);

gulp.task('update-patterns-index', async () => {
// Determine the name of the JS/CSS bundles (in prod they could contain a hash)
const jsBundleName = fs
.readdirSync('build/scripts')
.find(file => file.startsWith('pattern-library'));
const cssBundleName = fs
.readdirSync('build/styles')
.find(file => file.startsWith('pattern-library'));

if (!jsBundleName || !cssBundleName) {
throw new Error(
'JS and/or CSS bundles missing. Make sure bundles are generated first'
);
}

// Replace references to the generic bundle names with the resolved ones
const indexContent = fs
.readFileSync('templates/index.html')
.toString()
.replace('pattern-library.bundle.js', jsBundleName)
.replace('pattern-library.css', cssBundleName);

// eslint-disable-next-line no-undef
fs.writeFileSync('templates/index.html', Buffer.from(indexContent));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here templates/index.html has become an actual template instead of just a static file. If that is the case then I think we should make that obvious by rendering it with a template renderer when served or at build time. Assuming we're continuing to serve this as static content, then the output should go into the build/ directory rather than modifying the source file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dumbest possible template renderer is to use some obvious placeholder like {{ js_bundle }} and do a string search and replace all. We might as well use something like Mustache though and at least get proper escaping.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here templates/index.html has become an actual template instead of just a static file. If that is the case then I think we should make that obvious by rendering it with a template renderer when served or at build time. Assuming we're continuing to serve this as static content, then the output should go into the build/ directory rather than modifying the source file.

We recently renamed this file to change the mustache-specific extension to .html because it was static. If it's a "template again," we should once again change the source file name, methinks.

});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"scripts": {
"build-lib": "babel src/ --out-dir lib/ --extensions '.js,.ts,.tsx' --source-maps --ignore '**/test' --ignore '**/karma.config.js'",
"build": "yarn build-lib && tsc --build src/tsconfig.json",
"build-pattern-lib": "yarn gulp bundle-css && yarn rollup -c rollup.config.js",
"build-pattern-lib": "yarn gulp bundle-css && yarn rollup -c rollup.config.js && yarn gulp update-patterns-index",
"typecheck": "tsc --build src/tsconfig.json",
"lint": "eslint --cache .",
"checkformatting": "prettier --cache --check '**/*.{js,scss,ts,tsx,md}'",
Expand Down
6 changes: 4 additions & 2 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import commonjs from '@rollup/plugin-commonjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import { string } from 'rollup-plugin-string';

// eslint-disable-next-line no-undef
const isProd = process.env.NODE_ENV === 'production';

function bundleConfig(name, entryFile) {
return {
input: {
Expand All @@ -11,8 +14,7 @@ function bundleConfig(name, entryFile) {
output: {
dir: 'build/scripts/',
format: 'es',
chunkFileNames: '[name].bundle.js',
entryFileNames: '[name].bundle.js',
entryFileNames: isProd ? '[name]-[hash].bundle.js' : '[name].bundle.js',
},

// Suppress a warning (https://rollupjs.org/guide/en/#error-this-is-undefined)
Expand Down