@tamagui/vite-plugin 1.1.12 → 1.1.13

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/src/native.ts CHANGED
@@ -1,50 +1,21 @@
1
- // testing single file logic via https://github.com/richardtallent/vite-plugin-singlefile
2
-
3
- // helpful:
4
- // rollup config for react native
5
- // https://gist.github.com/pritishvaidya/171dcb8e857ec1df186c035c3df6ae16
6
-
7
- import micromatch from 'micromatch'
8
- import { OutputAsset, OutputChunk, OutputOptions } from 'rollup'
9
- import { Plugin } from 'vite'
10
-
11
- export function replaceScript(
12
- html: string,
13
- scriptFilename: string,
14
- scriptCode: string,
15
- removeViteModuleLoader = false
16
- ): string {
17
- const reScript = new RegExp(
18
- `<script([^>]*?) src="[./]*${scriptFilename}"([^>]*)></script>`
19
- )
20
- // we can't use String.prototype.replaceAll since it isn't supported in Node.JS 14
21
- const preloadMarker = /"__VITE_PRELOAD__"/g
22
- const newCode = scriptCode.replace(preloadMarker, 'void 0')
23
- const inlined = html.replace(
24
- reScript,
25
- (_, beforeSrc, afterSrc) => `<script${beforeSrc}${afterSrc}>\n${newCode}\n</script>`
26
- )
27
- return removeViteModuleLoader ? _removeViteModuleLoader(inlined) : inlined
28
- }
1
+ import { readFile } from 'fs/promises'
2
+ import { join } from 'path'
29
3
 
30
- export function replaceCss(
31
- html: string,
32
- scriptFilename: string,
33
- scriptCode: string
34
- ): string {
35
- const reCss = new RegExp(`<link[^>]*? href="[./]*${scriptFilename}"[^>]*?>`)
36
- const inlined = html.replace(reCss, `<style>\n${scriptCode}\n</style>`)
37
- return inlined
38
- }
4
+ import { esbuildFlowPlugin } from '@bunchtogether/vite-plugin-flow'
5
+ import { OutputOptions } from 'rollup'
6
+ import type { Plugin } from 'vite'
39
7
 
40
- const warnNotInlined = (filename: string) =>
41
- console.warn(`WARNING: asset not inlined: ${filename}`)
8
+ import { extensions } from './extensions.js'
42
9
 
43
10
  export function nativePlugin(): Plugin {
44
11
  return {
45
- name: 'vite:singlefile',
12
+ name: 'tamagui-native',
13
+ enforce: 'post',
14
+
46
15
  config: (config) => {
47
16
  if (!config.build) config.build = {}
17
+
18
+ config.build.modulePreload = { polyfill: false }
48
19
  // Ensures that even very large assets are inlined in your JavaScript.
49
20
  config.build.assetsInlineLimit = 100000000
50
21
  // Avoid warnings about large chunks.
@@ -56,15 +27,118 @@ export function nativePlugin(): Plugin {
56
27
  // Subfolder bases are not supported, and shouldn't be needed because we're embedding everything.
57
28
  config.base = undefined
58
29
 
59
- if (!config.build.rollupOptions) config.build.rollupOptions = {}
60
- if (!config.build.rollupOptions.output) config.build.rollupOptions.output = {}
30
+ config.resolve ??= {}
31
+
32
+ config.resolve.extensions = extensions
33
+
34
+ config.resolve.alias ??= {}
35
+ config.resolve.alias = {
36
+ ...config.resolve.alias,
37
+ 'react-native/Libraries/Renderer/shims/ReactFabric':
38
+ 'react-native/Libraries/Renderer/shims/ReactFabric',
39
+ 'react-native/Libraries/Utilities/codegenNativeComponent':
40
+ 'react-native/Libraries/Utilities/codegenNativeComponent',
41
+ 'react-native-svg': 'react-native-svg',
42
+ 'react-native-web': 'react-native',
43
+ 'react-native': 'react-native',
44
+ }
45
+
46
+ config.optimizeDeps ??= {}
47
+ config.optimizeDeps.esbuildOptions ??= {}
48
+ config.optimizeDeps.esbuildOptions.resolveExtensions = extensions
49
+
50
+ config.optimizeDeps.esbuildOptions.plugins ??= []
51
+ config.optimizeDeps.esbuildOptions.plugins.push(
52
+ esbuildFlowPlugin(
53
+ /node_modules\/(react-native\/|@react-native\/assets)/,
54
+ (_) => 'jsx'
55
+ )
56
+ )
57
+ // config.optimizeDeps.esbuildOptions.plugins.push(esbuildCommonjs(['react-native']))
58
+
59
+ config.optimizeDeps.include ??= []
60
+ config.optimizeDeps.include.push('react-native')
61
+
62
+ config.optimizeDeps.esbuildOptions.loader ??= {}
63
+ config.optimizeDeps.esbuildOptions.loader['.js'] = 'jsx'
64
+
65
+ config.optimizeDeps.esbuildOptions.plugins.push({
66
+ name: 'react-native-assets',
67
+ setup(build) {
68
+ build.onResolve(
69
+ {
70
+ filter: /\.(png|jpg|gif|webp)$/,
71
+ },
72
+ async ({ path, namespace }) => {
73
+ return {
74
+ path: '',
75
+ external: true,
76
+ }
77
+ }
78
+ )
79
+ },
80
+ })
81
+
82
+ config.build.rollupOptions ??= {}
83
+
84
+ config.build.rollupOptions.input =
85
+ '/Users/n8/tamagui/apps/kitchen-sink/src/index.tsx'
86
+
87
+ config.build.rollupOptions.output ??= {}
88
+
89
+ config.build.rollupOptions.plugins ??= []
90
+
91
+ config.build.rollupOptions.external = ['react-native', 'react', 'react/jsx-runtime']
92
+
93
+ if (!Array.isArray(config.build.rollupOptions.plugins)) {
94
+ throw `x`
95
+ }
96
+
97
+ if (process.env.DEBUG) {
98
+ console.log('config..', config)
99
+ }
100
+
101
+ config.build.commonjsOptions = {
102
+ include: /node_modules\/react\//,
103
+ }
104
+
105
+ config.build.rollupOptions.plugins.push({
106
+ name: `swap-react-native`,
107
+ async load(id) {
108
+ if (id.endsWith('react-native/index.js')) {
109
+ const bundled = await readFile(
110
+ join(process.cwd(), 'react-native.js'),
111
+ 'utf-8'
112
+ )
113
+ const code = bundled
114
+ return {
115
+ code: `
116
+ const run = () => {
117
+ ${bundled.replace(
118
+ `module.exports = require_react_native();`,
119
+ `return require_react_native();`
120
+ )}
121
+ }
122
+
123
+ const RN = run()
124
+
125
+ ${RNExportNames.map(
126
+ (name) =>
127
+ // adding exports
128
+ `export const ${name} = RN.${name}`
129
+ ).join('\n')}
130
+
131
+ `,
132
+ }
133
+ }
134
+ },
135
+ })
61
136
 
62
137
  const updateOutputOptions = (out: OutputOptions) => {
63
138
  // Ensure that as many resources as possible are inlined.
64
139
  out.inlineDynamicImports = true
65
140
 
66
141
  // added by me (nate):
67
- console.log('adding manualChunks = undefined')
68
142
  out.manualChunks = undefined
69
143
  }
70
144
 
@@ -75,78 +149,95 @@ export function nativePlugin(): Plugin {
75
149
  updateOutputOptions(config.build.rollupOptions.output as OutputOptions)
76
150
  }
77
151
  },
78
-
79
- enforce: 'post',
80
-
81
- generateBundle: (_, bundle) => {
82
- const inlinePattern = []
83
- const jsExtensionTest = /\.[mc]?js$/
84
- const htmlFiles = Object.keys(bundle).filter((i) => i.endsWith('.html'))
85
- const cssAssets = Object.keys(bundle).filter((i) => i.endsWith('.css'))
86
- const jsAssets = Object.keys(bundle).filter((i) => jsExtensionTest.test(i))
87
- const bundlesToDelete = [] as string[]
88
-
89
- console.log('bundle', bundle)
90
-
91
- // for (const name of htmlFiles) {
92
- // const htmlChunk = bundle[name] as OutputAsset
93
- // let replacedHtml = htmlChunk.source as string
94
- // for (const jsName of jsAssets) {
95
- // if (!inlinePattern.length || micromatch.isMatch(jsName, inlinePattern)) {
96
- // const jsChunk = bundle[jsName] as OutputChunk
97
- // if (jsChunk.code != null) {
98
- // bundlesToDelete.push(jsName)
99
- // replacedHtml = replaceScript(
100
- // replacedHtml,
101
- // jsChunk.fileName,
102
- // jsChunk.code,
103
- // false
104
- // // removeViteModuleLoader
105
- // )
106
- // }
107
- // } else {
108
- // warnNotInlined(jsName)
109
- // }
110
- // }
111
- // for (const cssName of cssAssets) {
112
- // if (!inlinePattern.length || micromatch.isMatch(cssName, inlinePattern)) {
113
- // const cssChunk = bundle[cssName] as OutputAsset
114
- // bundlesToDelete.push(cssName)
115
- // replacedHtml = replaceCss(
116
- // replacedHtml,
117
- // cssChunk.fileName,
118
- // cssChunk.source as string
119
- // )
120
- // } else {
121
- // warnNotInlined(cssName)
122
- // }
123
- // }
124
- // htmlChunk.source = replacedHtml
125
- // }
126
-
127
- // if (deleteInlinedFiles) {
128
- // for (const name of bundlesToDelete) {
129
- // delete bundle[name]
130
- // }
131
- // }
132
-
133
- // for (const name of Object.keys(bundle).filter(
134
- // (i) => !jsExtensionTest.test(i) && !i.endsWith('.css') && !i.endsWith('.html')
135
- // )) {
136
- // warnNotInlined(name)
137
- // }
138
- },
139
152
  }
140
153
  }
141
154
 
142
- // Optionally remove the Vite module loader since it's no longer needed because this plugin has inlined all code.
143
- // This assumes that the Module Loader is (1) the FIRST function declared in the module, (2) an IIFE, (3) is minified,
144
- // (4) is within a script with no unexpected attribute values, and (5) that the containing script is the first script
145
- // tag that matches the above criteria. Changes to the SCRIPT tag especially could break this again in the future.
146
- // Update example:
147
- // https://github.com/richardtallent/vite-plugin-singlefile/issues/57#issuecomment-1263950209
148
- const _removeViteModuleLoader = (html: string) =>
149
- html.replace(
150
- /(<script type="module" crossorigin>\s*)\(function\(\)\{[\s\S]*?\}\)\(\);/,
151
- '<script type="module">\n'
152
- )
155
+ const RNExportNames = [
156
+ 'AccessibilityInfo',
157
+ 'ActivityIndicator',
158
+ 'Button',
159
+ 'DatePickerIOS',
160
+ 'DrawerLayoutAndroid',
161
+ 'FlatList',
162
+ 'Image',
163
+ 'ImageBackground',
164
+ 'InputAccessoryView',
165
+ 'KeyboardAvoidingView',
166
+ 'MaskedViewIOS',
167
+ 'Modal',
168
+ 'Pressable',
169
+ 'ProgressBarAndroid',
170
+ 'ProgressViewIOS',
171
+ 'RefreshControl',
172
+ 'SafeAreaView',
173
+ 'ScrollView',
174
+ 'SectionList',
175
+ 'Slider',
176
+ 'StatusBar',
177
+ 'Switch',
178
+ 'Text',
179
+ 'TextInput',
180
+ 'Touchable',
181
+ 'TouchableHighlight',
182
+ 'TouchableNativeFeedback',
183
+ 'TouchableOpacity',
184
+ 'TouchableWithoutFeedback',
185
+ 'View',
186
+ 'VirtualizedList',
187
+ 'VirtualizedSectionList',
188
+ 'ActionSheetIOS',
189
+ 'Alert',
190
+ 'Animated',
191
+ 'Appearance',
192
+ 'AppRegistry',
193
+ 'AppState',
194
+ 'AsyncStorage',
195
+ 'BackHandler',
196
+ 'Clipboard',
197
+ 'DeviceInfo',
198
+ 'DevSettings',
199
+ 'Dimensions',
200
+ 'Easing',
201
+ 'findNodeHandle',
202
+ 'I18nManager',
203
+ 'ImagePickerIOS',
204
+ 'InteractionManager',
205
+ 'Keyboard',
206
+ 'LayoutAnimation',
207
+ 'Linking',
208
+ 'LogBox',
209
+ 'NativeDialogManagerAndroid',
210
+ 'NativeEventEmitter',
211
+ 'Networking',
212
+ 'PanResponder',
213
+ 'PermissionsAndroid',
214
+ 'PixelRatio',
215
+ // 'PushNotificationIOS',
216
+ 'Settings',
217
+ 'Share',
218
+ 'StyleSheet',
219
+ 'Systrace',
220
+ 'ToastAndroid',
221
+ 'TurboModuleRegistry',
222
+ 'UIManager',
223
+ 'unstable_batchedUpdates',
224
+ 'useColorScheme',
225
+ 'useWindowDimensions',
226
+ 'UTFSequence',
227
+ 'Vibration',
228
+ 'YellowBox',
229
+ 'DeviceEventEmitter',
230
+ 'DynamicColorIOS',
231
+ 'NativeAppEventEmitter',
232
+ 'NativeModules',
233
+ 'Platform',
234
+ 'PlatformColor',
235
+ 'processColor',
236
+ 'requireNativeComponent',
237
+ 'RootTagContext',
238
+ // 'unstable_enableLogBox',
239
+ // 'ColorPropType',
240
+ // 'EdgeInsetsPropType',
241
+ // 'PointPropType',
242
+ // 'ViewPropTypes',
243
+ ]
@@ -0,0 +1,99 @@
1
+ import { readFile } from 'fs/promises'
2
+
3
+ import { build } from 'esbuild'
4
+ import flowRemoveTypes from 'flow-remove-types'
5
+
6
+ import { extensions } from './extensions.js'
7
+
8
+ export async function nativePrebuild() {
9
+ console.log(`Prebuilding React Native (one time cost...)`)
10
+ await Promise.all([
11
+ // react
12
+ build({
13
+ bundle: true,
14
+ entryPoints: ['react'],
15
+ outfile: 'react.js',
16
+ format: 'cjs',
17
+ target: 'node14',
18
+ jsx: 'transform',
19
+ jsxFactory: 'react',
20
+ allowOverwrite: true,
21
+ platform: 'node',
22
+ define: {
23
+ __DEV__: 'true',
24
+ 'process.env.NODE_ENV': `"development"`,
25
+ },
26
+ logLevel: 'warning',
27
+ resolveExtensions: extensions,
28
+ }),
29
+ // react-jsx-runtime
30
+ build({
31
+ bundle: true,
32
+ entryPoints: ['react/jsx-runtime'],
33
+ outfile: 'react-jsx-runtime.js',
34
+ format: 'cjs',
35
+ target: 'node14',
36
+ jsx: 'transform',
37
+ jsxFactory: 'react',
38
+ external: ['react'],
39
+ allowOverwrite: true,
40
+ platform: 'node',
41
+ define: {
42
+ // metro serves this in production mode
43
+ __DEV__: 'false',
44
+ 'process.env.NODE_ENV': `"production"`,
45
+ },
46
+ logLevel: 'warning',
47
+ resolveExtensions: extensions,
48
+ }),
49
+ // react native
50
+ build({
51
+ bundle: true,
52
+ entryPoints: ['/Users/n8/tamagui/node_modules/react-native/index.js'],
53
+ outfile: 'react-native.js',
54
+ format: 'cjs',
55
+ target: 'node14',
56
+ jsx: 'transform',
57
+ jsxFactory: 'react',
58
+ allowOverwrite: true,
59
+ platform: 'node',
60
+ loader: {
61
+ '.png': 'dataurl',
62
+ '.jpg': 'dataurl',
63
+ '.jpeg': 'dataurl',
64
+ '.gif': 'dataurl',
65
+ },
66
+ define: {
67
+ __DEV__: 'true',
68
+ 'process.env.NODE_ENV': `"development"`,
69
+ },
70
+ logLevel: 'warning',
71
+ resolveExtensions: extensions,
72
+ external: ['react', 'react/jsx-runtime.js', 'react/jsx-runtime'],
73
+ plugins: [
74
+ {
75
+ name: 'remove-flow',
76
+ setup(build) {
77
+ build.onLoad(
78
+ {
79
+ filter: /.*.js/,
80
+ },
81
+ async (input) => {
82
+ if (!input.path.includes('react-native')) {
83
+ return
84
+ }
85
+ const code = await readFile(input.path, 'utf-8')
86
+ const output = flowRemoveTypes(code, { pretty: true })
87
+ const contents = output.toString().replace(/static\s+\+/g, 'static ')
88
+ return {
89
+ contents,
90
+ loader: 'jsx',
91
+ }
92
+ }
93
+ )
94
+ },
95
+ },
96
+ ],
97
+ }),
98
+ ])
99
+ }
package/src/plugin.ts CHANGED
@@ -8,14 +8,12 @@ import type { Plugin } from 'vite'
8
8
  export function tamaguiPlugin(
9
9
  options: TamaguiOptions & {
10
10
  useReactNativeWebLite?: boolean
11
- },
11
+ }
12
12
  ): Plugin {
13
- const components = [
14
- ...new Set([...options.components, 'tamagui', '@tamagui/core']),
15
- ]
13
+ const components = [...new Set([...options.components, 'tamagui', '@tamagui/core'])]
16
14
  const noExternalSSR = new RegExp(
17
15
  `${components.join('|')}|react-native|expo-linear-gradient`,
18
- 'ig',
16
+ 'ig'
19
17
  )
20
18
 
21
19
  const plugin: Plugin = {
@@ -36,13 +34,11 @@ export function tamaguiPlugin(
36
34
  _WORKLET: false,
37
35
  ...(process.env.NODE_ENV !== 'test' && {
38
36
  'process.env.TAMAGUI_TARGET': JSON.stringify(
39
- process.env.TAMAGUI_TARGET || 'web',
37
+ process.env.TAMAGUI_TARGET || 'web'
40
38
  ),
41
39
  'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || env.mode),
42
40
  'process.env.ENABLE_RSC': JSON.stringify(process.env.ENABLE_RSC || ''),
43
- 'process.env.ENABLE_STEPS': JSON.stringify(
44
- process.env.ENABLE_STEPS || '',
45
- ),
41
+ 'process.env.ENABLE_STEPS': JSON.stringify(process.env.ENABLE_STEPS || ''),
46
42
  'process.env.IS_STATIC': JSON.stringify(false),
47
43
  }),
48
44
  },
@@ -98,8 +94,7 @@ export function tamaguiPlugin(
98
94
  '.mjs',
99
95
  ],
100
96
  alias: {
101
- 'react-native/Libraries/Renderer/shims/ReactFabric':
102
- '@tamagui/proxy-worm',
97
+ 'react-native/Libraries/Renderer/shims/ReactFabric': '@tamagui/proxy-worm',
103
98
  'react-native/Libraries/Utilities/codegenNativeComponent':
104
99
  '@tamagui/proxy-worm',
105
100
  'react-native-svg': '@tamagui/react-native-svg',
@@ -0,0 +1,2 @@
1
+ export declare const extensions: string[];
2
+ //# sourceMappingURL=extensions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../src/extensions.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,UAWtB,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAGhD,OAAO,KAAK,EAAE,MAAM,EAAiC,MAAM,MAAM,CAAA;AAQjE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CA8OpE"}
package/types/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './plugin.js';
2
2
  export * from './extract.js';
3
3
  export * from './native.js';
4
+ export * from './nativePrebuild.js';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA"}
package/types/native.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { Plugin } from 'vite';
2
- export declare function replaceScript(html: string, scriptFilename: string, scriptCode: string, removeViteModuleLoader?: boolean): string;
3
- export declare function replaceCss(html: string, scriptFilename: string, scriptCode: string): string;
1
+ import type { Plugin } from 'vite';
4
2
  export declare function nativePlugin(): Plugin;
5
3
  //# sourceMappingURL=native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAIlC,wBAAgB,YAAY,IAAI,MAAM,CA+IrC"}
@@ -0,0 +1,2 @@
1
+ export declare function nativePrebuild(): Promise<void>;
2
+ //# sourceMappingURL=nativePrebuild.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nativePrebuild.d.ts","sourceRoot":"","sources":["../src/nativePrebuild.ts"],"names":[],"mappings":"AAOA,wBAAsB,cAAc,kBA2FnC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAElC;;GAEG;AAEH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,cAAc,GAAG;IACxB,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC,GACA,MAAM,CAqGR"}