From 1a73573f0da651b9d32103af1662058bf4441083 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 9 Jun 2023 12:38:43 +0200 Subject: [PATCH 1/2] Allow patter library to be served in dev from build artifcats --- gulpfile.js | 31 ++++++++++++++++--- package.json | 2 +- scripts/build-pattern-library-index.js | 25 +++++++++++++++ scripts/serve-pattern-library.js | 2 +- templates/{index.html => index.template.html} | 4 +-- 5 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 scripts/build-pattern-library-index.js rename templates/{index.html => index.template.html} (62%) diff --git a/gulpfile.js b/gulpfile.js index 332d35f2..8722230b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,20 +1,41 @@ -import { buildCSS, runTests, watchJS } from '@hypothesis/frontend-build'; +import { + buildCSS, + buildJS, + runTests, + watchJS, +} from '@hypothesis/frontend-build'; import gulp from 'gulp'; +import { buildPatternLibraryIndex } from './scripts/build-pattern-library-index.js'; import { servePatternLibrary } from './scripts/serve-pattern-library.js'; import tailwindConfig from './tailwind.config.js'; -gulp.task('serve-pattern-library', () => { - servePatternLibrary(); -}); - // The following tasks bundle assets for the pattern library for use locally // during development. Bundled JS and CSS are not published with the package. +gulp.task('build-pattern-library-index', async () => + buildPatternLibraryIndex() +); + gulp.task('bundle-css', () => buildCSS(['./styles/pattern-library.scss'], { tailwindConfig }) ); +gulp.task('bundle-js', () => buildJS('./rollup.config.js')); + +gulp.task( + 'build-pattern-library', + gulp.series( + gulp.parallel('bundle-js', 'bundle-css'), + 'build-pattern-library-index' + ) +); + +gulp.task( + 'serve-pattern-library', + gulp.series('build-pattern-library', () => servePatternLibrary()) +); + gulp.task( 'watch-css', gulp.series('bundle-css', () => diff --git a/package.json b/package.json index 571ceaab..798451ac 100644 --- a/package.json +++ b/package.json @@ -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 build-pattern-library", "typecheck": "tsc --build src/tsconfig.json", "lint": "eslint --cache .", "checkformatting": "prettier --cache --check '**/*.{js,scss,ts,tsx,md}'", diff --git a/scripts/build-pattern-library-index.js b/scripts/build-pattern-library-index.js new file mode 100644 index 00000000..d4290332 --- /dev/null +++ b/scripts/build-pattern-library-index.js @@ -0,0 +1,25 @@ +import { generateManifest } from '@hypothesis/frontend-build'; +import fs from 'fs'; + +const templateMap = [ + ['{{ css_bundle }}', 'styles/pattern-library.css'], + ['{{ js_bundle }}', 'scripts/pattern-library.bundle.js'], +]; + +export async function buildPatternLibraryIndex() { + const manifest = await generateManifest({ + pattern: 'build/{scripts,styles}/pattern-library*.{css,js}', + }); + const templateContent = fs + .readFileSync('templates/index.template.html') + .toString(); + + const processedTemplateContent = templateMap.reduce( + (content, [pattern, fileName]) => { + return content.replace(pattern, manifest[fileName] ?? pattern); + }, + templateContent + ); + + fs.writeFileSync('build/index.html', processedTemplateContent); +} diff --git a/scripts/serve-pattern-library.js b/scripts/serve-pattern-library.js index dfc9dc47..d9e58412 100644 --- a/scripts/serve-pattern-library.js +++ b/scripts/serve-pattern-library.js @@ -14,7 +14,7 @@ export function servePatternLibrary(port = 4001) { // For any other path, serve the index.html file to allow client-side routing app.get('/:path?', (req, res) => { - res.sendFile(path.join(dirname, '../templates/index.html')); + res.sendFile(path.join(dirname, '../build/index.html')); }); app.listen(port, () => { diff --git a/templates/index.html b/templates/index.template.html similarity index 62% rename from templates/index.html rename to templates/index.template.html index 68dbc6bb..4c85ced9 100644 --- a/templates/index.html +++ b/templates/index.template.html @@ -4,10 +4,10 @@ UI component pattern library - +
- + From 528e3a1ca9c30398674f33b9f3f0da28ba2e02f0 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 9 Jun 2023 12:49:54 +0200 Subject: [PATCH 2/2] Add caching options to nginx config file --- Dockerfile | 5 ++--- conf/nginx.conf | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 843c44ce..90084342 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:19.8.1-alpine as builder +FROM node:20.2.0-alpine as builder COPY . /frontend-shared RUN cd /frontend-shared && \ @@ -6,12 +6,11 @@ RUN cd /frontend-shared && \ yarn build-pattern-lib -FROM nginx:1.24.0-alpine +FROM nginx:1.25.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 ./images /usr/share/nginx/html/images COPY conf/nginx.conf /etc/nginx/conf.d/default.conf diff --git a/conf/nginx.conf b/conf/nginx.conf index d1e01785..65244be9 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -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 1d; + 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; @@ -18,6 +29,8 @@ 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 + expires -1; + try_files $uri $uri/ /index.html; } }