Skip to content

Commit 947f166

Browse files
authored
Merge pull request Expensify#68912 from callstack-internal/perf/xlsx-lazy-loading
Lazy load XLSX library
2 parents c0268a8 + 7c1ccd0 commit 947f166

13 files changed

Lines changed: 134 additions & 40 deletions

File tree

package-lock.json

Lines changed: 85 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@
204204
"react-native-webview": "13.13.1",
205205
"react-plaid-link": "3.3.2",
206206
"react-web-config": "^1.0.0",
207-
"react-webcam": "^7.1.1"
207+
"react-webcam": "^7.1.1",
208+
"xlsx": "^0.18.5"
208209
},
209210
"devDependencies": {
210211
"@actions/core": "1.10.0",
@@ -363,8 +364,7 @@
363364
"webpack-bundle-analyzer": "^4.5.0",
364365
"webpack-cli": "^5.0.4",
365366
"webpack-dev-server": "^5.2.1",
366-
"webpack-merge": "^5.8.0",
367-
"xlsx": "file:vendor/xlsx-0.20.3.tgz"
367+
"webpack-merge": "^5.8.0"
368368
},
369369
"overrides": {
370370
"braces": "3.0.3",

src/components/ImportSpreadsheet.tsx

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React, {useRef, useState} from 'react';
22
import {PanResponder, PixelRatio, Platform, View} from 'react-native';
33
import RNFetchBlob from 'react-native-blob-util';
44
import type {TupleToUnion} from 'type-fest';
5-
import * as XLSX from 'xlsx';
65
import useLocalize from '@hooks/useLocalize';
76
import useResponsiveLayout from '@hooks/useResponsiveLayout';
87
import useThemeStyles from '@hooks/useThemeStyles';
@@ -91,36 +90,45 @@ function ImportSpreadsheet({backTo, goTo, isImportingMultiLevelTags}: ImportSpre
9190
}
9291
const {fileExtension} = splitExtensionFromFileName(file?.name ?? '');
9392
const shouldReadAsText = CONST.TEXT_SPREADSHEET_EXTENSIONS.includes(fileExtension as TupleToUnion<typeof CONST.TEXT_SPREADSHEET_EXTENSIONS>);
94-
const readWorkbook = () => {
95-
if (shouldReadAsText) {
96-
return fetch(fileURI)
97-
.then((data) => {
98-
setIsReadingFile(true);
99-
return data.text();
100-
})
101-
.then((text) => XLSX.read(text, {type: 'string'}));
102-
}
103-
return fetch(fileURI)
104-
.then((data) => {
105-
setIsReadingFile(true);
106-
return data.arrayBuffer();
107-
})
108-
.then((arrayBuffer) => XLSX.read(new Uint8Array(arrayBuffer), {type: 'buffer'}));
109-
};
110-
readWorkbook()
111-
.then((workbook) => {
112-
const worksheet = workbook.Sheets[workbook.SheetNames[0]];
113-
const data = XLSX.utils.sheet_to_json(worksheet, {header: 1, blankrows: false}) as string[][] | unknown[][];
114-
const formattedSpreadsheetData = data.map((row) => row.map((cell) => String(cell)));
115-
setSpreadsheetData(formattedSpreadsheetData, fileURI, file.type, file.name, isImportingMultiLevelTags ?? false)
116-
.then(() => {
117-
Navigation.navigate(goTo);
93+
94+
setIsReadingFile(true);
95+
96+
import('xlsx')
97+
.then((XLSX) => {
98+
const readWorkbook = () => {
99+
if (shouldReadAsText) {
100+
return fetch(fileURI)
101+
.then((data) => {
102+
return data.text();
103+
})
104+
.then((text) => XLSX.read(text, {type: 'string'}));
105+
}
106+
return fetch(fileURI)
107+
.then((data) => {
108+
return data.arrayBuffer();
109+
})
110+
.then((arrayBuffer) => XLSX.read(new Uint8Array(arrayBuffer), {type: 'buffer'}));
111+
};
112+
readWorkbook()
113+
.then((workbook) => {
114+
const worksheet = workbook.Sheets[workbook.SheetNames[0]];
115+
const data = XLSX.utils.sheet_to_json(worksheet, {header: 1, blankrows: false}) as string[][] | unknown[][];
116+
const formattedSpreadsheetData = data.map((row) => row.map((cell) => String(cell)));
117+
setSpreadsheetData(formattedSpreadsheetData, fileURI, file.type, file.name, isImportingMultiLevelTags ?? false)
118+
.then(() => {
119+
Navigation.navigate(goTo);
120+
})
121+
.catch(() => {
122+
setUploadFileError(true, 'spreadsheet.importFailedTitle', 'spreadsheet.invalidFileMessage');
123+
});
118124
})
119-
.catch(() => {
120-
setUploadFileError(true, 'spreadsheet.importFailedTitle', 'spreadsheet.invalidFileMessage');
125+
.finally(() => {
126+
setIsReadingFile(false);
121127
});
122128
})
123-
.finally(() => {
129+
.catch((error) => {
130+
console.error('Failed to load XLSX library:', error);
131+
setUploadFileError(true, 'spreadsheet.importFailedTitle', 'spreadsheet.importSpreadsheetLibraryError');
124132
setIsReadingFile(false);
125133
});
126134
};

src/languages/de.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,7 @@ const translations = {
999999
sizeNotMet: 'Die Dateigröße muss größer als 0 Byte sein',
10001000
invalidFileMessage:
10011001
'Die Datei, die Sie hochgeladen haben, ist entweder leer oder enthält ungültige Daten. Bitte stellen Sie sicher, dass die Datei korrekt formatiert ist und die notwendigen Informationen enthält, bevor Sie sie erneut hochladen.',
1002+
importSpreadsheetLibraryError: 'Fehler beim Laden des Tabellenkalkulations-Moduls. Bitte überprüfen Sie Ihre Internetverbindung und versuchen Sie es erneut.',
10021003
importSpreadsheet: 'Tabellenkalkulation importieren',
10031004
downloadCSV: 'CSV herunterladen',
10041005
importMemberConfirmation: () => ({

src/languages/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,7 @@ const translations = {
990990
sizeNotMet: 'File size must be greater than 0 bytes',
991991
invalidFileMessage:
992992
'The file you uploaded is either empty or contains invalid data. Please ensure that the file is correctly formatted and contains the necessary information before uploading it again.',
993+
importSpreadsheetLibraryError: 'Failed to load spreadsheet module. Please check your internet connection and try again.',
993994
importSpreadsheet: 'Import spreadsheet',
994995
downloadCSV: 'Download CSV',
995996
importMemberConfirmation: () => ({

src/languages/es.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,7 @@ const translations = {
983983
sizeNotMet: 'El archivo adjunto debe ser más grande que 0 bytes.',
984984
invalidFileMessage:
985985
'El archivo que subiste está vacío o contiene datos no válidos. Asegúrate de que el archivo esté correctamente formateado y contenga la información necesaria antes de volver a subirlo.',
986+
importSpreadsheetLibraryError: 'Error al cargar el módulo de hojas de cálculo. Por favor, verifica tu conexión a internet e inténtalo de nuevo.',
986987
importSpreadsheet: 'Importar hoja de cálculo',
987988
downloadCSV: 'Descargar CSV',
988989
importMemberConfirmation: () => ({

src/languages/fr.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,7 @@ const translations = {
10011001
sizeNotMet: 'La taille du fichier doit être supérieure à 0 octet',
10021002
invalidFileMessage:
10031003
'Le fichier que vous avez téléchargé est soit vide, soit contient des données invalides. Veuillez vous assurer que le fichier est correctement formaté et contient les informations nécessaires avant de le télécharger à nouveau.',
1004+
importSpreadsheetLibraryError: 'Échec du chargement du module de feuille de calcul. Veuillez vérifier votre connexion Internet et réessayer.',
10041005
importSpreadsheet: 'Importer une feuille de calcul',
10051006
downloadCSV: 'Télécharger CSV',
10061007
importMemberConfirmation: () => ({

src/languages/it.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,7 @@ const translations = {
996996
sizeNotMet: 'La dimensione del file deve essere maggiore di 0 byte',
997997
invalidFileMessage:
998998
'Il file che hai caricato è vuoto o contiene dati non validi. Assicurati che il file sia formattato correttamente e contenga le informazioni necessarie prima di caricarlo di nuovo.',
999+
importSpreadsheetLibraryError: 'Impossibile caricare il modulo di fogli di calcolo. Controlla la tua connessione internet e riprova.',
9991000
importSpreadsheet: 'Importa foglio di calcolo',
10001001
downloadCSV: 'Scarica CSV',
10011002
importMemberConfirmation: () => ({

src/languages/ja.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,7 @@ const translations = {
998998
sizeNotMet: 'ファイルサイズは0バイトより大きくなければなりません',
999999
invalidFileMessage:
10001000
'アップロードしたファイルは空であるか、無効なデータが含まれています。ファイルが正しくフォーマットされ、必要な情報が含まれていることを確認してから、再度アップロードしてください。',
1001+
importSpreadsheetLibraryError: 'スプレッドシートモジュールの読み込みに失敗しました。インターネット接続を確認して、もう一度お試しください。',
10011002
importSpreadsheet: 'スプレッドシートをインポート',
10021003
downloadCSV: 'CSVをダウンロード',
10031004
importMemberConfirmation: () => ({

src/languages/nl.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,7 @@ const translations = {
997997
sizeNotMet: 'Bestandsgrootte moet groter zijn dan 0 bytes',
998998
invalidFileMessage:
999999
'Het bestand dat u heeft geüpload is ofwel leeg of bevat ongeldige gegevens. Zorg ervoor dat het bestand correct is opgemaakt en de benodigde informatie bevat voordat u het opnieuw uploadt.',
1000+
importSpreadsheetLibraryError: 'Spreadsheet-module laden mislukt. Controleer uw internetverbinding en probeer het opnieuw.',
10001001
importSpreadsheet: 'Spreadsheet importeren',
10011002
downloadCSV: 'CSV downloaden',
10021003
importMemberConfirmation: () => ({

0 commit comments

Comments
 (0)