The code of my frontend library is split into several source files.
Example:
// a.ts
function a() {}
// b.ts
function b() {}
// main.ts
const myLib = {
a: a,
b: b
}
I need to build one ES6 module (ie. one JavaScript file) that exports only myLib
, as the default export.
I see two options. The first one:
- Run
tsc
to compile each file to JavaScript;
- Concatenate all the generated JS files into a single file
my-lib.js
;
- Append the code needed by ES6 (
export …
).
The second one:
- Concatenate all the TypeScript files into a single file
my-lib.ts
;
- Append the export:
export default myLib
;
- Run
tsc
on the concatenated file.
Both options are ugly and loose the map
file.
Is there a better way to do that?
The correct way is to create a barrel file that will re export the modules.
// foo/a.ts
export function a() {}
// foo/b.ts
export function b() {}
// foo/index.ts
export {a} from './a';
export {b} from './b';
Then in your consumer:
import {a, b} from './foo';
a();
b();
I add an answer because today the correct way for a frontend library is to use Rollup.
First, write ES6 modules, import
and export
them:
// file-a.ts
export function a() {}
// file-b.ts
export function b() {}
// main.ts
export { a } from "./file-a"
export { b } from "./file-b"
Then, compile the code to JavaScript using tsc
with the option module
set to "es6"
.
Then, let Rollup build a flat bundle from the JavaScript code. For the code above, Rollup generates this bundle:
function a() {}
function b() {}
export { a, b };
See also:
- The Rollup REPL: https://rollupjs.org/repl
- The article: Webpack and Rollup: the same but different
Notice: The definitive solution to build the definition file (.d.ts
) is not implemented yet (March, 2018). I still concatenate files with a Node.js script to generate exported types in a single TypeScript definition file.