Use git hash to break cache (#1684)
authorSleeplessOne1917 <abias1122@gmail.com>
Thu, 29 Jun 2023 14:29:33 +0000 (10:29 -0400)
committerGitHub <noreply@github.com>
Thu, 29 Jun 2023 14:29:33 +0000 (10:29 -0400)
* Use git hash to break cache

* Address PR feedback

* Make hash docker agnostic

* Add trailing slash

* Update .prettierignore

Co-authored-by: Alec Armbruster <35377827+alectrocute@users.noreply.github.com>
* Remove debugging log

* implement getStaticDir util

---------

Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
Co-authored-by: Alec Armbruster <35377827+alectrocute@users.noreply.github.com>
.prettierignore
dev.dockerfile
package.json
src/server/index.tsx
src/server/utils/create-ssr-html.tsx
src/shared/components/common/icon.tsx
src/shared/components/person/person-listing.tsx
src/shared/config.ts
src/shared/utils/env/get-static-dir.ts [new file with mode: 0644]
src/shared/utils/env/index.ts
webpack.config.js

index 004c815f9b04377fd9e27304462ec7ead6646fec..c6145fd800d00da26ec20019987abb1cad7a1feb 100644 (file)
@@ -2,3 +2,4 @@ src/shared/translations
 lemmy-translations
 src/assets/css/themes/*.css
 stats.json
+dist
index 3bfc10daed7f14b92853e908e5e16c488f45e1e3..881d9bc35f3e800e6dba154530cd9f2c6f05da71 100644 (file)
@@ -20,6 +20,7 @@ COPY generate_translations.js \
 \r
 COPY lemmy-translations lemmy-translations\r
 COPY src src\r
+COPY .git .git\r
 \r
 # Set UI version \r
 RUN echo "export const VERSION = 'dev';" > "src/shared/version.ts"\r
index 16d3aec0d52fd787fd7567cd5c1ec0748797747c..3bbc0b60d95c0c01e5f2298fe68511cdca50f775 100644 (file)
@@ -8,9 +8,9 @@
   "scripts": {
     "analyze": "webpack --mode=none",
     "prebuild:dev": "yarn clean && node generate_translations.js",
-    "build:dev": "webpack --mode=development",
+    "build:dev": "webpack --env COMMIT_HASH=$(git rev-parse --short HEAD) --mode=development",
     "prebuild:prod": "yarn clean && node generate_translations.js",
-    "build:prod": "webpack --mode=production",
+    "build:prod": "webpack --env COMMIT_HASH=$(git rev-parse --short HEAD) --mode=production",
     "clean": "yarn run rimraf dist",
     "dev": "yarn build:dev --watch",
     "lint": "yarn translations:generate && tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx \"src/**\" && prettier --check \"src/**/*.{ts,tsx,js,css,scss}\"",
index 270f33c6837b957ca7d282c80bc1c551f0b702e5..e1b36e2a6bc1f81fa3134b02f84b7b609aac3298 100644 (file)
@@ -1,4 +1,5 @@
 import { setupDateFns } from "@utils/app";
+import { getStaticDir } from "@utils/env";
 import express from "express";
 import path from "path";
 import process from "process";
@@ -19,7 +20,7 @@ const [hostname, port] = process.env["LEMMY_UI_HOST"]
 
 server.use(express.json());
 server.use(express.urlencoded({ extended: false }));
-server.use("/static", express.static(path.resolve("./dist")));
+server.use(getStaticDir(), express.static(path.resolve("./dist")));
 server.use(setCacheControl);
 
 if (!process.env["LEMMY_UI_DISABLE_CSP"] && !process.env["LEMMY_UI_DEBUG"]) {
index 13775981b2972d97ff1561b264bbd0093b6d7ee2..f6d46b02058b055adae1d7e1367c52c0c88f87ad 100644 (file)
@@ -1,3 +1,4 @@
+import { getStaticDir } from "@utils/env";
 import { Helmet } from "inferno-helmet";
 import { renderToString } from "inferno-server";
 import serialize from "serialize-javascript";
@@ -87,7 +88,7 @@ export async function createSsrHtml(
     <link rel="apple-touch-startup-image" href=${appleTouchIcon} />
   
     <!-- Styles -->
-    <link rel="stylesheet" type="text/css" href="/static/styles/styles.css" />
+    <link rel="stylesheet" type="text/css" href="${getStaticDir()}/styles/styles.css" />
   
     <!-- Current theme and more -->
     ${helmet.link.toString() || fallbackTheme}
@@ -102,7 +103,7 @@ export async function createSsrHtml(
       </noscript>
   
       <div id='root'>${root}</div>
-      <script defer src='/static/js/client.js'></script>
+      <script defer src='${getStaticDir()}/js/client.js'></script>
     </body>
   </html>
   `;
index 5b6ddf818677edde9e0c4279ed20b367936dba5d..92a41a3deb5a4cf8733cd4dd7d95267bcb14680f 100644 (file)
@@ -1,3 +1,4 @@
+import { getStaticDir } from "@utils/env";
 import classNames from "classnames";
 import { Component } from "inferno";
 import { I18NextService } from "../../services";
@@ -23,7 +24,9 @@ export class Icon extends Component<IconProps, any> {
         })}
       >
         <use
-          xlinkHref={`/static/assets/symbols.svg#icon-${this.props.icon}`}
+          xlinkHref={`${getStaticDir()}/assets/symbols.svg#icon-${
+            this.props.icon
+          }`}
         ></use>
         <div className="visually-hidden">
           <title>{this.props.icon}</title>
index 6631a8eab53f9491afbe5d4ceab13448b6968052..dfc5d6634fe90819d777f191ac8426807a4c20cd 100644 (file)
@@ -1,4 +1,5 @@
 import { showAvatars } from "@utils/app";
+import { getStaticDir } from "@utils/env";
 import { hostname, isCakeDay } from "@utils/helpers";
 import classNames from "classnames";
 import { Component } from "inferno";
@@ -88,7 +89,7 @@ export class PersonListing extends Component<PersonListingProps, any> {
           !this.props.person.banned &&
           showAvatars() && (
             <PictrsImage
-              src={avatar ?? "/static/assets/icons/icon-96x96.png"}
+              src={avatar ?? `${getStaticDir()}/assets/icons/icon-96x96.png`}
               icon
             />
           )}
index 97b28d2597bdd9662be9bb40a4bf7073a452764d..58ecc08b19ad1b48d1601ff52c5145c861f758b1 100644 (file)
@@ -1,5 +1,7 @@
-export const favIconUrl = "/static/assets/icons/favicon.svg";
-export const favIconPngUrl = "/static/assets/icons/apple-touch-icon.png";
+import { getStaticDir } from "@utils/env";
+
+export const favIconUrl = `${getStaticDir()}/assets/icons/favicon.svg`;
+export const favIconPngUrl = `${getStaticDir()}/assets/icons/apple-touch-icon.png`;
 
 export const repoUrl = "https://github.com/LemmyNet";
 export const joinLemmyUrl = "https://join-lemmy.org";
diff --git a/src/shared/utils/env/get-static-dir.ts b/src/shared/utils/env/get-static-dir.ts
new file mode 100644 (file)
index 0000000..1d19596
--- /dev/null
@@ -0,0 +1,5 @@
+// Returns path to static directory, intended
+// for cache-busting based on latest commit hash.
+export default function getStaticDir() {
+  return `/static/${process.env.COMMIT_HASH}`;
+}
index e14c6735b054a38f59c98741cb12b3e0afd5bdd9..3a9a3fedeadb6e9727306be8bfbec4b10eee9211 100644 (file)
@@ -6,6 +6,7 @@ import getHttpBaseExternal from "./get-http-base-external";
 import getHttpBaseInternal from "./get-http-base-internal";
 import getInternalHost from "./get-internal-host";
 import getSecure from "./get-secure";
+import getStaticDir from "./get-static-dir";
 import httpExternalPath from "./http-external-path";
 import isHttps from "./is-https";
 
@@ -18,6 +19,7 @@ export {
   getHttpBaseInternal,
   getInternalHost,
   getSecure,
+  getStaticDir,
   httpExternalPath,
   isHttps,
 };
index a2b31d04383f752d93d99a739fd9fad42ab044c8..9afdb5266f3b75e7cb5b3aad66981c96f9eceb73 100644 (file)
@@ -14,56 +14,62 @@ const banner = `
   @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL v3.0
   `;
 
-const base = {
-  output: {
-    filename: "js/server.js",
-    publicPath: "/",
-    hashFunction: "xxhash64",
-  },
-  resolve: {
-    extensions: [".js", ".jsx", ".ts", ".tsx"],
-    alias: {
-      "@": path.resolve(__dirname, "src/"),
-      "@utils": path.resolve(__dirname, "src/shared/utils/"),
+function getBase(env) {
+  return {
+    output: {
+      filename: "js/server.js",
+      publicPath: "/",
+      hashFunction: "xxhash64",
     },
-  },
-  performance: {
-    hints: false,
-  },
-  module: {
-    rules: [
-      {
-        test: /\.(scss|css)$/i,
-        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
+    resolve: {
+      extensions: [".js", ".jsx", ".ts", ".tsx"],
+      alias: {
+        "@": path.resolve(__dirname, "src/"),
+        "@utils": path.resolve(__dirname, "src/shared/utils/"),
       },
-      {
-        test: /\.(js|jsx|tsx|ts)$/, // All ts and tsx files will be process by
-        exclude: /node_modules/, // ignore node_modules
-        loader: "babel-loader",
-      },
-      // Due to some weird babel issue: https://github.com/webpack/webpack/issues/11467
-      {
-        test: /\.m?js/,
-        resolve: {
-          fullySpecified: false,
+    },
+    performance: {
+      hints: false,
+    },
+    module: {
+      rules: [
+        {
+          test: /\.(scss|css)$/i,
+          use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
         },
-      },
+        {
+          test: /\.(js|jsx|tsx|ts)$/, // All ts and tsx files will be process by
+          exclude: /node_modules/, // ignore node_modules
+          loader: "babel-loader",
+        },
+        // Due to some weird babel issue: https://github.com/webpack/webpack/issues/11467
+        {
+          test: /\.m?js/,
+          resolve: {
+            fullySpecified: false,
+          },
+        },
+      ],
+    },
+    plugins: [
+      new webpack.DefinePlugin({
+        "process.env.COMMIT_HASH": `"${env.COMMIT_HASH}"`,
+      }),
+      new MiniCssExtractPlugin({
+        filename: "styles/styles.css",
+      }),
+      new CopyPlugin({
+        patterns: [{ from: "./src/assets", to: "./assets" }],
+      }),
+      new webpack.BannerPlugin({
+        banner,
+      }),
     ],
-  },
-  plugins: [
-    new MiniCssExtractPlugin({
-      filename: "styles/styles.css",
-    }),
-    new CopyPlugin({
-      patterns: [{ from: "./src/assets", to: "./assets" }],
-    }),
-    new webpack.BannerPlugin({
-      banner,
-    }),
-  ],
-};
+  };
+}
 
-const createServerConfig = (_env, mode) => {
+const createServerConfig = (env, mode) => {
+  const base = getBase(env);
   const config = merge({}, base, {
     mode,
     entry: "./src/server/index.tsx",
@@ -90,13 +96,14 @@ const createServerConfig = (_env, mode) => {
   return config;
 };
 
-const createClientConfig = (_env, mode) => {
+const createClientConfig = (env, mode) => {
+  const base = getBase(env);
   const config = merge({}, base, {
     mode,
     entry: "./src/client/index.tsx",
     output: {
       filename: "js/client.js",
-      publicPath: "/static/",
+      publicPath: `/static/${env.COMMIT_HASH}/`,
     },
     plugins: [
       ...base.plugins,
@@ -104,7 +111,7 @@ const createClientConfig = (_env, mode) => {
         enableInDevelopment: mode !== "development", // this may seem counterintuitive, but it is correct
         workbox: {
           modifyURLPrefix: {
-            "/": "/static/",
+            "/": `/static/${env.COMMIT_HASH}/`,
           },
           cacheId: "lemmy",
           include: [/(assets|styles|js)\/.+\..+$/g],