Skip to content

Commit 12230c6

Browse files
authored
chore: add @ui-kitten/metro-config package
1 parent b0b85b8 commit 12230c6

17 files changed

+1188
-192
lines changed

docs/src/articles/guides/configure-navigation.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,7 @@ UI Kitten includes much more components that can be used with React Navigation:
170170
## Note on the other navigation libraries
171171

172172
Since React Navigation is not the only solution to perform routing within the React Native app, you might be interested
173-
in other navigation libraries like React Native Navigation by Wix. Currently, UI Kitten is not well-adopted to be used
174-
with this library and might have some performance issues.
175-
176-
Consider using React Navigation since UI Kitten has better API support with it.
173+
in other navigation libraries like React Native Navigation by Wix. By default, UI Kitten is not well adopted to work with this library, and you may need to [improve it's performance](guides/improving-performance).
177174

178175
<hr>
179176

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Improving Performance
2+
3+
By default, UI Kitten is configured with processing Eva mapping packages during the runtime. This may lead to performance issues when using [mapping customization](design-system/customize-mapping) or React Native Navigation by Wix. By following this guide, you will know how to get rid of this and save time your application takes on loading.
4+
5+
## Configuration
6+
7+
Install the additional metro configuration:
8+
9+
```bash
10+
npm i -D @ui-kitten/metro-config
11+
```
12+
13+
Create **metro.config.js** at the root of your project if you don't have this file yet and place the following code:
14+
15+
```js
16+
const MetroConfig = require('@ui-kitten/metro-config');
17+
18+
const evaConfig = {
19+
evaPackage: '@eva-design/eva',
20+
// Optional, but may be useful when using mapping customization feature.
21+
// customMappingPath: './custom-mapping.json',
22+
};
23+
24+
module.exports = MetroConfig.create(evaConfig, {
25+
// Whatever was previously specified
26+
});
27+
```
28+
29+
Modify props passed to ApplicationProvider:
30+
31+
```jsx
32+
import React from 'react';
33+
import { ApplicationProvider } from '@ui-kitten/components';
34+
import * as eva from '@eva-design/eva';
35+
36+
export default () => (
37+
<ApplicationProvider {...eva} theme={eva.light}>
38+
// ...
39+
</ApplicationProvider>
40+
);
41+
```
42+
Restart Metro Bundler if it is running to apply the changes.
43+
44+
<hr>
45+
46+
## Definition
47+
48+
Let's take a look on the **evaConfig** we define:
49+
50+
**evaPackage** represents the name of Eva Design System package installed.
51+
52+
In this example, we use `@eva-design/eva`.
53+
It may be one of the valid Eva Design System packages.
54+
55+
**customMappingPath** represents a path to custom mapping if you use [mapping customization](design-system/customize-mapping) feature. You may omit it if you do not customize Eva.
56+
57+
The second argument of `create` function is a standard configuration of Metro Bundler. In case you had `metro.config.js` previously, pass the object you had to merge it with UI Kitten configuration.

docs/src/structure.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,17 @@ export const structure = [
9797
},
9898
],
9999
},
100+
{
101+
type: 'page',
102+
name: 'Improving Performance',
103+
children: [
104+
{
105+
type: 'block',
106+
block: 'markdown',
107+
source: 'guides/improving-performance.md',
108+
},
109+
],
110+
},
100111
],
101112
},
102113
{

scripts/bump-version.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const PACKAGES: string[] = [
1212
'components',
1313
'date-fns',
1414
'eva-icons',
15+
'metro-config',
1516
'moment',
1617
'template-js',
1718
'template-ts',

scripts/publish-packages.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ function rebuild(done: GulpCompletionCallback): void {
2727

2828
function publish(done: GulpCompletionCallback): void {
2929
execSync(`npm publish ${PACKAGES_BUILD_DIR}/components`, { cwd: ROOT_DIR });
30-
execSync(`npm publish ${PACKAGES_BUILD_DIR}/eva-icons`, { cwd: ROOT_DIR });
3130
execSync(`npm publish ${PACKAGES_BUILD_DIR}/date-fns`, { cwd: ROOT_DIR });
31+
execSync(`npm publish ${PACKAGES_BUILD_DIR}/eva-icons`, { cwd: ROOT_DIR });
32+
execSync(`npm publish ${PACKAGES_BUILD_DIR}/metro-config`, { cwd: ROOT_DIR });
3233
execSync(`npm publish ${PACKAGES_BUILD_DIR}/moment`, { cwd: ROOT_DIR });
3334
execSync(`npm publish ${PACKAGES_DIR}/template-js`, { cwd: ROOT_DIR });
3435
execSync(`npm publish ${PACKAGES_DIR}/template-ts`, { cwd: ROOT_DIR });

src/components/theme/application/applicationProvider.component.tsx

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,18 @@ import { StyleProvider } from '../style/styleProvider.component';
1616
import { ThemeProviderProps } from '../theme/themeProvider.component';
1717
import { ModalPanel } from '../modal/modalPanel.component';
1818

19-
interface ComponentProps {
19+
interface EvaRuntimeProcessingProps {
2020
mapping: SchemaType;
2121
customMapping?: CustomSchemaType;
2222
}
2323

24-
export type ApplicationProviderProps = ComponentProps & ThemeProviderProps;
24+
interface EvaBuildtimeProcessingProps {
25+
styles: ThemeStyleType;
26+
}
27+
28+
type EvaProcessingProps = EvaRuntimeProcessingProps | EvaBuildtimeProcessingProps;
29+
30+
export type ApplicationProviderProps = EvaProcessingProps & ThemeProviderProps;
2531
export type ApplicationProviderElement = React.ReactElement<ApplicationProviderProps>;
2632

2733
interface State {
@@ -38,55 +44,56 @@ interface State {
3844
* @extends React.Component
3945
*
4046
* @property {SchemaType} mapping - Determines the mapping for basic components.
41-
* This is designed to be provided by developers team and can be imported from npm package (e.g. `@eva-design/eva`).
47+
* This is designed to be provided from any `@eva-design/*` package (e.g. `@eva-design/eva`)
48+
* If provided, will be merged with customMapping to bootstrap eva during the runtime.
4249
*
43-
* @property {CustomSchemaType} customMapping - Determines the customization mapping.
50+
* @property {CustomSchemaType} customMapping - Determines the customized mapping.
4451
* This is merged with `mapping` property and designed to be used components customization.
4552
*
4653
* @property {ThemeType} theme - Determines the theme for basic components.
4754
* This is designed to be provided by developers team and can be imported from npm package (e.g. `@eva-design/eva`).
4855
*
56+
* @property {ThemeStyleType} styles - Determines the styles compiled by bootstrapping eva.
57+
* If provided, will replace runtime styles calculation.
58+
* Should be used with `@ui-kitten/metro-config` package.
59+
*
4960
* @property {ReactNode} children - Determines application root component.
5061
*
5162
* @overview-example Simple Usage
5263
*
5364
* ```
5465
* import React from 'react';
5566
* import { ApplicationProvider, Layout, Text } from '@ui-kitten/components';
56-
* import { mapping, light as lightTheme } from '@eva-design/eva';
67+
* import * as eva from '@eva-design/eva';
5768
*
58-
* export default class App extends React.Component {
59-
*
60-
* render() {
61-
* return (
62-
* <ApplicationProvider
63-
* mapping={mapping}
64-
* theme={lightTheme}>
65-
* <Layout style={{ flex: 1 }}>
66-
* <Text>Welcome to UI Kitten</Text>
67-
* </Layout>
68-
* </ApplicationProvider>
69-
* );
70-
* }
71-
* }
69+
* export default () => (
70+
* <ApplicationProvider {...eva} theme={eva.light}>
71+
* <Layout style={{ flex: 1 }}>
72+
* <Text>Welcome to UI Kitten</Text>
73+
* </Layout>
74+
* </ApplicationProvider>
75+
* );
7276
* ```
7377
*/
7478
export class ApplicationProvider extends React.Component<ApplicationProviderProps, State> {
7579

80+
public state: State = {
81+
styles: (this.props as EvaBuildtimeProcessingProps).styles,
82+
};
83+
7684
private schemaProcessor: SchemaProcessor = new SchemaProcessor();
7785

7886
constructor(props: ApplicationProviderProps) {
7987
super(props);
80-
const { mapping, customMapping } = this.props;
8188

82-
const styles: ThemeStyleType = this.createStyles(mapping, customMapping);
83-
84-
this.state = { styles };
89+
if (!this.state.styles) {
90+
const { mapping, customMapping } = this.props as EvaRuntimeProcessingProps;
91+
this.state.styles = this.createStyles(mapping, customMapping);
92+
}
8593
}
8694

8795
private createStyles = (mapping: SchemaType, custom: CustomSchemaType): ThemeStyleType => {
8896
const customizedMapping: SchemaType = merge({}, mapping, custom);
89-
9097
return this.schemaProcessor.process(customizedMapping);
9198
};
9299

src/metro-config/index.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import Fs from 'fs';
2+
import LodashMerge from 'lodash.merge';
3+
import MetroConfig from 'metro-config/src/defaults';
4+
import BootstrapService from './services/bootstrap.service';
5+
import { EvaConfig } from './services/eva-config.service';
6+
import ProjectService from './services/project.service';
7+
8+
// TS definitions for metro config?
9+
type MetroConfigType = any;
10+
11+
const defaultMetroConfig = MetroConfig.getDefaultValues();
12+
const customMappingWatchOptions = {
13+
/*
14+
* How often the custom mapping should be polled in milliseconds
15+
*/
16+
interval: 100,
17+
};
18+
19+
/**
20+
* Creates custom Metro config for bootstrapping Eva packages.
21+
*
22+
* @param {EvaConfig} evaConfig - configuration of Eva Design System used in project.
23+
* @see {EvaConfig}
24+
*
25+
* @param metroConfig - configuration of Metro Bundler used in project.
26+
* @link https://facebook.github.io/metro/docs/configuration
27+
*
28+
* @returns a combination of two metro configurations.
29+
*
30+
* @example Usage
31+
*
32+
* ```metro.config.js
33+
* const MetroConfig = require('@ui-kitten/metro-config');
34+
*
35+
* const evaConfig = {
36+
* evaPackage: '@eva-design/eva', // Required.
37+
* customMappingPath: './custom-mapping.json', // Optional.
38+
* };
39+
*
40+
* module.exports = MetroConfig.create(evaConfig, {
41+
* // Whatever was previously specified
42+
* });
43+
* ```
44+
*/
45+
export const create = (evaConfig: EvaConfig, metroConfig?: MetroConfigType): MetroConfigType => {
46+
47+
const handleMetroEvent = (event): void => {
48+
const reporter = metroConfig && metroConfig.reporter || defaultMetroConfig.reporter;
49+
50+
if (reporter && reporter.update) {
51+
reporter.update(event);
52+
}
53+
54+
if (event.type === 'initialize_started') {
55+
BootstrapService.run(evaConfig);
56+
57+
const customMappingPath: string = ProjectService.resolvePath(evaConfig.customMappingPath);
58+
const customMappingExists: boolean = Fs.existsSync(customMappingPath);
59+
60+
if (customMappingExists) {
61+
Fs.watchFile(customMappingPath, customMappingWatchOptions, () => {
62+
BootstrapService.run(evaConfig);
63+
});
64+
}
65+
}
66+
};
67+
68+
const libConfig: MetroConfigType = {
69+
reporter: {
70+
update: handleMetroEvent,
71+
},
72+
};
73+
74+
return LodashMerge({}, libConfig, metroConfig);
75+
};

src/metro-config/package.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "@ui-kitten/metro-config",
3+
"description": "UI Kitten config for Metro Bundler",
4+
"version": "4.4.0",
5+
"author": "akveo <contact@akveo.com>",
6+
"license": "MIT",
7+
"homepage": "https://github.com/akveo/react-native-ui-kitten#readme",
8+
"repository": {
9+
"type": "git",
10+
"url": "git+https://github.com/akveo/react-native-ui-kitten.git"
11+
},
12+
"bugs": {
13+
"url": "https://github.com/akveo/react-native-ui-kitten/issues"
14+
},
15+
"publishConfig": {
16+
"access": "public"
17+
},
18+
"devDependencies": {
19+
"@eva-design/dss": "^1.4.0",
20+
"@eva-design/processor": "^1.4.0",
21+
"@types/lodash.merge": "ts3.7",
22+
"chalk": "^3.0.0",
23+
"lodash.merge": "^4.6.1"
24+
},
25+
"peerDependencies": {
26+
"metro-config": "^0.58.0"
27+
}
28+
}

0 commit comments

Comments
 (0)