简体   繁体   English

带有 Create-react-app 的 Cordova

[英]Cordova with Create-react-app

I have created a ReactJs app with create-react-app and then made the Production build with npm run build .我使用create-react-app创建了一个 ReactJs 应用程序,然后使用npm run build进行了生产npm run build In my www folder created with Cordova I just copy all the files from the create-react-app's build folder and that's fine.在我用 Cordova 创建的www文件夹中,我只是从create-react-app 的构建文件夹中复制所有文件,这很好。

I want to know how do I hook into Cordova's events like for example:我想知道如何与 Cordova 的事件挂钩,例如:

function startApp() {
  // your app logic
}
if (window.cordova) {
  document.addEventListener('deviceready', startApp, false);
} else {
  startApp();
}

For example I want to call the minified JS file inside startApp() .例如,我想在startApp()调用缩小的 JS 文件。 Or is there any other workflow that can be used to make Cordova events work with react app.或者是否有任何其他工作流程可用于使 Cordova 事件与 react 应用程序一起使用。

A small example would be helpful.一个小例子会有所帮助。

Is it possible to use the build file at all and just use the React App directly inside Cordova?是否可以完全使用构建文件并直接在 Cordova 中使用 React App? I am unsure how that would work given that there is Webpack settings which transpiles the ES6 code to ES5 and all.鉴于有将 ES6 代码转换为 ES5 和所有代码的 Webpack 设置,我不确定这将如何工作。

I am new to Cordova and struggling with this integration aspect.我是 Cordova 的新手,正在努力解决这个集成方面的问题。

I have found to make the two work and will post here for anyone else looking for the same.我发现可以让这两个工作,并将在这里发布给其他寻找相同的人。 There maybe other methods to do this , but this is what worked for me.也许还有其他方法可以做到这一点,但这对我有用。

So basically we will create a Cordova App using(say) : cordova create testapp com.test.testapp testapp This will give me a Folder Structure as so:所以基本上我们将使用(说)创建一个 Cordova 应用程序:cordova create testapp com.test.testapp testapp 这会给我一个文件夹结构,如下所示:

testapp
        --hooks
        --platforms
        --plugins
        --www
        --config.xml

Now inside the testapp folder we run : create-react-app teastappReact Which will add my react app inside testapp folder.现在在 testapp 文件夹中我们运行: create-react-app testappReact 这将在 testapp 文件夹中添加我的反应应用程序。 Your react app will have a main index.js in the /src directory.您的 React 应用程序将在 /src 目录中有一个主要的 index.js。

I the index.js make sure to wrap your main logic inside a function and then call the function along with Cordova object like so:我 index.js 确保将您的主要逻辑包装在一个函数中,然后像这样调用该函数和 Cordova 对象:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';


const startApp = () => {
ReactDOM.render(
  <App />,
  document.getElementById('root')
);
}

if(!window.cordova) {
  startApp()
} else {
  document.addEventListener('deviceready', startApp, false)
}

That should do now your app will have the Cordova instance along with Device objects like navigator.camera inside your app.现在应该这样做了,您的应用程序将拥有 Cordova 实例以及您的应用程序内的 navigator.camera 等设备对象。

Also in your react apps index.html which can be found in the public folder copy the html from the index.html that you will find in the Codova www folder.同样在您的反应应用程序 index.html 中,它可以在公共文件夹中找到,从您将在 Codova www 文件夹中找到的 index.html 中复制 html。 Now we can delete all files from www folder.现在我们可以删除 www 文件夹中的所有文件。 We will later manually or via a script copy all files from react apps build folder to Cordova www folder.我们稍后将手动或通过脚本将所有文件从 react apps build 文件夹复制到 Cordova www 文件夹。

So my index.html would look something like below, notice the cordova.js file thats included as a script.所以我的 index.html 看起来像下面这样,注意作为脚本包含的 cordova.js 文件。

<!DOCTYPE html>
<!--
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
-->
<html>

<head>
    <!--
        Customize this policy to fit your own app's needs. For more guidance, see:
            https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
        Some notes:
            * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
            * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
            * Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
                * Enable inline JS: add 'unsafe-inline' to default-src
        -->
    <meta http-equiv="Content-Security-Policy" content="default-src * 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src * data: content:;">
    <meta name="format-detection" content="telephone=no">
    <meta name="msapplication-tap-highlight" content="no">
    <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">

    <!-- Latest compiled and minified CSS -->
    <title>React App</title>
</head>

<body>
    <div id="root"></div>
   <script type="text/javascript" src="cordova.js"></script>
</body>

</html>

Finally in your react apps' package.json add the following line: .... "homepage": "../www" .... This will make sure your final build file is pointing at the right path.最后在你的 React 应用程序的 package.json 中添加以下行: .... "homepage": "../www" .... 这将确保你的最终构建文件指向正确的路径。 we can also add the following lines in your package.json build script.我们还可以在 package.json 构建脚本中添加以下几行。

  "scripts": {
    "start": "react-scripts start",
    ***"build": "react-scripts build && robocopy .\\build ..\\www /MIR",***
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject",
    "deploy": "npm run build&&gh-pages -d build"
  }

It can be robocopy or cp-r based on the OS(Windows/Linux etc)..它可以是基于操作系统(Windows/Linux 等)的 robocopy 或 cp-r。

We should have our Cordova app ready to be build with cordova build android/ios.我们应该准备好使用cordova build android/ios构建我们的Cordova应用程序。

I solved the issue.我解决了这个问题。 Here's what I did in a step-by-step format for anyone looking for the solution:以下是我为寻找解决方案的人提供的分步格式:

  1. Copy/Create-a-new React project (created using create-react-app ) just inside the Cordova app directory.Cordova应用程序目录中复制/创建一个新的React项目(使用create-react-app )。
  2. Clear all the contents of www folder of Cordova app.清除Cordova应用程序www文件夹中的所有内容。
  3. cd to React project folder (which you just copied/created) & open package.json . cd到 React 项目文件夹(您刚刚复制/创建)并打开package.json
  4. Before dependencies add "homepage": "./", & inside scripts change build to "build": "react-scripts build && robocopy .\\\\build ..\\\\www /MIR",dependencies项之前添加"homepage": "./", & 内部脚本将build更改为"build": "react-scripts build && robocopy .\\\\build ..\\\\www /MIR",
  5. Do npm run build in same ( React 's) directory & go back to parent ( Cordova ) folder then build and emulate your project in desired platform.在相同的( React的)目录中执行npm run build并返回父( Cordova )文件夹,然后在所需的平台上buildemulate您的项目。
  6. Bonus Tip : If you are using <Router> in your project change that to <HashRouter> otherwise you'll see a blank display as nothing will get rendered to the screen.额外提示:如果您在项目中使用<Router>将其更改为<HashRouter>否则您将看到空白显示,因为屏幕上不会呈现任何内容。

I thought it was quite hard to find a complete guide how to fix this.我认为很难找到如何解决这个问题的完整指南。 I solved it like this, start to finish, to be able to run Create React App on an emulated Android device on Windows:我是这样解决的,从头到尾,以便能够在 Windows 上的模拟 Android 设备上运行 Create React App:

Start by creating a react app or use your existing app.首先创建一个 React 应用程序或使用您现有的应用程序。

npx create-react-app my-app

https://github.com/facebook/create-react-app#creating-an-apphttps://github.com/facebook/create-react-app#creating-an-app

Then install Cordova:然后安装科尔多瓦:

npm install -g cordova

https://cordova.apache.org/docs/en/latest/guide/cli/ https://cordova.apache.org/docs/en/latest/guide/cli/

Create a new cordova application inside the my-app folder in my case:在我的例子中,在my-app文件夹中创建一个新的cordova应用程序:

cordova create hello com.example.hello HelloWorld

Change directory to hello or what you called your Cordova application.将目录更改为hello或您所说的 Cordova 应用程序。

cordova platform add ios
cordova platform add android

Run cordova requirements to see what you need to build the project.运行cordova requirements以查看构建项目所需的内容。

在此处输入图片说明

Since I'm on Windows I will only build it for Android in this example.因为我使用的是 Windows,所以在这个例子中我只会为 Android 构建它。

cordova platform remove ios

and confirm I have only Android with cordova platform ls并确认我只有带有cordova platform ls Android cordova platform ls

在此处输入图片说明

Install what you need based on cordova requirements command.根据cordova requirements命令安装你需要的东西。 Since I had a fresh install I needed everything: Java Development Kit (JDK) 8, Gradle and Android SDK.因为我是全新安装的,所以我需要一切:Java 开发工具包 (JDK) 8、Gradle 和 Android SDK。 Links can be found here:链接可以在这里找到:

https://cordova.apache.org/docs/en/latest/guide/platforms/android/index.html#requirements-and-support https://cordova.apache.org/docs/en/latest/guide/platforms/android/index.html#requirements-and-support

Or:或者:

https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html

https://gradle.org/install/ https://gradle.org/install/

https://developer.android.com/studio/index.html https://developer.android.com/studio/index.html

Open Android Studio after it is installed.安装后打开Android Studio。 I choose a standard installation but it failed with the following warning:我选择了标准安装,但失败并显示以下警告:

Failed to install Intel HAXM.无法安装英特尔 HAXM。 For details, please check the installation log: "C:\\Users\\Oscar\\AppData\\Local\\Temp\\haxm_log.txt" Intel® HAXM installation failed.详情请查看安装日志:“C:\\Users\\Oscar\\AppData\\Local\\Temp\\haxm_log.txt” Intel® HAXM 安装失败。 To install Intel® HAXM follow the instructions found at: https://software.intel.com/android/articles/installation-instructions-for-intel-hardware-accelerated-execution-manager-windows Installer log is located at要安装英特尔® HAXM,请按照以下说明安装: https ://software.intel.com/android/articles/installation-instructions-for-intel-hardware-accelerated-execution-manager-windows 安装程序日志位于

C:\\Users\\Oscar\\AppData\\Local\\Temp\\haxm_log.txt Installer log contents: === Logging started: 2020-07-10 16:39:27 === This computer does not support Intel Virtualization Technology (VT-x) or it is being exclusively used by Hyper-V. C:\\Users\\Oscar\\AppData\\Local\\Temp\\haxm_log.txt 安装程序日志内容: === Logging started: 2020-07-10 16:39:27 === 这台计算机不支持 Intel Virtualization Technology (VT- x) 或者它专门由 Hyper-V 使用。 HAXM cannot be installed.无法安装 HAXM。 Please ensure Hyper-V is disabled in Windows Features, or refer to the Intel HAXM documentation for more information.请确保在 Windows 功能中禁用 Hyper-V,或参阅英特尔 HAXM 文档了解更多信息。

I could however start the application anyway and add an Android Virtual Device (AVD) found under Configure.然而,我无论如何都可以启动应用程序并添加在配置下找到的 Android 虚拟设备 (AVD)。

在此处输入图片说明

I choose to add a Pixel XL with R system image.我选择添加带有R系统映像的Pixel XL

However running cordova requirements again I could see I needed an Android target with API level 28. R is level 30.但是再次运行cordova requirements ,我可以看到我需要一个API级别为28的Android目标。R是30级。

在此处输入图片说明

I therefore installed Pie with API level 28 x86_64 and created a new virtual device.因此,我安装了 API 级别为 28 x86_64 的Pie并创建了一个新的虚拟设备。

在此处输入图片说明

Instead of opening AVD Manager i opened SDK manager and also downloaded the Android 9.0 Pie SDK.我没有打开AVD Manager而是打开了SDK manager ,还下载了 Android 9.0 Pie SDK。

在此处输入图片说明

Now everything looked good:现在一切看起来都不错:

在此处输入图片说明

Then run cordova emulate android to test the default Cordova application.然后运行cordova emulate android来测试默认的Cordova 应用程序。

If it works it should look like this:如果它有效,它应该是这样的:

在此处输入图片说明

Change directory to my-app .将目录更改为my-app

Edit package.json and add "homepage": "./", before dependencies:编辑package.json并在依赖项之前添加"homepage": "./",

在此处输入图片说明

Thanks to @BlackBeard for that.感谢@BlackBeard。 Source: https://stackoverflow.com/a/46785362/3850405来源: https : //stackoverflow.com/a/46785362/3850405

Run npm run build运行npm run build

Clear everything in my-app\\hello\\www then copy everything from my-app\\build to my-app\\hello\\www .清除my-app\\hello\\www所有内容,然后将my-app\\build所有内容复制到my-app\\hello\\www

Voilà:瞧:

在此处输入图片说明

If you don't edit my-app package.json and add "homepage": "./", it will look like this:如果不编辑my-app package.json并添加"homepage": "./",它将如下所示:

在此处输入图片说明

Lessons learnt:得到教训:

1. 1.

If you are using <Router> in your project change that to <HashRouter> otherwise you'll see a blank display as nothing will get rendered to the screen.如果您在项目中使用<Router>将其更改为<HashRouter>否则您将看到空白显示,因为屏幕上不会呈现任何内容。 Works for both iOS and Android.适用于 iOS 和 Android。

Source: https://stackoverflow.com/a/46785362/3850405来源: https : //stackoverflow.com/a/46785362/3850405

2. 2.

You need a whitelist to allow URLs.您需要一个白名单来允许 URL。 From documentation:从文档:

By default navigations are only allowed to file:// URLs.默认情况下,只允许导航到 file:// URL。 To allow others URLs, you must add tags to your config.xml:要允许其他 URL,您必须在 config.xml 中添加标签:

https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-whitelist/ https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-whitelist/

Install like this:像这样安装:

cordova plugin add cordova-plugin-whitelist

Then edit config.xml which is located in your application's root directory and add any of the following:然后编辑位于应用程序根目录中的config.xml并添加以下任何内容:

<!-- Allow links to example.com -->
<allow-navigation href="http://example.com/*" />

<!-- Wildcards are allowed for the protocol, as a prefix
     to the host, or as a suffix to the path -->
<allow-navigation href="*://*.example.com/*" />

<!-- A wildcard can be used to whitelist the entire network,
     over HTTP and HTTPS.
     *NOT RECOMMENDED* -->
<allow-navigation href="*" />

Source: https://stackoverflow.com/a/30327204/3850405来源: https : //stackoverflow.com/a/30327204/3850405

3. 3.

Even though you are using a whitelist you may still need to access an http API that does not support https.即使您使用的是白名单,您可能仍然需要访问不支持 https 的 http API。 By default this is not allowed and can cause some real headache.默认情况下,这是不允许的,可能会导致一些真正的头痛。 Solve this as well by editing config.xml and add the following under <platform name="android"> :也可以通过编辑config.xml并在<platform name="android">下添加以下内容来解决此问题:

<edit-config xmlns:android="http://schemas.android.com/apk/res/android"  file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application">     <application android:usesCleartextTraffic="true" /></edit-config>

Given that you do not browse to a URL any API call must specify the actual server.鉴于您没有浏览到 URL,任何 API 调用都必须指定实际服务器。 I normally use Axios so we only needed to add our server to the default URL.我通常使用 Axios,所以我们只需要将我们的服务器添加到默认 URL。 Example:例子:

import axios, { AxiosPromise, AxiosRequestConfig, Method } from 'axios';

const getConfig = (url: string, method: Method, params?: any, data?: any) => {
     const config: AxiosRequestConfig = {
         url: 'http://192.168.1.249' + url,
         method: method,
         responseType: 'json',
         params: params,
         data: data,
         headers: { 'X-Requested-With': 'XMLHttpRequest' },
    }
    return config;
}

export const sendRequest = (url: string, method: Method, params?: any, data?: any): AxiosPromise<any> => {
    return axios(getConfig(url, method))
}

Then called like this:然后像这样调用:

const path = '/api/test/'

export const initialLoad = (number: number): AxiosPromise<InitialLoadDto> => {
    return sendRequest(path + 'InitialLoad/' + number, 'get');
}

npm i -g react.cordova

https://www.npmjs.com/package/react.cordova . https://www.npmjs.com/package/react.cordova

It's cli that does all the work for you. cli 为您完成所有工作。 It has been repaired and works amazing now.它已经被修复,现在工作得很好。

*I wrote this *我写了这个

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM