Quantcast
Channel: Meteor Blog - Medium
Viewing all 160 articles
Browse latest View live

Hot Code Push, step by step

$
0
0

This is a guest post by Bart Sturm, co-founder of TutorMundi, a Brazilian on-demand tutoring app.

Hot Code Push is one of my favorite features of Meteor.

It’s amazing to be able to push new versions of your app to all users across all devices and platforms at once.

Though as a bridge between several different technologies with many moving parts, it doesn’t always work seamlessly. When you realize it’s not working reliably in your app, what can you do?

Common issues and solutions

Let’s not reinvent the wheel — let’s start with some time-tested solutions:

How to dig deeper

But what if none of these solve your particular issue?

Then let’s start looking at your client side logs.

Of course, you may find the cause of your issue right then and there.

If not, that’s okay — we’re about to start logging a whole lot more. We’re going to follow Hot Code Push every step on the way.

(Note: I shared similar code samples in the Meteor Guide. Also, the libraries Tracker and lodash used here are helpful but not necessary. )

Step 1. Server creates new client hash

Whenever the server thinks the client side may have changed, it calculates a hash of your entire client bundle. We can log the following both on the server and client, and compare:

__meteor_runtime_config__.autoupdate.versions['web.cordova']

Step 2. The client subscribes to new hashes

The server publishes this hash to all clients. The clients subscribe to this publish.

To check the status of our subscription, we can log this in the client:

Meteor.default_connection._subscriptions

This shows lots of information about each of your subscriptions. For more readable output, I like to select the subscription I’m interested in and pick some specific properties. For example:

const { ready, inactive } = _.chain(Meteor)
.get('default_connection._subscriptions', {})
.toPairs()
.map(1)
.find({ name: 'meteor_autoupdate_clientVersions' })
.pick(['inactive', 'ready'])
.value();
console.log(‘ready:’, ready);
console.log(‘inactive:’, inactive);

We can modify this a bit to check the status of the subscription every time the subscription changes (for example, when ready goes from false to true):

const hcpSub = _.chain(Meteor)
.get('default_connection._subscriptions', {})
.toPairs()
.map(1)
.find({ name: 'meteor_autoupdate_clientVersions' })
.value(); // no .pick() this time; return whole object

Tracker.autorun(() => {
hcpSub.readyDeps.depend(); // Rerun when the subscription changes
console.log('hcpSub.ready', hcpSub.ready);
});

Step 3. A new client hash arrives

If the client receives client hashes different from its own, our Cordova app starts downloading the new version. (On web, the download only occurs after the reload; our Meteor app is simply a website after all.)

At this point the reactive Autoupdate.newClientAvailable() will start returning true:

Tracker.autorun(() => {
console.log(Autoupdate.newClientAvailable());
});

Step 4. (Cordova only): the new version was downloaded

On mobile, when the new version is downloaded, Meteor will trigger the callback passed to WebAppLocalServer.onNewVersionReady. There can only be one such callback. To log this step without breaking the next, our code can define a new callback that adds logs and then add the code from the original. At the time of writing, it looks like this:

WebAppLocalServer.onNewVersionReady(() => {
console.log('new version is ready!');
// Copied from original in autoupdate/autoupdate_cordova.js
if (Package.reload) {
Package.reload.Reload._reload();
}
});

Step 5. Ask for permission to reload

The client will now announce that it will reload. The app and packages get a chance to save their data or to deny or delay the reload. To find out if this point is reached, we can add a callback to _onMigrate:

Reload._onMigrate(() => {
console.log('going to reload now');
return [true];
});

Step 6. Reload

If every Reload._onMigrate callback grants permission, the app reloads.

As part of this, all startup callbacks are run again. To know whether a startup was the result of a Hot Code Push or simply of opening the app, we could use a Session variable, which are preserved across Hot Code Push updates:

Meteor.startup(() => {
console.log('Was HCP:', Session.get('wasHCP'));
Session.set('wasHCP', false);

Reload._onMigrate(() => {
Session.set('wasHCP', true);
return [true];
});
});

Going further

Want to know more? The new Hot Code Push article in the Meteor Guide explains this topic in more depth.

Hot Code Push is at its most powerful when you can rely on it without any doubts. I hope these articles help you solve your own Hot Code Push issues so you can speed up your development cycle and focus on serving your customers.

PS: did this article help you solve an undocumented issue? Congrats 🥳 you are in a unique position to do many developers just like you a big favor! You can add your solution to the Meteor guide or even suggest a fix to Meteor.


Hot Code Push, step by step was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.


Announcing Meteor 1.11

$
0
0

Meteor 1.11 brings Apollo skeleton, Vue.js skeleton, and many more exciting updates including build performance optimizations and cache for deploys.

We started working on Meteor 1.11 right after Meteor 1.10.2 was released. We’ve been busy — there were 22 items in this release.

During the last months we have always kept our issues up-to-date, our PRs moving forward and our roadmaps updated on both Meteor and Galaxy.

The Meteor community has been contributing a ton, as always. We strongly encourage you, Meteor developer, to become an active contributor in the community if you aren’t one already. We will always rely heavily on our community to improve Meteor. It’s what keeps us moving forward.

Check out our roadmap for ideas on what to work on, or send us a message on Forums. Everyone is also strongly encouraged to join our Community Slack. We’d love to see you there!

Let's dive into a few highlights of 1.11:

Performance Improvements

We had multiple PRs improving the performance of our build in different parts (thank you Zodern):

If you were using Meteor on Windows and your rebuilds were taking longer than expected, we’d ask you to try it again.

Depending on the app these changes can result in up to:

  • 40% less memory and 50% less CPU when idling between builds;
  • Reduction in the number of times the disk is accessed during a build, or switched to lighter weight operations;
  • On Windows, Meteor will only write modified files during a full rebuild instead of all files. This optimization was partially enabled for Windows in 1.8.1, and added for all other operating systems in Meteor 1.2;
  • Other optimizations to remove unnecessary work and better use caches.

If your app takes more than 2 seconds to do a full rebuild, please help us improve. Use the build-profiler package to take a CPU profile and share it by opening a new Github issue and providing as much information as you can. We’d appreciate it!

Cache your builds

We are also introducing a new option in our deploy command: --cache-build . Using it in your deploy command Meteor will re-use your bundle if your git repository is in the same commit as the last time you deployed. Unless you are not deploying from a git repository, you should use this option all the time.

Cache build is helpful in two situations:

  • Flaky connection: if your bundle upload is failing, sometimes you can retry without waiting the build time again — it will start the upload right away.
  • Deploy to multiple environments: you can send the same bundle to multiple targets, for example, your staging and production environment. The second environment deploy will be faster as Meteor won't build your code again and you will be sure both environments are running the same exact bundle.

TL;DR: use --cache-build when deploying to Galaxy.

Galaxy Logs view also got better recently, watch this video where Renan explains what is new and how to use it.

Apollo skeleton

GraphQL is a query language to ask for data (queries) and to perform mutations in your server. One very popular implementation of GraphQL is Apollo. It was always possible to use GraphQL and Apollo with Meteor (we have many packages integrating these technologies), but we didn't have a simple one line command to create a new app with Meteor and GraphQL.

meteor create now supports --apollo as skeleton option. If you want to start a new project with Meteor using Apollo in the data layer you only need to run: meteor create myproject --apollo and you are good to go. Thanks Storyteller!

Your project will also use React, but if you want you can replace by any other UI Framework that you like most. We choose to integrate with Apollo in the skeleton using the apollo-server-express to keep the integration as simple as possible and easy to understand for non-Meteor developers as well.

We also have packages using Meteor WebSocket as the link for Apollo. This is great combination as you can use the power of EJSON combined with GraphQL. You can also use Meteor Methods or Meteor Publications where you believe they are going to work better than GraphQL sharing the same WebSocket connection.

Vue.js skeleton

Vue is a progressive framework for building user interfaces that is growing a lot in popularity. Now we also have a simple one line command to create a new project using Meteor and Vue: meteor create myproject --vue .

It's really ideal for Vue developers who want to try out Meteor for the first time, or for Meteor developers who would like to quickly get a project up to try out Vue on the client.

Meteor already supports hot module replacement with Vue so you will check your changes quickly and iterate faster.

Fixes and updates

1.11 also includes many fixes and updates such as:

  • Node.js was updated to 12.18.3;
  • MongoDB driver was updated to 3.6.0;
  • MongoDB binary included in Meteor for development was updated to 4.2.8;
  • Cordova integration was producing errors when removing Cordova plugins that depends on CLI variables;
  • Email package was updated and now exposes hookSend that runs before emails are send.

You can update your Meteor project to 1.11 now running meteor update inside your project folder.

You can also install Meteor and start using it to create new projects. Want to publish your app? Galaxy Hosting offers 30-days free trial for up to 4gb’s of usage. You can also start using our domain .meteorapp.com so you don't need to buy a new domain to have a public version of your work!

Get started with Galaxy here!


Announcing Meteor 1.11 was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Nested Imports in Meteor

$
0
0

A unique feature to Meteor is nested imports. It is undocumented, except for several references in the changelog and a short section in the Meteor 1.4 migration guide. Possibly due to this, it seems to not be well known.

According to the specification, ECMAScript modules only allow import/export at the top level. They can not be placed within any blocks, such as in a function or if block. This means that when the main bundle or dynamic imports are loaded, all modules imported in the bundle would have to be executed right away.

After v8 downloads a js file, it goes through a process of parsing, compiling, then executing it. Other js engines are likely similar. According to the v8 blog post The cost of JavaScript in 2019, they found that Post-download, script execution time is now a dominant cost. This is especially true for mobile devices.

With require, you can delay or avoid executing a module by placing require in a function or if block. The module will be downloaded, parsed, and compiled by the web browser, but execution is delayed until the first time it is required. Meteor, Node, and many bundlers that support commonjs modules do this. However, most bundlers are not able to tree shake modules imported with require, and the ECMAScript specification does not provide a way to do this with import.

ECMAScript modules in Meteor were implemented by Ben Newman with reify. Reify compiles js files to allow using ECMAScript modules within a commonjs environment. Its implementation allows using import statements anywhere in a file. He wrote a document explaining why someone would want to nest imports, along with an ECMAScript Proposal.

Nested imports should not be confused with dynamic imports. Dynamic imports delay downloading a file until it is needed. In contrast, the files imported by nested imports will always be downloaded at the same time as the file with the nested imports. Nested imports reduce execution time, but will not make your client bundle smaller.

// This is a top-level import
// alerts.js is evaluated immediately
import { showAlert } from './alerts.js';

export function reportError() {
// This is a nested import.
// errors.js has already been downloaded, but
// will not be evaluated until the
// first time reportError is called
import sendError from './errors.js';
}

export function showHint () {
// This is a dynamic import.
// hint.js is not downloaded or evaluated until the first time
// showHint is called
import('./hint.js').then(({ showRandomHint }) => {
showRandomHint()
});
}

Since nested imports are not part of the ECMAScript specification, many js parsers do not support them by default.

  • Typescript can not parse them. Typescript files must use require instead to delay an import or make it conditional.
  • The Babel parser has an allowImportExportEverywhere option.
  • Acorn also has an allowImportExportEverywhere option.
  • The default parser in eslint, Espree, does not support nested imports. Instead, you can configure eslint to use Babel as the parser:
{
"parser": "babel-eslint",
"parserOptions": {
"allowImportExportEverywhere": true
}
}

Nested imports have successfully been used by many companies to provide a better experience on mobile for their users. At Monti APM, we halved the execution time of our app code with 3 nested imports. To help you get started with your app, I’ve created a package to identify any imports that could be worth nesting.

Originally published at https://zodern.me.


Nested Imports in Meteor was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

How Any.Run Became The Most Popular Malware Sandbox in the World with Meteor.js.

$
0
0

How Any.Run Became the Most Popular Malware Sandbox in the World using Meteor.js.

This is a guest post written by our friends at ANY.RUN (Meteor users since 2016).

What is ANY.RUN?

We are creating a service that allows our clients all over the world to analyze, detect and monitor cybersecurity threats. ANY.RUN malware analysis service, our main product, is the first interactive online malware analysis sandbox where the user controls the flow of the analysis.

Imagine: you get access to the malware laboratory with lots of different tools within a second, and most of these features are free for our community. You can use it to analyze and research the latest malware samples from all over the web as if you were to launch it on your PC, but absolutely safe!

We do our best to make our community exchange information as much as possible and get access to the new malware samples for free. We also have paid subscriptions for malware analysts that means they don’t need to worry about the privacy of their analyses at all. Paid users also get extended functionalities such as different versions of operating systems, video recording, and teamwork.

ANY.RUN has more than 2 million public tasks with tons of malware samples and IOCs (Indicators of Compromise). You can analyze network, file, module, registry activity, interact with the OS directly from the browser window, and immediately see the feedback from your actions.

Also ANY.RUN conducts signature analysis and shows you whether your submission has a malicious or suspicious activity.

Our Tech Stack

The majority of the stack is developed in JS to make our solution more productive, and also to give an opportunity for all developers in our team to help each other and contribute to it.

It’s amazing that Meteor allows us to work with JS both at the back-end and front-end. That’s a huge advantage for us!

Moreover, MongoDB has native JS support, and works great together with Meteor as it is very convenient for real-time data output to the client. We would like to mention that communication between virtual machines and Node.js is a serious miracle; that’s why it’s developed on C++ to increase its speed by using native data transfer.

Of course, it’s not the only stack we use, we deal with different databases such as Redis, Elasticsearch, and OrientDB that allow our microservices to do internal work.

Our Journey with Meteor

ANY.RUN started its beginning back in 2016. Our relatively small team chose Meteor.js because it allowed you to have server-client interactivity out-of-the-box, which is exactly what we were looking for. We’ve had no regrets about the choice.

Interestingly, our development started with Blaze on a client side, as it’s handy for developing quick prototypes. As soon as our team grew, we switched to Vue.js. This jump was easy, as there is a 99% chance that Meteor can be used with any front-end library of your choice.

Since 2019, we are very proud to say so, ANY.RUN has become the most popular malware sandbox in the world. And still, our only development team is not that big: it absolutely fits Amazon’s Jeff Bezos’ rule that a team shouldn’t be larger than what two pizzas can feed.

Scaling Meteor for Highload

Scaling Meteor is very easy and exciting! When we decided to release our app to production, there was no particular guide on how to scale Meteor, so we had to find the way on our own.

Over time we came to a solution with a few Meteor instances run by pm2 routed and load-balanced with nginx.

Of course, as with any solution, there can be challenges at the point of scaling. We would like to share our experience with you:

One day we faced one serious issue with mongo oplog. It turned out that the CPU went to 100%, and we were working to the bone to find out the reason for it. First, our team decided to perform profiling, but it did not give much of a result, so then we decided to ask on the Meteor forum.

Happily, Meteor has a great community around it, and we have found a cult-of-coders redis-oplog package. After we integrated it with our service and node.js back-end, CPU went down to its 10–20%, and it hasn’t risen higher since then, knock on wood…

What’s Next?

ANY.RUN is a very fast-growing community of developers and malware researchers. Next year, we are going to release tons of awesome features and new services such as Threat Intelligence service.

We will extend our community version so there is a place where people can chat with each other and discuss the latest pieces of malware. So, stay tuned! Our small company has grown, and our goal is to beat the market with the best and most useful solution for malware analysts.

Our staff is rapidly growing too, and thus we can develop more complex and advanced features and services. We will raise the bar and go deeper into research and statistics to provide our customers with new huge amounts of data and features they need together with an amazing UI for the best user experience.

We hope you will hear a lot from us very soon!

Business Glance at Meteor

Meteor is not great just for production, but it is also good for prototyping purposes, to scale the idea of any solution. You can start with one person who will be responsible for everything and gradually divide it into the front-end, back-end, etc.

Moreover, prototype MVP can be done much faster on Meteor if you compare it with other frameworks (where you have to write front-end and back-end parts separately).

Think about your business logic, and don’t waste your time on things that every app has (like registration/authorization for example). Just use the ready package! Atmosphere.js has lots of them for Meteor.

Meteor packages make it easy to manage your team and focus on what really matters.

Challenges

We like the fact that Meteor is written in JS and, most importantly, is open-source. This helps when we face challenges, some parts don’t work properly and we’re confused about what to do — we can always look directly at Meteor’s source code and get how it all works quickly, or add functionality by ourselves. Nevertheless, we eventually get almost everything we have ever thought or dreamt of in Meteor.

There are some fundamental issues that we have to solve by ourselves. For example, websocket. The lack of websocket protection and connection between the front-end and a back-end that allows crawlers to automatically download all the data directly from the websocket without visiting the front-end part.*

It would be nice to have some sort of protection against that because the DDP limiter is not that safe when the bad guys have millions of IP addresses to use in such an attack.* (quick note here from the Meteor Team: we do have this, it comes prebuilt through our new “App Protection” feature on Galaxy Hosting).

Finally, we are in a happy, long-lasting relationship with Meteor. We have been using it for 4 years and are very satisfied with it.

We encourage the developer community to give it a try and find out how it will fit your business!


How Any.Run Became The Most Popular Malware Sandbox in the World with Meteor.js. was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Meteor Impact 2020 is this week!

$
0
0

The time has finally come! After weeks of hasty preparations we have reached the finish line and Meteor Impact starts in few days.

In total there are 33 talks/meetings planned for Thursday and Friday. These are all spread out so that people across all the timezones can take part.

There are 3 keynotes:

These three are just the top of the iceberg! You will find many more talks from members of the Meteor community and famous Meteor contributors. Talks range from basic topics like securing Meteor application, PWA setup to performance monitoring and user authentication across multiple servers.

Beside technical talks there are talks about other topics that affect Meteor community like Meteor marketing or introduction for new community members to get themselves oriented in the community space.

You also get to enjoy guest panels about hot topics in the Meteor community:

Another category we have are showcases where you’ll get to learn about companies growing with Meteor, tools for debugging, interesting packages or tools for debugging and monitoring if you are hosting outside of Galaxy.

Finally there are meetings where you can virtually hang out with other Meteor developers, talk about Meteor or whatever else comes to your mind, just like you would at a real conference. Some of these are more thematically set than others.

With the exception of meetings you can already submit questions to any of the talks and few of the talks already have polls for the audience that you can answer.

And we are getting just started! Beyond the agenda you can browse exhibitors that show some companies/projects that use Meteor or helped with the conference.

October is Hacktoberfest and Meteor and Meteor Community Packages are both setup to be part of it. So your submissions count towards it.

Till Sunday the conference site will remain open for you to setup private meetings with other attendees and speakers that you meet during the conference.

And all of that for free! But we would like to encourage you to consider sponsoring community developers and organizers.

If you have any question on how to use the platform take a look at the first meeting which holds many resources to help you get started.

Please share the news with other Meteor developers and interested friends!

Thank you and see you at the conference!

Originally published at https://dev.to on October 19, 2020.


Meteor Impact 2020 is this week! was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Meteor Fibers meet Promises meet Callbacks — A practical guide

$
0
0

Meteor Fibers meet Promises meet Callbacks — A practical guide

We’ve all been there before. You have a native asynchronous JavaScript function you need to use in your Meteor code, or maybe a Meteor function you’d like to invoke in your Meteor-agnostic code. After considerable time, you end up banging your head on the wall after realizing it won’t be as trivial as it first sounded.

Meteor uses these guys called Fibers under the hood to enable asynchronous execution. Fibers come from the time before JavaScript supported native Promises or async-await keywords. Their goal was to enable developers to write asynchronous code that looks synchronous, without a callback and Promise hell. Given their origin, Fibers aren’t too fond of native ES6 Promises. For some use cases, the Meteor framework provides useful utility functions for conversion between Fiber and non-Fiber functions, such as Meteor.wrapAsync or Meteor.bindEnvironment. However, these operate with callback-style asynchronous functions and don’t play too well with ES6 style async-await paradigm.

At Apify, we’ve been fans of Meteor since 2015 when we built our web scraping and automation platform on top of it. Over the years, we’ve encountered exactly these challenges. In this post, we’d like to share how you can deal with these kinds of conversions easily and effectively. Let’s befriend Fibers and Promises once for all!

Example functions

In the following examples, we’ll consider the three functions that all correspond to the same underlying business logic.

fnPromise
ES6 style asynchronous function which returns a promise.

fnCallback
Asynchronous function that accepts a callback as an argument. Note we assume that callback itself accepts 2 arguments, error (or null if no error) and value.

fnFiber
Meteor async function which can be run synchronously (from a developer perspective) in Meteor code thanks to Fiber.

There are six possible directions you can perform conversions between these three functions.

Possible pairwise conversions between Callback, Promise and Fiber style functions

Conversions

In this section, we show how to perform these six conversions.

Converting Promise to Callback function

In general, it is not recommended to convert an async Promise function to a Callback one in order to avoid callback hell. But if you really need to, you can do it as follows.

Converting Callback to Promise function

For the opposite direction, one can use native util.promisify() in Node.

Converting Callback to Fiber function

The conversion from Callback to Meteor Fiber function is also quite straightforward. Use Meteor.wrapAsync() as follows:

Converting Fiber to Callback function

For the opposite direction, you can use Meteor.bindEnvironment() as follows:

Converting Fiber to Promise function

Quite likely, you are using ES6 promises in your application and you’re most interested in the final two conversions between Promise and Meteor functions. In order to convert from Meteor to a Promise function, you can use Meteor.bindEnvironment() together with creating a new Promise.

Converting Promise to Fiber

For the other direction, you can use this utility to do the trick.

Then, you can use the utility as follows.

Conclusion

For those of you who like pictures like me, the conversions look schematically as follows.

How to perform conversions between Promise, Callback, and Fiber style functions

And finally, for the geeks out there, we close with an example on how to convert Fiber function to itself by first converting it to Callback function, then to Promise function, and finally back to Fiber function again.

Warning: don’t try this at home :P.

So at the end of the day, Promises and Fibers can indeed live side by side, happily ever after!


Meteor Fibers meet Promises meet Callbacks — A practical guide was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Meteor 1.12 is here!

$
0
0

We have some exciting news for you on Meteor 1.12, and the major one is Typescript 4.1.2 with Decorators and Metadata Reflection.

Thanks to everyone that worked on this release, the Meteor community is absolutely awesome! We encourage you to join us and contribute.

Check out our roadmap for ideas on what to work on, or send us a message on Forums. Everyone is also strongly encouraged to join our Community Slack. We’d love to see you there!

Let’s dive in:

Typescript is now on 4.1.2 and it brings Decorators and Metadata reflection support out of the box with the new meteor-babel version. You can now use @decorators like the following example:

class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
} @enumerable(false)
greet() {
return "Hello, " + this.greeting;
}
}

You can create decorators based on reflection, or simply use the power of reflection inside Typescript with zero configurations. It surely does bring us memory on the power of Java here, without the hassle.

Please make sure you are aware of the implications here when updating your Typescript project, breaking changes are introduced on its version changes.

It’s easy to start building with Meteor in Typescript, just run:

meteor create --typescript your_awesome_project

And voilá!

We also have updates on several packages, with bug fixes and improvements,

facebook-oauth@1.7.3 — Is now using Facebook GraphAPI v8
browser-content-policy@1.1.1 — Adds support for nonce
dynamic-import@0.5.4 — Fixes prefetch errors
meteor-tool@1.12 — supports Cordova add plugin command working again with plugin id or plugin name in the git URL as it was before Meteor 1.11
minimongo@1.6.1 — fixes a null reference exception, if an array contains null values while compiling a fields projection.

and several more, please check the full changelog here.

You can update your Meteor project to 1.11 now running meteor update inside your project folder.

You can also install Meteor and start using it to create new projects. Want to publish your app? Galaxy Hosting offers a 30-days free trial for up to 4gb’s of usage. You can also start using our domain .meteorapp.com so you don’t need to buy a new domain to have a public version of your work!

Get started with Galaxy here!


Meteor 1.12 is here! was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Introducing Meteor Cloud

$
0
0

The only full-service cloud offering built specifically for Meteor apps

After months of hard work and feedback from customers and the incredible Meteor community, our team is excited to Introduce Meteor Cloud — the only full-service cloud offering built specifically for your Meteor app.

This is an exciting update for us, so let’s jump right into things. The release of Meteor Cloud is the evolution of our existing commercial offering. Put simply, we are unifying the product offering for Galaxy Hosting, APM, and Atmosphere into one home: Meteor Cloud. At the same time, we are adding some key features that have been requested for many years. We couldn’t be more thrilled.

Why Meteor Cloud?

Our team is constantly working to improve the Meteor experience, which led us to these changes. To understand how we got to Meteor Cloud, we have to go back to the current functionality.

Meteor Developer Accounts have always been separate from Galaxy Hosting. Users would create their Meteor Developer Accounts and host separately through Galaxy, not having a simple or cohesive dashboard for seeing what’s being used across applications. It worked, but we knew it could be better.

What’s included in Meteor Cloud

By unifying Galaxy Hosting, APM, and Atmosphere together, we’re building a space that encompasses everything you will need when building and hosting your Meteor applications. Everything is now accessed through one login portal. We’ve also aimed to create a user experience for all levels of developers. Whether you’re a new developer or a seasoned pro, Meteor Cloud is optimized for every skillset.

The biggest visual changes you’ll notice will be after login into your account. After you log in, you’ll now be brought to your Meteor Cloud dashboard, which is essentially a launchpad for Galaxy Hosting, APM, and Atmosphere. Since we’re simplifying the overall experience, we wanted to simplify the dashboard design and make everything flow cohesively together. Check it out below.

New Meteoor Cloud Dashboard

What does this mean for you?

If you’re already a customer of Galaxy Hosting and have an app deployed, nothing changes! You will log in with your existing Meteor credentials and have all of the same features and functionality available to you, along with the new design upgrades and easier navigation across Regions, Organizations and Apps in the Meteor Cloud navigation:

New Meteor Cloud Nav Bar

The 3 Components of Meteor Cloud

Galaxy Hosting

Galaxy is the only hosting platform designed specifically for Meteor applications. Once you build your application, you can seamlessly deploy and host your Meteor app with Galaxy. Galaxy is the preferred hosting product for Meteor applications of every size, from hobby projects up to Fortune 500 companies. Galaxy continues to be the most efficient way for you to host and scale your Meteor application because it removes the need for expensive DevOps work. More than 2,000 companies rely on Galaxy to host their Meteor application.

APM

APM brings sophisticated application performance monitoring to Meteor applications. With APM conveniently located in your dashboard, you’ll have a window directly into your app’s performance. You’ll be able to see real-time metrics so you can monitor how your application is running and make any necessary fixes.

Atmosphere

Atmosphere is the central home of all open-source Meteor packages. Within Cloud, Atmosphere brings together the library of open source packages that make building a Meteor app more efficient and powerful. Each package is free for you to install and use in your Meteor app.

Additional Improvements in Cloud

The return of the Free Plan

One of the features we’re most eager to announce is the return of the free plan. This is something that was deprecated a few years back, but we’ve been itching to bring it back. This means that every Meteor Cloud account that is created will be free by default, with access to Atmosphere and a small (perfect for testing and hobby projects) Galaxy Hosting plan to make it easier to deploy a Meteor app. This is available today with Meteor 2.0 (stay tuned for a full announcement next week).

MongoDB Hosting

Meteor Cloud now also comes with a free shared MongoDB instance. Support for MongoDB out of the box has been requested by the community for quite some time and will make setting up a database for your application much simpler. This is a shared MongoDB instance across all applications in the same region, so we recommend swapping in your own MongoDB instance when you move to production, but this is a great solution for getting started quickly. MongoDB Hosting is available with Meteor 2.0.

GitHub Sign Up and Sign In

We’ve also added GitHub authentication button to the sign-up/sign-in flow. This will allow for simpler creation of Meteor Cloud accounts, quicker sign-ins and a better developer experience. This is our recommended account creation option (you can give it a try here).

Plan Updates

We’ve also updated our plan structure to be a bit simpler and easier to understand. You’ll see each plan of Meteor Cloud broken out on our pricing page. These plans range from Free all the way up to Enterprise and are built to support your needs as your application grows.

New plan options include Enterprise and Free

We’re thrilled to have such an incredible community around us, and we’re excited for you to check out Meteor Cloud and all it has to offer. If you have any questions or feedback, please do share in the Meteor Forum or reach out to us.

If you’re ready to dig in, click here to log into your account or sign up here.

Now, let’s get building!


Introducing Meteor Cloud was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.


Meteor 2.0 is here!

$
0
0

There’s a lot of really exciting and long-anticipated updates in our 2.0 release, so let’s dive right into them.

It's no secret that free deploys were great in the early days of Meteor. The community has been asking to have it as a nice way to expose the great work they are doing.

Meteor 2.0 is a milestone release as it brings back Meteor Free deploy, powered by Meteor Cloud which includes MongoDB as well.

Free deploy

What does this mean for our community?

You can now deploy any Meteor app for free with a simple command. Yes, it’s as simple as that, just with one command and no configuration required:

meteor deploy myapp.meteorapp.com --free --mongo

If you run the above command on any Meteor app and it’ll be live in minutes with your MongoDB database. If you don't have an app ready to be deployed, you can create a new one by running:

meteor create my-free-deploy-app

This is possible as Galaxy, the hosting offer inside Meteor cloud, is going to set up MongoDB for you, include its URI in your settings and then deploy your app in the desired meteorapp.com sub-domain.

So if you are building a Meteor app, your app should be always available for your peers or friends to check your progress. And the best, you are not going to spend any money.

Meteor 2.0 is a great improvement on your path to production that allows you for free to test your app in a cloud environment from day one. Without adding any costs to you.

Hot Module Replacement

Meteor 2.0 is not just about the addition of free deployment, we have also introduced the first version of Hot Module Replacement that will serve as a base for a much quicker feedback loop in development. React is the first framework to take advantage of Hot Module Replacement support in Meteor. We use React Refresh to provide the best experience possible.

Imagine a regular day, where you need to update your UI components probably more than 50 times. If your app takes 3 seconds to refresh you can spend a few minutes everyday just waiting. This is not the case anymore as with HMR support, your app is going to refresh immediately. What’s even better is React Refresh also keeps the state of your UI intact.

So if you need a few clicks and keystrokes to get to the desired state in your app, HMR will keep your app in this state while you are making changes to your code.

Also, Hot Module Replacement is not only available for React. A new package will bring the support for Blaze soon (check this PR to test it today).

We are not leaving anyone behind. This is very important for us and also for companies that are making money with Meteor in production.

Migration steps

As always you can migrate to the next version of Meteor by running:

meteor update

We don't have any breaking change in this release. It's a major version as we are delivering a lot of great features, and this release is just the first of many coming within 2.x.

Is it not great to have a great new feature without breaking changes? That was and always will be the idea with Meteor.

We love to avoid breaking changes, as we have more than 2,000 companies using Cloud/Galaxy who are running real businesses with Meteor. We value our clients a lot and we don’t want to break anything by requiring major rewrites, even when we release major new features. Sometimes this is going to be inevitable but not at this time.

You can check out our changelog as we are starting to deprecate some old packages.

If you want to see how easy it is to update to a new Meteor version check out this video. In this clip, we explain how to make updates on Meteor React tutorial and also I updated the tutorial app to Meteor 2.0, also added hot-module-replacement and dev-error-overlay.

If you like to see more videos as a way to learn, check How to Create an App channel, where I'm creating a platform (www.howtocreateanapp.dev) from scratch with Meteor without editing my mistakes, in a series called Making Of. New videos every Monday, Wednesday, and Friday.

How to Create an App is a project to teach web development in general (from beginners to experienced) as I cover topics that I’ve learned during 14 years of web development, all of which are still useful today. Meteor is a key piece in these videos as it is the most effective way to build apps with Javascript for production.

What is coming next

Meteor 2.1, 2.2, are coming in the next weeks as we have already many PRs close to an end.

You can check a few of them here:

  • Node.js 14; PR
  • Cordova 10; PR
  • Remove deprecated code pre v1; PR
  • Tree-shaking; PR
  • Blaze HMR; PR
  • Tutorials migration (help needed, watch here or read here);

Now with Meteor cloud out and 2.0 available, you should expect even more frequent releases and features coming. Our Roadmap is the best way for you to understand where we are going next.

To continue moving forward even faster we are looking for new developers to be part of our core team and of course, if you are already contributing to Meteor you have a head start.

Do you want to be the next Meteor core member? Understand what we are looking for here and how to apply.

Looking to the future

As you can see in the Roadmap we are already thinking about what is going to be Meteor 3.0.

We expect to have new features focusing on ease app development in Meteor 3.0 and probably some in Meteor 2.x as well, the first step is to review our feature requests one more time and define new priorities.

Maybe we should also have a new way of prioritization for new features, right now this repository with issues is not good enough in our opinion, the plan is to be even more open for feedbacks and collaboration. If we make changes in this process we are going to announce in the Forums and Slack as always.

We all had a tough year in 2020, we were able to help clients during this weird time, but we are really excited about 2021 and I hope you are as well.


Meteor 2.0 is here! was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Updating Meteor Packages for HMR

$
0
0

With Meteor 2 released last month, we now have hot module replacement (HMR) in Meteor apps. With the first version, you’re not able to update modules within Meteor packages (it is on the horizon though), but our Meteor packages can affect the experience of using HMR with Meteor apps.

If you want more information about HMR, and Meteor’s implementation of it, you can look at:

A more detailed description of how HMR works is available in the Meteor docs, but the details relevant to this post are:

  1. Meteor re-runs modules when applying updates, either because the module was modified or one of its dependencies was modified. Until the old module gets garbage collected, there are multiple instances of it running within the app.
  2. Before re-running each module, Meteor calls any dispose callbacks the module had registered. These dispose callbacks take care of making sure the old instance of the module no longer affects the running app. For example, it can stop Tracker computations, remove event listeners, clear timers, etc.

Before HMR, Meteor would always reload the client if it was modified. We didn’t always need to worry about adding a way to remove event listeners or hooks, or provide a way to undo other things an app could configure with our package. If a developer changed a hook registered with our package or how it configured our package, the page would reload, and the old version would be gone. With HMR, it isn’t that simple. In case one of the modules that are re-run uses our package, we should make sure our packages provide the necessary api’s so the module can be disposed properly.

For an example, we will work with an imagined package named extensive-error-reporting. This package hooks into various parts of Meteor to give us the errors Meteor normally logs to the console.

The package’s code might look like:

let errorListeners = [];

function init() {
// Here the package would hook into Meteor to
// receive the errors. When there is an error,
// it will call all of the functions in errorListeners
}

init();

export const onError = (listener) => {
errorListeners.push(listener);
};

And the package could be used like:

import { onError } from 'meteor/extensive-error-reporting';

onError(err => {
console.log('There was an error!', err);
});

If updates to this module get accepted (maybe React Fast Refresh accepts updates for one of its parents), anytime it is re-ran it will add an extra listener and an extra console.log message. If you change what the listener does, such as sending the error to an error tracking service instead of logging it, the old listeners will still log the error.

If you understand that this is caused by HMR and there are multiple instances of the module running, you might reload the page to get back to one instance of the module. You might next add some code to prevent this module from being re-ran (Meteor will reload the page instead) to prevent this from happening again (it can get annoying if it happens too often):

if (module.hot) {
module.hot.decline();
}

Additionally, by making a small change to the package, we could allow the module to still be updated with HMR. onError could return a function that removes the listener:

let errorListeners = [];

function init() {
// Here the package would hook into Meteor to
// receive the errors. When there is an error,
// it will call all of the functions in errorListeners
}

init();

export const onError = (listener) => {
errorListeners.push(listener);

return () => {
const index = errorListeners.indexOf(listener);

if (index > -1) {
errorListeners.splice(index, 1);
}
};
};

Then, the module in our app can be updated to call the returned function when the module is disposed:

import { onError } from 'meteor/extensive-error-reporting';

const removeListener = onError(err => {
console.log('There was an error!', err);
});

if (module.hot) {
module.hot.dispose(() => removeListener());
}

Now, every time this module is re-ran, there will still be one error listener, and it will always be from the newest version of the module.

It would be nice if the app’s developer wouldn’t have to think about and write the code for the dispose callback. If onError is usually called in the top-level of the module, our package can record which error listeners were added by each module, and automatically add dispose callbacks. This can be done with module.hot.onRequire. We will have a variable with the id of the current running module, and add hooks to run before and after each module is imported to update the variable. It will record which event listeners were added by the current module, and add a dispose callback to remove them. The code would look like:

let errorListeners = [];

// This has the id of the current module. For example:
// /imports/client/app.jsx
let currentModule = null;
let addedBy = new WeakMap();

if (module.hot) {
module.hot.onRequire({
before(module, parentModuleId) {
currentModule = module.id;

if (module.hot) {
// When the module is disposed, remove all error listeners
// it added
module.hot.dispose(() => {
for (let i = errorListeners.length - 1; i >= 0; i--) {
if (addedBy.get(errorListeners[i]) === module.id) {
errorListeners.splice(i, 1);
}
}
});
}

// Return the parent id so after this module
// finishes running, the after hook can update
// currentModule
return { parentModuleId };
},
after(module, beforeData) {
currentModule = beforeData.parentModuleId;
}
});
}

function init() {
// Here the package would hook into Meteor to
// receive the errors. When there is an error,
// it will call all of the functions in errorListeners
}

init();

export const onError = (listener) => {
if (listener) {
addedBy.set(listener, currentModule);
}

errorListeners.push(listener);

return () => {
const index = errorListeners.indexOf(listener);

if (index > -1) {
errorListeners.splice(index, 1);
}
};
};

Now, we can change the file in the app back to how it was originally, and the error listener will still be removed when the old module instance is disposed.

import { onError } from 'meteor/extensive-error-reporting';

const removeListener = onError(err => {
console.log('There was an error!', err);
});

This added a lot of extra complexity and code to our package. Is it worth it? I decided it was for zodern:pure-admin, but for many packages simply providing a way for the app to handle disposing itself is enough, or the package might not need to worry about this at all. Some things you might want to consider:

  1. Will the package be used in files for the view layer, or in other files imported by those files for the view layer? If so, changes to those files will likely be applied with HMR, and for a good experience our package should support it.
  2. Will developers want to rapidly iterate on the code that uses our package? If they do and our package is compatible with HMR, they could add module.hot.accept() to files that use our package so they are updated with HMR.

The module.hot.onRequire hooks can be used for more than just helping to dispose modules. The blaze-hot (used to provide HMR for Blaze) and react-fast-refresh Meteor packages also use it to detect modules that can safely call module.hot.accept(). In addition to telling Meteor which files can be updated with HMR, module.hot.accept() also tells Meteor how many modules need to be re-ran to use the new exports from the modified module. Meteor re-runs the modules that were modified, the modules that imported those, and so on until it gets to the modules that accepted the update. Let's look at a simple example of where this can be used.

Let’s use another imagined package: simple-i18n. This package is for the internationalization of apps. We give it an object for each language where the key is a message-id, and the value is the message in that language. The package might also provide methods to change the current language and to get the message for a specific id in the current language, but we are going to ignore those since they are not important to this example.

import { registerMessages } from 'meteor/simple-i18n';

registerMessages('en', {
welcome: 'Welcome',
goodbye: 'Goodbye'
});

registerMessages('es', {
welcome: 'Bienvenido',
goodbye: 'Adiós'
});

registerMessages('fr', {
welcome: 'Bienvenue',
goodbye: 'Au revoir'
});

This file will be frequently changed as we add messages for new features. We could simply add some code to the file so it is updated with HMR, and document this in the package’s documentation.

if (module.hot) {
module.hot.accept();
}

This is probably a good scenario though where the package could automatically accept updates to this module. To identify modules that can be updated with HMR, we will use these two requirements:

  1. The module has no exports. If it does have exports, we want the modules that imported it to be re-run to use the new exports, and accepting updates in this module would prevent that.
  2. The module calls registerMessages.

The code for this in the package would look like the following:

let registerMessagesCalled = false;

if (module.hot) {
module.hot.onRequire({
before(module, parentModuleId) {
let parentCalled = registerMessagesCalled;

registerMessagesCalled = false;

// This will be available in the after hook as beforeData.
return { parentCalled };
},
after(module, beforeData) {
// Make sure HMR is available,
// the module has no exports,
// and the module added messages
if (module.hot && registerMessagesCalled && !module.exports) {
module.hot.accept();
}

registerMessagesCalled = beforeData.parentCalled;
}
});
}


export function registerMessages(language, messages) {
registerMessagesCalled = true;

// Here it would store the messages
}

Now, any change to our file with the messages will be automatically applied with HMR.

Some projects put the messages in a Meteor package so they can be shared between multiple apps. Would this work for those projects? At this time, no, because HMR isn’t able to update files within packages. However, once Meteor is able to, the integration we created would work with packages with no modification.

The types of files that this can be done for are small. Many files do things that need special dispose handlers, or there is no good way to detect that they can be safely updated with HMR. But when this can be done in a way that works reliably, it greatly improves the developer experience, as can be experienced when modifying React components in a Meteor app with HMR.

To recap:

  • If your package is used in files that are automatically updated with HMR (for example, files with components or templates), or in files that are frequently modified and would benefit from HMR, you should make sure your package provides a way for the old instances of the file to properly disposed itself.
  • If your package is normally used when a file is first run, the package can use module.hot.onRequire to add dispose handlers to automatically clean up modules.
  • If the files that use your package are frequently modified, have no exports, and don’t do anything that would cause issues with there being multiple instances of the module, you could consider automatically accepting updates to those files. However, you should be careful when doing this since accepting updates for modules that don’t support being re-run can cause a worse experience than reloading the page.

We already have at least 5 packages providing integrations with HMR for different view layers, showing build errors on the client, and applying changes to an admin dashboard. What else can packages do to improve the developer experience when using HMR? I am excited to see what you come up with!

Originally published at https://zodern.me.


Updating Meteor Packages for HMR was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Scale your app with multi-core

$
0
0

A quick note about myself

I’m a self-taught developer based in Paris, I worked as a freelancer for a few years, before starting to work for my family's company Place-des-Arts.

Place-des-Arts is an art gallery specialized in modern and contemporary prints with more than 20 000 references, feel free to check out the open beta here.

Scaling my Apps

It’s been almost 3 years since I’ve started to use Meteor for my work, and it’s been great!

During this time I met several issues with scalability and used a microservices approach to tackle heavy/scheduled/recurring jobs problematics such as:

  • Resource generation (images, pdf, JSON, CSV)
  • Automated React templated emailing
  • Automated Database backup to an external server
  • External services such as payment and delivery providers
  • Static React templating generation
  • Search engine management
  • Sitemap management

At some point I found myself reinventing the wheel with underlying inter-dependencies, and I thought:

“why not going back for an all-meteor solution”?

I decided to migrate all my external services back in Meteor by implementing a multiprocess job queue (or worker pool) using the node cluster module.

I was not deceived: not only my server-side codebase was reduced by more than 40% 😮, but performances were better, and managing my code became a piece of 🍰 ​!

That’s why I’m thrilled to introduce to you the official release of nschwarz:cluster, a brainless multi-core solution for your app 🥳

It supports:

  • Both async and sync jobs
  • Both in-memory and mongoDB job queues
  • scheduled and recurring jobs
  • Job prioritization
  • IPC messaging between master and worker
  • Event listeners

You can find the full documentation and examples here.

A quick worker pool summary

A worker pool is inspired by both the master/slave and thread pool models, and it's composed of:

  • A job queue, which stores all the jobs in order
  • A Master, which supervise the queue and the workers
  • Workers, which execute the tasks sent by the Master on individual processes

The master checks if jobs are in the queue, if so, It forks itself to create workers.

The worker then receive the job, execute it, and tells the master the job's done.

The master removes the job, if no more jobs are available it closes the worker.

This behavior is repeated at regular intervals.

Using this approach has many advantages :

  • It enables you to offload your main event loop (which will result in more responsiveness)
  • The offloaded tasks are executed more efficiently since they are not deferred by other events
  • It enables you to write fewer, clearer, and modular code because you’ll need to break it down into subroutines
  • It becomes painless to design scheduled and recurring events
  • It’s easier to manage your application growth (both in code, and performance)

A real-world usage

Race condition safe event management and failure proofed mailer:

When a customer makes a payment on the website, 2 events occur:

  • As soon as my bank receives a payment, it sends a POST request to my server to notify me that a payment was made.
  • As soon as the payment is made on the bank website, the customer is redirected to a page saying “thank you”, “sorry, the payment was refused”, or “checking payment”. If the status is “checking payment”, the page will pull from the server at regular intervals until the status is updated to either success or failure.

In both cases, my server runs the same routine which:

  • Gets the payment status from my bank through their API
  • Updates the order in my database
  • Updates the products stocks
  • Sends an email to the customer with the order summary

Because NodeJs is non-blocking and these 2 events are often triggered at the same time, a race condition could happen, and this routine could be fired multiple times.

Plus if an error occurs while sending the email, I need to safely save it to send it back later.

Thus, I can split this routine into three subroutines :

// gets the payment status from my bank through their API
// update the order in my database
async function onNewOrder(job) {
const order = Orders.findOne({ _id: job.data._id })
  // abort if order has already been handled before
if (order.status !== 'WAITING_PAYMENT') {
return
}
  const paymentStatus = await getBankPaymentStatus(order.paymentId)
order.paymentStatus = paymentStatus
  if (paymentStatus === 'accepted') {
order.status = 'WAITING_ACCEPT'
order.save()
/* technically this is not called here,
but in a hook after the save event */
handleStocks(order.products)
TaskQueue.addTask({
taskType: 'sendMail',
data: { orderId: order._id, mailType: 'onNewOrder' },
priority: 5
})
} else if (paymentStatus === 'refused') {
order.status = 'REFUSED_PAYMENT'
order.save()
}
// if neither of the 2, paymentStatus === 'waiting_payment'
}
// updates the products stocks
function handleStocks(products) {
products.forEach(p => {
const product = Products.findOne({ _id: p._id })
product.stock -= p.qty
product.save()
})
}
// sends an email to the customer with the order summary
function sendMail(job) {
const { orderId, mailType } = job.data
const order = Orders.findOne({ _id: orderId })
const html = getReactMailTemplate({ order, mailType })
Email.send({
html,
to: order.customer.email,
from: 'somemail@somedomain',
subject: getMailSubject({ order, mailType })
})
}

Now I can safely do :

// called by the client / bank requests
function getOrderStatus(_id) {
const order = Orders.findOne({ _id })
if (order === undefined) {
throw new Error(`order${_id}:NOT_FOUND`)
}

if (order.status === 'WAITING_PAYMENT') {
const taskId = `onNewOrder${order._id}`
const exists = TaskQueue.findOne({
taskType: 'onNewOrder',
_id: taskId
})
if (exists === undefined) {
TaskQueue.addTask({
_id: taskId,
taskType: 'onNewOrder',
data: { _id },
priority: 11
})
}
}
return order.paymentStatus
}

It’s now race condition safe because:

  • You can only have one task with the _id : onNewOrder${order._id} at the same time.
  • Even if the task is called a 2nd time (there’s a small window), it will abort because order.statuswas previously modified.

Now let’s talk about the mailer safety net:

One time my mail server was down for a short period, leading to some unsent mails.

Because I hadn’t thought about this, some emails never went to the customers without me knowing for a while 😨.

Thankfully the failed tasks are kept in the queue, so I was able to send them back 🙏 .

To avoid any further fuss, I made a simple mechanism using an event listener :

import { add } from 'date-fns'
function onTaskError({ value, task }) {
if (task.taskType === 'sendMail') {
// notify the admins through a Notification Collection
Notifications.insert({
type: 'MAIL_ERROR',
task: task._id,
...someData
})
// retry in 30 minutes
const dueDate = add(new Date(), { minutes: 30 })
TaskQueue.update({ _id: task._id }, { $set: {
dueDate, onGoing: false
}})
}
}

It’s now time to configure the cluster :

const taskMap = {
onNewOrder,
sendMail,
}
const cluster = new Cluster(taskMap, { maxAvailableWorkers: 4 })
Meteor.startup(() => {
if (Cluster.isMaster()) {
TaskQueue.addEventListener('error', onTaskError)
}
})

What’s next?

Performances upgrades are coming up :

  • Using UNIX sockets instead of TCP for IPC which is already available in meteor
  • Adding a settable keepAlive field for each individual worker to reduce the cost of worker startup/shutdown routine
  • Sending back a job to a worker as soon as a job is finished instead of waiting for the next cycle
  • Putting up a meteor core pull request to fully disable the TCP server with an environment variable to reduce the cost and delay of the workers' startup

features roadmap :

  • Multiple “filterable” event listeners
  • Support for load balancing (to be discussed) :

As I went through the meteor feature request repo and the forum, I saw that one of the issues with scaling meteor apps was load-balancing (you can find one thread here).

Some meteor packages such as meteorhacks/cluster or arunoda/meteor-cluster were developed originally for load-balancing but have not been updated for a while (more than 5 years).

Since this package uses forked processes, assigning workers to handle requests passed from the master instead of working on tasks would be a no-brainer to integrate.

Making an isomorphic worker could be interesting :

It could handle requests when traffic is high and switch back to handling jobs when the network load is manageable by the master.

If you’re interested, let me know 😉

  • Meteor core integration for build phases :

There’s a lot of complaints about meteor building time, providing the ability to build the app using multiple cores would be one of the solutions to reduce delay.

Using multi-core on the soon to be tree-shaking feature is also in discussion.

Get started with meteor add nschwarz:cluster!

Please let me know if you have any feedback!


Scale your app with multi-core was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

First load optimization with Meteor

$
0
0

You write your unique new Meteor Application, but it takes time to load at first. What can you do? This issue has many causes, but it probably means you are loading too much or waiting for too long.

We will go through some basic optimizations here that, when applied, can get you a massive lift in first-page loading time and app performance.

But how can we optimize something that we can’t measure? No way. Let’s start by seeing ways to measure our performance and bottlenecks, and then we will proceed to optimize things.

Know your bottleneck

There are several tools for measuring performance, but there are some that I find essential when analyzing first load performance.

1- Lighthouse

Chrome’s feature for analyzing app performance is a massive ally in getting data. If you run it on your production website, or at least on a minified environment, most commonly in your staging env, you will have easily measurable numbers for performance.

If your new testing release performs worse than the current version in production, you may have to stop and optimize and analyze the latest PRs.

Golden tip: It’s also an excellent choice to create regression tests using lighthouse node API in your CI.

Lighthouse for Meteor Docs

2- Chrome Profiler

We know the app is slow, but why is it slow? You can check which javascript methods are taking more time with chrome profile. With this, you know if it’s your local DB, your UI, a startup script, or whatever is taking that much time. The most common culprit is that you are loading TOO MUCH CODE, and it’s incredible how slow things get when your bundle grows.

Chrome javascript profiler

If you see the example above, this app probably needs some love into the initial bundle, as the code evaluation is taking almost 1sec. If that is not blocking the initial render, that’s fine. Otherwise, we have many ways to overcome this, and we will get into more details in the next section.

3- Bundle Visualizer

Let’s suppose you are sending all React Components from Material UI in the initial bundle. You don’t know about that yet, but you know your app is slow to load.

How can we find that this is the issue? With bundle-visualizer.
If you do the following import, without tree-shaking, on meteor:

import { Button } from “@material-ui/core”

You will end up with all the library components in your bundle, which means MBs and MBs of unused files being sent to your user. You for sure don’t want that, right?

Bundle Visualizer view on Meteor, more details here

So, for generating the pretty chart above and identifying that your bundle has 5 megabytes of material-UI components, you can run your app locally as follows:

meteor --extra-packages bundle-visualizer --production

The solution for the issue varies from case to case, and we will explain it better in the next section.

4- Meteor DevTools Evolved

You can’t optimize if you can’t measure. That’s a rule of thumb.

Subscription monitoring with Meteor DevTools Evolved

With this chrome extension, you will be able to see how many subscriptions you are waiting for, at which time; see the number of documents you are loading on minimongo, which will directly impact your performance when searching for items with find(remember, minimongo don’t have indexes so that all searches will do a full scan in your collection — except for _id only queries)

Ok, now we know our numbers, and we know what is slow. I will point out in this article some standard optimizations that I think are easily implemented and can bring tremendous results, apart from the ones I’ve already mentioned earlier here. This is not an exhaustive list but a comprehensive one to help you get started.

Let’s start with easy wins then:

1- CDN

Do you know what a CDN is? Even if you don’t, you have for sure used one before. It is a way to distribute your static assets in several places, boosting the speed at which they can be served to users. It does this by caching and distributing your content over machines worldwide. You can read more about it here. But imagine you are hosting with Meteor Cloud at us-east-1, and a user in Brazil is accessing it. The RTT for this operation is vast, and your user will suffer from loading times.

Applying it to your galaxy-hosted app is easy, but it takes some steps depending on what you want to be served through it. We will be complete here, so if you want the maximum boost, follow all steps.

First, you will need to choose a CDN provider. Your CDN provider must have “origin” support, like Cloudfront. You need to create a new distribution in there and set origin support, like the following screenshot:

Create your CF distribution as follows. It’s ok to leave all settings as default, and optimize it further if needed

After that, we have to:

  1. Serve images with CDN:

Change all your URLs to point to your new URL showed in the dashboard, ex: https://d3ku71hz1f7ov0.cloudfront.net/.

From:

<img src="/instagram-icon.png" height="26" alt="Instagram" style="max-width: 30px; vertical-align: sub; display: inline-block;">

to

<img src="https://d3ku71hz1f7ov0.cloudfront.net/instagram-icon.png" height="26" alt="Instagram" style="max-width: 30px; vertical-align: sub; display: inline-block;">

If you want to automatically bust the cache for images on a new version, you can also append ?_g_app_v_={process.env.GALAXY_APP_VERSION_ID} to the URL. But keep in mind you will need to get this info back from the server, as it’s server only:

<img src="https://d3ku71hz1f7ov0.cloudfront.net/instagram-icon.png?_g_app_v_={process.env.GALAXY_APP_VERSION_ID}" height="26" alt="Instagram" style="max-width: 30px; vertical-align: sub; display: inline-block;">

2. Serve CSS/JS

Meteor does have a “hook” inside WebApp internals to change the URL we serve the JS/CSS assets, which is, by default, served from the server itself. We don’t want that, and we want that the CDN serves it, so we need to change the URL we send in the header that loads the assets.

It’s also important to note that Meteor already handles cache-busting by generating unique hashes on assets by bundle content, so you don’t need to worry about caching issues in your origin-supported CDN.

Rewrite the served JS/CSS URLs to use the CDN one, with the following call inside your server code:

WebAppInternals.setBundledJsCssUrlRewriteHook(
url => `https://d3ku71hz1f7ov0.cloudfront.net/${url}&_g_app_v_=${process.env.GALAXY_APP_VERSION_ID}`
);

3. Add CORS headers in your fonts requests

Serving fonts and other assets from another origin, i.e., your CDN URL, will cause access control origin issues. You have to set the header to allow it. Use your CDN URL for maximum security, or use a wildcard “*”.

WebApp.rawConnectHandlers.use((req, res, next) => {
if (
req._parsedUrl.pathname.match(
/\.(ttf|ttc|otf|eot|woff|woff2|font\.css|css|js|scss)$/
)
) {
res.setHeader('Access-Control-Allow-Origin', 'https://d3ku71hz1f7ov0.cloudfront.net');
}
next();
});

2- Initial Data SSR

If you have a dashboard or any dynamic system, you are probably building your screen based on data. And for this, you need data available to render your app at first.

You do have some options, like using skeleton, which is a great alternative. The solution I will present will make everything snappy and fast without sacrificing a meaningful first render.

Meteor Fast Methods is a library I made for Pathable Inc. It includes a way to preload data inside the HTML, which will populate the Minimongo and thus make your finds easy, as everything will be available as soon as possible. We remove the RTT needed when loading data after the app is loaded on the client.

The approach this library takes is sending with the initial HTML a JSON that contains all the data you need to render your app, and after that, it starts listening with Redis Vent, from the package redis-oplog changes on that cursors.

The usage is straightforward, just add the cursors you need available at the preloadData() method on the server, and use it after FastMethods.ready() is true.

If you want to use the redis-oplog part, also check the FastMethods.startListeningToChanges call.

This has dropped some seconds from the initial page loading at Pathable.

3- Split your client bundle and delay JS evaluation

You can use Meteor dynamic import to split your bundle into smaller parts. This helps significantly with first load performance, and it’s also an essential point on lighthouse scoreboard.

Using React and Meteor, it’s effortless to do. You will have to create a component that is not loaded in your app’s home screen and make it default exported(or create a wrapper). Then, just use react-router and React Suspense with Meteor dynamic import to load the route as needed.

AdminDashboardContainer file:

const AdminDashboard = () => <div>Heavy component here</div>
export default AdminDashboard;

In your route definition file, use react lazy() and Meteor import() to split your bundle and load as needed:

const AdminDashboardContainer = lazy(() =>
import('../../../app/admin/ui/AdminDashboardContainer')
);
<Route
path={`/adminDashboard`}
component={props => <AdminDashboardContainer {...props} />}
/>

You also have to set Suspense for showing a loading indicator while we fetch the bundle related to this screen. In your main app file, do the following:

<Suspense fallback={<Loading />}>
<ErrorBoundary history={history}>
<Routes />
</ErrorBoundary>
</Suspense>

And voilá! You are doing bundle splitting and saving a LOT of client loading time. Imagine your admin app, that some screens are rarely used, and you may have dozens of screens. The benefits are huge.

There is also a new concept applied in the above example, and it’s Nested Importing. You can read more details about it in our previous post, so we will only do some en passant observations.

Nested imports delay the evaluation of JS code until they are needed. This is extremely useful on Cordova, as most webviews implementations are slow to evaluate code. Do this if you see a high delay inside your profiling regarding “code evaluation.” How to do it? Simple, instead of importing everything at the header of the file, do it when you need the library. Example:

function doSomethingWithDates(){
import moment from 'moment'
  return moment().add(2, 'days').toDate();
}

And, in another file, you have this:

export const DateComponent = () => {
const date = doSomethingWithDates();
return <div> {date.toString()} </div>
}

Moment won’t be evaluated until DateComponent is used, saving evaluation time at startup.

4- Reduce your bundle size

This might seem obvious, but there are subtle things you might found when analyzing your bundle with a bundle analyzer.

If you don’t use the entire library components, why are you serving it fully to your client?

To solve it, prefer libraries with ‘es’ implementations, so you can directly import the components and smaller libraries that can be measured with Bundlephobia.

Instead of including all lodash library in this way:

import _ from 'lodash';

Which is roughly 69.9kB minified, prefer to include only the methods you use:

import keyby from 'lodash.keyby';
or
import
sumBykeybyfrom 'lodash-es/keyby';

5- Scale aggressively

It’s hard to be fast when your server is suffering. With Galaxy, this is easy to solve. You can set some triggers to upscale more aggressively while you fix your code or if you want maximum performance.

You can check how this is done with triggers here. I will share one that is a good starting point if you want to have more distributed connections:

With this trigger, we are saying that we will scale up one by one container if any of the following rules are matched:

  • Cluster CPU usage is above 30%
  • Cluster Memory usage is above 40%

With this, you will ramp your servers earlier than your load, and more containers will be spawn, hopefully meeting your demand. Wrapping up

Let’s summarize what we have learned today. The basic principle: If you can’t measure, you can’t optimize. With this in mind, we discovered some approaches for measuring bottlenecks and app performance, which were:

Measuring:

  • Lighthouse
  • Profiler
  • Meteor DevTools Evolved
  • Bundle Visualizer

We also learned some common easy wins in first load performance that can be applied today in your application.

Fixes:

  • Use a CDN
  • Serve data with SSR
  • Split your client bundle and delay JS evaluation
  • Reduce your bundle size
  • Scale as needed

And that is it for today, I hope you have found this useful, and let me know in the comment section how all these things are helping you optimize your application and produce fast-and-furious Meteor apps.


First load optimization with Meteor was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

New Meteor Meetups

$
0
0

Meteor Meetups has a new home!

Author: Chris Montgomery

With the on-going lockdowns, restrictions, and uncertainty, Alim Gafar approached me about establishing online Meteor Meetups in the same way we did Meteor Impact. The thought here is to help consolidate all groups, and allow easy sharing between them, and have the opportunity and flexibility to do more exciting things. We have support from Meteor Software and Pathable and with that, a new home for Meteor meetups was born: Meteor Meetups!

So what do meetups look like so far?

First off, we have dedicated pages to each local group so you can share information about yourself and additional information on companies using Meteor in your area. This will become more interesting once we’re able to transition to meeting people offline and connecting with Meteor users in person. In the meantime, you can at least scout out users in your general area.

How do the meetups work?

Each group can use the Pathable platform to schedule online meetings and hangouts. With meetings recorded, it will benefit other members of the community as well, as they can see great stuff from other meetups in other communities.

Once you sign-up, please go and edit your profile. Add your location (there is already plenty of options to choose from, but you can add your own as well) and if it exists select your Meteor group.

We will kick-off the meetups with Meteor New York with an introductory presentation about Meteor Community, our new meetup platform, and some announcements about Meteor Impact 2021.

We are now looking for group organizers and speakers. If you are interested in one of those, please don’t hesitate to contact me! Our goal is to have each meetup group meet at least once a quarter.

I hope to see you there!

If you like Jan’s work, please consider sponsoring him on GitHub Sponsors ❤️.


New Meteor Meetups was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

How Avion Brings User Story Mapping To Product Teams using Meteor

$
0
0

The Avion team has built an elegant, effective web-based tool for remote teams to Post-It virtually.

When you think of user story mapping, you probably envision a group of developers staring at a whiteboard with colorful Post-Its, lined up in neat rows.

User story mapping helps teams to plan a product and its features from the perspective of their customers and users.

Post-Its define actions the user can take (aka user stories) within the context of a product’s core user journeys. So, for example, core user journeys on YouTube include watching a video, posting a video, searching for content, and reporting videos.

Under each core journey, teams then add Post-It notes to better visualize the steps that their users will need to take. This helps teams identify what they need to work on next and how to build it, whilst also constructing a birds-eye view of the whole product backlog.

So, with the help of the Meteor framework, Avion built a digital version of this process, enabling remote teams to collaborate around a user story map.

Avion — User Story Mapping For Product Teams

At its core, Avion is a tool that enables product teams to build, plan, and prioritize their backlogs better, using the technique outlined above — user story mapping.

Its co-founders, Tim Ramage and James Sear, wanted to bring the traditionally offline experience to the web in a modern and collaborative interface. And since they’re both experienced engineers, having worked in agile teams ranging from startups to global enterprise, they knew that the two most crucial elements to get right were user experience and third-party integrations.

Two years after launching, Avion is a tool that hundreds of product teams around the world now rely on to plan, build and collaborate around their backlogs.

What You Can Do With Avion

Avion helps teams:

Focus on their users

In Avion, user stories can only be defined inside user journeys and steps, which forces product teams to think about their end-users when writing features and user stories.

Translate designs into actionable releases

Avion provides an environment that is perfect for taking a set of wireframes or visual designs and translating them into user stories. From there, teams can build up horizontal “slices” that make up a set of deliverable releases.

Prioritize and challenge releases

The story map is a perfect place for conversations around the priority of releases and features. It encourages teams to be more lean and ask questions like “is this release as focused as it can be?”. As Jeff Patton says — Minimize output, and maximize outcome and impact.

Synchronize planned releases with other backlog tools

Once the hard planning work has been done in Avion, releases can be pushed to more development-focused backlog tools, like Jira or Trello. Avion will then keep stories synced up in the background, giving the team context wherever they are working.

Why Avion Chose Meteor

An early version of Avion was built using a framework called FeathersJS. Though the Avion team enjoyed some elements of Feathers, there were also some frustrating restrictions of the framework at the time, such as filtering and manipulating published data to connected clients.

As the dissatisfaction grew whilst building an MVP, Avion co-founder Tim — who had some previous experience working with Meteor — suggested that they make the switch. And they haven’t looked back since!

“Meteor gave us the ability to create a fully real-time application with absolute ease”

If you want to build a real-time application that has connected clients using websockets, there really aren’t many other frameworks that will cater for this need. As is often done, comparing Meteor to frameworks like Next and Gatsby — is like comparing Apples to Oranges — these frameworks do completely different things. Meteor gave us the ability to create a fully real-time application with absolute ease. Avion also proves that Meteor is not just a tool for building prototypes; we are live and have not struggled to scale at all.

Finally, the fact the Meteor is just a Node app under the hood gives us so much peace of mind that we can always just write custom functionality and hook into the Meteor app. We have recently done this by delivering multi-tenanted SSO, all whilst using Meteor’s core authentication system.

Avion’s Tech Stack

The Avion team insisted on a real-time web application. They wanted users to see updates without ever having to click Refresh, giving them that same collaborative experience and real-time feel of moving Post-Its around on a wall.

However, since both founders were JavaScript developers, they realized that they didn’t have many real-time framework options. And, they didn’t have time to build a customized framework and a startup simultaneously.

Meteor was very attractive in this respect because it’s an open-source framework for seamlessly building and deploying web, mobile, and desktop applications in JavaScript. Meteor enabled the Avion team to focus on the experience, without having to worry about managing complex technical aspects like websockets.

A Consistent Front and Back-End Infrastructure

As Meteor automatically syncs the data between the front and back-end, Avion’s stack is very simple. They only decouple aspects of the Meteor application where it makes sense, using core AWS services, such as Lambda functions, SQS queues and SNS emailing.

Data and rendering performance is absolutely critical for the Avion application since it has an almost canvas-like DOM setup. The screen can become very wide and very tall with many DOM nodes. To contend with this, The Avion team takes advantage of a custom setup to consume Meteor publications in their React app, which leverages MobX for super fast state diffing and data management.

Current Challenges and Future Goals for Avion

2020 was an amazing year of growth for Avion, which ended with them securing a seed round of investment from Haatch Ventures, who work with Marvel and Poplar.

Current Tech Challenge — Scale, Scale, Scale!

Avion offers tight two-way integrations with backlog tools like Jira, Trello, and GitHub. But due to the nature of their integrations, the Avion application can receive thousands of updates per second, that their system needs to queue and deal with. The Avion team is working hard to ensure their infrastructure can continue to scale up and handle this level of traffic.

What’s Next for Avion

Over 2021, the Avion team is looking to build out their platform to offer more value to product teams, including road mapping and alternative prioritization techniques.

Commercially, the Avion team wants to encourage more product teams to try user story mapping to drive their backlog in 2021. If teams are searching for an intuitive, user-focused, lean way to plan their release roadmap, they’d be wise to give Avion a try.

Want to give Meteor a try for your business? Click here to install and find out how it will fit your business! Interested in hosting with us? Check out Meteor Cloud for all of your hosting and app monitoring needs.


How Avion Brings User Story Mapping To Product Teams using Meteor was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Meteor 2.3 has been released!

$
0
0
Meteor 2.3.1
Announcing Meteor 2.3.1

Announcing Meteor 2.3.1: Node 14, removal of deprecated APIs, improved HMR, and much more

Meteor 2.3 & 2.3.1 bring a lot of long-expected upgrades and improvements. It also has a small diet with the removal of long deprecated code in packages which allows us to more focus on the future.

Node 14 upgrade

The first major change in Meteor 2.3 is Node version upgrade to Node 14.17.3 from 12.22.1. This gets Meteor to the current LTS version of Node bringing updates in V8. Read the release article of Node 14 for more information. Some of the improvements that are present in Node 14 like new JavaScript features (like optional chaining) have been already available in Meteor.

Like with any Node upgrade this will require you to review your apps to see if your dependencies are compatible with the new version. You should remove your node_modules folder and install your dependencies via meteor npm install.

As with any Node update, meteor-tool dependencies also got updated, with the most notably:

  • npm updated to 6.14.13 to correlate with the Node update
  • fibers v5.0.0
  • promise v8.1.0
  • node-gyp v8.0.0
  • @babel/runtime v7.14.0
  • request v2.88.2
  • tar v2.2.2
  • sqlite3 v5.0.2
  • moment v2.29.1
  • underscore v1.13.1
  • optimism v0.16.1
  • @wry/context v0.6.0

Improved reload and HMR

Zodern has been hard at work making incremental improvements and fixes for HMR, most notably improving tracking of which files are used by building plugins to know when it should do a complete rebuild, a faster client-only rebuild, or completely skip rebuilding after a file is modified. This should work with any file in any directory and for both files in the app and files in packages.

The most noticeable improvement is when modifying a file only used on the client. Meteor will only rebuild the client, even if the file is not inside imports or a client folder. This now removed the need to have an imports folder so that changes in the UI don’t restart the server. This was a bug introduced after the addition of meteor mainModule option in the package.json, and now it’s fixed!

On the experimental side, we are testing reducing time spent by the server (re)start in development by adding a cache for Reify. This optimization is on by default in development, if you want to have it in production you can enable it by setting the METEOR_REIFY_CACHE_DIR environment variable.

Accounts packages breaking changes

Accounts packages got many improvements in this release cycle. While most are minor improvements or changes there are few that required a major version bump for some of the packages. This major version bump will require action from all package maintainers that depend on accounts-base, accounts-password, and oauth packages to include the new range like this: api.versionsFrom([‘1.12’, ‘2.3’]) or api.use(‘accounts-base@1.0.1 || 2.0.0’) .

This is due to the removal of old APIs as described below, breaking of the enrollment workflow, and removal of SRP style password, all as described below.

Enroll account workflow has been separated from reset password workflow (the enrollment token records are now stored in a separate db field services.password.enroll instead of services.password.reset). If have been doing any operations related to enrollment flow you will most likely need to change your DB queries.

Finally, the old SRP-style password mechanisms from before Meteor 1.0 have been now completely removed. Other API calls from before Meteor 1.0 that have been deprecated (and now for the most part just pointing to their current equivalents) met their end in this release. See history for the full details.

Removal of deprecated APIs in packages

With the release of Meteor 2.0 it was only a matter of time until old deprecated APIs from before Meteor 1.0 would be removed. This release takes the first step focusing on removal of deprecated APIs around packages. Starting with packages API itself the old underscore style calls have been removed. So ancient calls like api.add_files will no longer work and you should used the camel case variant (api.add_files => api.addFiles).

Across the entirety of core packages, any deprecated API endpoints from before Meteor 1.0 have been removed, see history for the full details. This should affect only packages and apps that have been with us since the very beginning and failed to migrate to the new API calls.

Deprecated flag for packages

Among all these removals we have a new addition for the package life cycle. In a life cycle of a package, there might come a time to end the development for various reasons, or it gets superseded. In either case, Meteor now allows you to easily notify the users of the package by setting the deprecated flag to true: deprecated: true in the package description. In addition, you can replace it with a string that tells the users where to find a replacement or what to do.

The notice and instructions will display in the console when the deprecated package is added or updated.

If you want to see example usage, check out the deprecated packages in Meteor.

Typescript 4.3.2

For fans of strongly typed JavaScript we are upgrading Typescript to 4.3.2. Check out the needed goodies:

WebApp responses

Webapp will respond appropriately to unsupported requests instead of sending content, including handling for new HTTP verbs like OPTIONS, to improve compliance in the following way:

GET

  • Respond with the requested resource; static asset, boilerplate etc.

HEAD

  • Return headers identical to GET request
  • Do not send content (It’s ignored by user agents anyway)

OPTIONS

  • Respond with 200
  • Send an Allow Header listing acceptable request methods
  • Do not send content

CONNECT, DELETE, PATCH, POST, PUT, TRACE, etc.

  • Respond with 405 Method Not Allowed
  • Send an Allow Header listing acceptable request methods
  • Do not send content

DDP_DEFAULT_CONNECTION_URL behavior changed

The undocumented environment variable DDP_DEFAULT_CONNECTION_URL behavior has changed. Setting DDP_DEFAULT_CONNECTION_URL when running the server (development: meteor run or production: node main.js) sets the default DDP server value for meteor. But this did not work for Cordova apps. Now you can define the Cordova app default DDP server value by setting DDP_DEFAULT_CONNECTION_URL when building.

New platforms flag

A new flag --platforms have been added to the meteor build command to specify the platform you want to build for. meteor build . —-platforms=android. This is useful for example when you are not using a MacOS and you want to build your app only for Android. Or you can use this to save time on CI not building all the platforms all the time.

New deploy option

--build-only is a new deploy option. This is helpful if you want to build first and after some validations proceed with the upload and deploy. More about this on Cloud docs.

http@2.0.0

Thanks to Jan Küster, the http package got a complete rewrite to use fetch internally. This is to aid you toward migration to fetch. This will allow you to use the current http API that you are used to and will continue to work. This will remove issues with deprecation of http. Though this is the end of the package and it will be now completely deprecated.

New default format for Android builds

In 2.3.1 there has been a change in the default output for Android Cordova apps. The new default format is .aab, following the announcement from Google that starting in August new apps will have to use this new format.

If you still want to use the old apk format use the following flag in the build command:--packageType=apk

And much more!

And this is just the beginning, there are many other smaller fixes and improvements. Please give the changelog for Meteor 2.3 a look for a detailed list of all changes.

You can update to Meteor 2.3.2 today as usual with

meteor update --release 2.3.2

We had some issues with Windows and webapp package on Meteor 2.3 final version and that is why we are recommending the upgrade directly to 2.3.2.

If you want to contribute for beta releases of Meteor with your feedback and testing your apps go ahead and Sign Up in our Community Slack and join our #beta-feedback channel.

UPDATE 07/13/2021 — We have identified an issue when running android projects with the new bundle format. It was fixed on 2.3.2, so we recommend going directly to this version


Meteor 2.3 has been released! was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.


How ConvertCalculator Uses Meteor (+ Math) To Sell More

$
0
0

Fact: When you give website visitors an intuitive calculator to price services or grab an instant quote, they make smarter buying decisions.

But creating one of these interactive calculator forms typically costs businesses loads of time and money they don’t have.

So ConvertCalculator decided to make the process easier.

This team out of Rotterdam, Netherlands, created a versatile calculator form that’s easy to add to any website (zero coding skills required!). It quickly helps brands grow their business — and it’s all built with the help of Meteor.

ConvertCalculator’s Origin Story

September 2017: programmer Joris de Ruiter was doing freelance work and living the gig life. One customer asked Joris to build a price quote calculator for their website. He decided to build it, but not as a standalone feature.

Joris developed a calculator form builder as a SaaS product instead, with prices ranging from free to $60 per month. The initial version took one week to build, and the first paying customer followed just one week later.

ConvertCalculator started earning $2,500 in monthly recurring revenue during 2018, marking the moment Joris knew he had to go full-time with his project.

So he expanded his team and continued to improve every aspect of his product to keep up with ConvertCalculator’s steady, substantial growth.

ConvertCalculator By The Numbers (2021)

  • 12,158 Users
  • 9.4 million Calculator Visits
  • 171,000 Form Submissions
  • 3,970 Live Calculators

ConvertCalculator’s success is no surprise once you know all it delivers.

How ConvertCalculator Works

How ConvertCalculator Works

Essentially, ConvertCalculator offers clients a drag-and-drop calculation form builder that seamlessly integrates alongside the most popular website builders.

Their powerful calculation “engine” sets their product apart from alternatives. With their formulas, ConvertCalculator can use the question inputs to create an output, enabling a wide range of use-cases from number questions to option questions like multiple choice.

Brands can utilize their templates and forms to create a:

  • Price quote calculator
  • ROI and savings calculator
  • Product configurator
  • Order form
  • SaaS pricing calculator
  • Lead generation form
  • Loan and debt calculators
  • Customer support form
  • Timesheet calculator
  • … and so much more!

ConvertCalculator gives businesses the flexibility of a drag-and-drop website builder in combination with the raw power of a spreadsheet to turn any set of inputs into the desired output.

These calculator forms help businesses increase online conversions, grow sales, and save time.

After all, creating a calculation form from scratch is a costly feat. Not to mention the time, effort, and stress when making changes. ConvertCalculator allows businesses to stop wasting their valuable time and money and focus on their core offerings.

Their clients love ConvertCalculator because:

No Coding Skills Necessary

The drag-and-drop calculation form builder is just as easy to use as drag-and-drop website builders like Webflow or Squarespace. If you know how to use Excel or Google Spreadsheets, you can use their calculator builder. Even the most advanced forms don’t require any coding skills or programming abilities.

Plus, there are tons of templates to choose from (according to your business needs), so you can add a form in a few minutes and get started ASAP.

Forms Look Fantastic On Any Website

They seamlessly integrate with platforms such as Godaddy, Hubspot, Squarespace, Webflow, Weebly, Wix, WordPress, CraftCMS, ExpressionEngine, and many more. Their forms are also optimized for mobile and integrate with 1,000+ apps through Zapier, Slack, Stripe, and others.

Selling Is Easier For Brands And Customers Alike

Create a website calculator or instant quote form for your website, and you’ll capture more leads faster and follow up with confidence.

Website visitors can turn the knobs and see how their choices affect the price, ROI, savings, etc., without performing complicated math on their own. ConvertCalculator does all the heavy lifting.

Brands can even accept online payments directly from their calculator forms.

It’s Designer And Dev-Friendly

Rendered as HTML on your site (not an iframe), your team has total design freedom. Just use the JS API to power up your calculator, and have fun.

Why ConvertCalculator Chose Meteor

ConvertCalculator has been building with Meteor for over five years — and the team says they’ve loved it from the start. They never faced any real challenges when moving to Meteor Cloud, a bonus they didn’t take for granted.

Meteor allows ConvertCalculator to develop software faster than any other framework. It does so many things out of the box, allowing their team to concentrate on their core product and what makes ConvertCalculator unique.

The team says they also love Publish/Subscribe, using it throughout their app for years. However, they rethought the need for that and replaced some parts with Meteor Methods. It took some time to replace all Publish/Subscribe codes to Meteor Methods, but now they’ve switched most data fetching over to Meteor Methods, leaving Publish/Subscribe only in places where they need it. The team says they might love Meteor Methods even more than Publish/Subscribe.

“We’re no DevOps specialists, and Meteor Cloud allows us to not think about hosting too much.”

ConvertCalculator not only benefits from Meteor’s easy deployment and simple configuration but enjoys the ability to autoscale easily and monitor application performance with APM closely (which is a huge dealmaker for the team).

ConvertCalculator’s Tech Stack

According to the ConvertCalculator gurus, Meteor has many features but never gets in their way. Meteor’s abstraction provides simplicity, flexibility, and it’s “not too opinionated.”

So the ConvertCalculator team uses MeteorJS (with MongoDB) together with React and Tailwind on the front-end. They also utilize a bunch of community packages to make their lives easier, the most important ones being:

  • aldeed:collection2 (with simple-schema)
  • percolate:migrations
  • simple:rest
  • msavin:sjobs
  • edgee:slingshot
  • meteortesting:mocha

A few other components within their current setup with Cloud include:

An Extra Worker App that handles background jobs and longer tasks for production. It’s the same app with a different Meteor setting to execute code only in that specific environment.

Autoscaling Triggers to ensure their app keeps running smoothly without inflating their costs. This is where APM takes a starring role and becomes invaluable.

What’s Next for ConvertCalculator

The ConvertCalculator product is super versatile, allowing the team to support many use-cases across different industries and scale with ease. But their chameleon-like qualities can be both a blessing and a curse.

The team admits they’re constantly balancing between improving their core features and chasing new and exciting opportunities. So they tend to take a conservative opportunistic approach that delivers the best of both worlds. This approach also keeps the business and product development process interesting.

ConvertCalculator’s next priorities include:

1. Maturing the core product, where the team improves the inner workings, the overall UX/UI, and current functionality. They’ll also be launching an additional plan, enabling users to create workspaces/teams to increase collaboration.

2. Creating custom integrations. There are many use-cases where brands may want to import or export data into or from their form. Additional integrations would allow users to interface with calendars, spreadsheets, CRM programs, and more, further increasing the value of their product.

3. Expanding functionality where it makes sense to provide an end-to-end solution. A good example of this is PDF generation to offer an integrated quoting solution.

4. Reaching more SMEs. Stretching into bigger markets and getting SMEs aware that ConvertCalculator exists will be an important priority in the next few months.

Attracting more users requires an emphasis on a smooth onboarding and activation experience. The team hopes to expand their Help Center to show new users all the cool things they can create with ConvertCalculator and get the results they require.

The team says:

“It’s pretty awesome to see how other SaaS products like Webflow and Tailwind have organized their customer success, so we’re really looking forward to taking steps forward on that front.”

ConvertCalculator + Meteor = A Winning Formula

ConvertCalculator has lots of bright days ahead. The team is “extremely excited” to improve and expand their product, grow their customer base, and enable more SMEs to increase their online sales and overall conversions.

This future wouldn’t be possible without the help of Meteor in their corner.

What can Meteor do for your business? Click here to install and learn how we can help. Interested in hosting with us? Check out Meteor Cloud for all of your hosting and app monitoring needs too!


How ConvertCalculator Uses Meteor (+ Math) To Sell More was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

How real-time data works on Meteor — Know your pub/subs

$
0
0

How real-time data works on Meteor — Know your pub/subs

Let’s start with how publications and subscriptions work on Meteor, which is the “under the hood” of Meteor’s real-time data model.

It’s easier to understand when seeing the flow of new data, excluding client simulations:

  • You do a method call and change an object in a collection.
  • Mongo oplog will propagate that change to observers that tails it (publications create observers on oplog).
  • Publications observers detect oplog changes that affect its observed data, and it spawns a data re-fetch on mongo database.
  • Meteor merge box will check the diffs and propagate it to the client, as added/changed/removed.
  • Meanwhile, your method results might come after or before. It’s usually before, but if your oplog is fast and you have more computation after changing the DB, it might come after.
Flow for real-time updates on Meteor full-stack architecture

Ok!

Now we have an overview of how a publication works and the server resources involved in getting real-time data from the server/database.

In most cases, you can also use Meteor Methods simulation, which runs the same code you run in the server, in the client, but targeting the minimongo. In this way, you don’t need to wait for the server response, and the client gets updated instantly.

But why is this so important to understand? If you want to have fast applications using real-time data, you have to know how it works and structure your application to take the best from every aspect. Let’s talk about the ideal architecture for publications, then.

How to structure your publications

The ideal architecture is:

  • Small publications only with reactive data. (Remember merge-box? Yes, it will compute every diff on change docs for every user. Publish data with care!)
  • With data that is scoped. How scoped, you might ask, scoped as something you can restrict when invalidating.

Let’s grab an example:

A chat app. It might incline you to do a publication containing all messages from all chat groups. But, that would cause tremendous overhead on the server.

  • The ideal scenario is to do publications based on groups, like:
subscribe(“MessagesForUserFromGroup”, groupId)

— more performant, will cause fewer cursor invalidations

Compared with

subscribe(“AllMessagesForUser”)

The goal of publications is to avoid cursor invalidations. It’s a normal course of publications, caused by changes in the underlying data layer, as we saw, but if you restrict what you publish or do it smartly, you can reduce it.

Also, the best thing is to think in your architecture so that you can reuse the same cursors, which is done when subscribing with the same parameters.

These are some high-level thoughts I have on publications! I hope it helps.


How real-time data works on Meteor — Know your pub/subs was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Testing a Meteor app with Cypress

$
0
0

From zero to start writing end-to-end tests

When it comes to testing big applications, we need to test several modules or parts associated with one another.

Usually, these modules are tested independently (e.g., unit tested), but that does not necessarily mean that they work as expected when combined.

For testing these kinds of situations, we may use integration testing or end-to-end (E2E) testing.

Integration testing often entails evaluating a certain function that is dependent on other functions. Integration testing aims at testing the connection and communication of different software modules or components.

As for end-to-end testing, you are looking to test the application the same way a real user experiences it. You want to make sure everything (dependencies, environment, database, UI, and so on) works as expected. End-to-end testing aims at testing functionality and performance. Again, this is all done in an automated manner.

This guide aims to help understand how to set up and run end-to-end tests using Cypress against the Meteor framework. You’ll find the corresponding code in our example repository.

Outline

What is end-to-end testing?

Software may be tested at various levels. The unit test is the most basic level. In unit testing, we write code to test the correctness of a function or routine (a “unit”). Unit tests should be fast. When run, they give us immediate feedback on whether a routine is working as expected (for example, returning the expected output for defined input).

However, confirming that all of those minor bits operate correctly in isolation might be insufficient. It does not guarantee that they will operate properly together. Our app still might break. Integration or end-to-end tests come into play here.

Usually, integration tests are performed before end-to-end tests. Having a set of integration tests might help reduce the number of end-to-end tests. This is recommended since integration testing is faster to write “theoretically” and more efficient.

End-to-end tests simulate a user’s step-by-step experience. They allow you to validate different parts and layers of the application. They help gain confidence about the intended functionality of the application’s crucial capabilities, such as connecting with other systems, interfaces, databases, networks, and other applications.

Each type of testing (unit, integration, end-to-end) takes a different approach but they all have the same goal: to determine whether the outcome of some code execution meets a certain expectation. They are complementary in their purpose, and when combined, they can provide you with confidence that your application is running as intended.

Why use Cypress?

Cypress is a Javascript end-to-end testing framework that allows you to easily write tests for user interfaces. It facilitates tests that simulate normal user interaction in a web application. Cypress provides a plethora of tools like commands, plugins, time travel, screenshots, videos, etc., that will help you write robust tests faster.

Selenium was the go-to tool for end-to-end testing as it has been around for nearly 17 years. During that time, the web — and with it, the requirements for testing — have changed dramatically. Cypress is a testing framework designed specifically for the asynchronous nature of today’s web. It operates within your application and provides full control over it.

Furthermore, what I like best about Cypress.io is the huge community backing it, the abundance of recipes, well-written documentation, and its public roadmap.

Limitations of Cypress

Be that as it may, there are some limitations to Cypress, too. Be aware of them before you jump onto a new tool for your stack.

  • You cannot use Cypress to drive two browsers at the same time.
  • It doesn’t provide support for multi-tabs.
  • Cypress only supports JavaScript for creating test cases.
  • Cypress doesn’t provide support for browsers like Safari and IE at the moment.
  • Limited support for iframes (but it’s on the roadmap).

Installing Node.js and Meteor

Meteor is a free and open-source JavaScript web framework written on top of Node.js with many cool features such as reactivity, hot code push, a client-side database, and client/server code reuse capabilities.

In this article, I assume that you are already familiar with Meteor, have a working Meteor development environment, and a working Meteor app.

For the sake of explanation, we’re using the React todo app from Meteor. But in general, you can use Meteor with any frontend framework. You can still follow this guide, even when you don’t know about React.

Node.js and npm (or yarn) should also be installed on your machine and available from the command line. If you haven’t already, get it from the official website or use a handy tool like n.

Installing Cypress

First, let’s install Cypress. I’ll be integrating it into a todo app built with Meteor and React from Meteor’s tutorial series. If you’d like to try out Cypress in a clean app, you can download the todo app and start from there (you’ll need to run npm install and might want to run meteor update -all-packages to get the newest release). But you can also follow this guide to integrate Cypress into your own Meteor app.

cd /your/project/path
npm install cypress --save-dev

It will take a few minutes to install the packages as well as the Cypress binaries required to run tests. The folder structure we need for Cypress will be created when we run it for the first time (more on that below).

Next, let’s add npm scripts to packages.json to run Cypress, which we’ll use throughout this article.

After adding these scripts, you can run npm run cypress:ui (or yarn cypress:ui) for a graphical test runner and npm run cypress:headless (or yarn cypress:headless) to run it in headless mode (i.e., on the console or in a CI environment).

Run npm run cypress:ui to open the Cypress UI and spend some time getting to know the test runner.

Next, we’ll have a look at some new files and directories that Cypress produces after running one of these commands.

Files created by Cypress on the first run

You’ll discover a new directory cypress/ and a new cypress.json config file at the root of our project.

cypress/
├── fixtures/
├── integration/
├── plugins/
└── support/
cypress.json

cypress/fixtures

In the fixtures folder, you may save static data that will be utilized throughout our tests. We won’t spend much time discussing this area of Cypress, but if you want to learn more, I recommend looking at the official documentation about fixture files.

cypress/integration

This folder is where all of our tests will live. The sample tests that you experimented with earlier will all have been generated here.

cypress/plugins

Cypress is running a node process that can be used to extend some of its functionality. This is done via plugins. It includes configuring file pre-processors or loading configurations, both of which will be covered below.

cypress/support

Out of the box, Cypress provides the cypress/support/index.js file that will be run before every test. It can be used for several things such as a global beforeEach hook overrides and setting up custom commands which I will also demonstrate as part of this article.

Configuration and setup of Cypress in a Meteor app

Let’s delete all example tests generated by Cypress and write our first test.

# Delete all Cypress example tests
rm -rf cypress/integration/examples

Configure test directories in cypress.json

Meteor by default loads every .js file in our project directory (except for specific folders likeimports/). Attempting the same with our new tests files will result in an error:

While processing files with static-html (for target web.browser):

Your program is crashing. Error while waiting for a file change.

To avoid this, do one of the following:

  1. Move the cypress directory to tests/cypress/ (a tests folder will be ignored by Meteor by default), or
  2. add cypress/* to .meteorignore (to tell Meteor to ignore this folder)

You will have to edit cypress.json accordingly. In the remainder of this article, I assume that you went with option (1) and your Cypress folder is now located under tests/cypress in your project.

You can find more details about these configurations in the official Cypress docs.

Create a new folder tests/cypress/integration/tests so we can add some extra logic (e.g helper functions …) in tests/cypress/integration without Cypress detecting it as actual tests.

Adding a placeholder for the first test

Now we are ready to create our first spec file. Create a login.spec.js file in tests/cypress/integration/tests to test the login feature.

Now run npm run cypress:ui, select our newly created spec file login.spec.js and you should see this result:

Way to go!

Have a dedicated environment for running tests

When running tests, you should do so on a separate database. I find it handy to use Meteor’s local database that is created when starting a local server. Even when you are developing your app on a local database, you can create another database as a dedicated test database.

To do so, Meteor has an undocumented (only appears in the changelog) environment variable METEOR_LOCAL_DIR which specifies the directory from which Meteor launches everything. By default, it is set to .meteor/local. When changed to .meteor/test, the test instance will be completely isolated from the development instance, including the database.

Also, I prefer to run Meteor on a different port than in development, so we have a completely separate environment to work on. Let’s add the script for this in package.json:

Besides METEOR_LOCAL_DIR, we set two more environment variables:

  • BABEL_ENV: This will be used to load the “test” configuration in .babelrc which we’ll need for test coverage.
  • DISABLE_REACT_FAST_REFRESH: This will disable hot module replacement, which we won’t need for running tests. You will only have to set this when using React and the react-fast-refresh package.

Run and stop Meteor automagically

You still have to manually launch Meteor (npm run e2e) and run your tests in a different terminal (for example, npm run cypress:headless). To make this more convenient, you can install start-server-and-test (npm install --save-dev start-server-and-test). As the name suggests, this package starts the server, waits until it’s ready, and launches the tests in one command. So in our package.json we now should have:

Run npm run test:dev:headlessand the server should start and Cypress will run after that.

Fetching DOM elements in Cypress

While using Cypress, one best practice for querying DOM elements is to add data-* attributes to these elements, rather than using class or tag selectors.

Anti-Pattern: Using highly brittle selectors that are subject to change.
Best Practice: Use data-* attributes to provide context to your selectors and isolate them from CSS or JS changes.

To avoid repeating ourselves, we create a helper function testProp and some constants that hold the IDs that we’ll add to the elements to test.

Create a new file imports/testIds.js:

We’ll do the same for our app’s routes. It’s likely that your test scenarios require visiting routes throughout your app. Let’s add a new file imports/routes.js:

Let’s import everything from testIds.js and routes.js into a new file tests/cypress/integration/constants/index.js. This is to make sure that we have all our test dependencies in one place.

Whenever we need to access an ID or a route in a test, we import it from tests/cypress/integration/constants.

In the LoginForm component (of the example todo app), add the ID to the element using our helper function:

By using testProp (instead of directly setting data-test-id) we have the flexibility to easily change the data attributes in the future and to only set these attributes when the app is running in testing mode (and hide them in production).

Seeding the database

Usually, when testing, it’s preferred to have a clean state of the database for each test. The database should have a defined set of data to test against.

By resetting the database before each test, we avoid:

  • having inconsistent data throughout our test suites,
  • tests which depend on previous tests (which can be hard to reason about),
  • complicated test scenarios and dependencies,
  • unstable and unreliable test data.

There are several ways to fill the database with initial data:

  • Create a test that interacts with your UI so that data is created that then will be used by the following tests.
  • Expose Meteor methods to set up a certain test on the server. This results in “backdoor” functionalities that you don’t want to expose in production.
  • We can simply use fixtures for filling out forms, setting user credentials, and most of the data that a user might put into your application.
  • Use a Cypress task. In a task, you can execute code in Cypress’s Node.js process. We can leverage this API to tear down or seed a database with data we’re in control of.

Using a Cypress task is arguably the cleanest approach and is also recommended by the Cypress documentation. It provides flexibility, a good developer experience, and isolates the seeding from the rest of the code. However, resetting the database before each test this way is certainly not the fastest approach and it might slow down your test suits.

There is a helpful library called mongo-seeding that manages to seed the database for us (assuming you’re using Meteor with MongoDB). All we have to do is provide the JSON files for the documents that we’d like to put into the database and implement the seeding as a Cypress task.

npm install --save-dev mongo-seeding

First, let’s create a tests/cypress/plugins/data directory that contains a tasks and a users directory (same as the collection names “tasks” and “users” in our todo app example). Then add a tests/cypress/plugins/data/tasks/tasks.json and tests/cypress/plugins/data/tasks/users.json file:

Next, let’s create a seeder.jsfile in/tests/cypress/plugins :

Then, import this seeder as a Cypress task like so:

tests/cypress/plugins/index.js

Now, whenever we need to seed our database we just call the task in the beforeEach hook:

Running tests

Let’s improve the login.spec.jstest to see Cypress in action.

Now, run npm run test:dev:headless (or yarn test:dev:headless) in your console, and the test should pass successfully.

Custom Cypress commands for querying elements

cy.get or cy.visit are examples of built-in commands in Cypress.

The ability to create custom commands is another feature of Cypress that improves the developer experience and test reusability. This is especially handy for routines such as logging in.

The supportdirectory is a good location to put our custom commands.

For this example, I am going to create a custom command cy.getById(ID_STRING) to query an element by its data-test-id attribute.

in tests/cypress/support/commands.js

We can now rewrite our test to look like this:

Now that you get the gist of what commands are, let’s see how we can write some that will help us test in Meteor.

Custom Cypress commands for Meteor

cy.getMeteor()

As you noticed in our login.spec.js test we run cy.window().its('Meteor').invoke('user') to get the window object, get Meteor from it, and then call the Meteor.user() function to assert that the user is authenticated.

As you will use the Meteor object often, this will be tedious. You probably guessed right — we can put this in a custom command.

in tests/cypress/support/commands.js

Now we can update the tests/cypress/integration/tests/login.spec.js:

cy.allSubscriptionsReady()

Another support command that we need is waiting for Meteor subscriptions to be ready after a page load.

in tests/cypress/support/commands.js

cy.visitAndWaitForSubscriptions(…)

We need this mostly when visiting a URL within our app. So let’s create another custom command that waits for all the subscriptions after visiting a URL.

in tests/cypress/support/commands.js

Now, we can be sure that after visiting a route we have all subscriptions ready before we make any assertions.

cy.callMethod(…)

One other important command that we’ll add is cy.callMethod. It calls a Meteor method by passing it the method name and parameters :

in tests/cypress/support/commands.js

Finally login.spec.js will look like this :

Using Fixtures

Fixtures are a way to load predefined data during a test. They are complementary to seeding the database before each test as they are used within a test.

Accessing aliases as properties with this.* will not work if you use arrow functions for your tests or hooks.

To be consistent in our test suits, we use the regular function () {} syntax as opposed to the lambda “fat arrow” syntax () => {}. Sometimes we’ll need to use this to access a Cypress feature in a test which is only possible with the function syntax.

First, let’s create our fixtures file:

tests/cypress/fixtures/tasks.json

Let’s create a new test spec file for tasks called tests/cypress/integration/tests/tasks.spec.js where we will use fixtures and our custom command cy.callMethod().

As you noticed in the beforeEachhook we fetch the fixtures and assign an alias for it named tasks. To get the first task in fixtures we use this.tasks.testUserTask[0].

Test coverage

In terms of quality and efficacy, test coverage (how many lines of code your tests cover) is an essential metric in software testing.

This metric is computed using the following formula:

We need to utilize specific tools to identify the lines of code that were executed when running our test cases. Essentially, each line of code is provided with a counter of how often it was run. This is called code instrumentation.

Luckily, Cypress provides a library @cypress/code-coverage to automate this. In the background, it uses istanbul.js for instrumentation and generating code coverage reports.

For more about test coverage, the official Cypress documentation about test coverage is as usual pretty good.

Test coverage on the client

Now, let’s add test coverage to our app. The first step is to install the @cypress/code-coverage library:

npm install --save-dev @cypress/code-coverage

To set it up, add totests/cypress/support/index.js

Adapt your tests/cypress/plugins/index.js

Next, we must add the following dependencies to our project:

npm install --save-dev @babel/preset-env babel-plugin-istanbul
npm install --save-dev @babel/preset-react # Only for React, ymmv

Since Meteor transpiles new JavaScript features out-of-the-box, we usually don’t need to care about setting up Babel. However, here we make sure that the instrumentor istanbul.js also understands the source code of our app.

These dependencies are used to configure the preprocessor to transpile our source code to the instrumentor.

Additionally, we configure Babel in a .babelrc file at the root of the project.

Remember BABEL_ENV? By setting BABEL_ENV=test, we ensure that the following presets and plugins are only used in a test environment.

istanbul.js provides a command-line tool nyc that is used for instrumenting the code. To configure that to our needs as well, add nyc.config.js to the root of your project.

Now run the test.

  • A .nyc_outputdirectory will be created in our project root folder containing the raw coverage data from nyc.
  • A tests/cypress/coveragedirectory containing the reports is created:

You’ll see a graphical representation of the code coverage results when you open tests/cypress/coverage/index.html.

Test coverage on the server

One final but important step is to also collect server code coverage. Right now, Cypress cannot know what happens on the server until we provide an interface to retrieve this data. To do this we hook into Meteor’s WebApp and expose a route to fetch the __coverage__ object. Note that we only expose the route when the app is running in a test environment.

In server/coverage.js add this code:

Then import this file to server/main.js (or wherever your server entry point lives).

Now add the config necessary for Cypress to detect and merge it with the client coverage.

In cypress.json add :

After running the tests again, the report should like this with new files detected from the server:

Conclusion

It’s time to rejoice! By now you should’ve set up Cypress in your Meteor app, be able to generate coverage reports, understand how custom commands make your life easier, and be ready to test away.

You can view all that was said in this article in this example repository. If you have suggestions on how to improve this guide, please let us know.

Next steps?

Now that you’ve set up everything, you can start writing meaningful end-to-end tests for your app. Code coverage reports can give you pointers where tests are missing. Apart from that, the official Cypress documentation will often come to the rescue.

Resources

This guide wouldn’t have been possible without the documentation, posts, discussions, and ideas of the open-source community. Here are the original sources.

This article was written by Idriss Mahjoubi and Timo Schneider from consider.ly. If you like it, tell your friends about it 😊


Testing a Meteor app with Cypress was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

How ALLOHOUSTON Makes Organizations Smarter with Meteor

$
0
0

Many businesses have the will to innovate but lack the roadmap to do so efficiently and intelligently.

There’s where the experts at ALLOHOUSTON become invaluable.

This lean software startup based in France helps organizations create and transform their processes with customized digital solutions.

Whether a business wants to launch a new product or service, create an app, optimize its growth model, or better serve its customers, ALLOHOUSTON provides the roadmap to help them navigate this complex digital landscape with ease. And they’ve been achieving these end-to-end solutions using Meteor.

In this case study, we’ll walk through ALLOHOUSTON’s process, check out their tech stack, and see how Meteor makes it all happen.

Meet the ALLOHOUSTON Team

ALLOHOUSTON says they’re a technical partner for any organization wanting to transform its ways of working.

Launched in 2016, this independent startup has no external investors, supporting its growth through controlled equity. Its founders say everyone on the team shares the same convictions and values: pragmatism, simplicity, teamwork, empathy, and transparency.

And in typical startup fashion, the ALLOHOUSTON team works in a garage transformed into an Open Innovation space (“Le Square”) at the Filles du Calvaire metro station in Paris, France.

So What Does ALLOHOUSTON Do?

ALLOHOUSTON specializes in understanding each business’s needs and achieving solutions that exceed them.

Their customers are business professionals who don’t know how to handle digital transformation or optimization and face daily challenges in their jobs as a result.

Starting from a simple brief, an ALLOHOUSTON Consultant-Developer approaches each project with pragmatism and simplicity. They work closely with future users to create a digital response that fits their needs and the needs of their clients.

And since ALLOHOUSTON’s team speaks all operational languages, it’s easy to help clients choose the best course of action.

Once a plan’s in place, their team carries out all aspects related to their method, including:

  • DSI Relations
  • Contractualization
  • Development
  • Commissioning
  • Maintenance
  • Monitoring

This mission helped ALLOHOUSTON land some pretty impressive clients, and their follow-through led to even more remarkable achievements.

ALLOHOUSTON’s Top Achievements To Date

ALLOHOUSTON works on projects of all sizes and in all business sectors. Though most of their experience comes from working for big and small organizations in France, the team has also successfully partnered with international clients.

Check out this list of projects they’ve shipped:

PARIS INTERNATIONAL AIRPORTS. Provided new innovative services based on the measurement of passenger flows (four new services designed and tested in ten months).

ACPM. Enabled the certification of Podcast downloads for the organisation that audits media circulation. A daily processing of podcasts logs ensures metrics consistency. The new certification was ready to launch within 2 months.

RENAULT GROUP. Enabled the production, monitoring, and analysis of downstream supply chain indicators 100x faster.

RENAULT NISSAN CONSULTING. Improved client satisfaction and the health of the firm’s projects with a new business process supported by a mobile application (in four weeks).

Want all the details on these stellar wins? Click here to take a deeper dive into how AlloHouston achieved these (and more!).

So how does ALLOHOUSTON do it?

Take a Peek at the ALLOHOUSTON Tech Stack

ALLOHOUSTON says almost all their projects use Meteor + Blaze.

ALLOHOUSTON uses Mongo as the database and very often Grapher from Cult Of Coders to provide complex and efficient data fetching. They occasionally use AWS DynamoDB as the database engine.

Inside the apps, they love the abilities given by d3 and crossfilter libraries. Around the apps, they like to use Python and Apache Spark to build data processing pipelines from data files provided by other systems. They also perform computations and store results in MongoDB.

For mobile development, ALLOHOUSTON relies on React-Native either with Meteor or with AWS Amplify.

Why ALLOHOUSTON Builds With Meteor

ALLOHOUSTON is proud to say they’ve been using Meteor since v0.8!

The ALLOHOUSTON team wasn’t trained as developers, so they loved the idea of learning a single language and being able to code at the same time for servers, web browsers, and mobile.

They initially used Meteor to build side projects like their first app: an event planner that helped guests organize what they should bring to a house party. The users’ live updates made the app fun to use and “felt really modern at the time.”

When they officially launched ALLOHOUSTON, Meteor helped them build almost every project to this day. They started with and continue to use Blaze because “it’s so easy and fast.”

“Meteor + Blaze is, in our mind, the most efficient way to build a new product from scratch.”

The team says they’ve developed a very personal way to use Meteor with their own tooling. For example:

  • Starter apps configured with their best practices and standards.
  • Shell scripts for scaffolding new Templates or new Mongo Collections.
  • Utilities around data input (for fields and forms).
  • Data fetching and displaying, such as server-side pagination, pagination for UI and mechanisms, lists of items, search, etc.
  • Tooling to deploy and maintain applications in the cloud.

But this success was not without its fair share of ups and downs.

3 Challenges ALLOHOUSTON Solved with Meteor

According to ALLOHOUSTON, the “bulletproof” Meteor guide written by Arunoda helped their team navigate the complex waters of performance and security during their first years.

Upon reflection, most of their challenges came from:

Daily Data Handling and Processing

ALLOHOUSTON had to find ways to handle data consistently and efficiently, so it didn’t affect performance. Several of their apps regularly receive data files from customers, which they process using Apache Spark and store computation results in MongoDB.

In addition to good indexing of collections, the team uses tricks like dynamically creating Mongo Collections depending on the month, or storing the history of information so they don’t lose details while overwriting data.

High-Level App Security Requirements

Before they delivered their first app in production for Renault, they received a formal checklist of security specifics they’d need to guarantee. Having full control over the application code and the server infrastructure allowed them to comply in full and move on.

ALLOHOUSTON enjoys not having to waste time taking care of user and password management or the handling of user sessions when building their apps — Meteor covers these bases for them.

“Meteor’s internal security is first class, and we saved a lot of time thanks to it.”

ALLOHOUSTON has been able to get these security tools and functionalities running quickly with Meteor over the last few years:

  • SSL connections
  • SSO based on OpenId technology
  • Logging of all database modification and access
  • Data encryption at rest at a field level
  • Data encryption at rest of the database and user files
  • Enforcing password strength for users
  • Server isolation
  • Protection against XSS
  • Antimalware scanning of uploaded files
  • Superior user authorization for methods and publications

One of their apps went through a full audit from Orange Business Services and was soon validated by them. According to ALLOHOUSTON, Orange Business Services was “quite impressed” with the WebSocket connections (DDP) and Meteor’s security and solidness.

Monitoring

The ALLOHOUSTON team says monitoring was “quite a challenge at first” in two aspects: ensuring application availability, but also application performance.

They used the “excellent” APM developed initially by Arunoda for performance monitoring, and Statuscake as a monitoring and alerting tool for availability.

What’s Next for ALLOHOUSTON

The next steps for ALLOHOUSTON include:

1. Developing tooling to be more efficient. The team wants to gain speed when creating applications, so they can serve more clients without compromising quality and expand their steady business.

2. Grow their team (PS: They’re hiring!). AH hired its first employee with very few technical skills (only three intensive months of web classes in HTML, CSS, and JSS). They helped her ramp up her competencies so she can now create a wide range of functionalities in their apps.

ALLOHOUSTON calls this a “great achievement” for their company. They hope to hire many more employees who embody their company’s mission and values.

3. Convince more people to embrace their ways of working. AH believes their new and unique way of working holistically and intelligently on projects will soon become mainstream.

Their philosophy includes:

  • Enhancing collaboration inside a company around a business process
  • Automating reporting and computations
  • Providing missing links between other business software
  • Creating a backoffice to manage a specific business

There’s no stopping the ALLOHOUSTON team from reaching all these goals in the near future. So what about your team?

Ready To See How Meteor Can Help Skyrocket Your Team To Greatness?

Meteor is an open-source framework for seamlessly building and deploying web, mobile, and desktop applications in Javascript. And as we’ve seen in this case study, our customers skyrocket to success with our help.

So what can Meteor do for you?

If you’re ready to find out, join the community of more than 500k developers from all over the world that trust and rely on Meteor today!


How ALLOHOUSTON Makes Organizations Smarter with Meteor was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Announcing Meteor 2.4 And The New Installer

$
0
0
Announcing Meteor 2.4

Version 2.4 brings you new features, performance improvements, and a new installer.

You probably know that Meteor has had a few different installers during the years. Our most recent update allowed Meteor users on Windows to use NPM to install Meteor.

Now we are enabling this option for Unix & macOS, and we’re happy to announce the new way to install Meteor:

npm install -g meteor 

Yes, it’s that simple. Just an easy npm install and you are ready to go. Read more about this installer in our docs.

Continue reading for other news in Meteor 2.4.

Windows improvements

Some Meteor commands were hanging on Windows and we finally isolated the problem. This problem was caused by the native file watcher library that we’re using, but in many cases, this watcher was not necessary.

One case that was happening very often was in the meteor create command, specifically after the first install. Now, this command is not using this library and meteor create shouldn’t hang anymore in Windows.

We’re researching another library to fix this problem in the long term but for now, we should be good with this workaround.

New Collection method: createIndex

Following the deprecation and removal of ensureIndex method in MongoDB 5, we are making the first step towards this MongoDB release by deprecating our own _ensureIndex method on collections and replacing it with createIndex.

There are no changes in the behavior so you can use createIndex as you were using _ensureIndex before. Behind the scenes Collection _ensureIndex is using the same implementation as createIndex so both are safe to use.

Email: custom transport and known services

In version 2.2 of the email package, we are adding two new features.

First Email.customTransport, which allows you to override the sending functionality with your own handling. This way you can stop sending emails via SMTP that you set in MAIL_URL env var and instead use API provided specifically by the service you use. See how to use this with Postmark below:

As you have informed a customTransport Meteor is going to send all the emails using it. Read the docs for more details.

Second is the option to use Meteor.settings.packages.email to set options for sending using known services of Nodemailer. You just need to provide the name of the known service, user, and password in the settings and the package is going to take care of the rest.

Make sure to check over the updated email documentation for all the implementation details.

The MAIL_URL env var is still going to work and we have no plans to deprecate it.

Runtime Performance Improvements

The latest version of reify reduces the overhead of import statements and some uses of export ... from, especially when a module is imported a large number of times or re-exports a large number of exports from other modules.

The benefits are clear when working with huge libraries like @material-ui/icons, you can read more details in the PRs. 12

This optimization opens the door for us to resume the work in Tree-shaking as huge libraries are not a big problem for us in development anymore and Tree-shaking can now be enabled only for production builds.

Publications Fine Tune

Publications can now use different strategies in the way it uses the mergebox. You can tune the behavior so that you can better manage bandwidth usage and server-side memory. There are 3 strategies available SERVER_MERGE, NO_MERGE and NO_MERGE_NO_HISTORY to choose from.

Keeping it simple:

SERVER_MERGE: Default Meteor behavior, nothing new here.

NO_MERGE_NO_HISTORY: Should only be chosen for special use cases like send-and-forget queues.

NO_MERGE: Remembers only the IDs sent to the client and applies new rules when adding, updating, and removing documents into Minimongo.

These strategies are selected for each publication so you can have a mix of them in your app, choosing the best strategy for each scenario. It will be nice to see new ways to combine Publications emerging from the community now that we have different options available. Read all the details in the docs.

Vue 3 integration

Since July we started to use GitHub Discussions to discuss ideas and feature requests for Meteor.

At this moment the #1 discussion is the discussion about Vue 3 integration and we are happy to announce the first version of this integration!

If you want to help with testing the integration you can install the package, read the docs and give it a try:

meteor add vuejs:vue3

This release was possible because of our amazing community, led by Guillaume Chau.

Apollo server 3

New major version of Apollo server has been released. For those starting a new project, we have upgraded our Apollo skeleton with the necessary changes so you can start your new Meteor Apollo project easily.

For those who are already running on Apollo server v2 and would like to quickly know how to upgrade, there is an article how to do so, but keep in mind that based on what features you are using, you might need to do much more work and as such you should consult the Apollo upgrade guide.

Runtime configuration hooks

The latest webapp package now allows you to create a runtime config hooks that get called when runtime config is set or changes.

For example, in some cases, it is valuable to be able to control the __meteor_runtime_config__ variable that initializes Meteor at runtime.

There are occasions when a single Meteor server would like to serve multiple Cordova applications that each have a unique ROOT_URL. But there are two problems:
1. Meteor server can only be configured to serve a single ROOT_URL.
2. Cordova applications are build-time configured with a specific ROOT_URL.

These two conditions break autoupdate for Cordova applications. cordova-plugin-meteor-webapp will fail the update if the ROOT_URL from the server does not match the build time configured ROOT_URL of the Cordova application.

To remedy this problem webapp has now a few hooks for dynamically configuring __meteor_runtime_config__ on the server.

These are:

  • WebApp.addRuntimeConfigHook
  • WebApp.addUpdatedConfigHook
  • WebApp.decodeRuntimeConfig
  • WebApp.encodeRuntimeConfig

Read more in the docs.

Facebook OAuth login handler

facebook-oauth now features a new login handler hook same as the one for Google package which should make it easier for you to retrieve data if you are using React Native and similar tools. Read more.

Typescript Upgrade

Typescript upgrade to v4.3.5 is a patch release with a bug fix for auto-imports in JSX components.

And much more!

There were many other smaller improvements and updates made for this release like updated dependencies for minifiers and bug fixes that are either part of this release or were released independently in their respective packages. Make sure to read the full changelog for a list of all the details and upgrade to Meteor 2.4 by running meteor update in your app directory!

If you have any questions for us, feel free to reach out in the Forums, or to support@meteor.com.


Announcing Meteor 2.4 And The New Installer was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Viewing all 160 articles
Browse latest View live