I’m having trouble understanding how server-only imports work in client-server mixed code. I’m getting an error in one of my files which is based on this example. A ValidatedMethod executes some server-side code in a client-server file, splitting it using isSimulation.
What I don’t understand is, in that same file the server-side code should be imported somewhere like this:
import MMR from 'xxx /server/MMR.js';
Which, when you start your app should throw an error like this on the client (server is obviously fine):
// In a file loaded on client and server
const Meteor.users.methods.updateMMR = new ValidatedMethod({
name: 'Meteor.users.methods.updateMMR',
validate: null,
run() {
if (this.isSimulation) {
// Simulation code for the client (optional)
} else {
import myServerOnlyCode from './server/api.js';
myServerOnlyCode();
}
}
});
Yes, actually myMethod.call();, I didn’t include it in the sample to simplify it, but the error still triggers in my real code, where methods are called correctly.
For the ‘secret’ methods I didn’t use meteor validated methods and imports, instead I used a global server object and attached JS functions to it and then only call this object form within a server block.
I also had no issues importing and using validated methods in a shared file (client and server) but all the methods has a the Meteor.isServer check for server side only code.
I had a different use case where I was trying to import npm stripe package in the test environment and the IDE (webstorm) was complaining the I can’t use import in the middle of the file, which I worked around by using require and disable the eslint
// Using require instead of import to prevent IDE
// inspection error on statement expected. Also loading
// stripe.js only on the server since
// it contains global server methods used by stripe methods being tested here.
// If the isServer check is removed,
// Meteor will attempt to load stripe.js at the client but it will not be able to find it
if (Meteor.isServer) {
require('/imports/api/membership/server/stripe.js');
then I disabled the eslint global with /* eslint-disable global-require*/
But I’ve never encountered the"myMethod" is read-only error.I hope that helps.
Hey @florianbienefelt not sure if understand correctly what you are trying to achieve. But in case you want to define a method that contains some code that is only supposed to run server side, I would do as follows:
1- I define my method in some common folder available for both client and server:
// In a file loaded on client and server
const MyMethod = new ValidatedMethod({
name: 'MyMethod',
validate: null,
run() {
if (this.isSimulation) {
// Simulation code for the client (optional)
} else {
import myServerOnlyCode from './server/api.js';
myServerOnlyCode();
}
}
});
export { MyMethod };
Later on, whenever I want to use my method, I have 2 options
Old approach:
import { Meteor } from 'meteor/meteor';
// bla bla
Meteor.call('MyMethod', someParams, (err) => {
if (err) {
// handle error
}
})
My last question was about how to do this in a DRY way. I was wondering if there was a way to use ES6 import statements in a function and return those later. I ended up using require to do it, which works well!