reactjsreact-nativenext.jswebviewantd

NextJS + Antd Webview 83 Uncaught SyntaxError: Unexpected token '(' _app-455-3437e82bbe2dfd49.js:1


This is my webview information in react native User Agent: Mozilla/5.0 (Linux; Android 11; D2_2nd_STGL Build/942; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.120 Safari/537.36 Run on Sunmi D2 device

Error content message

Error description: It can't attached antd style just show a raw element

i tried to use "browserslist": [ "chrome 83" ], in my package.json but it didn't work

My package.json

{
  "name": "mona-fnb",
  "version": "0.1.0",
  "private": true,
  "browserslist": [
    "chrome 83"
  ],
  "scripts": {
    "dev": "next dev -p 3030",
    "build": "next build",
    "start": "next start  -H 192.168.3.121",
    "prd-start": "bun run build && bun start",
    "lint": "next lint",
    "export": "next build",
    "host": "next dev -p 3030 -H 192.168.3.121",
    "export:live": "env-cmd -f .env.live yarn build && yarn export",
    "export:mona": "env-cmd -f .env.mona yarn build && yarn export"
  },
  "dependencies": {
    "@ant-design/cssinjs": "^1.21.1",
    "@dnd-kit/core": "^6.1.0",
    "@dnd-kit/sortable": "^9.0.0",
    "@microsoft/signalr": "^8.0.7",
    "@nivo/bar": "^0.88.0",
    "@nivo/boxplot": "^0.88.0",
    "@nivo/core": "^0.88.0",
    "@nivo/line": "^0.88.0",
    "@nivo/pie": "^0.88.0",
    "@number-flow/react": "^0.4.2",
    "@react-google-maps/api": "^2.20.3",
    "@studio-freight/lenis": "^1.0.42",
    "@studio-freight/react-lenis": "^0.0.47",
    "@tanstack/react-query": "^5.59.8",
    "@tinymce/tinymce-react": "^6.0.0",
    "@types/tinymce": "^4.6.9",
    "antd": "5.21.3",
    "axios": "^1.7.7",
    "clsx": "^2.1.1",
    "date-fns": "^4.1.0",
    "dayjs": "^1.11.13",
    "devtools-detector": "2.0.22",
    "gsap": "^3.12.5",
    "html2pdf.js": "^0.10.2",
    "html5-qrcode": "2.2.7",
    "js-cookie": "^3.0.5",
    "jszpl": "^1.1.8",
    "jwt-decode": "^4.0.0",
    "leaflet": "^1.9.4",
    "leaflet-geosearch": "^4.0.0",
    "lodash": "^4.17.21",
    "next": "14.2.13",
    "nprogress": "^0.2.0",
    "react": "^18",
    "react-confetti": "^6.1.0",
    "react-date-range": "^2.0.1",
    "react-dnd": "^16.0.1",
    "react-dnd-html5-backend": "^16.0.1",
    "react-dom": "^18",
    "react-grid-layout": "^1.5.0",
    "react-icons": "^5.4.0",
    "react-intersection-observer": "^9.13.1",
    "react-leaflet": "^4.2.1",
    "react-lottie-player": "^2.1.0",
    "react-player": "^2.16.0",
    "react-thermal-printer": "^0.19.3",
    "react-to-print": "^3.0.5",
    "react-zoom-pan-pinch": "^3.4.4",
    "sass": "^1.79.4",
    "sharp": "^0.33.5",
    "uuid": "^10.0.0",
    "zustand": "4.5.4"
  },
  "devDependencies": {
    "@tanstack/eslint-plugin-query": "^5.59.7",
    "@tanstack/react-query-devtools": "^5.59.8",
    "@types/js-cookie": "^3.0.6",
    "@types/leaflet": "^1.9.14",
    "@types/lodash": "^4.17.13",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-date-range": "^1.4.9",
    "@types/react-dom": "^18",
    "@types/uuid": "^10.0.0",
    "@types/w3c-web-usb": "^1.0.10",
    "@types/web-bluetooth": "^0.0.21",
    "autoprefixer": "^10.4.20",
    "env-cmd": "^10.1.0",
    "eslint": "^8",
    "eslint-config-next": "14.2.13",
    "postcss": "^8",
    "tailwind-merge": "^2.5.4",
    "tailwindcss": "^3.4.1",
    "typescript": "^5"
  }
}

_document.tsx

import { createCache, extractStyle, StyleProvider } from "@ant-design/cssinjs";
import type { DocumentContext } from "next/document";
import Document, { Head, Html, Main, NextScript } from "next/document";

const MyDocument = () => (
  <Html lang="en">
    <Head />
    <body>
      <Main />
      <NextScript />
    </body>
    <div id="root-printer"></div>
  </Html>
);

MyDocument.getInitialProps = async (ctx: DocumentContext) => {
  const cache = createCache();
  const originalRenderPage = ctx.renderPage;
  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: (App) => (props) =>
        (
          <StyleProvider cache={cache}>
            <App {...props} />
          </StyleProvider>
        ),
    });

  const initialProps = await Document.getInitialProps(ctx);
  const style = extractStyle(cache, true);

  return {
    ...initialProps,
    styles: (
      <>
        {initialProps.styles}
        <style dangerouslySetInnerHTML={{ __html: style }} />{" "}
      </>
    ),
  };
};

export default MyDocument;

React native Webview.tsx

import React, {useEffect, useRef} from 'react';
import {
  ActivityIndicator,
  BackHandler,
  Dimensions,
  StyleSheet,
  View,
} from 'react-native';
// import OneSignal from 'react-native-onesignal';
import {WebView} from 'react-native-webview';

interface WebViewComponentProps {
  uri: string;
}

// export async function initOneSignal() {
//   OneSignal.setAppId('fd0f11c8-2347-4dfb-bec6-baa4997a1434');

//   if (Platform.OS == 'ios') {
//     OneSignal.promptForPushNotificationsWithUserResponse(response => {
//       // console.log('App - Prompt response:', response)
//     });
//   }

//   OneSignal.setNotificationWillShowInForegroundHandler(
//     notificationReceivedEvent => {
//       let notification = notificationReceivedEvent.getNotification();
//       // console.log('notification: ', notification)
//       const data = notification.additionalData;
//       // console.log('additionalData: ', data)
//     },
//   );
// }

// export function configPushNotification() {
//   if (Platform.OS == 'android') {
//     requestMultiple([PERMISSIONS.ANDROID.POST_NOTIFICATIONS]).then(statuses => {
//       initOneSignal();
//     });
//   } else {
//     initOneSignal();
//   }
// }
const INJECTED_JS =
  'window.ReactNativeWebView.postMessage(navigator.userAgent);';

const WebViewComponent: React.FC<WebViewComponentProps> = ({uri}) => {
  const webViewRef = useRef<any>(null);

  useEffect(() => {
    // initOneSignal();

    const handleBackPress = () => {
      if (webViewRef.current) {
        webViewRef.current?.goBack(); // Navigate back in WebView
        return true; // Prevent app from closing
      }
      return false;
    };

    const backHandler = BackHandler.addEventListener(
      'hardwareBackPress',
      handleBackPress,
    );

    return () => {
      backHandler.remove();
    };
  }, []);

  const renderLoadingView = () => (
    <View style={styles.loadingContainer}>
      <ActivityIndicator size="large" color="#0000ff" />
    </View>
  );

  const handleError = () => {
    // Handle error cases here
    console.error('WebView failed to load');
  };

  return (
    <WebView
      source={{uri}}
      style={styles.container}
      // renderLoading={renderLoadingView}
      // startInLoadingState={true}
      onError={handleError}
      androidLayerType="software"
      javaScriptEnabled={true}
      domStorageEnabled={true}
      startInLoadingState={false}
      scalesPageToFit={true}
      injectedJavaScript={INJECTED_JS}
      onMessage={event => console.log('User Agent:', event.nativeEvent.data)}
    />
  );
};
const deviceWidth = Dimensions.get('window').width;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    width: deviceWidth,
  },
  loadingContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'red',
  },
});

export default WebViewComponent;

Solution

  • I've finally determined the issue, that is some library doesn't support for older chrome version and modern css syntax as well, as in this case is chrome 83 If you are struggling with the same problem, the first thing you do is to check where libraries that you've installed support the old version or not for example:
    with antd => https://ant.design/docs/react/compatible-style with tanstack-query => https://tanstack.com/query/latest/docs/framework/react/installation

    and css as well, in my case svh was be used in my css so it just only support for at least 108 version
    => i use "postcss-viewport-unit-fallback" to solve this so whenever using modern css you need to considering check "can i use" page to check this out