By default, your express application will store session data in memory. That means if your server restarts all users will need to log back in. Additionally, this does not scale to more than one instance, leaks memory and does other mean things. While this works while developing your local computer (notice how you always need to log in after making a code change), you will want something better for production.
Heroku even warns you if you do this. Try running $ heroku logs --tail to see this.
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker.
Step 1: Create the heroku add on
$ heroku addons:create heroku-redis:hobby-dev
This will create a REDIS_URL in the heroku config that you will use to connect. Use $ heroku config:get REDIS_URL to see this value.
Step 2: Download the connect-redis package for your project
$ npm install -s connect-redis
Step 3: Pass in express-session into connect-redis
Step 4: Create an instance of RedisStore as the store property of your session configuration
Note: your local computer probably does not have REDIS_URL set.
Step 5: Push to heroku and try your new session store
$ git push heroku master
How do you run your project locally now?
Option 1: default to memory session store locally
Check your NODE_ENV setting and if its not production we will default the store property to null.
Option 2: default to using a redis instance locally
Run these commands and connect to your instance directly.
Gotcha Error: req.flash() requires sessions
If you try running your project locally, you will notice that your session store fails to initialize and things break – this happens since you likely do not have the REDIS_URL set.
Note that redis on hobby dev will not allow SSL and to secure a production redis, you will need to pay for a production plan and add “stunnel” to your buildpack. (link)
The best way to do this is to run the npm init command
$ npm init
This will insure you have the required package.json file with name and version set.
Step 2: Publish
$ npm publish
If you are not logged in, you will need to run npm login
Step 3: Test your npm package
Double check your package information with $ npm info <package_name>
Alternatively, go to another repo and run $ npm install <package_name>
Congrats! Your code is out in the wild on the npm registry 🙂
Troubleshooting: Package name already exists
You might run into the issue where someone else has taken the name of your npm package. Note that you can set a different name on npm than your github repo. One option is get super creative with your npm package name and change the “name” key in package.json. Another option is to namespace your package to your username like this:
and then publishing this with the public flag
$ npm publish --access=public
What if I want to publish a new version?
npm will reject your package if you do not bump the version number. Use npm version and choose either major, minor, or patch. This is the example for patch
You are in flow developing on your local database and you decide to upload everything to heroku and share it with the world.
How do you configure your production database?
It’s easier than you think. Let’s assume you have already set up your site.
If you used the sequelize init command, you will have a file db/models/index.js that looks like this
Usually, your sequelize database will initialize with the usual database, username password, etc but in the special case that your config has use_env_variable, sequelize will recognize that an environment variable (usually representing a URI) can be used in place of the usual credentials.
What is your env/config variable?
Find your heroku config variables in the heroku website or by running $ heroku config. Note, config and env variables are used to reference the same settings here.
When you create a database on your heroku account, it will default a new configuration setting called “DATABASE_URL”
You can access this with process.env.DATABASE_URL in any of your node.js code (on production). Your local machine will have different environment variables set.
Step 1: Set use_env_variable
But set it to what? Set it what heroku designates as your database url, DATABASE_URL!
You may need to migrate your database if you aren’t using sync
Step 2: Migrate your database
Simply run the migrate command in the heroku environment with heroku run. This avoids any configuration errors of running from your local environment
$ heroku run ./node_modules/.bin/sequelize db:migrate --debug
Step 3: Check your database
Run the heroku psql command and run the “list tables” command.
$ heroku psql
Error: no pg_hba.conf entry for host…, SSL OFF
Add the ssl setting into dialectOptions of your config.json
Error: The server does not support SSL connections
This may be an outdated error. But previously, users who tried to migrate on their local computer would run into this error.
This will not work correctly unless you set up your local computer to support ssl in the migration. You could get a certificate and configure your sequelize config to use that BUT theres an easier way.
If you use .sync with sequlize and have a model name like User, your database ends up with a table called Users. More clearly, when you use the sequelize-cli model generator the generated file will show this pluralized table. Here is the code: (link)
What is Utils?
* Note Sequelize has a directory called Utils AND a file at lib/utils.js.
What’s in lib/util.js?
We find the function! This is how sequelize defines utils.pluralizelink
Many browsers have implemented events “online” and “offline”; in addition to this, browsers also expose the navigator.onLine property that will return “online” or “offline”
How many browsers is many?
caniuse says every major browser (Chrome, Firefox, Safair, IE11…) except Opera mini has this functionality (as of July 4th 2018).
How can I check the online status?
How can I listen to events?
Be loud if core functionality depends on staying online
If your app depends on autosaving,
BE LOUD ABOUT NOT BEING ABLE TO SAVE.
Be like workflowy*. Tell the users, make them listen.
You will likely need more error handling than this. For example: what if your server is offline? what if the request body has malformed? what if the server is up but your database is down? what if the api hits a 404 and do you let your devs know about this?
Imagine you’re playing Mario Kart on a four person split screen. There are four Yoshis on the screen for each player. How many Yoshis should we model?
The obvious answer is four: there are four Yoshis on the screen, so there must be four Yoshis. The problem is that this answer misses something important, and fails to answer a critical question: what if there were no Yoshis on anyone’s screen right now? Does that mean there should be zero Yoshis? No, of course not, Yoshi can fall behind in the race and should still exist.
The real answer is there is only one Yoshi – one source of truth that dictates where Yoshi is, how fast he’s going, what items he has, and what he’s about to do. Fundamentally, all this means is that Yoshi exists separate from his representation to the user. We can organize our code to represent this by grouping our data about Yoshi in a single location.
Models as the source of truth
Models are used to encapsulate data. A Model stores data properties and serves as the ultimate reference in other parts of our game. In our example Yoshi, Mario, Bowser are all Models – they have a single state and source of truth that’s associated with them. With this distinction we avoid searching for information on multiple Yoshis or creating logic to determine which copy of Yoshi is the most updated version of our racer.
Models are isolated from the code that displays the screen to the user so while Yoshi may turn a corner and disappear from the screen, our game logic continues figuring out how fast and far Yoshi has gone. We decide what to show users through building Views.
Views as Lakitu
Views decide what to show the user. Each View is associated with a model, and decides exactly how that model should be shown on screen. We wouldn’t want to just show the user all the stats about Yoshi, we want to make it a cute green dinosaur in a cart that you can see and aim at – View’s make that happen.
You can have lots of Views for a single model. For instance, even though there’s one Yoshi there’s actually up to four Views associated with him! In regards to Views, four is actually the right answer. Our Model for Yoshi has only one location and one speed, but our View shows him in four different places on each screen and renders him going in different directions depending on where you
If we began to store information about Yoshi in the graphic, we run the risk of creating data inconsistent with our original source of truth. What if there are multiple Yoshi graphics? By separating the storage of data from the representation of data we ensure that all players see the same Yoshi.
Events as a Blue Shell
When Bowser grabs a blue shell and throws it, this is a global event that every racer wants to know about. A smart group of Views will have event listeners on its respective Models. Smart Views can listen to events from the Model such as a ‘change’ or ‘add’ event. As our Models pass these event notifications to our Views, the screen responds by showing the player a blue shell rushing towards first place.
Our method of drawing data becomes increasingly more important as we add online players to the race from Mario Karts game servers. Having one source of data ensures that every player has a uniform experience. As there is only one Yoshi, there should only be one tweet, wall post and chat message that our Views are listening to.
Libraries and Frameworks
Concise code lends itself to become more reusable and testable. Our clear sense of separation and organization allows us to write modular code that is focused on clearly defined tasks. Every library and framework implements this differently and it will take some exploring to find the right fit.