Trying to Get Capacitor Working in Vanilla JS Ionic Project

I am in the process of migrating an SPA started several years ago using Onsen UI and Cordova to a vanilla JavaScript Ionic project using Capacitor. I’ve successfully ported most of the existing functionality over, and am just starting to explore adding native functionality using Capacitor. I am struggling mightily and unable to get anything to work. I haven’t worked with the new module syntax previously, and am not sure what I’m doing wrong. I also haven’t previously worked with Webpack.

Here’s some specifics on my development environment:

  • I’m working on an M1 Mac running Sonoma
  • Node version is 20.17.0
  • Ionic is 7.2.0
  • Capacitor version is 6.1.2

I initially tried adding the Ionic Storage plugin, and managed to get my init() function to create a Store object. But when I try adding the Camera plugin to the project, I get the following error message:

Uncaught TypeError: The specifier “@ionic/storage” was a bare specifier, but was not remapped to anything. Relative module specifiers must start with “./”, “…/” or “/”.

Any pointers to get me moving in the right direction would be greatly appreciated. Here is my index.js file:

import { Storage } from "@ionic/storage";
import { Camera, CameraResultType, CameraSource } from "@capacitor/camera";
import { defineCustomElements } from "@ionic/pwa-elements/loader";

defineCustomElements(window);

async function initStorage() {
	const store = new Storage();
	await store.create();
	console.log("Ionic Storage is ready");

	// Assign store to the global window object for access in the console
	window.store = store;
}

initStorage();

export async function takePhoto() {
	const image = await Camera.getPhoto({
		quality: 90,
		allowEditing: false,
		resultType: CameraResultType.Uri,
		source: CameraSource.Camera,
	});

	console.log("Photo URL:", image.webPath);
}

Here is package.json:

{
	"name": "pageone-inspection",
	"version": "0.0.1",
	"dependencies": {
		"@capacitor/android": "^6.1.2",
		"@capacitor/app": "6.0.1",
		"@capacitor/camera": "^6.0.2",
		"@capacitor/core": "6.1.2",
		"@capacitor/haptics": "6.0.1",
		"@capacitor/ios": "^6.1.2",
		"@capacitor/keyboard": "6.0.2",
		"@capacitor/status-bar": "6.0.1",
		"@ionic/core": "^8.2.7",
		"@ionic/pwa-elements": "^3.3.0",
		"@ionic/storage": "^4.0.0"
	},
	"devDependencies": {
		"@babel/core": "^7.25.2",
		"@babel/preset-env": "^7.25.4",
		"@capacitor/cli": "6.1.2",
		"babel-loader": "^9.2.1",
		"html-webpack-plugin": "^5.6.0",
		"webpack": "^5.95.0",
		"webpack-cli": "^5.1.4",
		"webpack-dev-server": "^5.1.0"
	},
	"scripts": {
		"start": "webpack serve --config webpack.config.js",
		"ionic:build": "webpack --config webpack.config.js",
		"ionic:serve": "webpack serve --config webpack.config.js"
	},
	"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}

And here is webpack.config.js:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");

module.exports = {
	entry: path.resolve(__dirname, "www/js/index.js"),
	output: {
		filename: "bundle.js", // Output bundle file
		path: path.resolve(__dirname, "www/dist"),
	},
	devServer: {
		static: path.join(__dirname, "www"),
		port: 8080,
	},
	plugins: [
		new HtmlWebpackPlugin({
			template: "./www/index.html",
		}),
	],
	module: {
		rules: [
			{
				test: /\.js$/,
				exclude: /node_modules/,
				use: {
					loader: "babel-loader",
					options: {
						presets: ["@babel/preset-env"],
					},
				},
			},
		],
	},
	resolve: {
		modules: [path.resolve(__dirname, "node_modules")],
		alias: {
			"@capacitor": path.resolve(__dirname, "node_modules/@capacitor"),
			"@capacitor/camera": path.resolve(__dirname, "node_modules/@capacitor/camera/dist/index.js"),
		},
		fallback: {
			"@capacitor/camera": false,
		},
	},
	mode: "development",
	cache: false,
};

My project directory structure is organized as follows:

  • Project root
    • package.json
    • webpack.config.js
    • android
    • ios
    • node_modules
      • @capacitor
      • @ionic
    • www
      • css
      • dist
        • bundle.js
      • js
        • index.js
      • css
        • main.css
      • index.html

I’m happy to provide any other files or details that would be helpful. Thanks to anyone for taking a look~

I got things working by switching to Vite. Interesting that both Vite and Webpack wouldn’t work with the default configuration of NPM http-server, but my Vite configuration worked right away with the server bundled with Vite. I still would be interested if anyone knows why this wasn’t working using Webpack and http-server…

1 Like