Search code examples
cordovanpmcordova-ioscordova-android

cordova platform add: adding second platform removes node modules for existing plugins and platforms


I am basically doing the following:

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

This installs the plugins and [email protected] which is there in node modules along with pluginA, pluginB and pluginC once the add completes. I then do:-

cordova platform add ios@5

Installs cordova-ios, but removes cordova-android module and all the plugin modules from node_modules. Doesn't remove the platform, just the node modules.

With npm timing turned on, I can see it running the following npm command, and that npm command removes cordova-android and the plugins

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 ]

I have managed to reproduce the issue with a basic project setup, based on my real project cut to the bone:

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="[email protected]" 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"
}

From ~/.npm/_logs I can see the following npm commands are executed:

/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

And from the npm log for the install cordova-ios@5 can see that npm decided to uninstall cordova-android

97 silly diffTrees remove [email protected]
98 silly diffTrees remove [email protected]

NPM Version Information:

2 info using [email protected]
3 info using [email protected]

Also, for reference, using these commands to enable npm logging:

npm config set timing true
npm config set logs-max 10000

Solution

  • The behaviour is triggered by having a single <engine/> node in config.xml. Specifying both engines, or no engines at all, the modules are not removed when adding a second platform.

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

    The following config.xml works.

    <?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="[email protected]" href="http://www.yourcompany.com">Your Company</author>
      <content src="index.html" />
    </widget>
    

    Quite why the <engine/> node is influencing npm to remove those modules I have no idea.

    The following script works, leaving both the plugins and cordova platforms intact.

    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="[email protected]" 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
    }