diff --git a/README.md b/README.md index 03bf8a38b..008f05c04 100644 --- a/README.md +++ b/README.md @@ -410,6 +410,7 @@ Options --onFailure Run a command on a failed build --noClean Don't clean the dist folder --transpileOnly Skip type checking + --preserveModules Preserve module structure; do not bundle -h, --help Displays this message Examples @@ -423,6 +424,7 @@ Examples $ tsdx watch --onSuccess "echo Successful build!" $ tsdx watch --onFailure "echo The build failed!" $ tsdx watch --transpileOnly + $ tsdx watch --preserveModules ``` ### `tsdx build` @@ -442,6 +444,7 @@ Options --extractErrors Opt-in to extracting invariant error codes --tsconfig Specify your custom tsconfig path (default /tsconfig.json) --transpileOnly Skip type checking + --preserveModules Preserve module structure; do not bundle -h, --help Displays this message Examples @@ -452,6 +455,7 @@ Examples $ tsdx build --extractErrors $ tsdx build --tsconfig ./tsconfig.foo.json $ tsdx build --transpileOnly + $ tsdx build --preserveModules ``` ### `tsdx test` diff --git a/src/createRollupConfig.ts b/src/createRollupConfig.ts index 0092baf28..9fca8be5e 100644 --- a/src/createRollupConfig.ts +++ b/src/createRollupConfig.ts @@ -43,6 +43,18 @@ export async function createRollupConfig( .filter(Boolean) .join('.'); + const outputDir = [ + `${paths.appDist}/${opts.format}`, + opts.env, + shouldMinify ? 'min' : '', + ] + .filter(Boolean) + .join('/'); + + const output = opts.preserveModules + ? { dir: outputDir } + : { file: outputName }; + let tsconfigJSON; try { tsconfigJSON = await fs.readJSON(opts.tsconfig || paths.tsconfigJson); @@ -79,10 +91,11 @@ export async function createRollupConfig( // Punchline....Don't use getters and setters propertyReadSideEffects: false, }, + preserveModules: opts.preserveModules, // Establish Rollup output output: { - // Set filenames of the consumer's package - file: outputName, + // Set filenames or directories of the consumer's package + ...output, // Pass through the file format format: opts.format, // Do not let Rollup call Object.freeze() on namespace import objects diff --git a/src/index.ts b/src/index.ts index 58d8d6cf4..790a88af0 100755 --- a/src/index.ts +++ b/src/index.ts @@ -285,6 +285,8 @@ prog .example('build --transpileOnly') .option('--extractErrors', 'Extract invariant errors to ./errors/codes.json.') .example('build --extractErrors') + .option('--preserveModules', 'Preserve module structure; do not bundle') + .example('watch --preserveModules') .action(async (dirtyOpts: WatchOpts) => { const opts = await normalizeOpts(dirtyOpts); const buildConfigs = await createBuildConfigs(opts); @@ -393,6 +395,8 @@ prog .example( 'build --extractErrors=https://reactjs.org/docs/error-decoder.html?invariant=' ) + .option('--preserveModules', 'Preserve module structure; do not bundle') + .example('build --preserveModules') .action(async (dirtyOpts: BuildOpts) => { const opts = await normalizeOpts(dirtyOpts); const buildConfigs = await createBuildConfigs(opts); diff --git a/src/types.ts b/src/types.ts index e6878897e..936c2944b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,6 @@ interface SharedOpts { + // Should preserve source structure? If true, files will not be bundled + preserveModules: false; // JS target target: 'node' | 'browser'; // Path to tsconfig file diff --git a/test/tests/tsdx-build.test.js b/test/tests/tsdx-build.test.js index b91bc9808..28c79d578 100644 --- a/test/tests/tsdx-build.test.js +++ b/test/tests/tsdx-build.test.js @@ -102,6 +102,32 @@ describe('tsdx build', () => { expect(code).toBe(0); }); + it('should preserve modules after compilation', () => { + util.setupStageWithFixture(stageName, 'build-default'); + + const output = shell.exec( + 'node ../dist/index.js build --format esm,cjs --preserveModules' + ); + + // ESM build + expect(shell.test('-f', 'dist/esm/index.js')).toBeTruthy(); + expect(shell.test('-f', 'dist/esm/foo.js')).toBeTruthy(); + expect(shell.test('-f', 'dist/esm/index.d.ts')).toBeTruthy(); + expect(shell.test('-f', 'dist/esm/foo.d.ts')).toBeTruthy(); + // CJS dev build + expect(shell.test('-f', 'dist/cjs/development/index.js')).toBeTruthy(); + expect(shell.test('-f', 'dist/cjs/development/foo.js')).toBeTruthy(); + expect(shell.test('-f', 'dist/cjs/development/index.d.ts')).toBeTruthy(); + expect(shell.test('-f', 'dist/cjs/development/foo.d.ts')).toBeTruthy(); + // CJS prod build + expect(shell.test('-f', 'dist/cjs/production/min/index.js')).toBeTruthy(); + expect(shell.test('-f', 'dist/cjs/production/min/foo.js')).toBeTruthy(); + expect(shell.test('-f', 'dist/cjs/production/min/index.d.ts')).toBeTruthy(); + expect(shell.test('-f', 'dist/cjs/production/min/foo.d.ts')).toBeTruthy(); + + expect(output.code).toBe(0); + }); + afterEach(() => { util.teardownStage(stageName); });