Calling Meteor server side methods from public js asset - meteor

What is the approach for doing a Meteor.call to the server from a js file within the /public folder?
I tested, but the call does not work. I am unable to get any result from Meteor.call when using it within the js filed that is served on the public...
Will I need to create a middleware api ?

Why is the JS file in the public directory? If you want the JS code to be executed on the client, then put it in the /client directory and the functions will be available to the client.
If it's in the public folder, then it is served "as-is" to the client. From the docs:
public
All files inside a top-level directory called public/ are served as-is to the client. When referencing these assets, do not include public/ in the URL, write the URL as if they were all in the top level. For example, reference public/bg.png as . This is the best place for favicon.ico, robots.txt, and similar files
UPDATE
Since now I can see you are trying to load an external JS, the correct answer is to either use NPM (with meteor 1.3+) or place them in the client/compatibility directory. From the docs (http://guide.meteor.com/structure.html):
client/compatibility
This folder is for compatibility with JavaScript libraries that rely on variables declared with var at the top level being exported as globals. Files in this directory are executed without being wrapped in a new variable scope. These files are executed before other client-side JavaScript files.
It is recommended to use npm for 3rd party JavaScript libraries and use import to control when files are loaded.

Related

What are valid page names in Next.js? And how does it distinguish between pages and static resources?

I'm new to Next.js and am trying to get my head around client side and server side routing and what files need to be made available to download when Next.js is configured to use server-side rendering.
When I do a production build of a Next.js project, a .next directory is created (details here). When I call next start and then load a page that uses SSR (by defining getServerSideProps()) then I can see in the developer console that the page that I load downloads resources that are prefixed _next (e.g. <script src="/_next/static/chunks/main-3123a443c688934f.js" defer=""></script>).
Can someone confirm whether the .next directory contents (.next/server/**, .next/static/**) are just made available on the server by being renamed to _next?
I tried creating a new page in a file called _next.js as an experiment. The project builds correctly (no errors reported and there are build artifacts created with the same naming convention as the other pages). However, when I try to load that page, I get a 404.
Are there restrictions on what constitutes a validly named page in Next.js? If so, what are they and where is this defined.
How does the Next.js server know what is a static resource that should just be given to the client and what is a page for which Next.js should render an output? Is it simply an algorithm like "if the path starts _next/ then return what is requested, otherwise render?"
How does Next.js know to distinguish between resources that are in the public directory and pages? e.g. if there's a collision between the name of a page and a resource in the public folder, how does the server know what to return to the user?

Bundle custom static files in meteor

I'd like to bundle many static files from various dirs in a meteor appplication. I have a different folders structure than the standard prescribed. I have static files in various directories and I serve them using the webapp. This works in dev on my machine where I access them directly by a path from C:\.... But when the app is bundled those files will not make it to the bundle. Is there any way how to tell meteor that it should also bundle those directories?
I try to achieve an encapsulation of modules. So each module would have its own static files and each would be a pack of all source and static files needed to run within an app. The static files need to be inside app folders. I have a Modules dir where are modules like Users and Notes and each of the modules can have its own static files which would be accessed by url and later by node fs, but they are not imported by js. That's why they'll not get into the bundle.
The files are consumed by
const realpath = path.normalize(base + filepath);
const data = fs.readFileSync(realpath);
res.writeHead(200, { "Content-Type": mime.lookup(realpath) });
res.write(data);
res.end();
Where filepath is calculated by function from url.
I explicitly don't want to use public folder or any folder of standard meteor folder structure. I have defined custom folder structure with idea of encapsulation in mind. I'm aware of api.addAssets(filenames, architecture) but that's only for packages AFAIK. But that's something as I'd need I guess. I'd expect that there would be possibility to write some script that would run while bundling and would provide information for bundler which files to include.
Thanks.
Using meteor's /private directory would prevent any public access, and allow you to bundle your application code.

Meteor "use strict" with global alias

In another SO post here, the second option is to write G.this; in the first "top" file in order to create a namespace.
And then write "use strict" on the top of every other js file.
Is that all the content of such a file? and if so, where the "top" file should be located (server, client, both) and what name? as Meteor loads files based on their paths. Thanks
One of ways to create a global namespace in Meteor (as suggested in the SO answer) is to have a file where a global alias to this is declared, such as:
G = this;
This file should, ideally, be loaded first and on both client and server.
To achieve this, according to the doc:
Files within lib/ directory are loaded first (after loading template files on client).
Meteor will load any file outside client/ or server/ directories on both client and server.
Where no other rules may apply, alphabetical ordering of the paths is used to determine load order of the files.
So, in keeping with these rules I would save the file as app.js (or any similar name that would come first alphabetically). Then I would place this file at the root of lib/ folder so that it gets loaded both on client and server.
So, the path to app.js would be : ./your_meteor_project_root/lib/app.js

Meteor method not accessing method outside of its file

My Meteor methods call generic/utility type of methods that I don't want to keep redefining in each collection file. As long as the method remains inside of the collection file, the method is accessible. Once the method is moved to a different file, this error is generated: ReferenceError: myMethod is not defined
The collection file is located in: lib/collections/posts.js
If myMethod() is located in this posts.js file, it is accessible. If I create another file such as lib/_utils.js and move myMethod() there, it won't load. I intentionally added the underscore for it to load prior to the collection files.
The post titled Ordering of the css and js files loaded by Meteor explains the order in which the files are loaded, but something is still amiss. I'm guessing this is a security issue surrounding how Meteor methods work.
Can a Meteor method make a call to a method in another .js file? If so, where should this other .js file be located?
This question is answered in post Why can't my Meteor app recognize my function?

Conditionally load internal assets in Meteor

Is there a way to prevent automatic loading of all assets in my /client folder?
I am looking at a scenario where my login page uses different css/js files than my registration or view users folders. What is the best way to do this?
The closest I have come to a solution is this but that still doesn't solve my problem.
Or the best approach is to host my files externally then user the external-file-loader with conditional statements?
I have just published modules smart package which more or less does the job for you. You can add it to your project with
mrt add modules
Then, you will need to change the extensions of all files that you want to load asynchronously to .module_js or .module_html (currentlly we do not support css). Now suppose that the structure of your directory is more or less
modules
module1
file1.module_js
file2.module_js
module2
file1.module_js
file2.module_js
client
main.js
server
public
...
Initially only main.js will be present in your application. To load additional code for the client use the asynchronous require call:
require('module1', function () {
console.log('the files contained in module1 folder are now loaded');
});

Resources