Dynamically loadable plugin?

Hello,

I have already wrote a small Meteor application, which offers both desktop and mobile experience (https://ronin.trychlos.org). This was rather for me a sort of POC for my ability to use the framework.

As I’m looking for a second application, I would need it to be dynamically extensible, both on client and server sides. The only other thread I’ve found on this topic is rather old (Plugin system for a Meteor App, dynamic module loading) and not really been answered.

In 2022 today, does Meteor team or someone here has an idea if this is possible and how ?
Thanks in advance for your help.

Regards
Barbap’s

Hey maybe this can be of help: Plugin architecture with Meteor - DEV Community

1 Like

Hi,

Thanks a lot for the pointer : I didn’t found this article and it is interesting:

  • pros: the async registering through a dynamic import
  • cons: the meteor create --package my-plugin : imho, the principle of a dynamic plugin is to not be created into the application tree. The application is expected to be bundled without any plugins, and the plugins be dropped in at runtime only…

So I have imagined to dynamically load something dropped in a “assets/plugins” subtree.
At the moment, I am stucked on the dynamic import which resolves on MODULENOTFOUND error, though the path displayed in the stack trace is correct :frowning:

According to Meteor documentation (and boot.js), import() resolves to a Npm.requires. Debug work goes on… :wink:

Here is the code :

   // dynamically import defined files from the plugins root tree
    importFiles( path ){
        this.json.files.forEach(( f ) => {
            const fname = path+'/'+this.name+'/'+f;
            import( fname )
                .then(( ret ) => {
                    console.log( fname, ret );
                })
                .catch( reason => console.error( reason ));
        });
    }

where fname resolves to:

assets/app/plugins/my-sample-plugin/myfirst.js

and the stack trace is

W20220124-09:49:34.134(1)? (STDERR) Error: Cannot find module 'assets/app/plugins/my-sample-plugin/myfirst.js'
W20220124-09:49:34.134(1)? (STDERR) Require stack:
W20220124-09:49:34.134(1)? (STDERR) - /home/pierre/data/eclipse/adomo-ng/.meteor/local/build/programs/server/boot.js
W20220124-09:49:34.135(1)? (STDERR) - /home/pierre/data/eclipse/adomo-ng/.meteor/local/build/main.js
W20220124-09:49:34.135(1)? (STDERR)     at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)
W20220124-09:49:34.135(1)? (STDERR)     at Function.resolve (internal/modules/cjs/helpers.js:99:19)
W20220124-09:49:34.135(1)? (STDERR)     at Object.require (/home/pierre/data/eclipse/adomo-ng/.meteor/local/build/programs/server/boot.js:286:34)
W20220124-09:49:34.135(1)? (STDERR)     at makeInstallerOptions.fallback (packages/modules-runtime.js:618:18)
W20220124-09:49:34.135(1)? (STDERR)     at Module.require (packages/modules-runtime.js:244:14)
W20220124-09:49:34.136(1)? (STDERR)     at Module.moduleLink [as link] (/home/pierre/data/.meteor/packages/modules/.0.18.0.3d5dgm.d3v5r++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/@meteorjs/reify/lib/runtime/index.js:52:22)
W20220124-09:49:34.136(1)? (STDERR)     at getNamespace (packages/dynamic-import.js:630:10)
W20220124-09:49:34.136(1)? (STDERR)     at packages/dynamic-import.js:465:12
W20220124-09:49:34.136(1)? (STDERR)     at /home/pierre/data/.meteor/packages/promise/.0.12.0.1xgsb7g.to06++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/fiber_pool.js:43:40 {
W20220124-09:49:34.136(1)? (STDERR)   code: 'MODULE_NOT_FOUND',
W20220124-09:49:34.136(1)? (STDERR)   requireStack: [
W20220124-09:49:34.137(1)? (STDERR)     '/home/pierre/data/eclipse/adomo-ng/.meteor/local/build/programs/server/boot.js',
W20220124-09:49:34.139(1)? (STDERR)     '/home/pierre/data/eclipse/adomo-ng/.meteor/local/build/main.js'
W20220124-09:49:34.139(1)? (STDERR)   ]
W20220124-09:49:34.140(1)? (STDERR) }

The behavior is the same if I try to dynamically import just the basename of the file (here ‘myfirst.js’)…

That would imply to eval insecure code. The dynamic import in Meteor uses hashes to verify source integrity with those at build time in order to ensure, that we eval code that is not tampered or otherwise insecure.

Otherwise, if you really want to enable to download any plugin from external public source you need to override dynamic import with your own mechanism, which basically breaks down to

  • fetch js resource using fetch or class XmlHttpRequest
  • validate resource (which you have then to conceptualize and find a way that is secure)
  • eval resource to integrate into your app env
  • provide a common api for this resource to communicate with your app packages

You’re right : using dynamic plugins provided by external sources from other developers is insecure by nature. But imho only a bit less secure than ‘meteor add <any_package_here>’ when downloading from atmospherejs.com :wink:

Nonetheless, I just find dynamic-import | Meteor API Docs, from what I understand that my goal of dynamic plugins is just not possible regarding Meteor build strategy :frowning:

So, yes, I’ll try via eval()… Thanks another time for your time :slight_smile:

Regards