Status of Vue 3 + Meteor?

A new version 3.0.0-beta.3 of vue-meteor-tracker is out on NPM to support Vue 3:

https://github.com/meteor-vue/vue-meteor-tracker

It is a full rewrite with TypeScript, Composition (and Options) API support. The Options API is very similar to the Vue 2 version (minus some removed APIs such as $startMeteor/$stopMeteor).

Together with vite:bundler, support of Vue 3 is nearly complete.

9 Likes

It is a full rewrite with TypeScript, Composition (and Options) API support. The Options API is very similar to the Vue 2 version (minus some removed APIs such as $startMeteor/$stopMeteor).

My dream has come true!! :star_struck:. I will be upgrading my apps (along with Vuetify 3 Beta) and I will share any feedback about the update :smiley:. Thank you very much for this support!

4 Likes

Wow. This is great news! Once all the pieces are in place, will move my app over to Vue 3 as well.

1 Like

I believe one can already write a meteor app with Vue 3 unless you need SSR (which isn’t supported by vite:bundler yet). It’s mostly a matter of finding bugs and fixing them now. :smiley:

6 Likes

I’m interested to try this with meteor-desktop for Electron apps. Has anyone given that a shot yet?

3 Likes

If only Vuetify 3.0 included v-data-table component. :frowning: Hoping it’s included in 3.1

Hi,

I opened a issue (https://github.com/meteor-vue/vue-meteor-tracker/issues/77) for vue-meteor-tracker.

Can someone check it and confirm it?

Thanks.

1 Like

Are you using the Vite integration or the integration from the repo you created the issue? The recommendation is to follow the example below created by @akryum.

I am using the Vite integration.

Hi, I was updating my app to Vue 3 (with Vite). The migration is basically complete but I am getting this error in the javascript console (browser):

Uncaught SyntaxError: Identifier 'Accounts' has already been declared (at accounts-base:15:14)

In the server console doesn’t appear anything.

I was searching the problem and I found a similar issue (it says Meteor instead of Accounts) [ERROR] Identifier Meteor has already been declared · Issue #10234 · meteor/meteor · GitHub. But I don’t have much context to solve it, so, any help would be appreciated @akryum.

My app includes the new version of Vuetify along with other libraries such as:

  • Vue Router
  • Vuex
  • Vee Validate
  • Vue Draggable
  • Vue transitions
  • Sass

So, I think it is a very good app example to test the Vite bundler. In case anyone want to try it, you can do it in this branch Feat: Update to Vue 3 by diavrank · Pull Request #5 · diavrank/theory-swe · GitHub . I am waiting for Vuetify 3.1 to include the v-data-table (since I had to change that component for v-table by the moment) and then I will merge it.

1 Like

I updated to Meteor 2.8 and now I got this error:

Uncaught SyntaxError: Unexpected token 'default' (at accounts-base:17:14)

Screen Shot 2022-11-16 at 19.02.24

I was debugging with a simpler app (the one which comes as example from the repo) and it seems that error happen when I import Accounts package in a vue component, as shown:

import { Accounts } from 'meteor/accounts-base';

However, I can still use the package in the client side (since it is a global variable) but it provokes this typescript error:
image

This is necessary to use functions from the client side such as:

  • verifyEmail
  • resetPassword
  • forgotPassword
  • changePassword

I could fix the previous issue with a temporary solution by removing the import statements of Accounts but now, I am getting a new issue, which is:

browser (page is in blank)

Profile.ts
Screen Shot 2022-11-16 at 19.48.40

Profile.ts is the file which contains the Profile collection to do find queries in the client side, like:

return ProfileCollection.find({}).fetch();

I am using Astronomy as ODM for my data layer, and it seems that Vite is complaining as well. In this case, I cannot remove that import statement because it is needed to create the profile collection as shown:

export const Profile = Class.create<ProfileType>({
	name: 'Profile',
	collection: ProfileCollection,
	fields: {
		name: String,
		description: String,
		permissions: [String]
	},
	indexes: {
		name: {
			fields: { name: 1 },
			options: { unique: true }
		}
	},
	helpers: {
		getPermissions() {
			return Meteor.roles.find({ _id: { $in: this.permissions } });
		},
		getPermissionsComplement() {
			return Meteor.roles.find({ _id: { $not: { $in: this.permissions } } });
		}
	},
	events: {
		afterUpdate(event: any) {
			if (event.oldDoc.name !== event.doc.name) {
				Meteor.users.update({ 'profile.profile': event.oldDoc.name }, {
					$set: {
						'profile.profile': event.doc.name
					}
				}, { multi: true });
			}
			const users = Meteor.users.find({ 'profile.profile': event.doc.name }, { fields: { _id: 1 } }).fetch();
			const userIds = users.map(user => user._id);
			// @ts-ignore
			Meteor.roleAssignment.remove({ 'user._id': { $in: userIds } });
			Roles.setUserRoles(userIds, event.currentTarget.permissions, event.currentTarget.name);
		}
	}
});

Any suggestion to solve it @akryum ?

I could solve the other issue by separating the model and the collection in different files, as shown:

ProfileCollection.ts

import { Mongo } from 'meteor/mongo';
import { RoleType } from '/imports/api/Permissions/Permission';

export interface ProfileType {
	_id: string;
	name: string;
	description: string;
	permissions: string[];

	getPermissions(): Mongo.Cursor<MeteorAstronomy.Model<RoleType>>;
	getPermissionsComplement(): Mongo.Cursor<MeteorAstronomy.Model<RoleType>>;
}

export const ProfileCollection = new Mongo.Collection<ProfileType>('profiles');

Profile.ts

import { AstronomyEvent, Class } from 'meteor/jagi:astronomy';
import { ProfileCollection, ProfileType } from '/imports/api/Profiles/ProfileCollection';

export const Profile = Class.create<ProfileType>({
	name: 'Profile',
	collection: ProfileCollection,
	fields: {
		name: String,
		description: String,
		permissions: [String]
	},
	indexes: {
		name: {
			fields: { name: 1 },
			options: { unique: true }
		}
	},
	helpers: {
		getPermissions() {
			return Meteor.roles.find({ _id: { $in: this.permissions } });
		},
		getPermissionsComplement() {
			return Meteor.roles.find({ _id: { $not: { $in: this.permissions } } });
		}
	},
	events: {
		afterUpdate(event: AstronomyEvent<ProfileType>) {
			if (event.oldDoc.name !== event.doc.name) {
				Meteor.users.update({ 'profile.profile': event.oldDoc.name }, {
					$set: {
						'profile.profile': event.doc.name
					}
				}, { multi: true });
			}
			const users = Meteor.users.find({ 'profile.profile': event.doc.name }, { fields: { _id: 1 } }).fetch();
			const userIds = users.map(user => user._id);
			// @ts-ignore
			Meteor.roleAssignment.remove({ 'user._id': { $in: userIds } });
			Roles.setUserRoles(userIds, event.currentTarget.permissions, event.currentTarget.name);
		}
	}
});

So, in this way, I can use the ProfileCollection in the client side to do find queries (when a subscription is made), while I have the model only available in the server side. I think that could help in the security scope (to avoid exposing the collection structure to the client side), but I’d like to know if that was the purpose by Vite? or should it support it? cc: @akryum

By the moment, I could already visualize something in my app :star_struck:

Maybe, it is just missing to fix some things for the migration to Vue 3.

2 Likes

My app is practically migrated and working correctly :heart_eyes: ! It is just missing to fix some minor parts of design (due to the migration to Vuetify 3). I have just one question related to my unit tests. When I run meteor test, it is throwing this error:

W20221120-07:00:13.029(0)? (STDERR) internal/process/esm_loader.js:74
W20221120-07:00:13.051(0)? (STDERR)     internalBinding('errors').triggerUncaughtException(
W20221120-07:00:13.052(0)? (STDERR)                               ^
W20221120-07:00:13.053(0)? (STDERR) 
W20221120-07:00:13.054(0)? (STDERR) Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite' imported from /tmp/meteor-test-run3218uq.h76io/.meteor/local/build/programs/server/assets/packages/vite_bundler/worker-dev.mjs
W20221120-07:00:13.055(0)? (STDERR)     at new NodeError (internal/errors.js:322:7)
W20221120-07:00:13.055(0)? (STDERR)     at packageResolve (internal/modules/esm/resolve.js:732:9)
W20221120-07:00:13.056(0)? (STDERR)     at moduleResolve (internal/modules/esm/resolve.js:773:18)
W20221120-07:00:13.056(0)? (STDERR)     at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:887:11)
W20221120-07:00:13.057(0)? (STDERR)     at Loader.resolve (internal/modules/esm/loader.js:89:40)
W20221120-07:00:13.058(0)? (STDERR)     at Loader.getModuleJob (internal/modules/esm/loader.js:242:28)
W20221120-07:00:13.058(0)? (STDERR)     at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:76:40)
W20221120-07:00:13.059(0)? (STDERR)     at link (internal/modules/esm/module_job.js:75:36) {
W20221120-07:00:13.060(0)? (STDERR)   code: 'ERR_MODULE_NOT_FOUND'
W20221120-07:00:13.060(0)? (STDERR) }

However, they are passing as shown:

My tests are only for the server, so, maybe vite shouldn’t run. Or is there a way to skip vite in the meteor test command? @akryum

On the other hand, I will be deploying my app and giving feedback about it.

3 Likes

Hi, I got this error in the build of my app with a docker image:

More info here: Error with Vite bundler for Meteor + Vue 3 app · Issue #129 · disney/meteor-base · GitHub

Has anyone faced the same problem?

I could deploy my app by doing the build in my computer and then, upload the bundle to the VM to use it in a custom docker image to run the app:

bundle.dockerfile

FROM node:14.20.1

COPY theory-swe.tar.gz /opt/
WORKDIR /opt
RUN tar -xzf theory-swe.tar.gz && cd bundle/programs/server && npm install && npm run install
WORKDIR /opt/bundle

ENV PORT 3000

EXPOSE 3000

RUN echo 'Starting app...'

CMD ["node", "main.js"]

So, now everything is working well in production.

2 Likes

What did you do to solve the issue with the error The requested module...?

I separated the model and the collection in different files, leaving the collection in the client side and the model in the server side. Here is the solution.

I faced many issues @diavrank95 mentioned but finally managed to deploy my Svelte application. I shared my experience in another thread.

1 Like

Your fix in the Vite build file worked for my Vue app as well. Thanks so much!

1 Like