Skip to content

Commit

Permalink
Production ready build (#175)
Browse files Browse the repository at this point in the history
 - Rename `public` -> `client` so it doesn't get copied automagically as-is (without hashes which we want for cache busting), https://vitejs.dev/guide/assets.html#the-public-directory
     - We still build the version files to `public/` so their copied as-is and Vite handles it for us (so we can use `emptyOutDir`) 
 - Use a multiple entrypoint `.js` Vite build so things can be more intelligently bundled and take less time
     - We aren't using library mode because it doesn't minify or bundle assets
 - Using hash asset tags for cache busting. Hash of the file included in the file name
 - We lookup these hashed assets from `manifest.json` that Vite builds (https://vitejs.dev/guide/backend-integration.html) to serve and preload
 - In terms of optimized bundles, I know the current output isn't great now but will have to opt to fix that up separately in the future. Tracked by #176
  • Loading branch information
MadLittleMods authored Apr 25, 2023
1 parent 50a1d65 commit 9c0b6fe
Show file tree
Hide file tree
Showing 31 changed files with 1,114 additions and 368 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
node_modules
.DS_Store
dist
dist-ssr
public
*.local

config.user-overrides.json
Expand Down
10 changes: 5 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
# - https://github.com/npm/cli/issues/4769
FROM node:16.14.2-buster-slim

# Pass through some GitHub CI variables which we use in the build
# Pass through some GitHub CI variables which we use in the build (for version
# files/tags)
ARG GITHUB_SHA
ENV GITHUB_SHA=$GITHUB_SHA
ARG GITHUB_REF
Expand All @@ -25,14 +26,13 @@ RUN npm install
# Copy what we need for the client-side build
COPY config /app/config/
COPY build-scripts /app/build-scripts/
COPY public /app/public/
COPY client /app/client/
COPY shared /app/shared/
# Also copy the server stuff (we reference the config from the `build-client.js`)
COPY server /app/server/
# Build the client-side bundle
RUN npm run build

# Copy the rest of the app
COPY server /app/server/

HEALTHCHECK CMD node docker-health-check.js

ENTRYPOINT ["/bin/bash", "-c", "npm start"]
38 changes: 0 additions & 38 deletions build-scripts/build-client-scripts.js

This file was deleted.

17 changes: 13 additions & 4 deletions build-scripts/build-client.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
'use strict';

const buildClientScripts = require('./build-client-scripts');
const vite = require('vite');
const mergeOptions = require('merge-options');

// Require the config before the Vite config so `process.env.NODE_ENV` is set
require('../server/lib/config');

const writeVersionFiles = require('./write-version-files');
const viteConfig = require('./vite.config');

async function buildClient(extraConfig = {}) {
await writeVersionFiles();

async function build(extraConfig) {
await Promise.all([writeVersionFiles(), buildClientScripts(extraConfig)]);
const resultantViteConfig = mergeOptions(viteConfig, extraConfig);
await vite.build(resultantViteConfig);
}

module.exports = build;
module.exports = buildClient;
44 changes: 0 additions & 44 deletions build-scripts/generate-vite-config-for-entry-point.js

This file was deleted.

80 changes: 80 additions & 0 deletions build-scripts/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// vite.config.js
'use strict';

const path = require('path');
const {
defineConfig, //splitVendorChunkPlugin
} = require('vite');

module.exports = defineConfig({
// We have to specify this otherwise Vite will override NODE_ENV as
// `production` when we start the server and watch build in our `start-dev.js`.
mode: process.env.NODE_ENV || 'dev',

plugins: [
// Alternatively, we can manually configure chunks via
// `build.rollupOptions.output.manualChunks`.
// Docs: https://vitejs.dev/guide/build.html#chunking-strategy
//
// This didn't seem to work for me though, so I've done the manual config way.
// splitVendorChunkPlugin(),
],

//root: './',
//base: './',
// optimizeDeps: {
// include: ['matrix-public-archive-shared'],
// },
resolve: {
alias: {
// The `file:` packages don't seem resolve correctly so let's add an alias as well
// See https://css-tricks.com/adding-vite-to-your-existing-web-app/#aa-aliases
'matrix-public-archive-shared': path.resolve(__dirname, '../shared'),
},
},
build: {
outDir: './dist',
rollupOptions: {
// Overwrite default `index.html` entry
// (https://vitejs.dev/guide/backend-integration.html#backend-integration)
input: [
path.resolve(__dirname, '../client/js/entry-client-hydrogen.js'),
path.resolve(__dirname, '../client/js/entry-client-room-directory.js'),
path.resolve(__dirname, '../client/js/entry-client-room-alias-hash-redirect.js'),
],
output: {
assetFileNames: (chunkInfo) => {
const { name } = path.parse(chunkInfo.name);
// Some of the Hydrogen assets already have hashes in the name so let's remove
// that in favor of our new hash.
const nameWithoutHash = name.replace(/-[a-z0-9]+$/, '');

return `assets/${nameWithoutHash}-[hash][extname]`;
},
},
},

// We want to know how the transformed source relates back to the original source
// for easier debugging
sourcemap: true,

// Generate `dist/manifest.json` that we can use to map a given file to it's built
// hashed file name and any dependencies it has.
manifest: true,
// We don't want to use the `ssrManifest` option. It's supposedly "for determining
// style links and asset preload directives in production"
// (https://vitejs.dev/config/build-options.html#build-ssrmanifest) (also see
// https://vitejs.dev/guide/ssr.html#generating-preload-directives) but doesn't seem
// very useful or what we want.
//
// ssrManifest: true,

// Copy things like the version files from `public/` to `dist/`
copyPublicDir: true,

// Fix `Error: 'default' is not exported by ...` when importing CommonJS files, see
// https://github.com/vitejs/vite/issues/2679 and docs:
// https://vitejs.dev/guide/dep-pre-bundling.html#monorepos-and-linked-dependencies
commonjsOptions: { include: [/shared/] },
},
});
8 changes: 4 additions & 4 deletions build-scripts/write-version-files.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ async function writeVersionFiles() {
);
}

await mkdirp(path.join(__dirname, '../dist/'));
await writeFile(path.join(__dirname, '../dist/GIT_COMMIT'), commit);
await writeFile(path.join(__dirname, '../dist/VERSION'), branch);
await writeFile(path.join(__dirname, '../dist/VERSION_DATE'), new Date().toISOString());
await mkdirp(path.join(__dirname, '../public/'));
await writeFile(path.join(__dirname, '../public/GIT_COMMIT'), commit);
await writeFile(path.join(__dirname, '../public/VERSION'), branch);
await writeFile(path.join(__dirname, '../public/VERSION_DATE'), new Date().toISOString());
}

module.exports = writeVersionFiles;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes.
9 changes: 9 additions & 0 deletions client/js/entry-client-hydrogen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'matrix-public-archive-shared/hydrogen-vm-render-script';

// Assets
// We have to disable no-missing-require lint because it doesn't take into
// account `package.json`. `exports`, see
// https://github.com/mysticatea/eslint-plugin-node/issues/255
// eslint-disable-next-line node/no-missing-import
import 'hydrogen-view-sdk/assets/theme-element-light.css';
import '../css/styles.css';
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ import assert from 'matrix-public-archive-shared/lib/assert';
import MatrixPublicArchiveURLCreator from 'matrix-public-archive-shared/lib/url-creator';
import redirectIfRoomAliasInHash from 'matrix-public-archive-shared/lib/redirect-if-room-alias-in-hash';

// Assets
// We have to disable no-missing-require lint because it doesn't take into
// account `package.json`. `exports`, see
// https://github.com/mysticatea/eslint-plugin-node/issues/255
// eslint-disable-next-line node/no-missing-import
import 'hydrogen-view-sdk/assets/theme-element-light.css';
import '../css/styles.css';

const config = window.matrixPublicArchiveContext.config;
assert(config);
assert(config.basePath);
Expand Down
14 changes: 14 additions & 0 deletions client/js/entry-client-room-directory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import 'matrix-public-archive-shared/room-directory-vm-render-script';

// Assets
// We have to disable no-missing-require lint because it doesn't take into
// account `package.json`. `exports`, see
// https://github.com/mysticatea/eslint-plugin-node/issues/255
// eslint-disable-next-line node/no-missing-import
import 'hydrogen-view-sdk/assets/theme-element-light.css';
import '../css/styles.css';
import '../css/room-directory.css';
// Just need to reference the favicon in one of the entry points for it to be copied
// over for all
import '../img/favicon.ico';
import '../img/favicon.svg';
Loading

0 comments on commit 9c0b6fe

Please sign in to comment.