one 1.2.45 → 1.2.46
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/dist/cjs/babel-plugins/remove-server-code.cjs +105 -0
- package/dist/cjs/babel-plugins/remove-server-code.js +125 -0
- package/dist/cjs/babel-plugins/remove-server-code.js.map +6 -0
- package/dist/cjs/babel-plugins/remove-server-code.native.js +153 -0
- package/dist/cjs/babel-plugins/remove-server-code.native.js.map +1 -0
- package/dist/cjs/metro-config/getViteMetroPluginOptions.cjs +8 -3
- package/dist/cjs/metro-config/getViteMetroPluginOptions.js +9 -1
- package/dist/cjs/metro-config/getViteMetroPluginOptions.js.map +1 -1
- package/dist/cjs/metro-config/getViteMetroPluginOptions.native.js +8 -3
- package/dist/cjs/metro-config/getViteMetroPluginOptions.native.js.map +1 -1
- package/dist/esm/babel-plugins/remove-server-code.js +102 -0
- package/dist/esm/babel-plugins/remove-server-code.js.map +6 -0
- package/dist/esm/babel-plugins/remove-server-code.mjs +71 -0
- package/dist/esm/babel-plugins/remove-server-code.mjs.map +1 -0
- package/dist/esm/babel-plugins/remove-server-code.native.js +116 -0
- package/dist/esm/babel-plugins/remove-server-code.native.js.map +1 -0
- package/dist/esm/metro-config/getViteMetroPluginOptions.js +9 -1
- package/dist/esm/metro-config/getViteMetroPluginOptions.js.map +1 -1
- package/dist/esm/metro-config/getViteMetroPluginOptions.mjs +7 -2
- package/dist/esm/metro-config/getViteMetroPluginOptions.mjs.map +1 -1
- package/dist/esm/metro-config/getViteMetroPluginOptions.native.js +7 -2
- package/dist/esm/metro-config/getViteMetroPluginOptions.native.js.map +1 -1
- package/package.json +14 -9
- package/src/babel-plugins/remove-server-code.ts +227 -0
- package/src/metro-config/getViteMetroPluginOptions.ts +10 -2
- package/types/babel-plugins/remove-server-code.d.ts +23 -0
- package/types/babel-plugins/remove-server-code.d.ts.map +1 -0
- package/types/metro-config/getViteMetroPluginOptions.d.ts.map +1 -1
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Babel plugin to remove server-only code (loader, generateStaticParams) from native bundles.
|
|
3
|
+
*
|
|
4
|
+
* This plugin transforms route files to remove server-only exports so they don't
|
|
5
|
+
* get included in the native bundle. It's the Metro equivalent of clientTreeShakePlugin.
|
|
6
|
+
*
|
|
7
|
+
* What it does:
|
|
8
|
+
* 1. Captures referenced identifiers BEFORE removing exports
|
|
9
|
+
* 2. Removes `export function loader() { ... }` and `export const loader = ...`
|
|
10
|
+
* 3. Removes `export function generateStaticParams() { ... }` and `export const generateStaticParams = ...`
|
|
11
|
+
* 4. Runs dead code elimination to remove imports that were only used by removed functions
|
|
12
|
+
* 5. Adds empty stubs back to prevent "missing export" errors
|
|
13
|
+
*
|
|
14
|
+
* Options:
|
|
15
|
+
* - routerRoot: The router root directory (e.g., 'app'). Only files in this directory are transformed.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { NodePath, PluginObj } from '@babel/core'
|
|
19
|
+
import * as t from '@babel/types'
|
|
20
|
+
import { deadCodeElimination, findReferencedIdentifiers } from 'babel-dead-code-elimination'
|
|
21
|
+
|
|
22
|
+
const SERVER_EXPORTS = ['loader', 'generateStaticParams'] as const
|
|
23
|
+
|
|
24
|
+
type ServerExport = (typeof SERVER_EXPORTS)[number]
|
|
25
|
+
|
|
26
|
+
type PluginOptions = {
|
|
27
|
+
routerRoot?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function removeServerCodePlugin(_: unknown, options: PluginOptions): PluginObj {
|
|
31
|
+
const { routerRoot = 'app' } = options
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
name: 'one-remove-server-code',
|
|
35
|
+
visitor: {
|
|
36
|
+
Program: {
|
|
37
|
+
enter(path: NodePath<t.Program>, state: { filename?: string; referenced?: Set<string> }) {
|
|
38
|
+
const filename = state.filename
|
|
39
|
+
|
|
40
|
+
// Only process route files in the router root
|
|
41
|
+
if (!filename) {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Check if file is in the router root directory
|
|
46
|
+
const routerRootPattern = new RegExp(`[/\\\\]${routerRoot}[/\\\\]`)
|
|
47
|
+
if (!routerRootPattern.test(filename)) {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Skip node_modules
|
|
52
|
+
if (filename.includes('node_modules')) {
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Quick check if file even has these exports
|
|
57
|
+
const code = path.toString()
|
|
58
|
+
if (!/generateStaticParams|loader/.test(code)) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Capture referenced identifiers BEFORE removing exports
|
|
63
|
+
// This is critical for dead code elimination to work
|
|
64
|
+
try {
|
|
65
|
+
state.referenced = findReferencedIdentifiers(path.node as any) as any
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.warn(
|
|
68
|
+
`[one/metro] Skipping tree shaking for ${filename} due to identifier analysis error:`,
|
|
69
|
+
error instanceof Error ? error.message : String(error)
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
exit(path: NodePath<t.Program>, state: { filename?: string; referenced?: Set<string> }) {
|
|
75
|
+
const filename = state.filename
|
|
76
|
+
|
|
77
|
+
// Only process route files in the router root
|
|
78
|
+
if (!filename) {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Check if file is in the router root directory
|
|
83
|
+
const routerRootPattern = new RegExp(`[/\\\\]${routerRoot}[/\\\\]`)
|
|
84
|
+
if (!routerRootPattern.test(filename)) {
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Skip node_modules
|
|
89
|
+
if (filename.includes('node_modules')) {
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// If we don't have referenced set from enter, skip
|
|
94
|
+
if (!state.referenced) {
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const removedExports: Set<ServerExport> = new Set()
|
|
99
|
+
|
|
100
|
+
// Find and remove server exports
|
|
101
|
+
// Note: babel-preset-expo may have already transformed async functions like:
|
|
102
|
+
// export async function loader() { ... }
|
|
103
|
+
// into:
|
|
104
|
+
// function _loader() { _loader = _asyncToGenerator(...); return _loader.apply(...) }
|
|
105
|
+
// export function loader() { return _loader.apply(...) }
|
|
106
|
+
// So we need to handle both the original form and the transformed form
|
|
107
|
+
path.traverse({
|
|
108
|
+
ExportNamedDeclaration(exportPath: NodePath<t.ExportNamedDeclaration>) {
|
|
109
|
+
const declaration = exportPath.node.declaration
|
|
110
|
+
|
|
111
|
+
// Handle: export function loader() { ... }
|
|
112
|
+
if (t.isFunctionDeclaration(declaration) && declaration.id) {
|
|
113
|
+
const name = declaration.id.name as ServerExport
|
|
114
|
+
if (SERVER_EXPORTS.includes(name)) {
|
|
115
|
+
removedExports.add(name)
|
|
116
|
+
exportPath.remove()
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Handle: export const loader = async () => { ... }
|
|
120
|
+
// Handle: export const loader = route.createLoader(...)
|
|
121
|
+
else if (t.isVariableDeclaration(declaration)) {
|
|
122
|
+
for (let i = declaration.declarations.length - 1; i >= 0; i--) {
|
|
123
|
+
const declarator = declaration.declarations[i]
|
|
124
|
+
if (t.isIdentifier(declarator.id)) {
|
|
125
|
+
const name = declarator.id.name as ServerExport
|
|
126
|
+
if (SERVER_EXPORTS.includes(name)) {
|
|
127
|
+
removedExports.add(name)
|
|
128
|
+
|
|
129
|
+
// Remove just this declarator
|
|
130
|
+
if (declaration.declarations.length === 1) {
|
|
131
|
+
exportPath.remove()
|
|
132
|
+
} else {
|
|
133
|
+
declaration.declarations.splice(i, 1)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
// Also remove helper functions created by babel's async-to-generator transform
|
|
142
|
+
// These are named _loader, _generateStaticParams, etc.
|
|
143
|
+
FunctionDeclaration(funcPath: NodePath<t.FunctionDeclaration>) {
|
|
144
|
+
if (!funcPath.node.id) return
|
|
145
|
+
const name = funcPath.node.id.name
|
|
146
|
+
// Check for helper functions like _loader, _generateStaticParams
|
|
147
|
+
for (const serverExport of SERVER_EXPORTS) {
|
|
148
|
+
if (name === `_${serverExport}`) {
|
|
149
|
+
// Verify this is indeed a babel-generated async helper
|
|
150
|
+
// by checking if it contains _asyncToGenerator
|
|
151
|
+
let isAsyncHelper = false
|
|
152
|
+
funcPath.traverse({
|
|
153
|
+
Identifier(idPath) {
|
|
154
|
+
if (idPath.node.name === '_asyncToGenerator') {
|
|
155
|
+
isAsyncHelper = true
|
|
156
|
+
idPath.stop()
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
})
|
|
160
|
+
if (isAsyncHelper) {
|
|
161
|
+
removedExports.add(serverExport)
|
|
162
|
+
funcPath.remove()
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
// Only proceed if we removed something
|
|
170
|
+
if (removedExports.size === 0) {
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Run dead code elimination to remove imports that were only used by removed functions
|
|
175
|
+
try {
|
|
176
|
+
deadCodeElimination(path.node as any, state.referenced as any)
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.warn(
|
|
179
|
+
`[one/metro] Dead code elimination failed for ${filename}:`,
|
|
180
|
+
error instanceof Error ? error.message : String(error)
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Add back empty stubs for removed exports to prevent "missing export" errors
|
|
185
|
+
const stubs: t.Statement[] = []
|
|
186
|
+
|
|
187
|
+
if (removedExports.has('loader')) {
|
|
188
|
+
// export function loader() { return "__vxrn__loader__"; }
|
|
189
|
+
stubs.push(
|
|
190
|
+
t.exportNamedDeclaration(
|
|
191
|
+
t.functionDeclaration(
|
|
192
|
+
t.identifier('loader'),
|
|
193
|
+
[],
|
|
194
|
+
t.blockStatement([t.returnStatement(t.stringLiteral('__vxrn__loader__'))])
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (removedExports.has('generateStaticParams')) {
|
|
201
|
+
// export function generateStaticParams() { }
|
|
202
|
+
stubs.push(
|
|
203
|
+
t.exportNamedDeclaration(
|
|
204
|
+
t.functionDeclaration(
|
|
205
|
+
t.identifier('generateStaticParams'),
|
|
206
|
+
[],
|
|
207
|
+
t.blockStatement([])
|
|
208
|
+
)
|
|
209
|
+
)
|
|
210
|
+
)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Add stubs at the end of the file
|
|
214
|
+
for (const stub of stubs) {
|
|
215
|
+
path.pushContainer('body', stub)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
console.info(
|
|
219
|
+
` 🧹 [one/metro] ${filename} removed ${removedExports.size} server-only exports`
|
|
220
|
+
)
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export default removeServerCodePlugin
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import module from 'node:module'
|
|
2
|
-
import path from 'node:path'
|
|
3
1
|
import type { metroPlugin } from '@vxrn/vite-plugin-metro'
|
|
4
2
|
import mm from 'micromatch'
|
|
3
|
+
import module from 'node:module'
|
|
4
|
+
import path from 'node:path'
|
|
5
5
|
import tsconfigPaths from 'tsconfig-paths'
|
|
6
6
|
import {
|
|
7
7
|
API_ROUTE_GLOB_PATTERN,
|
|
@@ -154,6 +154,14 @@ export function getViteMetroPluginOptions({
|
|
|
154
154
|
},
|
|
155
155
|
babelConfig: {
|
|
156
156
|
plugins: [
|
|
157
|
+
// Remove server-only code (loader, generateStaticParams) from route files
|
|
158
|
+
// This must run early to prevent server-only imports from being bundled
|
|
159
|
+
[
|
|
160
|
+
'one/babel-plugin-remove-server-code',
|
|
161
|
+
{
|
|
162
|
+
routerRoot: relativeRouterRoot,
|
|
163
|
+
},
|
|
164
|
+
],
|
|
157
165
|
[
|
|
158
166
|
'babel-plugin-module-resolver',
|
|
159
167
|
{
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Babel plugin to remove server-only code (loader, generateStaticParams) from native bundles.
|
|
3
|
+
*
|
|
4
|
+
* This plugin transforms route files to remove server-only exports so they don't
|
|
5
|
+
* get included in the native bundle. It's the Metro equivalent of clientTreeShakePlugin.
|
|
6
|
+
*
|
|
7
|
+
* What it does:
|
|
8
|
+
* 1. Captures referenced identifiers BEFORE removing exports
|
|
9
|
+
* 2. Removes `export function loader() { ... }` and `export const loader = ...`
|
|
10
|
+
* 3. Removes `export function generateStaticParams() { ... }` and `export const generateStaticParams = ...`
|
|
11
|
+
* 4. Runs dead code elimination to remove imports that were only used by removed functions
|
|
12
|
+
* 5. Adds empty stubs back to prevent "missing export" errors
|
|
13
|
+
*
|
|
14
|
+
* Options:
|
|
15
|
+
* - routerRoot: The router root directory (e.g., 'app'). Only files in this directory are transformed.
|
|
16
|
+
*/
|
|
17
|
+
import type { PluginObj } from '@babel/core';
|
|
18
|
+
type PluginOptions = {
|
|
19
|
+
routerRoot?: string;
|
|
20
|
+
};
|
|
21
|
+
declare function removeServerCodePlugin(_: unknown, options: PluginOptions): PluginObj;
|
|
22
|
+
export default removeServerCodePlugin;
|
|
23
|
+
//# sourceMappingURL=remove-server-code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove-server-code.d.ts","sourceRoot":"","sources":["../../src/babel-plugins/remove-server-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAY,SAAS,EAAE,MAAM,aAAa,CAAA;AAQtD,KAAK,aAAa,GAAG;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,iBAAS,sBAAsB,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,GAAG,SAAS,CAmM7E;AAED,eAAe,sBAAsB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getViteMetroPluginOptions.d.ts","sourceRoot":"","sources":["../../src/metro-config/getViteMetroPluginOptions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getViteMetroPluginOptions.d.ts","sourceRoot":"","sources":["../../src/metro-config/getViteMetroPluginOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAU1D,wBAAgB,yBAAyB,CAAC,EACxC,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,0BAA0B,EAC1B,SAAS,GACV,EAAE;IACD,WAAW,EAAE,MAAM,CAAA;IACnB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,iBAAiB,CAAC,EAAE,KAAK,CAAC,OAAO,MAAM,EAAE,CAAC,CAAA;IAC1C,0BAA0B,CAAC,EAAE,WAAW,CACtC,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAClC,CAAC,wBAAwB,CAAC,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CACzE,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAqMpC"}
|