Skip to content

Commit 4c73d4a

Browse files
committed
Adds readme and package json
1 parent 4971bb1 commit 4c73d4a

File tree

6 files changed

+1209
-74
lines changed

6 files changed

+1209
-74
lines changed

README.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# ⚡️ esbuild-node-tsc
2+
3+
Build your Typescript Node.js projects using blazing fast **[esbuild](https://github.com/evanw/esbuild)**.
4+
5+
Since esbuild can build large typescript node projects in subsecond speeds, this is quite useful for development builds too if you want to stick with `tsc` for production builds.
6+
7+
**_Please not this library doesnt do typechecking. For typechecking please continue to use tsc._**
8+
9+
## How does it work?
10+
11+
esbuild-node-tsc reads the tsconfig.json and builds the typescript project using esbuild. esbuild is the fastest typescript builder around. It also copies the non ts files such as json, graphql files, images,etc to the dist folder. If the assets are not copied correctly check the configuration guide below.
12+
13+
## Installation
14+
15+
```
16+
npm install --save-dev esbuild-node-tsc
17+
```
18+
19+
## Usage
20+
21+
```
22+
npx esbuild-node-tsc
23+
```
24+
25+
or use the short form.
26+
27+
```
28+
npx etsc
29+
```
30+
31+
Additionally, you can add it to your build scripts
32+
33+
```json
34+
{
35+
"name": "myproject",
36+
"version": "0.1.0",
37+
"scripts": {
38+
"dev": "etsc" <------ Add etsc or esbuild-node-tsc
39+
}
40+
}
41+
```
42+
43+
Then just run
44+
45+
```
46+
npm run dev
47+
```
48+
49+
## Live reloading (nodemon ❤️ esbuild-node-tsc)
50+
51+
Since esbuild can build large typescript projects in subsecond speeds you can use this library instead of ts-node-dev or ts-node which usually slow down when project scales.
52+
53+
To achieve live reloading:
54+
55+
```
56+
npm install --save-dev nodemon esbuild-node-tsc
57+
```
58+
59+
Then add the following script to package.json
60+
61+
```json
62+
{
63+
"name": "myproject",
64+
"version": "0.1.0",
65+
"scripts": {
66+
"dev": "nodemon"
67+
}
68+
}
69+
```
70+
71+
And add a `nodemon.json`
72+
73+
```json
74+
{
75+
"watch": ["src"],
76+
"ignore": ["src/**/*.test.ts"],
77+
"ext": "ts,mjs,js,json,graphql",
78+
"exec": "etsc",
79+
"legacyWatch": true
80+
}
81+
```
82+
83+
Finally run
84+
85+
```
86+
npm run dev
87+
```
88+
89+
## Optional configuration
90+
91+
By default esbuild-node-tsc should work out of the box for your project since it reads the necessary configuration from your tsconfig.json
92+
93+
But if things are not working as expected you can configure esbuild-node-tsc by adding `etsc.config.js` along side tsconfig.json.
94+
95+
Example `etsc.config.js`
96+
97+
```js
98+
module.exports = {
99+
outDir: "./dist",
100+
esbuild: {
101+
minify: false,
102+
target: "es2015",
103+
},
104+
assets: {
105+
baseDir: "src",
106+
filePatterns: ["**/*.json"],
107+
},
108+
};
109+
```
110+
111+
All of the above fields are optional
112+
113+
## License
114+
115+
MIT

package-lock.json

Lines changed: 17 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,35 @@
11
{
2-
"name": "esbuild-ts-node",
2+
"name": "esbuild-node-tsc",
33
"version": "1.0.0",
44
"main": "./dist/index.js",
55
"bin": {
6-
"esbuild-ts-node": "./dist/index.js"
6+
"esbuild-node-tsc": "./dist/index.js",
7+
"etsc": "./dist/index.js"
78
},
89
"license": "MIT",
910
"scripts": {
1011
"build": "tsc"
1112
},
13+
"keywords": [
14+
"esbuild",
15+
"node",
16+
"dev",
17+
"tsnode",
18+
"ts-node",
19+
"tsc",
20+
"typescript"
21+
],
1222
"devDependencies": {
1323
"@types/node": "^14.6.4",
24+
"@types/rimraf": "^3.0.0",
1425
"typescript": "^4.0.2"
1526
},
1627
"dependencies": {
1728
"cpy": "^8.1.1",
1829
"esbuild": "^0.7.6",
1930
"rimraf": "^3.0.2"
31+
},
32+
"peerDependencies": {
33+
"typescript": "*"
2034
}
2135
}

src/config.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export type Config = Partial<{
2+
outDir: string;
3+
esbuild: {
4+
entryPoints?: string[];
5+
minify?: boolean;
6+
target?: string;
7+
};
8+
assets: {
9+
baseDir?: string;
10+
filePatterns?: string[];
11+
};
12+
}>;
13+
14+
export async function readUserConfig(configPath: string): Promise<Config> {
15+
try {
16+
return require(configPath);
17+
} catch (err) {
18+
// Ignore the read error
19+
}
20+
return {};
21+
}

src/index.ts

Lines changed: 46 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,55 @@
11
#!/usr/bin/env node
2+
23
import ts, { BuildOptions } from "typescript";
34
import { build } from "esbuild";
45
import cpy from "cpy";
56
import path from "path";
6-
//@ts-ignore
77
import rimraf from "rimraf";
8+
import { Config, readUserConfig } from "./config";
89

9-
const config: Config = {
10-
outDir: "dist",
11-
esbuild: {
12-
entryPoints: [] as string[],
13-
minify: false,
14-
target: "es2015",
15-
},
16-
assets: {
17-
baseDir: "src",
18-
filePatterns: ["**", `!**/*.{ts,js,tsx,jsx}`],
19-
},
20-
};
21-
22-
type Config = {
23-
outDir?: string;
24-
esbuild?: {
25-
entryPoints?: string[];
26-
minify?: boolean;
27-
target?: string;
28-
};
29-
assets?: {
30-
baseDir?: string;
31-
filePatterns?: string[];
32-
};
33-
};
10+
const cwd = process.cwd();
3411

3512
function getTSConfig() {
3613
const tsConfigFile = ts.findConfigFile(
37-
process.cwd(),
14+
cwd,
3815
ts.sys.fileExists,
3916
"tsconfig.json"
4017
);
41-
const configFile = ts.readConfigFile(tsConfigFile!, ts.sys.readFile);
18+
if (!tsConfigFile) {
19+
throw new Error(`tsconfig.json not found in the current directory! ${cwd}`);
20+
}
21+
const configFile = ts.readConfigFile(tsConfigFile, ts.sys.readFile);
4222
const tsConfig = ts.parseJsonConfigFileContent(
4323
configFile.config,
4424
ts.sys,
45-
process.cwd()
25+
cwd
4626
);
4727
return { tsConfig, tsConfigFile };
4828
}
4929

5030
type TSConfig = ReturnType<typeof getTSConfig>["tsConfig"];
5131

5232
function esBuildSourceMapOptions(tsConfig: TSConfig) {
53-
let sourcemap = tsConfig.options.sourceMap;
54-
if (!sourcemap) {
33+
if (!tsConfig.options.sourceMap) {
5534
return false;
5635
}
57-
if (tsConfig.options.inlineSourceMap) {
58-
return "inline";
59-
}
60-
return "external";
61-
}
62-
63-
async function buildSourceFiles(esbuildOptions: Partial<BuildOptions>) {
64-
return await build({
65-
...esbuildOptions,
66-
bundle: false,
67-
format: "cjs",
68-
platform: "node",
69-
});
70-
}
71-
72-
type AssetsOptions = { baseDir: string; outDir: string; patterns: string[] };
73-
74-
async function copyNonSourceFiles({
75-
baseDir,
76-
outDir,
77-
patterns,
78-
}: AssetsOptions) {
79-
const relativeOutDir = path.relative(baseDir, outDir);
80-
return await cpy(patterns, relativeOutDir, {
81-
cwd: baseDir,
82-
parents: true,
83-
});
36+
return tsConfig.options.inlineSourceMap ? "inline" : "external";
8437
}
8538

8639
function getBuildMetadata(userConfig: Config) {
8740
const { tsConfig, tsConfigFile } = getTSConfig();
8841

89-
const outDir = tsConfig.options.outDir || config.outDir || "dist";
42+
const outDir = tsConfig.options.outDir || userConfig.outDir || "dist";
9043

9144
const esbuildEntryPoints = userConfig.esbuild?.entryPoints || [];
9245
const srcFiles = [...tsConfig.fileNames, ...esbuildEntryPoints];
9346
const sourcemap = esBuildSourceMapOptions(tsConfig);
9447
const target =
95-
config.esbuild?.target || tsConfig?.raw?.compilerOptions?.target || "es6";
96-
const minify = config.esbuild?.minify || false;
48+
userConfig.esbuild?.target ||
49+
tsConfig?.raw?.compilerOptions?.target ||
50+
"es6";
51+
52+
const minify = userConfig.esbuild?.minify || false;
9753

9854
const esbuildOptions: BuildOptions = {
9955
outdir: outDir,
@@ -104,20 +60,45 @@ function getBuildMetadata(userConfig: Config) {
10460
tsconfig: tsConfigFile,
10561
};
10662

63+
const assetPatterns = userConfig.assets?.filePatterns || ["**"];
64+
10765
const assetsOptions = {
10866
baseDir: userConfig.assets?.baseDir || "src",
10967
outDir: outDir,
110-
patterns: userConfig.assets?.filePatterns || [
111-
"**",
112-
`!**/*.{ts,js,tsx,jsx}`,
113-
],
68+
patterns: [...assetPatterns, `!**/*.{ts,js,tsx,jsx}`],
11469
};
11570

11671
return { outDir, esbuildOptions, assetsOptions };
11772
}
11873

74+
async function buildSourceFiles(esbuildOptions: Partial<BuildOptions>) {
75+
return await build({
76+
...esbuildOptions,
77+
bundle: false,
78+
format: "cjs",
79+
platform: "node",
80+
});
81+
}
82+
83+
type AssetsOptions = { baseDir: string; outDir: string; patterns: string[] };
84+
85+
async function copyNonSourceFiles({
86+
baseDir,
87+
outDir,
88+
patterns,
89+
}: AssetsOptions) {
90+
const relativeOutDir = path.relative(baseDir, outDir);
91+
return await cpy(patterns, relativeOutDir, {
92+
cwd: baseDir,
93+
parents: true,
94+
});
95+
}
96+
11997
async function main() {
98+
const config = await readUserConfig(path.resolve(cwd, "etsc.config.js"));
99+
120100
const { outDir, esbuildOptions, assetsOptions } = getBuildMetadata(config);
101+
121102
rimraf.sync(outDir);
122103

123104
await Promise.all([

0 commit comments

Comments
 (0)