feat: move css to different package for size reduction (#2168)

PR based on https://github.com/software-mansion/react-native-svg/pull/1452 extracting `css` related components to different package to reduce the size of the package.

***THIS IS A BREAKING CHANGE***. From now on, you should import 
```
  SvgCss,
  SvgCssUri,
  SvgWithCss,
  SvgWithCssUri,
  inlineStyles,
  LocalSvg,
  WithLocalSvg,
  loadLocalRawResource,
  ```
 from `react-native-svg/css` package instead.
This commit is contained in:
Wojciech Lewicki
2023-11-14 11:50:03 +01:00
committed by GitHub
parent f88532d195
commit 2b030dda12
15 changed files with 152 additions and 71 deletions

View File

@@ -12,6 +12,10 @@ module.exports = {
'react-native/react-native': true, 'react-native/react-native': true,
}, },
settings: { settings: {
'import/core-modules': [
'react-native-svg',
'react-native-svg/css',
],
'import/resolver': { 'import/resolver': {
'babel-module': { 'babel-module': {
extensions: ['.js', '.jsx', '.ts', '.tsx'], extensions: ['.js', '.jsx', '.ts', '.tsx'],

View File

@@ -57,7 +57,6 @@ const config = {
getTransformOptions: async () => ({ getTransformOptions: async () => ({
transform: { transform: {
experimentalImportSupport: false, experimentalImportSupport: false,
inlineRequires: true,
}, },
}), }),
}, },

View File

@@ -44,7 +44,6 @@ const config = {
getTransformOptions: async () => ({ getTransformOptions: async () => ({
transform: { transform: {
experimentalImportSupport: false, experimentalImportSupport: false,
inlineRequires: true,
}, },
}), }),
}, },

View File

@@ -40,7 +40,6 @@ const config = {
getTransformOptions: async () => ({ getTransformOptions: async () => ({
transform: { transform: {
experimentalImportSupport: false, experimentalImportSupport: false,
inlineRequires: true,
}, },
}), }),
}, },

View File

@@ -1,9 +1,18 @@
import React from 'react'; import React from 'react';
import { SvgFromUri, SvgFromXml, SvgUri, SvgXml, SvgCss, SvgCssUri, SvgWithCss, SvgWithCssUri, WithLocalSvg, LocalSvg } from 'react-native-svg'; import {SvgFromUri, SvgFromXml, SvgUri, SvgXml} from 'react-native-svg';
import {
SvgCss,
SvgCssUri,
SvgWithCss,
SvgWithCssUri,
WithLocalSvg,
LocalSvg,
} from 'react-native-svg/css';
const asset = require('../assets/ruby.svg'); const asset = require('../assets/ruby.svg');
const normalUri = "https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/ruby.svg"; const normalUri =
const uriWithCss = "http://thenewcode.com/assets/svg/accessibility.svg"; 'https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/ruby.svg';
const uriWithCss = 'http://thenewcode.com/assets/svg/accessibility.svg';
const xml = ` const xml = `
<svg width="32" height="32" viewBox="0 0 32 32"> <svg width="32" height="32" viewBox="0 0 32 32">
<path <path
@@ -39,7 +48,9 @@ const css = `
`; `;
export default () => { export default () => {
const [uri, setUri] = React.useState('https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/not_existing.svg') const [uri, setUri] = React.useState(
'https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/not_existing.svg',
);
return ( return (
<> <>
@@ -50,53 +61,29 @@ export default () => {
uri={uri} uri={uri}
/> />
<SvgFromUri <SvgFromUri
onError={(error) => console.log(error)} onError={error => console.log(error)}
width="100" width="100"
height="100" height="100"
uri={normalUri} uri={normalUri}
/> />
<SvgFromXml <SvgFromXml width="100" height="100" xml={xml} />
width="100" <SvgXml width="100" height="100" xml={xml} />
height="100" <SvgCss width="100" height="100" xml={css} />
xml={xml}
/>
<SvgXml
width="100"
height="100"
xml={xml}
/>
<SvgCss
width="100"
height="100"
xml={css}
/>
<SvgCssUri <SvgCssUri
onError={(error) => console.log(error)} onError={error => console.log(error)}
width="100" width="100"
height="100" height="100"
uri={uriWithCss} uri={uriWithCss}
/> />
<SvgWithCss <SvgWithCss width="100" height="100" xml={css} />
width="100"
height="100"
xml={css}
/>
<SvgWithCssUri <SvgWithCssUri
onError={(error) => console.log(error)} onError={error => console.log(error)}
width="100" width="100"
height="100" height="100"
uri={uriWithCss} uri={uriWithCss}
/> />
<WithLocalSvg <WithLocalSvg width="100" height="100" asset={asset} />
width="100" <LocalSvg width="100" height="100" asset={asset} />
height="100"
asset={asset}
/>
<LocalSvg
width="100"
height="100"
asset={asset}
/>
</> </>
); );
} };

View File

@@ -91,7 +91,7 @@ If remote SVG file contains CSS in `<style>` element, use `SvgCssUri`:
```jsx ```jsx
import * as React from 'react'; import * as React from 'react';
import { ActivityIndicator, View, StyleSheet } from 'react-native'; import { ActivityIndicator, View, StyleSheet } from 'react-native';
import { SvgCssUri } from 'react-native-svg'; import { SvgCssUri } from 'react-native-svg/css';
export default function TestComponent() { export default function TestComponent() {
const [loading, setLoading] = React.useState(true); const [loading, setLoading] = React.useState(true);
const onError = (e: Error) => { const onError = (e: Error) => {
@@ -125,7 +125,7 @@ existing in a different way and `fallback` if you want to render another compone
```jsx ```jsx
import * as React from 'react'; import * as React from 'react';
import { SvgUri } from 'react-native-svg'; import { SvgUri } from 'react-native-svg/css';
import { SvgFallback } from './components/SvgFallback'; import { SvgFallback } from './components/SvgFallback';
export default () => { export default () => {

View File

@@ -1,6 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import renderer from 'react-test-renderer'; import renderer from 'react-test-renderer';
import { SvgCss, parse, inlineStyles } from '../src/ReactNativeSVG'; import { parse } from '../src/ReactNativeSVG';
import { SvgCss, inlineStyles } from '../css';
const xml = `<?xml version="1.0" standalone="no"?> const xml = `<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"

6
css/package.json Normal file
View File

@@ -0,0 +1,6 @@
{
"main": "../lib/commonjs/css/index",
"module": "../lib/module/css/index",
"react-native": "../src/css/index",
"types": "../lib/typescript/css/index"
}

View File

@@ -18,6 +18,7 @@
"common", "common",
"lib", "lib",
"src", "src",
"css",
"RNSVG.podspec", "RNSVG.podspec",
"!android/build", "!android/build",
"windows", "windows",

View File

@@ -24,15 +24,27 @@ import Mask from './elements/Mask';
import Marker from './elements/Marker'; import Marker from './elements/Marker';
import ForeignObject from './elements/ForeignObject'; import ForeignObject from './elements/ForeignObject';
import { parse, SvgAst, SvgFromUri, SvgFromXml, SvgUri, SvgXml } from './xml';
import { import {
SvgCss, parse,
SvgCssUri, SvgAst,
SvgWithCss, SvgFromUri,
SvgWithCssUri, SvgFromXml,
inlineStyles, SvgUri,
} from './css'; SvgXml,
import { LocalSvg, WithLocalSvg, loadLocalRawResource } from './LocalSvg'; camelCase,
err,
fetchText,
JsxAST,
Middleware,
Styles,
UriProps,
UriState,
XmlAST,
XmlProps,
XmlState,
AstProps,
} from './xml';
import { import {
RNSVGCircle, RNSVGCircle,
RNSVGClipPath, RNSVGClipPath,
@@ -58,6 +70,17 @@ import {
RNSVGUse, RNSVGUse,
} from './fabric'; } from './fabric';
export {
SvgCss,
SvgCssUri,
SvgWithCss,
SvgWithCssUri,
inlineStyles,
LocalSvg,
WithLocalSvg,
loadLocalRawResource,
} from './deprecated';
export type { RectProps } from './elements/Rect'; export type { RectProps } from './elements/Rect';
export type { CircleProps } from './elements/Circle'; export type { CircleProps } from './elements/Circle';
export type { EllipseProps } from './elements/Ellipse'; export type { EllipseProps } from './elements/Ellipse';
@@ -81,8 +104,6 @@ export type { PatternProps } from './elements/Pattern';
export type { MaskProps } from './elements/Mask'; export type { MaskProps } from './elements/Mask';
export type { MarkerProps } from './elements/Marker'; export type { MarkerProps } from './elements/Marker';
export type { ForeignObjectProps } from './elements/ForeignObject'; export type { ForeignObjectProps } from './elements/ForeignObject';
export type { LocalProps } from './LocalSvg';
export type { UriProps, XmlProps, AstProps } from './xml';
export * from './lib/extract/types'; export * from './lib/extract/types';
@@ -117,14 +138,18 @@ export {
SvgFromXml, SvgFromXml,
SvgUri, SvgUri,
SvgXml, SvgXml,
SvgCss, camelCase,
SvgCssUri, err,
SvgWithCss, fetchText,
SvgWithCssUri, JsxAST,
inlineStyles, Middleware,
LocalSvg, Styles,
WithLocalSvg, UriProps,
loadLocalRawResource, UriState,
XmlAST,
XmlProps,
XmlState,
AstProps,
Shape, Shape,
RNSVGMarker, RNSVGMarker,
RNSVGMask, RNSVGMask,

View File

@@ -3,10 +3,9 @@ import { useState, useEffect, Component } from 'react';
import type { ImageSourcePropType } from 'react-native'; import type { ImageSourcePropType } from 'react-native';
import { Platform, Image } from 'react-native'; import { Platform, Image } from 'react-native';
import { fetchText } from './xml'; import { fetchText } from 'react-native-svg';
import { SvgCss, SvgWithCss } from './css'; import { SvgCss, SvgWithCss } from './css';
import type { SvgProps } from './elements/Svg'; import type { SvgProps } from 'react-native-svg';
import type { Spec } from './fabric/NativeSvgRenderableModule';
export function getUriFromSource(source: ImageSourcePropType) { export function getUriFromSource(source: ImageSourcePropType) {
const resolvedAssetSource = Image.resolveAssetSource(source); const resolvedAssetSource = Image.resolveAssetSource(source);
@@ -24,7 +23,7 @@ export function isUriAnAndroidResourceIdentifier(uri?: string) {
export async function loadAndroidRawResource(uri: string) { export async function loadAndroidRawResource(uri: string) {
try { try {
const RNSVGRenderableModule: Spec = const RNSVGRenderableModule: any =
// neeeded for new arch // neeeded for new arch
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires
require('./fabric/NativeSvgRenderableModule').default; require('./fabric/NativeSvgRenderableModule').default;

View File

@@ -9,8 +9,8 @@ import type {
XmlAST, XmlAST,
XmlProps, XmlProps,
XmlState, XmlState,
} from './xml'; } from 'react-native-svg';
import { camelCase, err, fetchText, parse, SvgAst } from './xml'; import { camelCase, err, fetchText, parse, SvgAst } from 'react-native-svg';
import type { import type {
Atrule, Atrule,
AtrulePrelude, AtrulePrelude,

20
src/css/index.tsx Normal file
View File

@@ -0,0 +1,20 @@
import {
SvgCss,
SvgCssUri,
SvgWithCss,
SvgWithCssUri,
inlineStyles,
} from './css';
import { LocalSvg, WithLocalSvg, loadLocalRawResource } from './LocalSvg';
export {
SvgCss,
SvgCssUri,
SvgWithCss,
SvgWithCssUri,
inlineStyles,
LocalSvg,
WithLocalSvg,
loadLocalRawResource,
};

37
src/deprecated.tsx Normal file
View File

@@ -0,0 +1,37 @@
export function showErrorCSS(name: string, type: string): never {
throw Error(
`[react-native-svg] You are trying to import a ${type} \`${name}\` that has been moved to a sub-package. Change your import from \`react-native-svg\` to \`react-native-svg/css\`.`
);
}
export function SvgCss(): never {
showErrorCSS('SvgCss', 'component');
}
export function SvgCssUri(): never {
showErrorCSS('SvgCssUri', 'component');
}
export function SvgWithCss(): never {
showErrorCSS('SvgWithCss', 'component');
}
export function SvgWithCssUri(): never {
showErrorCSS('SvgWithCssUri', 'component');
}
export function inlineStyles(): never {
showErrorCSS('inlineStyles', 'function');
}
export function LocalSvg(): never {
showErrorCSS('LocalSvg', 'component');
}
export function WithLocalSvg(): never {
showErrorCSS('WithLocalSvg', 'component');
}
export function loadLocalRawResource(): never {
showErrorCSS('loadLocalRawResource', 'function');
}

View File

@@ -2,6 +2,10 @@
"compilerOptions": { "compilerOptions": {
"baseUrl": ".", "baseUrl": ".",
"declaration": true, "declaration": true,
"paths": {
"react-native-svg": ["./src"],
"react-native-svg/css": ["./src/css/index.tsx"],
},
"preserveSymlinks": true, "preserveSymlinks": true,
"target": "es6", "target": "es6",
"module": "ESNext", "module": "ESNext",