Skip to content

Commit

Permalink
feat(build): add logic for non-bundling builds
Browse files Browse the repository at this point in the history
For Docker builds, we don't want to bundle the config files into the
dist/index.js file. By bundling them, we lose the ability to change
them without rebuilding the image. Rebuilding the image every time
we want to change the config files is not ideal and would prevent us
from using the image for other sites.

Solving this problem is a bit tricky because we want to use the same
build script for both Docker and non-Docker builds, keep the independent
core and scripts bundling, and retain the path aliasing functionality.
To achieve all of this, I used the following:
- tsup's 'external' option to exclude the "@config" modules from the bundle
- The tsc-alias package to resolve the "@config" paths to a relative path
- The process.env.DOCKER variable to determine whether to use tsup's
  'external' option or not (this variable is set in the Dockerfile).

By doing all of this, we can now pass the config files into the
container as volumes and change them without rebuilding the image. At
the same time, we can still use the same build script for local
development and retain the simplicity of standalone builds.

The use of tsc-alias was discovered in this issue:
evanw/esbuild#394 (comment).
Without it, "@config/*" paths would remain in the bundle and would
cause errors as there is no way for "@config" to be resolved as
a local path.
  • Loading branch information
ardelato committed Nov 30, 2023
1 parent 68fb3a3 commit d9d6942
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 0 deletions.
23 changes: 23 additions & 0 deletions build.config-alias-replacer.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* File must be named with a .cjs extension to be recognized by tsc-alias and
* work with the type: "module" setting in package.json.
* @see https://github.com/justkey007/tsc-alias/discussions/73#discussioncomment-4416038
*/
const fs = require('fs');

/**
* This script replaces '@config/' aliases with relative paths './' in the
* provided file.
* This is necessary for non-bundling scenarios like Docker, where we want to
* use files from the host machine.
* Without this, the referenced files would be bundled, which is not the
* desired behavior in this case.
*/
function configAliasReplace({ orig, file }) {
const fileContents = fs.readFileSync(file, 'utf8');
const newContents = fileContents.replace(/@config\//g, './');
fs.writeFileSync(file, newContents, 'utf8');
return orig;
}

exports.default = configAliasReplace;
23 changes: 23 additions & 0 deletions build.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { build as tsupBuild } from 'tsup';
import { replaceTscAliasPaths } from 'tsc-alias';
import yargs from 'yargs';

const CORE_DIR = 'dist';
const SCRIPTS_DIR = 'bin';
const isDocker = process.env.DOCKER === 'true';

const argv = yargs(process.argv.slice(2)).options({
target: {
Expand Down Expand Up @@ -33,6 +35,7 @@ const config = {
format: 'esm',
silent: argv.silent,
clean: argv.clean,
external: isDocker ? ['@config'] : [], // Don't resolve @config modules when building in docker
}

const CORE_BUILD = {
Expand All @@ -49,9 +52,29 @@ const SCRIPTS_BUILD = {
entry: ['src/scripts/*'],
}

/**
* Resolve paths after the build process because ESBuild only supports path
* resolution natively during bundling.
*
* "@config/" paths are replaced with relative-path "./" to allow for
* non-bundling scenarios like Docker.
*/
async function replaceConfigAliasPaths(outDir) {
await replaceTscAliasPaths({
configFile: 'tsconfig.json',
outDir: outDir,
watch: false,
replacers: ['build.config-alias-replacer.cjs']
});
}

async function build(buildConfig, buildTarget) {
try {
await tsupBuild(buildConfig);

if (isDocker) {
await replaceConfigAliasPaths(buildConfig.outDir);
}
} catch (e) {
console.error(`Failed to build ${buildTarget}:`, e);
process.exit(1);
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@tsconfig/node18": "^18.2.1",
"@types/node": "^20.5.9",
"@types/yargs": "^17.0.28",
"tsc-alias": "^1.8.8",
"tsup": "^8.0.1",
"typescript": "^5.2.2"
},
Expand Down
37 changes: 37 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d9d6942

Please sign in to comment.