Importing Capacitor app results in unable to read properties of undefined

Capacitor v7.0.1

package.json dependencies
@capacitor/cli”: “7.0.1”,
@rollup/plugin-commonjs”: “^28.0.3”,
@rollup/plugin-json”: “^6.1.0”,
@rollup/plugin-node-resolve”: “^16.0.0”,
@rollup/plugin-terser”: “^0.4.4”,
@capacitor/android”: “^7.0.1”,
@capacitor/app”: “^7.0.0”,
@capacitor/core”: “^7.0.1”,
@capacitor/ios”: “^7.0.1”,
@rollup/plugin-replace”: “^6.0.2”,
“npm”: “^11.2.0”,
“rollup”: “^4.21.0”,
“rollup-plugin-copy”: “^3.5.0”,
“rollup-plugin-minify”: “^1.0.3”,
“rollup-plugin-node-builtins”: “^2.0.0”,
“rollup-plugin-url-resolve”: “^0.2.0”,

Problem:

Adding @capacitor/core works as expected, running a Android build will push to an android device and run correctly, however when adding @capacitor/app the following warning when built and deployed to an android device is shown:

“TypeError: Failed to resolve module specifier “@capacitor/core”. Relative references must start with either “/”, “./”, or “../”.”

Rollup:

The following below is the output for the build for mobile. Using relative paths were required due to Rollup’s ‘node-resolve’ not actually resolving anything when run. This works for @capacitor/core but @capacitor/app has issues primarily due to it’s internal reference to core, that it is unable to resolve.

output: {
paths: {
@capacitor/core’ : ‘../../../node_modules/@capacitor/core/dist/index.js’,
@capacitor/app’: ‘../../../node_modules/@capacitor/app/dist/esm/index.js’
},
file: dist,
format: ‘es’,
}
}

Build file:

The following output below from the output from Rollup.js is correct:

import{Capacitor as e}from"../../../node_modules/@capacitor/core/dist/index.js";import{App as t}from"../../../node_modules/@capacitor/app/dist/esm/index.js";

The imported files exist and are accessible, however Capacitor throws the same error above stating:

“TypeError: Failed to resolve module specifier “@capacitor/core”. Relative references must start with either “/”, “./”, or “../”.” and this is from @Capacitor/App

What specifically is causing this hangup with Capacitor that it won’t respect the path to it’s associated files? Do we only need to call Capacitor instead of App, do we need to include both, the example I saw did not show adding Capacitor, only App so there’s some confusion there as well.

When doing a build via Iconic dashboard, clicking build, then sync, then running android.

The path for @capacitor/core when viewed in Visual Code Studio, always states

"Could not find a declaration file for module ‘../../node_modules/@capacitor/core/dist/index.js’. ‘/android/app/src/main/assets/public/node_modules/@capacitor/core/dist/index.js’ implicitly has an ‘any’ type.ts(701

Yet when you go and modify the path to see if the path actually will resolve, it always resolves correctly, yet Capacitor throws an error in logcat saying it can’t find it from Capacitor/Console:

Msg: TypeError: Failed to resolve module specifier “@capacitor/core”. Relative references must start with either “/”, “./”, or “../”.

yet the build bundle states

“import{Capacitor as e}from”../../node_modules/@capacitor/core/dist/index.js";import{App as t}from"../../node_modules/@capacitor/app/dist/esm/index.js";"

Pretty much dead in the water with this now :frowning:

I don’t have a solution for you but my guess is that it is an configuration issue with Rollup. Maybe switch to Vite. It for sure works with that. At least that is what I am using and that is what the Ionic Framework templates for React and Vue use.

I’m not certain that it’s a configuration issue and I say that only because if I just add @capacitor/core it works just fine. I can do a simple check to ensure it works on the device like:

import { Capacitor } from “@capacitor/core”;

if (Capacitor.getPlatform() === ‘ios’) {
alert('iOS! ');
} else if (Capacitor.getPlatform() === ‘android’) {
alert(‘Android!’);
}

Yet the moment I opt to add the following:

import { Capacitor } from “@capacitor/core”;
import { App } from “@capacitor/app”;

The same above code, never runs, and the following error is thrown in the logcat in Android about:

TypeError: Failed to resolve module specifier “@capacitor/core”. Relative references must start with either “/”, “./”, or “../”.

Yet the previous build worked just fine with it, but adding @capacitor/app throws this error, it’s very confusing. Considering the files are all in their proper respective places. And trying to add just the @capacitor/app and omitting core, will again throw the same above error, so something in the Capacitor packages seems to not be able to resolve itself. ( I also tried re-installing )

The bundler isn’t doing anything other than building the JS for the actual web build, the packages are all external and reside in node_modules. Rollup is modifying the paths to relative as there is no other way to get Capacitor to actually work without that portion either.

paths: {
@capacitor/core’ : ‘../../node_modules/@capacitor/core/dist/index.js’,
@capacitor/app’: ‘../../node_modules/@capacitor/app/dist/esm/index.js’
},

I appreciate the suggestion to try a completely different bundler but if I recall, Vite uses parts or portions of Rollup as well so I’d be wondering what the major difference is.

Yeah, Vite does still use Rollup under the hood; however, it does all the configuration for you.

Posting your Rollup config would be helpful so someone familiar with it could verify it is correct for Capacitor.

Here’s the rollup.config for someone who’s familiar with configuring Capacitor with Rollup


function filterPlugins(arr) {

  const internalFunctions = [
    terser(),
    copy({
      verbose: true,
      targets: [
        { src: './build', dest: './dist' },
    }),
    nodeResolve(),
    commonjs()
  ];

  return internalFunctions.filter(func => arr.includes(func.name));
}


 
function mobileBuild(src, dist, name, chosenPlugins){
  return {
      input: src,
      output: { 
        paths: { 
          '@capacitor/core' : '../node_modules/@capacitor/core/dist/capacitor.js',
          '@capacitor/app': '../node_modules/@capacitor/app/dist/esm/index.js'
        },  
        file: dist,
        format: 'es',
        name: 'petapp',
      },
      plugins: filterPlugins(chosenPlugins),
     external: []
  }
}


export default [
  mobileBuild('./build/js/buildbundle.js', './dist/build/buildbundle.min.js', 'petapp', ['nodeResolve', 'commonjs', 'terser', 'copy']), 
]