@tamagui/build 2.0.0-rc.4 → 2.0.0-rc.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-test$colon$web.log +47 -0
- package/.turbo/turbo-test.log +22 -13
- package/README.md +4 -2
- package/__tests__/fixtures/js-main-package/.turbo/turbo-build.log +2 -0
- package/__tests__/fixtures/js-main-package/LICENSE +1 -0
- package/__tests__/fixtures/js-main-package/dist/cjs/index.js +24 -0
- package/__tests__/fixtures/js-main-package/dist/cjs/index.js.map +6 -0
- package/__tests__/fixtures/js-main-package/dist/cjs/index.native.js +31 -0
- package/__tests__/fixtures/js-main-package/dist/cjs/index.native.js.map +1 -0
- package/__tests__/fixtures/js-main-package/dist/esm/index.mjs +3 -0
- package/__tests__/fixtures/js-main-package/dist/esm/index.mjs.map +1 -0
- package/__tests__/fixtures/js-main-package/dist/esm/index.native.js +3 -0
- package/__tests__/fixtures/js-main-package/dist/esm/index.native.js.map +1 -0
- package/__tests__/fixtures/js-main-package/package.json +14 -0
- package/__tests__/fixtures/js-main-package/src/index.ts +1 -0
- package/__tests__/fixtures/js-main-package/tsconfig.json +13 -0
- package/__tests__/fixtures/js-main-package/types/index.d.ts +2 -0
- package/__tests__/fixtures/js-main-package/types/index.d.ts.map +1 -0
- package/__tests__/fixtures/simple-package/.turbo/turbo-build.log +3 -2
- package/__tests__/fixtures/simple-package/package.json +3 -1
- package/__tests__/fixtures/simple-package/src/index.ts +27 -0
- package/__tests__/fixtures/simple-package/src/nested/index.ts +1 -0
- package/__tests__/fixtures/watch-package/.turbo/turbo-build.log +1 -1
- package/__tests__/integration.test.ts +106 -3
- package/package.json +13 -6
- package/pretty-print-errors.js +33 -0
- package/tamagui-build.js +213 -57
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
$ bun run test
|
|
2
|
+
$ vitest --run
|
|
3
|
+
|
|
4
|
+
RUN v4.0.4 /Users/n8/tamagui/code/packages/build
|
|
5
|
+
|
|
6
|
+
$ node ../../../tamagui-build.js
|
|
7
|
+
$ node ../../../tamagui-build.js --bundle
|
|
8
|
+
$ node ../../../tamagui-build.js --skip-mjs
|
|
9
|
+
$ node ../../../tamagui-build.js --skip-sourcemaps
|
|
10
|
+
$ node ../../../tamagui-build.js --ignore-base-url
|
|
11
|
+
stdout | __tests__/integration.test.ts > tamagui-build integration test > should rebuild the package on file change when --watch is used
|
|
12
|
+
Watch process output: built tamagui-build-test-watch-package in 88 ms
|
|
13
|
+
|
|
14
|
+
Initial build complete, modifying file...
|
|
15
|
+
|
|
16
|
+
stdout | __tests__/integration.test.ts > tamagui-build integration test > should rebuild the package on file change when --watch is used
|
|
17
|
+
Watch process output: built tamagui-build-test-watch-package in 388 ms
|
|
18
|
+
|
|
19
|
+
Rebuild after file modification complete
|
|
20
|
+
|
|
21
|
+
$ node ../../../tamagui-build.js
|
|
22
|
+
$ node ../../../tamagui-build.js
|
|
23
|
+
$ node ../../../tamagui-build.js
|
|
24
|
+
$ MINIFY=true node ../../../tamagui-build.js
|
|
25
|
+
$ node ../../../tamagui-build.js
|
|
26
|
+
$ node ../../../tamagui-build.js
|
|
27
|
+
$ node ../../../tamagui-build.js
|
|
28
|
+
$ node ../../../tamagui-build.js
|
|
29
|
+
✓ __tests__/integration.test.ts (12 tests) 11799ms
|
|
30
|
+
✓ should build the package correctly 708ms
|
|
31
|
+
✓ should bundle the package correctly 619ms
|
|
32
|
+
✓ should skip mjs files when --skip-mjs is used 705ms
|
|
33
|
+
✓ should skip sourcemaps when --skip-sourcemaps is used 687ms
|
|
34
|
+
✓ should ignore base URL when --ignore-base-url is used 695ms
|
|
35
|
+
✓ should rebuild the package on file change when --watch is used 806ms
|
|
36
|
+
✓ should generate correct platform-specific output 690ms
|
|
37
|
+
✓ should keep side-effectful native statements outside dev-only guards 696ms
|
|
38
|
+
✓ should minify the output when MINIFY=true is set 1402ms
|
|
39
|
+
✓ should clean stale outputs before building 2191ms
|
|
40
|
+
✓ should keep only the required js aliases after postprocessing 1112ms
|
|
41
|
+
✓ should keep explicit cjs .js mains as final output 1440ms
|
|
42
|
+
|
|
43
|
+
Test Files 1 passed (1)
|
|
44
|
+
Tests 12 passed (12)
|
|
45
|
+
Start at 18:32:32
|
|
46
|
+
Duration 11.92s (transform 44ms, setup 0ms, collect 51ms, tests 11.80s, environment 0ms, prepare 2ms)
|
|
47
|
+
|
package/.turbo/turbo-test.log
CHANGED
|
@@ -5,31 +5,40 @@ $ vitest --run
|
|
|
5
5
|
$ node ../../../tamagui-build.js
|
|
6
6
|
$ node ../../../tamagui-build.js --bundle
|
|
7
7
|
$ node ../../../tamagui-build.js --skip-mjs
|
|
8
|
+
$ node ../../../tamagui-build.js --skip-sourcemaps
|
|
8
9
|
$ node ../../../tamagui-build.js --ignore-base-url
|
|
9
10
|
[90mstdout[2m | __tests__/integration.test.ts[2m > [22m[2mtamagui-build integration test[2m > [22m[2mshould rebuild the package on file change when --watch is used
|
|
10
|
-
[22m[39mWatch process output: built tamagui-build-test-watch-package in
|
|
11
|
+
[22m[39mWatch process output: built tamagui-build-test-watch-package in 80 ms
|
|
11
12
|
|
|
12
13
|
Initial build complete, modifying file...
|
|
13
14
|
|
|
14
15
|
[90mstdout[2m | __tests__/integration.test.ts[2m > [22m[2mtamagui-build integration test[2m > [22m[2mshould rebuild the package on file change when --watch is used
|
|
15
|
-
[22m[39mWatch process output: built tamagui-build-test-watch-package in
|
|
16
|
+
[22m[39mWatch process output: built tamagui-build-test-watch-package in 361 ms
|
|
16
17
|
|
|
17
18
|
Rebuild after file modification complete
|
|
18
19
|
|
|
19
20
|
$ node ../../../tamagui-build.js
|
|
20
21
|
$ node ../../../tamagui-build.js
|
|
21
22
|
$ MINIFY=true node ../../../tamagui-build.js
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
[33m[2m✓[22m[39m should
|
|
28
|
-
[33m[2m✓[22m[39m should
|
|
29
|
-
[33m[2m✓[22m[39m should
|
|
23
|
+
$ node ../../../tamagui-build.js
|
|
24
|
+
$ node ../../../tamagui-build.js
|
|
25
|
+
$ node ../../../tamagui-build.js
|
|
26
|
+
$ node ../../../tamagui-build.js
|
|
27
|
+
[32m✓[39m __tests__/integration.test.ts [2m([22m[2m11 tests[22m[2m)[22m[33m 8801[2mms[22m[39m
|
|
28
|
+
[33m[2m✓[22m[39m should build the package correctly [33m 639[2mms[22m[39m
|
|
29
|
+
[33m[2m✓[22m[39m should bundle the package correctly [33m 556[2mms[22m[39m
|
|
30
|
+
[33m[2m✓[22m[39m should skip mjs files when --skip-mjs is used [33m 623[2mms[22m[39m
|
|
31
|
+
[33m[2m✓[22m[39m should skip sourcemaps when --skip-sourcemaps is used [33m 638[2mms[22m[39m
|
|
32
|
+
[33m[2m✓[22m[39m should ignore base URL when --ignore-base-url is used [33m 621[2mms[22m[39m
|
|
33
|
+
[33m[2m✓[22m[39m should rebuild the package on file change when --watch is used [33m 765[2mms[22m[39m
|
|
34
|
+
[33m[2m✓[22m[39m should generate correct platform-specific output [33m 629[2mms[22m[39m
|
|
35
|
+
[33m[2m✓[22m[39m should minify the output when MINIFY=true is set [33m 1268[2mms[22m[39m
|
|
36
|
+
[33m[2m✓[22m[39m should clean stale outputs before building [33m 1250[2mms[22m[39m
|
|
37
|
+
[33m[2m✓[22m[39m should keep only the required js aliases after postprocessing [33m 621[2mms[22m[39m
|
|
38
|
+
[33m[2m✓[22m[39m should keep explicit cjs .js mains as final output [33m 1149[2mms[22m[39m
|
|
30
39
|
|
|
31
40
|
[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
|
|
32
|
-
[2m Tests [22m [1m[
|
|
33
|
-
[2m Start at [22m
|
|
34
|
-
[2m Duration [22m
|
|
41
|
+
[2m Tests [22m [1m[32m11 passed[39m[22m[90m (11)[39m
|
|
42
|
+
[2m Start at [22m 17:43:04
|
|
43
|
+
[2m Duration [22m 8.91s[2m (transform 38ms, setup 0ms, collect 45ms, tests 8.80s, environment 0ms, prepare 2ms)[22m
|
|
35
44
|
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Some details on how it works:
|
|
|
14
14
|
- in `.mjs`, adds path-specific imports to non-specific imports
|
|
15
15
|
- outputs both `.js` and `.cjs` files in `dist/cjs`:
|
|
16
16
|
- in `.cjs`, adds path-specific imports to non-specific imports
|
|
17
|
-
-
|
|
17
|
+
- strips bare imports that esbuild leaves behind, respecting the `sideEffects` field in package.json
|
|
18
18
|
- outputs `.native.js` and regular `.js` files for all output files, so React Native always loads separate files from web. In the `native` specific files,
|
|
19
19
|
- swc is sued to transform to es5
|
|
20
20
|
- `process.env.TAMAGUI_TARGET` is defined `native` (otherwise `web`)
|
|
@@ -30,7 +30,6 @@ It assumes your package.json looks something like this:
|
|
|
30
30
|
"main": "dist/cjs",
|
|
31
31
|
"module": "dist/esm",
|
|
32
32
|
"type": "module",
|
|
33
|
-
"removeSideEffects": "true",
|
|
34
33
|
"scripts": {
|
|
35
34
|
"build": "tamagui-build",
|
|
36
35
|
"watch": "tamagui-build --watch",
|
|
@@ -69,12 +68,15 @@ It assumes your package.json looks something like this:
|
|
|
69
68
|
### Use
|
|
70
69
|
|
|
71
70
|
- `tamagui-build` - builds `src` folder to `dist` and `types` folders
|
|
71
|
+
- normal builds clear `dist` and `types` first, so stale transformed files don't hang around
|
|
72
|
+
- intermediary `.js` files are removed after `.mjs` / `.cjs` postprocessing, so published output stays lean
|
|
72
73
|
- `tamagui build .` second argument sets baseUrl to tsc
|
|
73
74
|
- `--bundle-modules` - inline node_modules
|
|
74
75
|
- `--declaration-root` - sets tsc flag `--declarationDir ./`
|
|
75
76
|
- `--ignore-base-url` - if not set, tsc is passed `--baseUrl .`
|
|
76
77
|
- `--skip-mjs` - don't output mjs files
|
|
77
78
|
- `--skip-native` - don't output native files
|
|
79
|
+
- `--skip-sourcemaps` - don't output js or declaration sourcemaps
|
|
78
80
|
- `--swap-exports` - swaps `exports.types` from `./src/*.ts` to `./types/*.d.ts` for publishing. if a command is given after `--`, runs it then swaps back. exit code is preserved.
|
|
79
81
|
- `tamagui-build --swap-exports` - build and swap, stays swapped (for manual publish)
|
|
80
82
|
- `tamagui-build --swap-exports -- npm publish` - build, swap, publish, swap back
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
MIT
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var index_exports = {};
|
|
19
|
+
__export(index_exports, {
|
|
20
|
+
jsMainFixture: () => jsMainFixture
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(index_exports);
|
|
23
|
+
const jsMainFixture = "ok";
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all) __defProp(target, name, {
|
|
9
|
+
get: all[name],
|
|
10
|
+
enumerable: true
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
16
|
+
get: () => from[key],
|
|
17
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
23
|
+
value: true
|
|
24
|
+
}), mod);
|
|
25
|
+
var index_exports = {};
|
|
26
|
+
__export(index_exports, {
|
|
27
|
+
jsMainFixture: () => jsMainFixture
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
var jsMainFixture = "ok";
|
|
31
|
+
//# sourceMappingURL=index.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","index_exports","__export","jsMainFixture","module","exports"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,YAAA,GAAAC,GAAA,IAAAC,WAAA,CAAAC,SAAA;EAAAC,KAAA;AAAA,IAAAH,GAAA;AAAA,IAAAI,aAAA;AAAAC,QAAA,CAAAD,aAAA;EAAAE,aAAA,EAAAA,CAAA,KAAAA;AAAA;AAAOC,MAAM,CAAAC,OAAA,GAAAT,YAAgB,CAAAK,aAAA","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["jsMainFixture"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"AAAO,MAAMA,aAAA,GAAgB","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["jsMainFixture"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"AAAO,IAAAA,aAAM,OAAgB","ignoreList":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tamagui-build-test-js-main-package",
|
|
3
|
+
"version": "2.0.0-rc.0-1769885482630",
|
|
4
|
+
"main": "dist/cjs/index.js",
|
|
5
|
+
"module": "dist/esm/index.mjs",
|
|
6
|
+
"types": "types/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "node ../../../tamagui-build.js"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@tamagui/build": "workspace:*",
|
|
12
|
+
"typescript": "~5.9.2"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const jsMainFixture = 'ok'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,OAAO,CAAA"}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
|
|
2
|
+
[0m[2m[35m$[0m [2m[1mnode ../../../tamagui-build.js[0m
|
|
3
|
+
built tamagui-build-test-simple-tpackage in [33m1466[39m ms
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
"name": "tamagui-build-test-simple-tpackage",
|
|
3
3
|
"version": "2.0.0-rc.0-1769885482630",
|
|
4
4
|
"main": "dist/cjs",
|
|
5
|
-
"module": "dist/esm
|
|
5
|
+
"module": "dist/esm",
|
|
6
|
+
"module:jsx": "dist/jsx",
|
|
6
7
|
"types": "dist/types/index.d.ts",
|
|
7
8
|
"scripts": {
|
|
8
9
|
"build": "node ../../../tamagui-build.js",
|
|
9
10
|
"build:bundle": "node ../../../tamagui-build.js --bundle",
|
|
10
11
|
"build:skip-mjs": "node ../../../tamagui-build.js --skip-mjs",
|
|
12
|
+
"build:skip-sourcemaps": "node ../../../tamagui-build.js --skip-sourcemaps",
|
|
11
13
|
"build:declaration-root": "node ../../../tamagui-build.js --declaration-root",
|
|
12
14
|
"build:ignore-base-url": "node ../../../tamagui-build.js --ignore-base-url",
|
|
13
15
|
"build:watch": "node ../../../tamagui-build.js --watch",
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { nestedHello } from './nested'
|
|
2
|
+
|
|
1
3
|
export const greet = (name: string): string => {
|
|
2
4
|
return `Hello, ${name}!`
|
|
3
5
|
}
|
|
@@ -8,3 +10,28 @@ export const paltformGreeter = (name: string): string => {
|
|
|
8
10
|
process.env.TAMAGUI_TARGET === 'native' ? (salutation = 'Hey') : (salutation = 'Hello')
|
|
9
11
|
return `${salutation}, ${name}!`
|
|
10
12
|
}
|
|
13
|
+
|
|
14
|
+
export function runNativeSideEffect(items: string[]) {
|
|
15
|
+
items.push('ran')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function guardNativeSideEffects(items: string[], debug?: string) {
|
|
19
|
+
runNativeSideEffect(items)
|
|
20
|
+
|
|
21
|
+
if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
|
|
22
|
+
console.log(items.length)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return items
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getPlatformMarker() {
|
|
29
|
+
return process.env.TAMAGUI_TARGET === 'native' ? 'native-only-marker' : 'web-only-marker'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function applyNativeLogicalMarker(items: string[]) {
|
|
33
|
+
process.env.TAMAGUI_TARGET === 'native' && items.push('native-logical-marker')
|
|
34
|
+
process.env.TAMAGUI_TARGET !== 'native' && items.push('web-logical-marker')
|
|
35
|
+
|
|
36
|
+
return items
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const nestedHello = 'nested hello'
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
$ node ../../../tamagui-build.js
|
|
2
|
-
built tamagui-build-test-watch-package in
|
|
2
|
+
built tamagui-build-test-watch-package in 653 ms
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execSync, spawn } from 'node:child_process'
|
|
2
|
-
import { existsSync, readFileSync, writeFileSync, statSync } from 'node:fs'
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, statSync, readdirSync } from 'node:fs'
|
|
3
3
|
import { describe, it, expect, beforeAll, afterAll } from 'vitest'
|
|
4
4
|
import { join } from 'node:path'
|
|
5
5
|
import { readFile } from 'node:fs/promises'
|
|
@@ -15,6 +15,8 @@ const distCjsFilePath = join(distPath, 'cjs', 'index.cjs')
|
|
|
15
15
|
const watchDistCjsFilePath = join(watchDistPath, 'cjs', 'watch.cjs')
|
|
16
16
|
const distEsmFilePath = join(distPath, 'esm', 'index.mjs')
|
|
17
17
|
const distTypesFilePath = join(simplePackagePath, 'types', 'index.d.ts')
|
|
18
|
+
const jsMainPackagePath = join(__dirname, 'fixtures', 'js-main-package')
|
|
19
|
+
const jsMainDistPath = join(jsMainPackagePath, 'dist')
|
|
18
20
|
// console.log({
|
|
19
21
|
// distCjsFilePath,
|
|
20
22
|
// distEsmFilePath,
|
|
@@ -28,6 +30,7 @@ describe('tamagui-build integration test', () => {
|
|
|
28
30
|
beforeAll(() => {
|
|
29
31
|
// Clean up dist directory before starting
|
|
30
32
|
execSync('rm -rf dist && rm -rf types', { cwd: simplePackagePath })
|
|
33
|
+
execSync('rm -rf dist && rm -rf types', { cwd: jsMainPackagePath })
|
|
31
34
|
})
|
|
32
35
|
|
|
33
36
|
it('should build the package correctly', () => {
|
|
@@ -43,6 +46,10 @@ describe('tamagui-build integration test', () => {
|
|
|
43
46
|
const esmOutput = readFileSync(distEsmFilePath, 'utf-8')
|
|
44
47
|
expect(cjsOutput).toContain('Hello,')
|
|
45
48
|
expect(esmOutput).toContain('Hello,')
|
|
49
|
+
expect(esmOutput).toContain("./nested/index.mjs")
|
|
50
|
+
expect(existsSync(join(distPath, 'cjs', 'index.cjs'))).toBe(true)
|
|
51
|
+
expect(existsSync(join(distPath, 'esm', 'index.js'))).toBe(true)
|
|
52
|
+
expect(existsSync(join(distPath, 'jsx', 'index.js'))).toBe(true)
|
|
46
53
|
})
|
|
47
54
|
|
|
48
55
|
it('should bundle the package correctly', () => {
|
|
@@ -57,6 +64,9 @@ describe('tamagui-build integration test', () => {
|
|
|
57
64
|
const esmOutput = readFileSync(distEsmFilePath, 'utf-8')
|
|
58
65
|
expect(cjsOutput).toContain('Hello,')
|
|
59
66
|
expect(esmOutput).toContain('Hello,')
|
|
67
|
+
expect(existsSync(join(distPath, 'cjs', 'index.cjs'))).toBe(true)
|
|
68
|
+
expect(existsSync(join(distPath, 'esm', 'index.js'))).toBe(true)
|
|
69
|
+
expect(existsSync(join(distPath, 'jsx', 'index.js'))).toBe(true)
|
|
60
70
|
})
|
|
61
71
|
|
|
62
72
|
it('should skip mjs files when --skip-mjs is used', () => {
|
|
@@ -66,6 +76,27 @@ describe('tamagui-build integration test', () => {
|
|
|
66
76
|
// Check if the output files exist
|
|
67
77
|
expect(existsSync(distCjsFilePath)).toBe(true)
|
|
68
78
|
expect(existsSync(distEsmFilePath)).toBe(false)
|
|
79
|
+
expect(existsSync(join(distPath, 'cjs', 'index.cjs'))).toBe(true)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('should skip sourcemaps when --skip-sourcemaps is used', () => {
|
|
83
|
+
execSync('rm -rf dist && rm -rf types', { cwd: simplePackagePath })
|
|
84
|
+
execSync('bun run build:skip-sourcemaps', { cwd: simplePackagePath })
|
|
85
|
+
|
|
86
|
+
expect(existsSync(distCjsFilePath)).toBe(true)
|
|
87
|
+
expect(existsSync(distEsmFilePath)).toBe(true)
|
|
88
|
+
expect(existsSync(distTypesFilePath)).toBe(true)
|
|
89
|
+
expect(existsSync(join(distPath, 'cjs', 'index.cjs.map'))).toBe(false)
|
|
90
|
+
expect(existsSync(join(distPath, 'esm', 'index.mjs.map'))).toBe(false)
|
|
91
|
+
expect(existsSync(join(simplePackagePath, 'types', 'index.d.ts.map'))).toBe(false)
|
|
92
|
+
|
|
93
|
+
const cjsOutput = readFileSync(distCjsFilePath, 'utf-8')
|
|
94
|
+
const esmOutput = readFileSync(distEsmFilePath, 'utf-8')
|
|
95
|
+
const typesOutput = readFileSync(distTypesFilePath, 'utf-8')
|
|
96
|
+
|
|
97
|
+
expect(cjsOutput).not.toContain('sourceMappingURL=')
|
|
98
|
+
expect(esmOutput).not.toContain('sourceMappingURL=')
|
|
99
|
+
expect(typesOutput).not.toContain('sourceMappingURL=')
|
|
69
100
|
})
|
|
70
101
|
|
|
71
102
|
it('should ignore base URL when --ignore-base-url is used', () => {
|
|
@@ -152,11 +183,31 @@ describe('tamagui-build integration test', () => {
|
|
|
152
183
|
expect(nativeOutput).toContain('greet:')
|
|
153
184
|
})
|
|
154
185
|
|
|
186
|
+
it('should keep side-effectful native statements outside dev-only guards', async () => {
|
|
187
|
+
execSync('bun run build', { cwd: simplePackagePath })
|
|
188
|
+
|
|
189
|
+
const nativeOutputPath = join(distPath, 'esm', 'index.native.js')
|
|
190
|
+
const nativeOutput = await readFile(nativeOutputPath, 'utf-8')
|
|
191
|
+
|
|
192
|
+
expect(nativeOutput).toContain('runNativeSideEffect(items);')
|
|
193
|
+
expect(nativeOutput).toContain('native-only-marker')
|
|
194
|
+
expect(nativeOutput).toContain('native-logical-marker')
|
|
195
|
+
expect(nativeOutput).not.toContain('if (runNativeSideEffect(')
|
|
196
|
+
expect(nativeOutput).not.toContain('if (false)')
|
|
197
|
+
expect(nativeOutput).not.toContain('if (true)')
|
|
198
|
+
expect(nativeOutput).not.toContain('runNativeSideEffect(items), process.env.NODE_ENV')
|
|
199
|
+
expect(nativeOutput).not.toContain('web-only-marker')
|
|
200
|
+
expect(nativeOutput).not.toContain('web-logical-marker')
|
|
201
|
+
expect(nativeOutput).not.toContain('&& items.push(')
|
|
202
|
+
})
|
|
203
|
+
|
|
155
204
|
it('should minify the output when MINIFY=true is set', () => {
|
|
156
205
|
// Build without minification and cache file sizes
|
|
157
206
|
execSync('bun run build', { cwd: simplePackagePath })
|
|
158
207
|
const originalCjsSize = statSync(distCjsFilePath).size
|
|
159
208
|
const originalEsmSize = statSync(distEsmFilePath).size
|
|
209
|
+
const originalCjsOutput = readFileSync(distCjsFilePath, 'utf-8')
|
|
210
|
+
const originalEsmOutput = readFileSync(distEsmFilePath, 'utf-8')
|
|
160
211
|
|
|
161
212
|
// Clean up the output
|
|
162
213
|
execSync('rm -rf dist && rm -rf types', { cwd: simplePackagePath })
|
|
@@ -183,12 +234,64 @@ describe('tamagui-build integration test', () => {
|
|
|
183
234
|
expect(esmOutput).not.toMatch(/^\s+$/m) // No lines with only whitespace
|
|
184
235
|
|
|
185
236
|
// Check that the number of lines is reduced
|
|
186
|
-
expect(cjsOutput.split('\n').length).
|
|
187
|
-
|
|
237
|
+
expect(cjsOutput.split('\n').length).toBeLessThanOrEqual(
|
|
238
|
+
originalCjsOutput.split('\n').length
|
|
239
|
+
)
|
|
240
|
+
expect(esmOutput.split('\n').length).toBeLessThanOrEqual(
|
|
241
|
+
originalEsmOutput.split('\n').length
|
|
242
|
+
)
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
it('should clean stale outputs before building', () => {
|
|
246
|
+
execSync('bun run build', { cwd: simplePackagePath })
|
|
247
|
+
|
|
248
|
+
const staleFilePath = join(distPath, 'esm', 'stale.mjs')
|
|
249
|
+
const staleTypesPath = join(simplePackagePath, 'types', 'stale.d.ts')
|
|
250
|
+
writeFileSync(staleFilePath, 'stale')
|
|
251
|
+
writeFileSync(staleTypesPath, 'stale')
|
|
252
|
+
|
|
253
|
+
expect(existsSync(staleFilePath)).toBe(true)
|
|
254
|
+
expect(existsSync(staleTypesPath)).toBe(true)
|
|
255
|
+
|
|
256
|
+
execSync('bun run build', { cwd: simplePackagePath })
|
|
257
|
+
|
|
258
|
+
expect(existsSync(staleFilePath)).toBe(false)
|
|
259
|
+
expect(existsSync(staleTypesPath)).toBe(false)
|
|
260
|
+
expect(readdirSync(join(distPath, 'esm'))).not.toContain('stale.mjs')
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
it('should keep only the required js aliases after postprocessing', () => {
|
|
264
|
+
execSync('bun run build', { cwd: simplePackagePath })
|
|
265
|
+
|
|
266
|
+
const distFiles = execSync('find dist -type f | sort', {
|
|
267
|
+
cwd: simplePackagePath,
|
|
268
|
+
encoding: 'utf-8',
|
|
269
|
+
})
|
|
270
|
+
.trim()
|
|
271
|
+
.split('\n')
|
|
272
|
+
.map((file) => file.replace(/^dist\//, ''))
|
|
273
|
+
|
|
274
|
+
expect(distFiles).toContain('cjs/index.cjs')
|
|
275
|
+
expect(distFiles).toContain('esm/index.js')
|
|
276
|
+
expect(distFiles).toContain('esm/index.js.map')
|
|
277
|
+
expect(distFiles).toContain('jsx/index.js')
|
|
278
|
+
expect(distFiles).toContain('jsx/index.js.map')
|
|
279
|
+
expect(distFiles).toContain('cjs/index.cjs')
|
|
280
|
+
expect(distFiles).toContain('esm/index.mjs')
|
|
281
|
+
expect(distFiles).toContain('esm/nested/index.mjs')
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
it('should keep explicit cjs .js mains as final output', () => {
|
|
285
|
+
execSync('bun run build', { cwd: jsMainPackagePath })
|
|
286
|
+
|
|
287
|
+
expect(existsSync(join(jsMainDistPath, 'cjs', 'index.js'))).toBe(true)
|
|
288
|
+
expect(existsSync(join(jsMainDistPath, 'cjs', 'index.mjs'))).toBe(false)
|
|
289
|
+
expect(existsSync(join(jsMainDistPath, 'esm', 'index.mjs'))).toBe(true)
|
|
188
290
|
})
|
|
189
291
|
|
|
190
292
|
afterAll(() => {
|
|
191
293
|
// Clean up dist directory after tests
|
|
192
294
|
execSync('rm -rf dist && rm -rf types', { cwd: simplePackagePath })
|
|
295
|
+
execSync('rm -rf dist && rm -rf types', { cwd: jsMainPackagePath })
|
|
193
296
|
})
|
|
194
297
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/build",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.40",
|
|
4
4
|
"gitHead": "a49cc7ea6b93ba384e77a4880ae48ac4a5635c14",
|
|
5
5
|
"bin": {
|
|
6
6
|
"tamagui-build": "tamagui-build.js",
|
|
@@ -10,27 +10,34 @@
|
|
|
10
10
|
"access": "public"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
-
"test": "vitest --run"
|
|
13
|
+
"test": "vitest --run",
|
|
14
|
+
"test:web": "bun run test"
|
|
14
15
|
},
|
|
15
16
|
"dependencies": {
|
|
16
17
|
"@babel/core": "^7.25.2",
|
|
17
18
|
"@babel/preset-typescript": "^7.26.0",
|
|
18
19
|
"@swc/core": "^1.14.0",
|
|
19
|
-
"@tamagui/babel-plugin-fully-specified": "2.0.0-rc.
|
|
20
|
+
"@tamagui/babel-plugin-fully-specified": "2.0.0-rc.40",
|
|
20
21
|
"@types/fs-extra": "^9.0.13",
|
|
21
|
-
"babel-plugin-react-compiler": "^1.0.0",
|
|
22
22
|
"baseline-browser-mapping": "^2.9.15",
|
|
23
23
|
"chokidar": "^3.5.2",
|
|
24
24
|
"esbuild": "^0.27.2",
|
|
25
|
-
"esbuild-plugin-es5": "^2.1.1",
|
|
26
25
|
"esbuild-register": "^3.6.0",
|
|
27
26
|
"execa": "^5.0.0",
|
|
28
27
|
"fast-glob": "^3.2.11",
|
|
29
28
|
"fs-extra": "^11.2.0",
|
|
30
29
|
"lodash.debounce": "^4.0.8",
|
|
31
|
-
"oxc-transform": "^0.
|
|
30
|
+
"oxc-transform": "^0.112.0",
|
|
32
31
|
"typescript": "~5.9.2"
|
|
33
32
|
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"babel-plugin-react-compiler": ">=1"
|
|
35
|
+
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"babel-plugin-react-compiler": {
|
|
38
|
+
"optional": true
|
|
39
|
+
}
|
|
40
|
+
},
|
|
34
41
|
"devDependencies": {
|
|
35
42
|
"vitest": "4.0.4"
|
|
36
43
|
}
|
package/pretty-print-errors.js
CHANGED
|
@@ -125,9 +125,42 @@ function printTypescriptCompilationError(err, packageName) {
|
|
|
125
125
|
console.error('')
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Pretty print OXC isolated declaration errors
|
|
130
|
+
* @param {Array<{ severity: string, message: string, labels: Array<{ message: string | null, start: number, end: number }>, helpMessage: string | null, codeframe: string | null }>} errors
|
|
131
|
+
*/
|
|
132
|
+
function printOxcErrors(errors) {
|
|
133
|
+
console.error('\n❌ Type declaration generation errors:\n')
|
|
134
|
+
|
|
135
|
+
errors.forEach((error) => {
|
|
136
|
+
const severity = error.severity === 'Error' ? '❌' : '⚠️ '
|
|
137
|
+
console.error(` ${severity} ${error.message}`)
|
|
138
|
+
|
|
139
|
+
if (error.labels && error.labels.length > 0) {
|
|
140
|
+
error.labels.forEach((label) => {
|
|
141
|
+
console.error(` at ${label.start}-${label.end}`)
|
|
142
|
+
if (label.message) {
|
|
143
|
+
console.error(` ${label.message}`)
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (error.helpMessage) {
|
|
149
|
+
console.error(` help: ${error.helpMessage}`)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (error.codeframe) {
|
|
153
|
+
console.error(`\n${error.codeframe}`)
|
|
154
|
+
}
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
console.error('')
|
|
158
|
+
}
|
|
159
|
+
|
|
128
160
|
module.exports = {
|
|
129
161
|
printTypescriptDiagnostics,
|
|
130
162
|
printEsbuildError,
|
|
131
163
|
printBuildError,
|
|
132
164
|
printTypescriptCompilationError,
|
|
165
|
+
printOxcErrors,
|
|
133
166
|
}
|
package/tamagui-build.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* tamagui-build --watch # watch mode
|
|
10
10
|
* tamagui-build --skip-types # js only
|
|
11
11
|
* tamagui-build --skip-native # skip native builds
|
|
12
|
+
* tamagui-build --skip-sourcemaps # disable js + d.ts sourcemaps
|
|
12
13
|
* tamagui-build clean # remove dist/types/node_modules
|
|
13
14
|
* tamagui-build clean:build # remove dist/types only
|
|
14
15
|
*
|
|
@@ -30,6 +31,7 @@ const createExternalPlugin = require('./externalNodePlugin')
|
|
|
30
31
|
const debounce = require('lodash.debounce')
|
|
31
32
|
const { basename, dirname } = require('node:path')
|
|
32
33
|
const { es5Plugin } = require('./esbuild-es5')
|
|
34
|
+
const { transformSync: oxcTransformSync } = require('oxc-transform')
|
|
33
35
|
const ts = require('typescript')
|
|
34
36
|
const path = require('node:path')
|
|
35
37
|
const childProcess = require('node:child_process')
|
|
@@ -38,6 +40,7 @@ const {
|
|
|
38
40
|
printEsbuildError,
|
|
39
41
|
printBuildError,
|
|
40
42
|
printTypescriptCompilationError,
|
|
43
|
+
printOxcErrors,
|
|
41
44
|
} = require('./pretty-print-errors')
|
|
42
45
|
|
|
43
46
|
const jsOnly = !!process.env.JS_ONLY
|
|
@@ -45,12 +48,59 @@ const skipJS = !!(process.env.SKIP_JS || false)
|
|
|
45
48
|
|
|
46
49
|
// write file only if contents changed to avoid triggering watchers
|
|
47
50
|
async function writeIfUnchanged(filePath, contents) {
|
|
51
|
+
const isExecutableScript = typeof contents === 'string' && contents.startsWith('#!')
|
|
48
52
|
const existing = await FSE.readFile(filePath, 'utf8').catch(() => null)
|
|
49
|
-
if (existing === contents)
|
|
50
|
-
|
|
53
|
+
if (existing === contents) {
|
|
54
|
+
if (isExecutableScript) {
|
|
55
|
+
await FSE.chmod(filePath, 0o755).catch(() => {})
|
|
56
|
+
}
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
await FSE.outputFile(filePath, contents, {
|
|
60
|
+
encoding: 'utf8',
|
|
61
|
+
mode: isExecutableScript ? 0o755 : 0o666,
|
|
62
|
+
})
|
|
63
|
+
if (isExecutableScript) {
|
|
64
|
+
await FSE.chmod(filePath, 0o755).catch(() => {})
|
|
65
|
+
}
|
|
51
66
|
return true
|
|
52
67
|
}
|
|
53
68
|
|
|
69
|
+
function dceTamaguiTarget(contents, { format, jsx, platform }) {
|
|
70
|
+
if (!contents.includes('process.env.TAMAGUI_TARGET')) {
|
|
71
|
+
return contents
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const result = oxcTransformSync(`tamagui-target.${jsx === 'preserve' ? 'jsx' : 'js'}`, contents, {
|
|
75
|
+
lang: jsx === 'preserve' ? 'jsx' : 'js',
|
|
76
|
+
jsx: jsx === 'preserve' ? 'preserve' : undefined,
|
|
77
|
+
sourceType: format === 'cjs' ? 'commonjs' : 'module',
|
|
78
|
+
define: {
|
|
79
|
+
'process.env.TAMAGUI_TARGET': JSON.stringify(platform),
|
|
80
|
+
},
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
if (result.errors?.length) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`Failed to DCE TAMAGUI_TARGET for ${platform}: ${result.errors
|
|
86
|
+
.map((error) => error.message)
|
|
87
|
+
.join('\n')}`
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return result.code || contents
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function hasFlag(flag) {
|
|
95
|
+
return process.argv.includes(flag)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function getEnvFlag(name) {
|
|
99
|
+
const value = process.env[name]
|
|
100
|
+
if (!value) return false
|
|
101
|
+
return !['0', 'false', 'no', 'off'].includes(String(value).toLowerCase())
|
|
102
|
+
}
|
|
103
|
+
|
|
54
104
|
/**
|
|
55
105
|
* esbuild plugin that runs React Compiler on TS/TSX files before transformation
|
|
56
106
|
*/
|
|
@@ -105,32 +155,34 @@ const reactCompilerPlugin = {
|
|
|
105
155
|
},
|
|
106
156
|
}
|
|
107
157
|
|
|
108
|
-
const shouldSwapExports =
|
|
158
|
+
const shouldSwapExports = hasFlag('--swap-exports')
|
|
109
159
|
|
|
110
160
|
// when swapping exports for publish, we MUST build types (ignore --skip-types)
|
|
111
161
|
const shouldSkipTypes = shouldSwapExports
|
|
112
162
|
? false
|
|
113
|
-
: !!(
|
|
163
|
+
: !!(hasFlag('--skip-types') || process.env.SKIP_TYPES)
|
|
114
164
|
|
|
115
|
-
const shouldSkipNative =
|
|
116
|
-
const shouldSkipMJS =
|
|
165
|
+
const shouldSkipNative = hasFlag('--skip-native')
|
|
166
|
+
const shouldSkipMJS = hasFlag('--skip-mjs')
|
|
167
|
+
const shouldSkipSourceMaps =
|
|
168
|
+
hasFlag('--skip-sourcemaps') || getEnvFlag('TAMAGUI_BUILD_SKIP_SOURCEMAPS')
|
|
117
169
|
// React Compiler is disabled by default - use --react-compiler to enable
|
|
118
170
|
const shouldEnableCompiler = !!(
|
|
119
|
-
|
|
171
|
+
hasFlag('--react-compiler') || process.env.REACT_COMPILER
|
|
120
172
|
)
|
|
121
|
-
const shouldBundleFlag =
|
|
122
|
-
const shouldBundleNodeModules =
|
|
173
|
+
const shouldBundleFlag = hasFlag('--bundle')
|
|
174
|
+
const shouldBundleNodeModules = hasFlag('--bundle-modules')
|
|
123
175
|
const shouldClean = !!process.argv.includes('clean')
|
|
124
176
|
const shouldCleanBuildOnly = !!process.argv.includes('clean:build')
|
|
125
|
-
const shouldWatch =
|
|
177
|
+
const shouldWatch = hasFlag('--watch')
|
|
126
178
|
|
|
127
179
|
// get command after "--" to run with swapped exports
|
|
128
180
|
const dashDashIndex = process.argv.indexOf('--')
|
|
129
181
|
const runCommandAfterSwap =
|
|
130
182
|
dashDashIndex > -1 ? process.argv.slice(dashDashIndex + 1) : null
|
|
131
183
|
|
|
132
|
-
const declarationToRoot =
|
|
133
|
-
const ignoreBaseUrl =
|
|
184
|
+
const declarationToRoot = hasFlag('--declaration-root')
|
|
185
|
+
const ignoreBaseUrl = hasFlag('--ignore-base-url')
|
|
134
186
|
const baseUrlIndex = process.argv.indexOf('--base-url')
|
|
135
187
|
const tsProjectIndex = process.argv.indexOf('--ts-project')
|
|
136
188
|
const exludeIndex = process.argv.indexOf('--exclude')
|
|
@@ -153,7 +205,6 @@ const pkgSource = pkg.source
|
|
|
153
205
|
const pkgModule = pkg.module
|
|
154
206
|
const pkgModuleJSX = pkg['module:jsx']
|
|
155
207
|
const pkgTypes = Boolean(pkg.types || pkg.typings)
|
|
156
|
-
const pkgRemoveSideEffects = pkg.removeSideEffects || false
|
|
157
208
|
|
|
158
209
|
// build config from package.json
|
|
159
210
|
const buildConfig = pkg['tamagui-build'] || {}
|
|
@@ -166,6 +217,20 @@ const bundleExternal = buildConfig.bundleExternal || null
|
|
|
166
217
|
const flatOut = [pkgMain, pkgModule, pkgModuleJSX].filter(Boolean).length === 1
|
|
167
218
|
|
|
168
219
|
const avoidCJS = pkgMain?.endsWith('.js')
|
|
220
|
+
const getJsEntryAliasPath = (entry) => {
|
|
221
|
+
if (!entry) return null
|
|
222
|
+
if (!path.extname(entry)) {
|
|
223
|
+
return path.join(entry, 'index.js').replace(/\\/g, '/')
|
|
224
|
+
}
|
|
225
|
+
if (entry.endsWith('.js')) {
|
|
226
|
+
return entry.replace(/\\/g, '/')
|
|
227
|
+
}
|
|
228
|
+
return null
|
|
229
|
+
}
|
|
230
|
+
const cjsMainAliasPath = getJsEntryAliasPath(pkgMain)
|
|
231
|
+
const esmAliasPaths = [getJsEntryAliasPath(pkgModule), getJsEntryAliasPath(pkgModuleJSX)].filter(
|
|
232
|
+
Boolean
|
|
233
|
+
)
|
|
169
234
|
|
|
170
235
|
const replaceRNWeb = {
|
|
171
236
|
esm: (content) =>
|
|
@@ -236,13 +301,14 @@ if (shouldClean || shouldCleanBuildOnly) {
|
|
|
236
301
|
if (shouldWatch) {
|
|
237
302
|
process.env.IS_WATCHING = true
|
|
238
303
|
process.env.DISABLE_AUTORUN = true
|
|
239
|
-
const rebuild = debounce(build, 100)
|
|
304
|
+
const rebuild = debounce(() => build({ cleanOutput: false }), 100)
|
|
240
305
|
const chokidar = require('chokidar')
|
|
241
306
|
|
|
242
307
|
if (!process.env.SKIP_INITIAL_BUILD) {
|
|
243
308
|
// do one js build but not types
|
|
244
309
|
build({
|
|
245
310
|
skipTypes: true,
|
|
311
|
+
cleanOutput: true,
|
|
246
312
|
})
|
|
247
313
|
}
|
|
248
314
|
|
|
@@ -365,10 +431,18 @@ function swapExportsTypes(pkg, direction) {
|
|
|
365
431
|
return swapped
|
|
366
432
|
}
|
|
367
433
|
|
|
368
|
-
async function build({ skipTypes } = {}) {
|
|
434
|
+
async function build({ skipTypes, cleanOutput = !shouldWatch } = {}) {
|
|
369
435
|
if (process.env.DEBUG) console.info('🔹', pkg.name)
|
|
370
436
|
try {
|
|
371
437
|
const start = Date.now()
|
|
438
|
+
const isSkippingTypesForBuild = Boolean(skipTypes || shouldSkipTypes || !pkgTypes)
|
|
439
|
+
|
|
440
|
+
if (cleanOutput) {
|
|
441
|
+
await Promise.allSettled([
|
|
442
|
+
FSE.remove('dist'),
|
|
443
|
+
isSkippingTypesForBuild ? null : FSE.remove('types'),
|
|
444
|
+
])
|
|
445
|
+
}
|
|
372
446
|
|
|
373
447
|
const allFiles = (await fastGlob(['src/**/*.(m)?[jt]s(x)?', 'src/**/*.css'])).filter(
|
|
374
448
|
(x) => !x.includes('.d.ts') && (exclude ? !x.match(exclude) : true)
|
|
@@ -441,29 +515,48 @@ async function buildTsc(allFiles) {
|
|
|
441
515
|
const compilerOptions = createCompilerOptions(config.options, targetDir)
|
|
442
516
|
|
|
443
517
|
if (config.options.isolatedDeclarations) {
|
|
444
|
-
const oxc =
|
|
518
|
+
const oxc = await import('oxc-transform')
|
|
445
519
|
|
|
446
|
-
await Promise.all(
|
|
520
|
+
const results = await Promise.all(
|
|
447
521
|
allFiles.map(async (file) => {
|
|
448
522
|
const source = await FSE.readFile(file, 'utf-8')
|
|
449
|
-
const { code, map } = oxc.isolatedDeclaration(file, source, {
|
|
450
|
-
sourcemap:
|
|
523
|
+
const { code, map, errors } = await oxc.isolatedDeclaration(file, source, {
|
|
524
|
+
sourcemap: !shouldSkipSourceMaps,
|
|
451
525
|
})
|
|
452
526
|
|
|
527
|
+
if (errors && errors.length > 0) {
|
|
528
|
+
return errors
|
|
529
|
+
}
|
|
530
|
+
|
|
453
531
|
const dtsPath = path
|
|
454
532
|
.join(`types`, ...file.split('/').slice(1))
|
|
455
533
|
.replace(/\.tsx?$/, '.d.ts')
|
|
456
534
|
const mapPath = `${dtsPath}.map`
|
|
457
535
|
|
|
458
|
-
const output =
|
|
536
|
+
const output = shouldSkipSourceMaps
|
|
537
|
+
? code
|
|
538
|
+
: `${code}\n//# sourceMappingURL=${path.basename(mapPath)}`
|
|
459
539
|
await FSE.ensureDir(dirname(dtsPath))
|
|
460
|
-
await
|
|
461
|
-
|
|
462
|
-
writeIfUnchanged(mapPath, JSON.stringify(map, null, 2))
|
|
463
|
-
|
|
540
|
+
await writeIfUnchanged(dtsPath, output)
|
|
541
|
+
if (!shouldSkipSourceMaps && map) {
|
|
542
|
+
await writeIfUnchanged(mapPath, JSON.stringify(map, null, 2))
|
|
543
|
+
} else {
|
|
544
|
+
await FSE.remove(mapPath)
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
return []
|
|
464
548
|
})
|
|
465
549
|
)
|
|
466
550
|
|
|
551
|
+
const allErrors = results.flat()
|
|
552
|
+
|
|
553
|
+
if (allErrors.length > 0) {
|
|
554
|
+
printOxcErrors(allErrors)
|
|
555
|
+
if (!shouldWatch) {
|
|
556
|
+
process.exit(1)
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
467
560
|
return
|
|
468
561
|
}
|
|
469
562
|
|
|
@@ -540,7 +633,7 @@ function createCompilerOptions(baseOptions, targetDir) {
|
|
|
540
633
|
...baseOptions,
|
|
541
634
|
declaration: true,
|
|
542
635
|
emitDeclarationOnly: true,
|
|
543
|
-
declarationMap:
|
|
636
|
+
declarationMap: !shouldSkipSourceMaps,
|
|
544
637
|
outDir: targetDir,
|
|
545
638
|
rootDir: 'src',
|
|
546
639
|
incremental: true,
|
|
@@ -701,6 +794,8 @@ async function buildJs(allFiles) {
|
|
|
701
794
|
platform: 'web',
|
|
702
795
|
bundle: shouldBundleFlag,
|
|
703
796
|
specifyCJS: !avoidCJS,
|
|
797
|
+
keepJsOutput: avoidCJS,
|
|
798
|
+
preserveJsPaths: [],
|
|
704
799
|
})
|
|
705
800
|
: null,
|
|
706
801
|
|
|
@@ -716,6 +811,7 @@ async function buildJs(allFiles) {
|
|
|
716
811
|
? esbuildWriteIfChanged(esmConfig, {
|
|
717
812
|
platform: 'web',
|
|
718
813
|
bundle: shouldBundleFlag,
|
|
814
|
+
preserveJsPaths: esmAliasPaths,
|
|
719
815
|
})
|
|
720
816
|
: null,
|
|
721
817
|
|
|
@@ -743,6 +839,7 @@ async function buildJs(allFiles) {
|
|
|
743
839
|
},
|
|
744
840
|
{
|
|
745
841
|
platform: 'web',
|
|
842
|
+
preserveJsPaths: esmAliasPaths,
|
|
746
843
|
}
|
|
747
844
|
)
|
|
748
845
|
: null,
|
|
@@ -784,9 +881,11 @@ async function buildJs(allFiles) {
|
|
|
784
881
|
async function esbuildWriteIfChanged(
|
|
785
882
|
/** @type { import('esbuild').BuildOptions } */
|
|
786
883
|
opts,
|
|
787
|
-
{ platform, env, specifyCJS } = {
|
|
884
|
+
{ platform, env, specifyCJS, keepJsOutput, preserveJsPaths } = {
|
|
788
885
|
platform: '',
|
|
789
886
|
specifyCJS: false,
|
|
887
|
+
keepJsOutput: false,
|
|
888
|
+
preserveJsPaths: [],
|
|
790
889
|
env: '',
|
|
791
890
|
}
|
|
792
891
|
) {
|
|
@@ -795,6 +894,10 @@ async function esbuildWriteIfChanged(
|
|
|
795
894
|
}
|
|
796
895
|
|
|
797
896
|
const isESM = opts.target === 'esm' || opts.target === 'esnext'
|
|
897
|
+
const preserveJsPathSet = new Set((preserveJsPaths || []).filter(Boolean))
|
|
898
|
+
const preserveJsPathAbsoluteSet = new Set(
|
|
899
|
+
[...preserveJsPathSet].map((preserveJsPath) => path.resolve(preserveJsPath))
|
|
900
|
+
)
|
|
798
901
|
|
|
799
902
|
const buildSettings = (() => {
|
|
800
903
|
// compat with jsx and hermes back a few versions generally:
|
|
@@ -846,21 +949,20 @@ async function esbuildWriteIfChanged(
|
|
|
846
949
|
format: isESM ? 'esm' : 'cjs',
|
|
847
950
|
|
|
848
951
|
treeShaking: true,
|
|
849
|
-
|
|
952
|
+
// We only want TAMAGUI_TARGET dead-code elimination during normal builds.
|
|
953
|
+
// Syntax minification can legally rewrite statements into comma expressions.
|
|
954
|
+
minifySyntax: false,
|
|
850
955
|
write: false,
|
|
851
956
|
|
|
852
957
|
color: true,
|
|
853
958
|
allowOverwrite: true,
|
|
854
959
|
keepNames: false,
|
|
855
|
-
sourcemap:
|
|
960
|
+
sourcemap: !shouldSkipSourceMaps,
|
|
856
961
|
sourcesContent: false,
|
|
857
962
|
logLevel: 'error',
|
|
858
963
|
...(platform === 'native' && nativeEsbuildSettings),
|
|
859
964
|
...(platform === 'web' && webEsbuildSettings),
|
|
860
965
|
define: {
|
|
861
|
-
...(platform && {
|
|
862
|
-
'process.env.TAMAGUI_TARGET': `"${platform}"`,
|
|
863
|
-
}),
|
|
864
966
|
...(env && {
|
|
865
967
|
'process.env.NODE_ENV': `"${env}"`,
|
|
866
968
|
}),
|
|
@@ -962,23 +1064,43 @@ async function esbuildWriteIfChanged(
|
|
|
962
1064
|
}
|
|
963
1065
|
}
|
|
964
1066
|
|
|
965
|
-
if (
|
|
966
|
-
|
|
1067
|
+
if (!isMap && path.endsWith('.js')) {
|
|
1068
|
+
contents = dceTamaguiTarget(contents, {
|
|
1069
|
+
format: opts.format,
|
|
1070
|
+
jsx: opts.jsx,
|
|
1071
|
+
platform,
|
|
1072
|
+
})
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
if (isESM && pkg.sideEffects !== true && pkg.sideEffects !== undefined) {
|
|
1076
|
+
const sideEffects = pkg.sideEffects
|
|
1077
|
+
// sideEffects: false means nothing has side effects, strip all bare imports
|
|
1078
|
+
// sideEffects: ["*.css", ...] means only matching files have side effects
|
|
1079
|
+
const picomatch = require('picomatch')
|
|
1080
|
+
const matchers = sideEffects === false
|
|
1081
|
+
? null // strip everything
|
|
1082
|
+
: (Array.isArray(sideEffects) ? sideEffects : []).map((p) => picomatch(p))
|
|
967
1083
|
|
|
968
1084
|
const result = []
|
|
969
1085
|
const lines = contents.split('\n')
|
|
970
1086
|
for (const line of lines) {
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
) {
|
|
1087
|
+
// only process bare imports: import "...";
|
|
1088
|
+
const match = line.match(/^import\s+["']([^"']+)["'];?$/)
|
|
1089
|
+
if (!match) {
|
|
975
1090
|
result.push(line)
|
|
976
1091
|
continue
|
|
977
1092
|
}
|
|
978
|
-
|
|
1093
|
+
const specifier = match[1].replace(/^\.\//, '')
|
|
1094
|
+
// sideEffects: false → strip all bare imports
|
|
1095
|
+
if (matchers === null) {
|
|
1096
|
+
result.push('')
|
|
1097
|
+
continue
|
|
1098
|
+
}
|
|
1099
|
+
// sideEffects: [...] → keep if specifier matches any pattern
|
|
1100
|
+
const hasSideEffect = matchers.some((m) => m(specifier))
|
|
1101
|
+
result.push(hasSideEffect ? line : '')
|
|
979
1102
|
}
|
|
980
1103
|
|
|
981
|
-
// match whitespace to preserve sourcemaps
|
|
982
1104
|
contents = result.join('\n')
|
|
983
1105
|
}
|
|
984
1106
|
|
|
@@ -1018,7 +1140,7 @@ async function esbuildWriteIfChanged(
|
|
|
1018
1140
|
: transform(contents, {
|
|
1019
1141
|
filename: path,
|
|
1020
1142
|
configFile: false,
|
|
1021
|
-
sourceMap:
|
|
1143
|
+
sourceMap: !shouldSkipSourceMaps,
|
|
1022
1144
|
plugins: [
|
|
1023
1145
|
[
|
|
1024
1146
|
require.resolve('@tamagui/babel-plugin-fully-specified/commonjs'),
|
|
@@ -1029,11 +1151,28 @@ async function esbuildWriteIfChanged(
|
|
|
1029
1151
|
].filter(Boolean),
|
|
1030
1152
|
})
|
|
1031
1153
|
|
|
1032
|
-
|
|
1154
|
+
const shouldPreserveJsAlias =
|
|
1155
|
+
preserveJsPathSet.has(path) || preserveJsPathAbsoluteSet.has(path)
|
|
1156
|
+
|
|
1157
|
+
if (!shouldPreserveJsAlias) {
|
|
1158
|
+
cleanupNonCjsFiles.push(path)
|
|
1159
|
+
cleanupNonCjsFiles.push(path + '.map')
|
|
1160
|
+
}
|
|
1033
1161
|
|
|
1034
1162
|
await flush(path.replace(/\.js$/, '.cjs'), result.code)
|
|
1163
|
+
|
|
1164
|
+
if (shouldPreserveJsAlias) {
|
|
1165
|
+
await flush(path, result.code)
|
|
1166
|
+
}
|
|
1035
1167
|
})
|
|
1036
1168
|
)
|
|
1169
|
+
if (cleanupNonCjsFiles.length) {
|
|
1170
|
+
await Promise.all(cleanupNonCjsFiles.map(async (file) => FSE.remove(file)))
|
|
1171
|
+
}
|
|
1172
|
+
return
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
if (keepJsOutput) {
|
|
1037
1176
|
return
|
|
1038
1177
|
}
|
|
1039
1178
|
|
|
@@ -1060,7 +1199,7 @@ async function esbuildWriteIfChanged(
|
|
|
1060
1199
|
: transform(contents, {
|
|
1061
1200
|
filename: newOutPath,
|
|
1062
1201
|
configFile: false,
|
|
1063
|
-
sourceMap:
|
|
1202
|
+
sourceMap: !shouldSkipSourceMaps,
|
|
1064
1203
|
plugins: [
|
|
1065
1204
|
[
|
|
1066
1205
|
isESM
|
|
@@ -1074,7 +1213,10 @@ async function esbuildWriteIfChanged(
|
|
|
1074
1213
|
].filter(Boolean),
|
|
1075
1214
|
})
|
|
1076
1215
|
|
|
1077
|
-
|
|
1216
|
+
const shouldPreserveJsAlias =
|
|
1217
|
+
preserveJsPathSet.has(path) || preserveJsPathAbsoluteSet.has(path)
|
|
1218
|
+
|
|
1219
|
+
if (!path.includes('.native.') && !shouldPreserveJsAlias) {
|
|
1078
1220
|
cleanupNonMjsFiles.push(path)
|
|
1079
1221
|
cleanupNonMjsFiles.push(path + '.map')
|
|
1080
1222
|
}
|
|
@@ -1083,25 +1225,39 @@ async function esbuildWriteIfChanged(
|
|
|
1083
1225
|
await flush(
|
|
1084
1226
|
newOutPath,
|
|
1085
1227
|
result.code +
|
|
1086
|
-
(result.map
|
|
1228
|
+
(result.map && !shouldSkipSourceMaps
|
|
1229
|
+
? `\n//# sourceMappingURL=${basename(newOutPath)}.map\n`
|
|
1230
|
+
: '')
|
|
1087
1231
|
)
|
|
1088
|
-
if (result.map) {
|
|
1232
|
+
if (result.map && !shouldSkipSourceMaps) {
|
|
1089
1233
|
await flush(newOutPath + '.map', JSON.stringify(result.map))
|
|
1234
|
+
} else {
|
|
1235
|
+
await FSE.remove(newOutPath + '.map')
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
if (shouldPreserveJsAlias) {
|
|
1239
|
+
await flush(
|
|
1240
|
+
path,
|
|
1241
|
+
result.code +
|
|
1242
|
+
(result.map && !shouldSkipSourceMaps
|
|
1243
|
+
? `\n//# sourceMappingURL=${basename(path)}.map\n`
|
|
1244
|
+
: '')
|
|
1245
|
+
)
|
|
1246
|
+
if (result.map && !shouldSkipSourceMaps) {
|
|
1247
|
+
await flush(path + '.map', JSON.stringify(result.map))
|
|
1248
|
+
} else {
|
|
1249
|
+
await FSE.remove(path + '.map')
|
|
1250
|
+
}
|
|
1090
1251
|
}
|
|
1091
1252
|
})
|
|
1092
1253
|
)
|
|
1093
1254
|
|
|
1094
|
-
//
|
|
1095
|
-
if (
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
[...cleanupNonMjsFiles, ...cleanupNonCjsFiles].map(async (file) => {
|
|
1102
|
-
await FSE.remove(file)
|
|
1103
|
-
})
|
|
1104
|
-
)
|
|
1105
|
-
}
|
|
1255
|
+
// remove intermediary .js files once the final .mjs/.cjs outputs exist
|
|
1256
|
+
if (cleanupNonMjsFiles.length || cleanupNonCjsFiles.length) {
|
|
1257
|
+
await Promise.all(
|
|
1258
|
+
[...cleanupNonMjsFiles, ...cleanupNonCjsFiles].map(async (file) => {
|
|
1259
|
+
await FSE.remove(file)
|
|
1260
|
+
})
|
|
1261
|
+
)
|
|
1106
1262
|
}
|
|
1107
1263
|
}
|