cordova 平台添加:添加第二个平台会删除现有插件和平台的节点模块

问题描述

我基本上是在做以下事情:

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Paper from '@material-ui/core/Paper';
import Stepper from '@material-ui/core/Stepper';
import Step from '@material-ui/core/Step';
import StepLabel from '@material-ui/core/StepLabel';
import Button from '@material-ui/core/Button';
import Link from '@material-ui/core/Link';
import Typography from '@material-ui/core/Typography';
import AddressForm from './CheckoutForm';
import PaymentForm from './PaymentForm';
import Review from './Review';


const useStyles = makeStyles((theme) => ({
  appBar: {
    position: 'relative',},layout: {
    width: 'auto',marginLeft: theme.spacing(2),marginRight: theme.spacing(2),[theme.breakpoints.up(1000 + theme.spacing(2) * 2)]: {
      width: 1100,marginLeft: 'auto',marginRight: 'auto',paper: {
    marginTop: theme.spacing(3),marginBottom: theme.spacing(3),padding: theme.spacing(2),[theme.breakpoints.up(700 + theme.spacing(3) * 2)]: {
      marginTop: theme.spacing(6),marginBottom: theme.spacing(6),padding: theme.spacing(3),backgroundColor: 'rgb(248,246,244)',stepper: {
    padding: theme.spacing(5,5),fontWeight: 'bold',buttons: {
    display: 'flex',justifyContent: 'flex-end',button: {
    marginTop: theme.spacing(3),marginLeft: theme.spacing(1),border: "none"    
  },}));

const steps = ['Shipping address','Payment details','Review your order'];

function copyright() {
  return (
    <Typography variant="body2" color="textSecondary" align="center">
      {'copyright © '}
      <Link color="inherit" href="https://material-ui.com/">
                  Your Website
      </Link>{' '}
      {new Date().getFullYear()}
      {'.'}
    </Typography>
  );
}

function getStepContent(step,formValues = null,changeFormValue = null) {
  switch (step) {
  case 0:
    return <AddressForm addressValues={formValues} changeAddressValue={changeFormValue} />;
  case 1:
    return <PaymentForm paymentFormValues={formValues} changePaymentFormValue={changeFormValue}  />;
  case 2:
    return <Review />;
  default:
    throw new Error('UnkNown step');
  }
}

export default function Checkout(props) {
  const classes = useStyles();
  const [paymentFormValues,setPaymentFormValues] = React.useState({});
  const [addressFormValues,setAddressFormValues] = React.useState({});
  const [activeStep,setActiveStep] = React.useState(0);

  const handleNext = () => {
    setActiveStep(activeStep + 1);
  };

  const handleBack = () => {
    setActiveStep(activeStep - 1);
  };

  const changeAddressFormValue = (key,value) => {
    let values = { ...addressFormValues };
    values[key] = value;
    setAddressFormValues(values);
  };

  const changePaymentFormValue = (key,value) => {
    let values = { ...paymentFormValues };
    values[key] = value;
    setPaymentFormValues(values);
  };

  return (
    <React.Fragment>
      <CssBaseline />
      <AppBar position="absolute" color="default" className={classes.appBar}></AppBar>
      <main className={classes.layout}>
        <Paper className={classes.paper}>
          <Typography component="h1" variant="h3" align="center">
                        Checkout
          </Typography>
          <Stepper activeStep={activeStep} className={classes.stepper}>
            {steps.map((label) => (
              <Step key={label}>
                <StepLabel><Typography component="h1" variant="h5" align="center">
                  {label} </Typography></StepLabel>
              </Step>
            ))}
          </Stepper>

          <React.Fragment>
            {activeStep === steps.length ? (
              <React.Fragment>
                <Typography variant="h5" gutterBottom>
                                    Thank you for your order.
                </Typography>
                <Typography variant="subtitle1">
                                    Your order number is #2001539. We have emailed your order 
                                     confirmation,and will
                                     send you an update when your order has shipped.
                </Typography>
              </React.Fragment>
            ) : (
              <React.Fragment>
                {
                  activeStep === 0 ? 
                    getStepContent(activeStep,addressFormValues,changeAddressFormValue)
                    : activeStep === 1 ?  getStepContent(activeStep,paymentFormValues,changePaymentFormValue)
                      : getStepContent(activeStep)
                }
                {activeStep === 0 ? <Button onClick={() => {
                  // All the address values will be availabe in addressFormValues object for further processes
                  console.log(addressFormValues);
                }} >Submit Address</Button> : null}
                {    <div className={classes.buttons}>
                  {activeStep !== 0 && (
                    <Button variant="contained" style={{outline: 'none'}} 
                      className={classes.button}
                      onClick={handleBack}
                    >
                        Back
                    </Button>
                  )}
                  <Button style={{outline: 'none'}}
                    variant="contained"
                    color="secondary"
                    onClick={handleNext}
                    className={classes.button}
                  >
                    {activeStep === steps.length - 1 ? 'Place order' : 'Next'}
                  </Button>
                </div> }
              </React.Fragment>
            )}
          </React.Fragment>
        </Paper>
        <copyright />
      </main>
    </React.Fragment>
  );
}

一旦添加完成,这将安装插件和cordova-android@8.1.0,它们与pluginA、pluginB和pluginC一起存在于节点模块中。然后我做:-

cordova plugin add pluginA 
cordova plugin add pluginC
cordova plugin add pluginX
cordova platform add android

安装cordova-ios,但从node_modules中删除cordova-android模块和所有插件模块。不删除平台,只删除节点模块。

打开 npm 计时,我可以看到它运行以下 npm 命令,并且该 npm 命令删除了cordova-android 和插件

cordova platform add ios@5

根据我切入骨的真实项目,我已经设法通过基本项目设置重现了该问题:

1 verbose cli [
1 verbose cli   '/usr/local/bin/node',1 verbose cli   '/usr/local/bin/npm',1 verbose cli   'install',1 verbose cli   'cordova-ios@5',1 verbose cli   '--production',1 verbose cli   '--save-exact'
1 verbose cli ]

mkdir issue && cd issue && { mkdir www echo '{}' > build.json cat >config.xml <<-EOF <?xml version='1.0' encoding='utf-8'?> <widget id="com.example.mobile.test" version="0.0.1" android-versionCode="1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:android="http://schemas.android.com/apk/res/android"> <name>Test Client</name> <description>Test Client</description> <author email="user@email.com" href="http://www.yourcompany.com">Your Company</author> <content src="index.html" /> <engine name="ios" spec="5" /> </widget> EOF cordova --verbose platform add --save android cordova --verbose platform add --save ios@5 test ! -d node_modules/cordova-android \ && echo "cordova-android has been removed" } 我可以看到执行了以下 npm 命令:

~/.npm/_logs

从安装cordova-ios@5的npm日志可以看出npm决定卸载cordova-android

/usr/local/bin/node /usr/local/bin/npm view cordova-custom-config --json
/usr/local/bin/node /usr/local/bin/npm install cordova-custom-config --production --save
/usr/local/bin/node /usr/local/bin/npm install cordova-android@^8.0.0 --production --save-exact
/usr/local/bin/node /usr/local/bin/npm install cordova-ios@5 --production --save-exact

NPM 版本信息:

97 silly diffTrees remove cordova-android@8.1.0
98 silly diffTrees remove cordova-custom-config@5.1.0

另外,作为参考,使用这些命令启用 npm 日志记录:

2 info using npm@6.14.8
3 info using node@v14.15.1

解决方法

该行为由 <engine/> 中的单个 config.xml 节点触发。指定两个引擎或根本不指定引擎,添加第二个平台时不会删除模块。

  <engine name="ios" spec="5" />
  <engine name="android" spec="8" />

以下 config.xml 有效。

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.example.mobile.test" version="0.0.1" android-versionCode="1"
    xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"
    xmlns:android="http://schemas.android.com/apk/res/android">
  <name>Test Client</name>
  <description>Test Client</description>
  <author email="user@email.com" href="http://www.yourcompany.com">Your Company</author>
  <content src="index.html" />
</widget>

为什么 <engine/> 节点会影响 npm 以删除我不知道的那些模块。

以下脚本有效,插件和cordova平台保持不变。

mkdir issue && cd issue && {
  mkdir www
  echo "{}" >build.json

  cat >config.xml <<-EOF
    <?xml version='1.0' encoding='utf-8'?>
    <widget id="com.example.mobile.test" version="0.0.1" android-versionCode="1"
      xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"
      xmlns:android="http://schemas.android.com/apk/res/android">
      <name>Test Client</name>
      <description>Test Client</description>
      <author email="user@email.com" href="http://www.yourcompany.com">Your Company</author>
      <content src="index.html" />
    </widget>
  EOF

  cordova plugin add cordova-custom-config
  cordova platform add --save android
  cordova platform add --save ios@5
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...