I git cloned an atmosphere Meteor package to make it lazy loading for dynamic import. Following what I believe are the instructions, I added api.mainModule('client/main.js', 'client', {lazy:true});
to the package.json of the module.
However, any attempt to import 'meteor/module-name'
results in
Uncaught (in promise) Error: Cannot find module 'meteor/module-name'
Has anybody run into this or knows the solution (using METEOR@1.6.1.3)
Hmmm, this should work. Let me try in a fresh repo
Could it be that you haven’t added the package to .meteor/packages
?
I tried it on a fresh repo and it worked both with static and dynamic imports:
Setup
meteor create meteor-forum-44390 --release=1.6.1.3
cd meteor-forum-44390
meteor create --package test
meteor add test
meteor
Steps taken
- Edited packages/test/package.js
- Checked that module had not loaded in client
- Edited client/main.js to match “static import”
- Checked that module had loaded on start, and behaved correctly
- Edited client/main.js to match “dynamic import”
- Checked that module had not loaded on start
- Checked that module correctly loaded after four button clicks and behaved correctly after five
static import
import { Template } from "meteor/templating";
import { ReactiveVar } from "meteor/reactive-var";
import "./main.html";
Template.hello.onCreated(function helloOnCreated() {
// counter starts at 0
this.counter = new ReactiveVar(0);
});
Template.hello.helpers({
counter() {
return Template.instance().counter.get();
},
gt(one, two) {
return one > two;
},
importTest() {
import { name } from "meteor/test";
return name;
},
});
Template.hello.events({
"click button"(event, instance) {
// increment the counter when button is clicked
instance.counter.set(instance.counter.get() + 1);
},
});
dynamic import
import { Template } from "meteor/templating";
import { ReactiveVar } from "meteor/reactive-var";
import "./main.html";
Template.hello.onCreated(function helloOnCreated() {
// counter starts at 0
this.counter = new ReactiveVar(0);
this.autorun(async () => {
if (this.counter.get() > 3) {
const { name } = await import("meteor/test");
this.name = name;
}
});
});
Template.hello.helpers({
counter() {
return Template.instance().counter.get();
},
gt(one, two) {
return one > two;
},
importTest() {
const inst = Template.instance();
return inst.name;
},
});
Template.hello.events({
"click button"(event, instance) {
// increment the counter when button is clicked
instance.counter.set(instance.counter.get() + 1);
},
});
package.js
Package.describe({
name: "test",
version: "0.0.1",
// Brief, one-line summary of the package.
summary: "",
// URL to the Git repository containing the source code for this package.
git: "",
// By default, Meteor will default to using README.md for documentation.
// To avoid submitting documentation, set this field to null.
documentation: "README.md",
});
Package.onUse(function(api) {
api.versionsFrom("1.6.1.3");
api.use("ecmascript");
api.mainModule("test.js", "client", { lazy: true });
});
Package.onTest(function(api) {
api.use("ecmascript");
api.use("tinytest");
api.use("test");
api.mainModule("test-tests.js");
});
EDIT: Added package.js
code
EDIT: Added setup and steps taken
1 Like
Definitely, package was already added to .meteor/packages. I just changed the package.json to not export anything and define api.mainModule(‘client/main.js’, ‘client’, {lazy:true});
can you post the package.js
?
I tried to make accounts-admin-ui-bootstrap-3 load lazy
Package.describe({
name: "accounts-admin-ui-bootstrap-3",
summary: "A roles based account management system using bootstrap 3",
version: "0.2.9",
git: "https://github.com/hharnisc/meteor-accounts-admin-ui-bootstrap-3.git"
});
//
// api.mainModule("main.js", "client", { lazy: true })
// https://docs.meteor.com/packages/modules.html#Lazy-loading-modules-from-a-package
// Note: Packages with lazy main modules cannot use api.export to export global symbols
//
Package.on_use(function (api, where) {
api.versionsFrom("METEOR@0.9.0");
api.use('reactive-var', ['client', 'server']);
api.use('standard-app-packages', ['client', 'server']);
api.use("alanning:roles@1.2.8", ['client', 'server']);
api.add_files('libs/user_query.js', ['client', 'server']);
// api.add_files('client/startup.js', 'client');
//api.add_files('client/accounts_admin.html', 'client');
//api.add_files('client/accounts_admin.js', 'client');
//api.add_files('client/delete_account_modal.html', 'client');
//api.add_files('client/delete_account_modal.js', 'client');
//api.add_files('client/info_account_modal.html', 'client');
//api.add_files('client/info_account_modal.js', 'client');
//api.add_files('client/update_account_modal.html', 'client');
//api.add_files('client/update_account_modal.js', 'client');
//api.add_files('client/update_roles_modal.html', 'client');
//api.add_files('client/update_roles_modal.js', 'client');
//api.add_files('client/filter_roles_modal.html', 'client');
//api.add_files('client/filter_roles_modal.js', 'client');
api.mainModule('client/main.js', 'client', {lazy:true});
// api.export('AccountsAdmin');
api.add_files('style/style.css', 'client');
api.add_files('server/startup.js', 'server');
api.add_files('server/publish.js', 'server');
api.add_files('server/methods.js', 'server');
});
Just created a new empty package and was able to use it with lazy, so it must have to do something with the original package.js file
First thing, I notice is that the docs say:
For packages, you can enable modules
by adding api.use('modules')
to the Package.onUse
or Package.onTest
sections of your package.js file.
And your package.js
doesn’t have that.
So I tried it on my repro and that didn’t work, but adding api.use("ecmascript")
(which implies modules
) did work!
I had to make a guess about the contents of client/main.js
so I just made one that imports all the other client files.
package client/main.js
import './startup.js';
import './accounts_admin.html';
import './accounts_admin.js';
import './delete_account_modal.html';
import './delete_account_modal.js';
import './info_account_modal.html';
import './info_account_modal.js';
import './update_account_modal.html';
import './update_account_modal.js';
import './update_roles_modal.html';
import './update_roles_modal.js';
And this worked with both static and dynamic imports. I changed my client/main.js
to log one of the blaze templates from that package before and after the dynamic import to test it:
Template.hello.onCreated(function helloOnCreated() {
// counter starts at 0
this.counter = new ReactiveVar(0);
this.autorun(async () => {
if (this.counter.get() === 4) {
console.log("Before:", Template.accountsAdmin);
await import("meteor/accounts-admin-ui-bootstrap-3");
console.log("After:", Template.accountsAdmin);
this.name = name;
}
});
});
Which logs:
main.js:12 Before: undefined
main.js:14 After: Blaze.Template {viewName: "Template.accountsAdmin", renderFunction: ƒ, __helpers: HelperMap, __eventMaps: Array(1), _callbacks: {…}, …}
So try adding api.use("ecmascript")
and see if it works for you too
1 Like
Thank you, that was definitely it.
Now I am having a problem with the import paths in the module. I created a main.js file in the root directory of the module that imports everything for the client side, like the first line is
import './client/accounts_admin.html';
but once I import the module I’m hit by
Error: Cannot find module './client/accounts_admin.html'
Any hints?