breaking: Standalone builds (#9496)

Fixes: FRMW-2742

In this PR, we fix the build output of the backend source code, which eliminates a lot of magic between the development and production environments.

Right now, we only compile the source files from the `src` directory and write them within the `dist` directory.

**Here's how the `src` directory with a custom module looks like**

```
src
├── modules
│   └── hello
│       ├── index.ts
```

**Here's the build output**

```
dist
├── modules
│   └── hello
│       ├── index.js
```

Let's imagine a file at the root of your project (maybe the `medusa-config.js` file) that wants to import the `modules/hello/index` file. How can we ensure that the import will work in both the development and production environments?

If we write the import targeting the `src` directory, it will break in production because it should target the `dist` directory.

## Solution
The solution is to compile everything within the project and mimic the file structure in the build output, not just the `src` directory.

**Here's how the fixed output should look like**

```
dist
├── src
│  ├── modules
│  │   └── hello
│  │       ├── index.js
├── medusa-config.js
├── yarn.lock
├── package.json
```

If you notice carefully, we also have `medusa-config.js`, `yarn.lock`, and `package.json` within the `dist` directory. We do so to create a standalone built application, something you can copy/paste to your server and run without relying on the original source code.

- This results in small containers since you are not copying unnecessary files.
- Clear distinction between the development and the production code. If you want to run the production server, then `cd` into the `dist` directory and run it from there.

## Changes in the PR

- Breaking: Remove the `dist` and `build` folders. Instead, write them production artefacts within the `.medusa` directory as `.medusa/admin` and `.medusa/server`.
- Breaking: Change the output of the `.medusa/server` folder to mimic the root project structure.
- Refactor: Remove `Symbol.for("ts-node.register.instance")]` check to find from where to load the source code.
- Refactor: Use `tsc` for creating the production build. This ensures we respect `tsconfig` settings when creating the build and also perform type-checking.

Co-authored-by: Adrien de Peretti <25098370+adrien2p@users.noreply.github.com>
This commit is contained in:
Harminder Virk
2024-10-09 21:29:08 +05:30
committed by GitHub
parent 5c9457bb4f
commit 1560d7ed5f
27 changed files with 292 additions and 220 deletions

View File

@@ -13,14 +13,14 @@ describe("configLoader", () => {
expect(configModule).toBeUndefined()
configLoader(entryDirectory, "medusa-config.js")
configLoader(entryDirectory, "medusa-config")
configModule = container.resolve(ContainerRegistrationKeys.CONFIG_MODULE)
expect(configModule).toBeDefined()
expect(configModule.projectConfig.databaseName).toBeUndefined()
configLoader(entryDirectory, "medusa-config-2.js")
configLoader(entryDirectory, "medusa-config-2")
configModule = container.resolve(ContainerRegistrationKeys.CONFIG_MODULE)
@@ -30,7 +30,7 @@ describe("configLoader", () => {
process.env.MEDUSA_WORKER_MODE = "worker"
configLoader(entryDirectory, "medusa-config-2.js")
configLoader(entryDirectory, "medusa-config-2")
configModule = container.resolve(ContainerRegistrationKeys.CONFIG_MODULE)

View File

@@ -30,17 +30,14 @@ export function configLoader(
entryDirectory: string,
configFileName: string
): ConfigModule {
const { configModule, error } = getConfigFile<ConfigModule>(
entryDirectory,
configFileName
)
const config = getConfigFile<ConfigModule>(entryDirectory, configFileName)
if (error) {
handleConfigError(error)
if (config.error) {
handleConfigError(config.error)
}
return configManager.loadConfig({
projectConfig: configModule,
projectConfig: config.configModule!,
baseDir: entryDirectory,
})
}

View File

@@ -4,7 +4,7 @@ export const customersGlobalMiddlewareMock = jest.fn()
export const customersCreateMiddlewareMock = jest.fn()
export const storeGlobalMiddlewareMock = jest.fn()
export const config: ConfigModule = {
export const config = {
projectConfig: {
databaseLogging: false,
http: {
@@ -17,4 +17,4 @@ export const config: ConfigModule = {
},
featureFlags: {},
plugins: [],
}
} satisfies Partial<ConfigModule>