令我非常恼火的是,我发现,我在Android(8.0)手机以及iPhone上成功开发和测试的Ionic 4应用程序卡住在Android(8.1)平板电脑和在iPad上启动时崩溃。通过使用adb logcat诊断技术,我观察到在错误的Android平板电脑上,vendor-es5.js中报告了一个语法错误,当我进入项目的www文件夹并转到错误的引用行时,即SyntaxError: Unexpected token *,我就进入了在明显来自node_modules/d3-delaunay/src/delaunay.js的代码中,并且使用了es6幂运算符**,特别是:

r = 1e-8 * Math.sqrt((bounds[3] - bounds[1])**2 + (bounds[2] - bounds[0])**2);

我不知道为什么此代码在某些设备上会出现问题,也不知道是什么导致了此代码,该代码不是es5(?)不能在未正确编译的情况下出现在vendor-es5.js文件中。为了更进一步,我手动破解了该delaunay.js文件,将所有幂运算实例替换为Math.pow()的等效用法,并且可以肯定的是,运行时间进一步扩大,但最终又在node_modules/vega-dataflow/src/dataflow/load.js和提示SyntaxError: Unexpected token function,特别是在这一行:

export async function request(url, format) {

同样,显然async/await不是es5构造,所以为什么它以vendor-es5.js结尾。在这一点上,我觉得这里有些系统上的错误,而且我没有能力去理解如何克服它,除非切换图形库?我想避免这种情况,所以我的问题是:
  • 为什么会这样?
  • 为什么只对某些设备(而不是所有设备)产生影响?
  • 有没有一种方法可以解决该问题,而无需切换到其他图形库?

  • 更新#1

    因为它是一个Ionic4项目,所以这意味着它是Angular 8项目,这意味着它是一个Webpack项目(与平台的默认设置相同)。所以这是我的angular.json文件:

    {
      "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
      "version": 1,
      "defaultProject": "app",
      "newProjectRoot": "projects",
      "projects": {
        "app": {
          "root": "",
          "sourceRoot": "src",
          "projectType": "application",
          "prefix": "app",
          "schematics": {},
          "architect": {
            "build": {
              "builder": "@angular-devkit/build-angular:browser",
              "options": {
                "outputPath": "www",
                "index": "src/index.html",
                "main": "src/main.ts",
                "polyfills": "src/polyfills.ts",
                "tsConfig": "tsconfig.app.json",
                "assets": [
                  {
                    "glob": "**/*",
                    "input": "src/assets",
                    "output": "assets"
                  },
                  {
                    "glob": "**/*.svg",
                    "input": "node_modules/ionicons/dist/ionicons/svg",
                    "output": "./svg"
                  }
                ],
                "styles": [
                  {
                    "input": "src/theme/variables.scss"
                  },
                  {
                    "input": "src/global.scss"
                  }
                ],
                "scripts": []
              },
              "configurations": {
                "production": {
                  "fileReplacements": [
                    {
                      "replace": "src/environments/environment.ts",
                      "with": "src/environments/environment.prod.ts"
                    }
                  ],
                  "optimization": true,
                  "outputHashing": "all",
                  "sourceMap": false,
                  "extractCss": true,
                  "namedChunks": false,
                  "aot": true,
                  "extractLicenses": true,
                  "vendorChunk": false,
                  "buildOptimizer": true,
                  "budgets": [
                    {
                      "type": "initial",
                      "maximumWarning": "2mb",
                      "maximumError": "5mb"
                    }
                  ]
                },
                "ci": {
                  "progress": false
                }
              }
            },
            "serve": {
              "builder": "@angular-devkit/build-angular:dev-server",
              "options": {
                "browserTarget": "app:build"
              },
              "configurations": {
                "production": {
                  "browserTarget": "app:build:production"
                },
                "ci": {
                  "progress": false
                }
              }
            },
            "extract-i18n": {
              "builder": "@angular-devkit/build-angular:extract-i18n",
              "options": {
                "browserTarget": "app:build"
              }
            },
            "test": {
              "builder": "@angular-devkit/build-angular:karma",
              "options": {
                "main": "src/test.ts",
                "polyfills": "src/polyfills.ts",
                "tsConfig": "tsconfig.spec.json",
                "karmaConfig": "karma.conf.js",
                "styles": [],
                "scripts": [],
                "assets": [
                  {
                    "glob": "favicon.ico",
                    "input": "src/",
                    "output": "/"
                  },
                  {
                    "glob": "**/*",
                    "input": "src/assets",
                    "output": "/assets"
                  }
                ]
              },
              "configurations": {
                "ci": {
                  "progress": false,
                  "watch": false
                }
              }
            },
            "lint": {
              "builder": "@angular-devkit/build-angular:tslint",
              "options": {
                "tsConfig": [
                  "tsconfig.app.json",
                  "tsconfig.spec.json",
                  "e2e/tsconfig.json"
                ],
                "exclude": ["**/node_modules/**"]
              }
            },
            "e2e": {
              "builder": "@angular-devkit/build-angular:protractor",
              "options": {
                "protractorConfig": "e2e/protractor.conf.js",
                "devServerTarget": "app:serve"
              },
              "configurations": {
                "production": {
                  "devServerTarget": "app:serve:production"
                },
                "ci": {
                  "devServerTarget": "app:serve:ci"
                }
              }
            },
            "ionic-cordova-build": {
              "builder": "@ionic/angular-toolkit:cordova-build",
              "options": {
                "browserTarget": "app:build"
              },
              "configurations": {
                "production": {
                  "browserTarget": "app:build:production"
                }
              }
            },
            "ionic-cordova-serve": {
              "builder": "@ionic/angular-toolkit:cordova-serve",
              "options": {
                "cordovaBuildTarget": "app:ionic-cordova-build",
                "devServerTarget": "app:serve"
              },
              "configurations": {
                "production": {
                  "cordovaBuildTarget": "app:ionic-cordova-build:production",
                  "devServerTarget": "app:serve:production"
                }
              }
            }
          }
        }
      },
      "cli": {
        "defaultCollection": "@ionic/angular-toolkit"
      },
      "schematics": {
        "@ionic/angular-toolkit:component": {
          "styleext": "scss"
        },
        "@ionic/angular-toolkit:page": {
          "styleext": "scss"
        }
      }
    }
    

    ...这是我的package.json文件与项目相关的子集:

    {
      "dependencies": {
        "@angular/common": "~8.1.2",
        "@angular/core": "~8.1.2",
        "@angular/forms": "~8.1.2",
        "@angular/http": "^7.2.15",
        "@angular/platform-browser": "~8.1.2",
        "@angular/platform-browser-dynamic": "~8.1.2",
        "@angular/router": "~8.1.2",
        "@ionic-native/core": "^5.15.1",
        "@ionic/angular": "^4.7.1",
        "vega": "~5.6.0",
        "vega-lite": "^3.4.0",
        "vega-themes": "^2.4.0",
        "zone.js": "~0.9.1"
      },
      "devDependencies": {
        "@angular-devkit/architect": "~0.801.2",
        "@angular-devkit/build-angular": "~0.801.2",
        "@angular-devkit/core": "~8.1.2",
        "@angular-devkit/schematics": "~8.1.2",
        "@angular/cli": "~8.1.2",
        "@angular/compiler": "~8.1.2",
        "@angular/compiler-cli": "~8.1.2",
        "@angular/language-service": "~8.1.2",
        "@ionic/angular-toolkit": "~2.0.0",
        "@types/jasmine": "~3.3.8",
        "@types/jasminewd2": "~2.0.3",
        "@types/node": "~8.9.4",
        "codelyzer": "^5.0.0",
        "jasmine-core": "~3.4.0",
        "jasmine-spec-reporter": "~4.2.1",
        "karma": "~4.1.0",
        "karma-chrome-launcher": "~2.2.0",
        "karma-coverage-istanbul-reporter": "~2.0.1",
        "karma-jasmine": "~2.0.1",
        "karma-jasmine-html-reporter": "^1.4.0",
        "protractor": "~5.4.0",
        "ts-node": "~7.0.0",
        "tslint": "~5.15.0",
        "typescript": "~3.4.3"
      }
    }
    

    更新#2

    继续尝试解决这个问题,我对package.json进行了以下更新:
      "dependences":
        "tslib": added => "^1.10.0"
        "vega": "~5.6.0" => "^5.9.0"
        "vega-lite": "^3.4.0" => "^4.0.2"
    
      "devDependencies":
        "@angular/compiler": "~8.1.2" => "~8.2.9"
        "@angular/compiler-cli": "~8.1.2" => "~8.2.9"
        "typescript": "~3.4.3" => "~3.5.3"
    

    ...经过这些更改,我认为我在www/vendor-es5.js文件中得到了明显的es5编译输出,而我的adb logcat结果似乎没有表明语法错误。不幸的是,该应用程序仍然无法通过“启动画面”(再次,仅在某些设备上是这种情况)。

    这是我来自项目的tsconfig.json文件:

    {
      "compileOnSave": false,
      "compilerOptions": {
        "baseUrl": "./",
        "outDir": "./dist/out-tsc",
        "sourceMap": true,
        "declaration": false,
        "module": "esnext",
        "moduleResolution": "node",
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "importHelpers": true,
        "target": "es2015",
        "typeRoots": [
          "node_modules/@types"
        ],
        "lib": [
          "es2018",
          "dom"
        ]
      },
      "angularCompilerOptions": {
        "fullTemplateTypeCheck": true,
        "strictInjectionParameters": true
      }
    }
    

    ...就vega的使用而言,关键是:

        const theme = vega.fivethirtyeight;
        this._view = new vega.View(vega.parse(vegaSpec, theme), {})
          .initialize(this.container.nativeElement)
          .logLevel(vega.Warn)
          .renderer('svg');
    

    ...在有问题的设备上,如果我将adb logcat输出过滤到E(错误)行,则会看到以下内容:
    01-10 09:17:27.650  6413  6413 E ApkAssets: Error while loading asset assets/natives_blob_64.bin: java.io.FileNotFoundException: assets/natives_blob_64.bin
    01-10 09:17:27.651  6413  6413 E ApkAssets: Error while loading asset assets/snapshot_blob_64.bin: java.io.FileNotFoundException: assets/snapshot_blob_64.bin
    01-10 09:17:27.680  6413  6413 E         : appName=xxxxxx, acAppName=/system/bin/surfaceflinger
    01-10 09:17:27.680  6413  6413 E         : 0
    01-10 09:17:27.683  6413  6413 E         : appName=xxxxxx, acAppName=vStudio.Android.Camera360
    01-10 09:17:27.683  6413  6413 E         : 0
    01-10 09:17:27.781  6413  6413 E MPlugin : Unsupported class: com.mediatek.common.telephony.IOnlyOwnerSimSupport
    01-10 09:17:28.153  6413  6464 E libEGL  : validate_display:99 error 3008 (EGL_BAD_DISPLAY)
    01-10 09:17:28.432  6413  6464 E         : appName=xxxxxx, acAppName=vStudio.Android.Camera360
    01-10 09:17:28.433  6413  6464 E         : 0
    01-10 09:17:28.436  6413  6464 E         : appName=xxxxxx, acAppName=vStudio.Android.Camera360
    01-10 09:17:28.436  6413  6464 E         : 0
    01-10 09:17:28.437  6413  6464 E         : appName=xxxxxx, acAppName=vStudio.Android.Camera360
    01-10 09:17:28.437  6413  6464 E         : 0
    01-10 09:17:30.514  6413  6455 E         : appName=xxxxxx, acAppName=vStudio.Android.Camera360
    01-10 09:17:30.514  6413  6455 E         : 0
    01-10 09:17:30.515  6413  6455 E         : app
    

    ...并且在很大程度上,这是W(警告)行:
    01-10 09:17:27.835  6413  6413 W chromium: [WARNING:password_handler.cc(33)] create-->contents = 0x9c66ec00, delegate = 0xa4b7edd0
    01-10 09:17:27.835  6413  6413 W chromium: [WARNING:password_handler.cc(41)] attaching to web_contents
    01-10 09:17:27.837  6413  6413 W cr_AwContents: onDetachedFromWindow called when already detached. Ignoring
    01-10 09:17:28.185  6413  6455 W libEGL  : [ANDROID_RECORDABLE] format: 1
    01-10 09:17:28.209  6413  6464 W VideoCapabilities: Unrecognized profile/level 1/32 for video/mp4v-es
    01-10 09:17:28.209  6413  6464 W VideoCapabilities: Unrecognized profile/level 32768/2 for video/mp4v-es
    01-10 09:17:28.209  6413  6464 W VideoCapabilities: Unrecognized profile/level 32768/64 for video/mp4v-es
    01-10 09:17:28.244  6413  6455 W libEGL  : [ANDROID_RECORDABLE] format: 1
    01-10 09:17:28.248  6413  6464 W VideoCapabilities: Unsupported mime video/x-ms-wmv
    01-10 09:17:28.253  6413  6464 W VideoCapabilities: Unsupported mime video/divx
    01-10 09:17:28.262  6413  6464 W VideoCapabilities: Unsupported mime video/xvid
    01-10 09:17:28.268  6413  6464 W VideoCapabilities: Unsupported mime video/flv1
    01-10 09:17:28.274  6413  6464 W VideoCapabilities: Unrecognized profile/level 1/32 for video/mp4v-es
    01-10 09:17:28.485  6413  6413 W cr_BindingManager: Cannot call determinedVisibility() - never saw a connection for the pid: 6413
    01-10 09:17:28.568  6413  6413 W cr_BindingManager: Cannot call determinedVisibility() - never saw a connection for the pid: 6413
    

    最佳答案

    首先,我想说这确实是vega包错误-我认为这是通过npm传递未转译代码的一种不好的方法。例如Angular Package Format保证您将获得es5有效代码(如果需要)。但是vega并不是一个明确的angular依赖项,因此让我们解决它。

    为什么会这样呢?

    因为有些开发人员以es6+标准提供软件包,所以在需要es5兼容应用程序之前是可以的。在我看来,库开发人员应该构建并交付es5es6 bundle ,否则对于他们的用户来说将是一个头痛的事情(例如您的vega案例)。

    为什么它只对某些设备(而不是所有设备)产生影响?

    老实说,我在原生移动开发方面的经验非常有限-我在这里只能说,例如,移动Chrome和台式机Chrome在引擎方面存在一些差异。这意味着不能保证使用相同的软件将提供相同的结果。有时,您可以在移动浏览器中找到该错误,而无法在 table 面浏览器中重现该错误。

    我认为在您的情况下,某些带有某些浏览器引擎的设备可以使用es6代码-有些则不能。
    同样在您的问题的第一个版本中有useragent字符串-我认为高级移动开发人员可以说比我更多的使用。

    有没有一种方法可以解决该问题而无需切换到其他图形库?

    是的。
    我创建了一个repo,其设置与您的设置非常相似-基于ionic@4的简单angular@8项目。

    现在,您的 bundle 是es5es6混合在一起的。让我们完全兼容es5以使其在任何浏览器中都可以工作(即使在ie11中,我也测试了该项目)。
    完成工作的步骤:

  • 安装依赖项。我们将在进一步的步骤中需要它们。
  • npm i -S regenerator-runtime
    npm i -D @angular-builders/custom-webpack babel-loader @babel/core @babel/preset-env
    
  • target中的es5属性更改为tsconfig"target": "es5"
  • 我们将转换async/await,因此我们需要将regenerator-runtime polyfill作为polyfills.ts添加到import 'regenerator-runtime/runtime'
  • 主要步骤。更改angular.json中的构建器,并添加webpack.config.js的路径以对buildserve使用自定义Webpack配置:
  •        "build": {
              "builder": "@angular-builders/custom-webpack:browser",
              "options": {
                "customWebpackConfig": {
                     "path": "./webpack.config.js"
                  },
    ...
            "serve": {
              "builder": "@angular-builders/custom-webpack:dev-server",
    
  • 在根文件夹中创建webpack.config.js,其中包含用于转换vega及其依赖项的规则。我以非常必要的方式找到了它们。
  • // these dependencies are es6!!!
    const transpileList = ['node_modules/vega', 'node_modules/d3', 'node_modules/delaunator'];
    
    module.exports = function(base) {
        return {
            ...base,
            module: {
                ...base.module,
                rules: [
                    ...base.module.rules,
                    {
                        test: function(fileName) {
                            return transpileList.some(name => fileName.includes(name)) && fileName.endsWith('.js');
                        },
                        use: {
                            loader: 'babel-loader',
                            options: {
                                presets: ['@babel/preset-env']
                            }
                        }
                    }
                ]
            }
        }
    }
    

    完成这些步骤后,希望您的应用程序可以在任何es5环境中运行。我尝试使用默认的三星浏览器在台式机ie11和平板电脑Samsung A中进行尝试。

    关于android - 在Ionic App中使用Vega Charts在某些设备上启动时会导致运行时错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59606443/

    10-12 22:47