From 5a2828c4dfd66e75de899080e461c3d482f152a0 Mon Sep 17 00:00:00 2001 From: jrtechs Date: Fri, 5 Oct 2018 21:47:25 -0400 Subject: [PATCH 1/2] Added a very basic latex support for blog posts using pandoc. --- README.md | 3 +++ admin.js | 2 +- admin/admin.js | 1 + admin/category/addCategory.js | 2 +- admin/downloads/manageDownloads.js | 2 +- admin/login/login.js | 6 +++-- admin/posts/newPost.js | 2 +- ...ngFibonacci.md => everything-fibonacci.md} | 0 includes/html/contact.html | 2 ++ includes/html/header.html | 5 ++++ package.json | 2 +- posts/singlePost.js | 21 +++++++++++---- utils/markdownToHTML.js | 26 +++++++++++++++++++ utils/sql.js | 8 +++--- 14 files changed, 66 insertions(+), 16 deletions(-) rename blogContent/posts/programming/{EverythingFibonacci.md => everything-fibonacci.md} (100%) create mode 100644 utils/markdownToHTML.js diff --git a/README.md b/README.md index 1ca66b0..2ca504d 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,9 @@ npm install memory-cache --save npm install request npm install nodemailer npm install nodemailer-smtp-transport + + +npm install node-pandoc ``` diff --git a/admin.js b/admin.js index 574263a..ff986e5 100644 --- a/admin.js +++ b/admin.js @@ -67,7 +67,7 @@ app.use(function(request, result) const file = "./admin/admin.js"; Promise.all([includes.printAdminHeader(), - require(file).main(filename, request), + require(file).main(request), includes.printFooter()]).then(function(content) { result.write(content.join('')); diff --git a/admin/admin.js b/admin/admin.js index 57fe199..967086a 100644 --- a/admin/admin.js +++ b/admin/admin.js @@ -22,6 +22,7 @@ module.exports= { utils.getPostData(request).then(function (postData) { + console.log(postData); Promise.all([require("./posts/newPost.js").main(postData), require("./category/addCategory.js").main(postData), require("./posts/editPost.js").main(postData), diff --git a/admin/category/addCategory.js b/admin/category/addCategory.js index 3dfbfc5..d05fac9 100644 --- a/admin/category/addCategory.js +++ b/admin/category/addCategory.js @@ -81,7 +81,7 @@ module.exports= { return new Promise(function(resolve, reject) { - Promise.all([utils.include("./admin/addCategory.html"), + Promise.all([utils.include("./admin/category/addCategory.html"), printCategories(), processPost(postData)]).then(function(html) { diff --git a/admin/downloads/manageDownloads.js b/admin/downloads/manageDownloads.js index be0e02b..84ef742 100644 --- a/admin/downloads/manageDownloads.js +++ b/admin/downloads/manageDownloads.js @@ -57,7 +57,7 @@ const addDownload = function(postData) return new Promise(function(resolve, reject) { Promise.all([addDownloadPostData(postData), - utils.include("./admin/addDownload.html")]).then(function(html) + utils.include("./admin/downloads/addDownload.html")]).then(function(html) { resolve("
" + html.join('') + "
"); }).catch(function(error) diff --git a/admin/login/login.js b/admin/login/login.js index 1521579..71aafd9 100644 --- a/admin/login/login.js +++ b/admin/login/login.js @@ -22,6 +22,7 @@ const processLogin = function(request) return sql.checkLogin(postData); }).then(function(loginResult) { + if(loginResult.pass) { request.session.user = loginResult.user; @@ -30,7 +31,8 @@ const processLogin = function(request) } else { - resolve(""); + console.log("password incorrect"); + resolve("Password incorrect"); } }).catch(function(err) { @@ -52,7 +54,7 @@ module.exports= { return new Promise(function(resolve, reject) { - Promise.all([utils.include('./admin/login.html'), + Promise.all([utils.include("./admin/login/login.html"), require("../../sidebar/sidebar.js").main(), processLogin(request)]).then(function(html) { diff --git a/admin/posts/newPost.js b/admin/posts/newPost.js index 787eb0b..f0d2cc5 100644 --- a/admin/posts/newPost.js +++ b/admin/posts/newPost.js @@ -55,7 +55,7 @@ module.exports= { return new Promise(function(resolve, reject) { - Promise.all([utils.include("./admin/newPost.html"), processPost(postData)]).then(function(html) + Promise.all([utils.include("./admin/posts/newPost.html"), processPost(postData)]).then(function(html) { resolve(html.join('')); }).catch(function(error) diff --git a/blogContent/posts/programming/EverythingFibonacci.md b/blogContent/posts/programming/everything-fibonacci.md similarity index 100% rename from blogContent/posts/programming/EverythingFibonacci.md rename to blogContent/posts/programming/everything-fibonacci.md diff --git a/includes/html/contact.html b/includes/html/contact.html index 12f5f3c..9efa102 100644 --- a/includes/html/contact.html +++ b/includes/html/contact.html @@ -51,6 +51,8 @@ +
+
diff --git a/includes/html/header.html b/includes/html/header.html index 873c01d..db302d4 100644 --- a/includes/html/header.html +++ b/includes/html/header.html @@ -25,6 +25,11 @@ } p{font-size:18px;} + + + + + diff --git a/package.json b/package.json index 03375c9..802a1d6 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,9 @@ "highlight": "^0.2.4", "highlight.js": "^9.12.0", "markdown": "^0.5.0", - "markdown-to-html": "^0.0.13", "memory-cache": "^0.2.0", "mysql": "^2.16.0", + "node-pandoc": "^0.3.0", "nodemailer": "^4.6.8", "nodemailer-smtp-transport": "^2.7.4", "promise": "^8.0.1", diff --git a/posts/singlePost.js b/posts/singlePost.js index d31b557..04dc292 100644 --- a/posts/singlePost.js +++ b/posts/singlePost.js @@ -5,6 +5,8 @@ const sql = require('../utils/sql'); const Remarkable = require('remarkable'); const hljs = require('highlight.js'); +const pandoc = require('../utils/markdownToHTML.js'); + const md = new Remarkable( { @@ -143,13 +145,22 @@ module.exports= var markDown = utils.getFileContents(pathName).toString(); markDown = markDown.split("(media/").join("(" + "../blogContent/posts/" + category[0].url + "/media/"); - html += md.render(markDown); + //html += md.render(markDown); + + pandoc.convertToHTML(markDown).then(function(result) + { + html +=result; + + html = html.split("").join(""); + html += "

"; - html = html.split("").join(""); - html += "

"; + resolve(htmlHead + html); + }).catch(function(error) + { + reject(error); + }) - resolve(htmlHead + html); }); } catch(ex) diff --git a/utils/markdownToHTML.js b/utils/markdownToHTML.js new file mode 100644 index 0000000..f2c9567 --- /dev/null +++ b/utils/markdownToHTML.js @@ -0,0 +1,26 @@ +const pandoc = require('node-pandoc'); +// const args = '-t html5'; + +const args = '-S --base-header-level=1 --toc --toc-depth=6 -N --normalize -s --mathjax -t html5'; + +console.log(""); +module.exports= + { + convertToHTML: function(markdownContents) + { + return new Promise(function(resolve, reject) + { + // Set your callback function + callback = function (err, result) + { + if (err) + { + reject(err); + } + resolve(result); + }; + console.log(markdownContents); + pandoc(markdownContents, args, callback); + }); + }, + } diff --git a/utils/sql.js b/utils/sql.js index 336fe97..fb86cf5 100644 --- a/utils/sql.js +++ b/utils/sql.js @@ -268,16 +268,16 @@ module.exports= if(post.username && post.password) { - var cleanName = sanitizer.sanitize(post.username); - var cleanPassword = sanitizer.sanitize(post.password); + const cleanName = sanitizer.sanitize(post.username); + const cleanPassword = sanitizer.sanitize(post.password); - var getSalt = "select * from users where user_name='" + + const getSalt = "select * from users where user_name='" + cleanName + "'"; fetch(getSalt).then(function(saltResult) { if(saltResult.length == 1) { - var hashedPassword = crypto.createHash('sha256') + const hashedPassword = crypto.createHash('sha256') .update(cleanPassword + saltResult[0].salt) .digest('hex'); if(saltResult[0].password === hashedPassword) From a0bb869642e723c481118c5372b13905e4bba502 Mon Sep 17 00:00:00 2001 From: jrtechs Date: Fri, 5 Oct 2018 21:59:15 -0400 Subject: [PATCH 2/2] Updated blog posts to look better with the new pandocs parser which creates a index list at the top of the blog post. --- .../posts/java/gremlin-in-10-minutes.md | 24 +++++----- .../java/top-three-recommended-java-ides.md | 16 +++---- blogContent/posts/other/why-do-i-blog.md | 19 ++++---- .../posts/programming/c-to-c++-tutorial.md | 32 ++++++------- .../posts/projects/steam-friends-graph.md | 14 +++--- .../web-development/history-of-jrtechs.md | 13 ++---- .../node-website-optimization.md | 46 +++++++++---------- 7 files changed, 80 insertions(+), 84 deletions(-) diff --git a/blogContent/posts/java/gremlin-in-10-minutes.md b/blogContent/posts/java/gremlin-in-10-minutes.md index bb484b2..ed696d1 100644 --- a/blogContent/posts/java/gremlin-in-10-minutes.md +++ b/blogContent/posts/java/gremlin-in-10-minutes.md @@ -1,4 +1,4 @@ -## What is Gremlin? +# What is Gremlin? Gremlin is a graph traversal language: think of Gremlin as the SQL for graph databases. Gremlin is not a graph database server, it is a language; but, there is a Gremlin Server and a Gremlin Console available for @@ -7,7 +7,7 @@ like [Titan](https://www.digitalocean.com/community/tutorials/how-to-set-up-the- and [HBase](https://docs.janusgraph.org/latest/hbase.html). -## Graph Data Base Basics +# Graph Data Base Basics A graph database is based on graph theory. A graph is composed of nodes, edges, and properties. A key object/component in a graph database is stored as a node. Nodes are connected via edges representing @@ -54,11 +54,11 @@ gremlin> g = graph.traversal().withRemote(DriverRemoteConnection.using(cluster, ``` -## Gremlin Syntax +# Gremlin Syntax Now that you have your gremlin server and console set up, you are ready to start executing Gremlin queries. -### Adding a Vertex +## Adding a Vertex In Gremlin nodes are referred to as "Vertexes". To add a node/vertex to the graph, you simply use the command addV() on your graph traversal source. For consistency, most people @@ -70,7 +70,7 @@ EX: g.addV('student').property('name', 'Jeffery').property('GPA', 4.0); ``` -### Updating a Property +## Updating a Property Unlike SQL, you are not limited to a specific schema in a graph database. If you want to add or change a property on a vertex or edge, you simply use the property command again. @@ -81,7 +81,7 @@ You can replace "g.V(1)" with a command to select a specific vertex or edge. g.V(1).property('name', 'Jeffery R'); ``` -### Selection +## Selection Selecting nodes and edges is the most complicated part of Gremlin. The concept is not particularly hard, but, there are dozens of ways to do graph traversals and selections. I will cover the most common aways to traverse a graph. @@ -111,7 +111,7 @@ g.V().hasLabel('student').order().by('gpa', decr).value('name') ``` -### Adding Edges +## Adding Edges The easiest way (my opinion) to add edges in Gremlin is by using aliasing. In this example we select two nodes and assign them a name: in this case it is "a", and "b". @@ -124,14 +124,14 @@ g.V(0).as('a').V(1).as('b').addE('knows') ``` -## Using Gremlin with Java +# Using Gremlin with Java Now that you know the basic syntax of Gremlin, you are ready to use it somewhere other than the Gremlin console. If you are trying to use Gremlin with Java, there is a great Maven dependency for TinkerPop and Gremlin. If you want to quickly connect to your Gremlin server with Java, make sure your server is set up exactly as it was before this tutorial started discussing Gremlin syntax. -#### Maven dependency for Java: +## Maven dependency for Java: ```html @@ -187,7 +187,7 @@ public class GraphConnection } ``` -#### Basic GraphConnection.java Usage: +## Basic GraphConnection.java Usage: ```java RemoteConnection con = new RemoteConnection() String query = "g.V().hasLabel('player')" + @@ -201,7 +201,7 @@ String query = "g.V().hasLabel('player')" + this.con.queryGraph(query); ``` -#### Overly complex usage with a lambda statement +## Overly complex usage with a lambda statement ```java /** * Fetches the list of a player's friends. @@ -255,7 +255,7 @@ I highly suggest that you look at the tutorial [SQL 2 Gremlin](http://sql2gremli If you plan on deploying this to production, it is recommended that you use HBase for a persistent back end storage server. -## Resources +# Resources - [SQL 2 Gremlin](http://sql2gremlin.com/) - [Practical Gremlin](http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html) diff --git a/blogContent/posts/java/top-three-recommended-java-ides.md b/blogContent/posts/java/top-three-recommended-java-ides.md index 1c106ee..5f4c2cb 100644 --- a/blogContent/posts/java/top-three-recommended-java-ides.md +++ b/blogContent/posts/java/top-three-recommended-java-ides.md @@ -7,8 +7,8 @@ highlighting which makes the code easier to read and error highlighting which makes finding that missing semi colon easier. Here is a list of three IDEs that work well for me. -NetBeans --------- +# NetBeans + NetBeans is the most productive IDE for large java projects. NetBeans is great at detecting errors in your code. You can also have multiple projects open in @@ -19,8 +19,8 @@ JavaScript and C/C++. ![NetBeans IDE](media/2a20326e77c3f67aa3753401ba4bc612.png) -Eclipse -------- +# Eclipse + Eclipse is a very popular programming IDE; however, it is harder to use than NetBeans. The largest benefit of Eclipse is that it has tons of templates for @@ -28,8 +28,8 @@ you to use. Eclipse also has a better GUI creation tool than NetBeans has. ![Eclipse](media/f5cb2682e219549cb07acd1d01c2ccb1.png) -JCreator --------- +# JCreator + I want to warn you that this is a old IDE. You hate yourself if you decide to use this program. The only reason I am putting this on my list is because I @@ -43,8 +43,8 @@ Science students who have to memorize/learn what certain errors mean. ![JCreator](media/c1e712bdead908ebd72921ec2d1cbd5e.png) -Intellij --------- +# Intellij + \*Update 2018 diff --git a/blogContent/posts/other/why-do-i-blog.md b/blogContent/posts/other/why-do-i-blog.md index cbdaeb7..879ebfe 100644 --- a/blogContent/posts/other/why-do-i-blog.md +++ b/blogContent/posts/other/why-do-i-blog.md @@ -5,8 +5,8 @@ Different people may have different takes on this. There is an incentive to start a website in the hopes that it will become popular and make add revenue. However, I argue that there is a intrinsic value to a personal blog. -Organize Your thoughts ----------------------- +# Organize Your thoughts + Being able to clearly articulate your ideas is beneficial. Having time to brew over topics in a blog posts helps that process. Even though I worked with both @@ -14,22 +14,22 @@ Nodejs and PHP, I might not be able to a convincingly debate with somebody why one is the better platform. Writing a blog posts allows me to fully flesh out my own ideas. -Learn ------ +# Learn + When writing a blog post, you want to be complete. If there are any gaps in my knowledge, I will look that information up. This is a great learning opportunity; like taking notes in a class. -Stand Out ---------- +# Stand Out + Out of everyone who uses the internet, only 1% of them contributes additional content. Blogging can make you stand out in a competitive economy when looking for jobs. -Relax ------ +# Relax + This may not be true of some bigger blogs, but, writing blog posts is very relaxing. It gives you time to slow down relax and reflect. There are dozens of @@ -39,8 +39,7 @@ There are already millions of tutorials on the internet, I just want to share my experience on topics that interest me. In this way writing blogs are relaxing and don’t feel like work. -Become A Better Blogger ------------------------ +# Become A Better Blogger There is no way to become better at something other than doing it a lot. Since starting this website when I was middle school, my writing skills have increased diff --git a/blogContent/posts/programming/c-to-c++-tutorial.md b/blogContent/posts/programming/c-to-c++-tutorial.md index 8cef1b6..0d0bcb0 100644 --- a/blogContent/posts/programming/c-to-c++-tutorial.md +++ b/blogContent/posts/programming/c-to-c++-tutorial.md @@ -4,7 +4,7 @@ enable people to use this as a quick reference to quickly jump into C++. This po that you have prior knowledge of both C and object oriented-programming concepts. Each topic is quickly covered in a code snippet and some additional explanation is provided if necessary. -## Input/Output +# Input/Output Input and output in C++ is easy, you use "cout" and "cin". When printing with "cout", you separate what your printing with "<<"; "endl" prints a new line. @@ -39,7 +39,7 @@ g++ helloWorld.cpp -o hello ``` -## Namespaces +# Namespaces Name spaces are used to enable you to have multiple functions/methods called the same thing and not conflict with one another. You use "namespacename::function/variable" @@ -90,7 +90,7 @@ int main() ``` -## Global Variable +# Global Variable Global variables are similar to C, however, you can now reference a global members with the "::" accessor. @@ -112,7 +112,7 @@ int main () } ``` -## Multiple Names for a Variable/Aliasing +# Multiple Names for a Variable/Aliasing This is NOT simply a pointer. In the following example pi, and x now are treated as the same exact variable. You cannot later change the pointer destination for x. @@ -128,7 +128,7 @@ cout << "pi: " << pi << " x: " << x << endl; // prints pi: 2.1 x: 2.1 ``` -## Passing Variables by Reference +# Passing Variables by Reference In C, everything was passed by value; C++ allows us to pass variables by reference. This is very powerful, in languages like Java, only Objects are passed by reference. C++ lets you decide exactly @@ -178,7 +178,7 @@ int main() ``` -## Functions Returning Variables References +# Functions Returning Variables References A function can return a value reference which can be treated as a variable. In the following example, a function returns the reference to the variable which is the smallest. @@ -211,7 +211,7 @@ int main () ``` -## Inline +# Inline Inline can be used to replace a function which contains very simple logic -- no for loops, etc. Like a macro, this will be inserted everywhere the code is used; a @@ -237,7 +237,7 @@ int main() } ``` -## Exceptions +# Exceptions Exceptions might help you stop segmentation faulting. The important thing to notice is that you can throw about any type in a try block. @@ -263,7 +263,7 @@ catch(int result) ``` -## Default Parameters for Functions +# Default Parameters for Functions This is exactly like default parameters in Python. If a function is called without the parameter, it is assumed to be that value. @@ -284,7 +284,7 @@ int main() ``` -## Function Overloading +# Function Overloading Like Java and Python, you can overload methods in C++. Not only can you overload the methods, but, the return type of the methods which are overloaded don't have to match. @@ -315,7 +315,7 @@ int main() ``` -## Operator Overloading +# Operator Overloading You can redefine basic operators like (+,/,-,<<,>>, +=) for certain data types by using operator overloading. @@ -367,7 +367,7 @@ int main () } ``` -## Functions with Generic Parameter Types +# Functions with Generic Parameter Types In C++ you can use a template class to create a method which has generic return and parameter types. @@ -400,7 +400,7 @@ type1 maximum (type1 a, type2 b) ``` -## Replacement for malloc and free +# Replacement for malloc and free Malloc and free still exists in C++, however, people typically use "new" and "delete" instead because it is cleaner. @@ -416,7 +416,7 @@ delete i; ``` -## Struct Functions +# Struct Functions You can now add functions to structs. @@ -655,7 +655,7 @@ int Cat::fly() } ``` -## Strings +# Strings Since C++ has classes, you can work with strings in a pleasant way. @@ -806,7 +806,7 @@ int main() } ``` -## Resources +# Resources You now know enough C++ to start programming with it. If you want to take your skills to the next level, I would recommend start working on a few projects in C++ and get diff --git a/blogContent/posts/projects/steam-friends-graph.md b/blogContent/posts/projects/steam-friends-graph.md index 351cf60..d96d6ab 100644 --- a/blogContent/posts/projects/steam-friends-graph.md +++ b/blogContent/posts/projects/steam-friends-graph.md @@ -1,11 +1,11 @@ -### Links +# Links - [GitHub](https://github.com/jrtechs/SteamFriendsGraph) - [Live Site](http://steam.jrtechs.net/) -### Project Description +# Project Description This project utilizes the steam API and graph databases to create friend graphs for clients in a web browser. Currently there are two types of graphs available: @@ -15,7 +15,7 @@ web browser. Currently there are two types of graphs available: This graph will only display your friends; however, it will draw edges between your friends’ if they are friends with each other. -### Motivation +# Motivation While learning about graph databases I thought that it would be awesome to create a massive graph database with steam friends in it. After a quick google search, I realized that some other people have @@ -29,7 +29,7 @@ in the future. ![Lucid chart diagram](media/steam/diagram.png) -### Technical Details +# Technical Details At the core of this project there is a java backend and a JavaScript frontend. I needed a backend for this project because you cannot distribute your steam API key, plus, this allows me to cache everything @@ -47,7 +47,7 @@ start applying a force to shake the graph until all the nodes are added to the g ![Steam friends graph](media/steam/jrtechs1.png) - ### Uses of Friends Graph Data Base +# Uses of Friends Graph Data Base There are tons of [academic papers](http://infolab.stanford.edu/~ullman/mmds/ch10.pdf) written on the usages of friends’ graphs. What you may be able to do with friends @@ -67,7 +67,7 @@ already does this to a certain extent when they recommend you games that are pop ![Steam friends graph](media/steam/ben2.png) -### Hosting the Project +# Hosting the Project Hosting the front end of this project is easy, it is just thrown on an apache server. The backend is trickier since it needs to run both a java app and a gremlin server. Currently I am hosting this @@ -76,7 +76,7 @@ loads it uses around 2 GB of ram and saturates my CPU. ![Steam friends graph](media/steam/jrtechs2.png) -### Future Plans for the Project +# Future Plans for the Project In the future I would love to add more graphs to this website. Instead of just displaying graphs it would also be cool to create pages which tries to identify friends’ groups, people you may know, and best diff --git a/blogContent/posts/web-development/history-of-jrtechs.md b/blogContent/posts/web-development/history-of-jrtechs.md index b774e89..2804fd6 100644 --- a/blogContent/posts/web-development/history-of-jrtechs.md +++ b/blogContent/posts/web-development/history-of-jrtechs.md @@ -1,5 +1,4 @@ -Original Site -------------- +# Original Site Jrtechs initially started as a static HTML site that I created early 2014 to build my HTML skills. I initially chose the name Jrtech, but that name was taken @@ -13,21 +12,19 @@ was working on. ![Original edgy site](media/fbd5a1128549b4feb5bafe3595ac1989.png) -Move to WordPress ------------------ +# Move to WordPress In 2015 I moved my website to the cloud and started a WordPress site. The website was focused on turorial like blog posts. ![Initial wordpress theme](media/4fcc3a9fe52f7b2e8bc1bfb164846073.png) -New Theme ---------- +# New Theme ![Second wordpress theme](media/55ad5b49fe28c6374968b0f8a5b3e48b.png) -Rebirth in Nodejs ------------------ +# Rebirth in Nodejs + If you want to read about why I created a new content management system and left WordPress read diff --git a/blogContent/posts/web-development/node-website-optimization.md b/blogContent/posts/web-development/node-website-optimization.md index 9416a01..cac48d5 100644 --- a/blogContent/posts/web-development/node-website-optimization.md +++ b/blogContent/posts/web-development/node-website-optimization.md @@ -5,7 +5,7 @@ done automatically. If you like to build stuff from scratch like me, there is a ton of work required to optimize a website. This post will cover the 8 things that I did to decrease the load time of this blog written in node by two seconds. -#### Final Results +# Final Results ![Final Website Speed Test](media/websiteOptimization/finalResults.png) @@ -17,8 +17,8 @@ waterfall for my home page, most of the time is a result of the youtube embedded videos loading. -1: Optimize Images ------------------- +# Optimize Images + Since images are the largest portion of a website's size, optimizing and reducing the size of images will decrease load time. In a perfect web @@ -72,8 +72,8 @@ The goal of this script is to make most of the images under 100kb for the web. It is ok to have a few images above 100kb; however, you should really avoid having images above 200kb. -2: Take advantage of Async calls --------------------------------- +# Take advantage of Async calls + One of the largest benefits of Node is its Async abilities: code is executed in a multi-threaded fashion. This can become a "callback hell" if not @@ -152,8 +152,8 @@ main: function(requestURL) } ``` -3: Client-Side Caching ----------------------- +# Client-Side Caching + Client-side caching is where the client's web browser stores static content they download from your website. For example, if a client caches a CSS style sheet, @@ -175,7 +175,7 @@ fast and I'm not worried about hash collisions for this application. You can do this in NGINX if you use it to serve static files, but, you can also do it directly in Node. -#### Caching CSS +## Caching CSS ```javascript var eTag = crypto.createHash('md5').update(content).digest('hex'); @@ -186,7 +186,7 @@ result.write(content); result.end(); ``` -#### Caching Images +## Caching Images ```javascript var eTag = crypto.createHash('md5').update(content).digest('hex'); @@ -197,15 +197,15 @@ result.write(content); result.end(); ``` -4: Server-Side Caching ----------------------- +# Server-Side Caching + Even with the best async server, there are still ways to improve performance. If you cache all the static pages that you generate in a HashMap, you can quickly access it for the next web user without ever having to query the database or do file IO. -#### Ex: +## Ex: ```javascript const cache = require('memory-cache'); @@ -247,8 +247,8 @@ server's cache. ![Server Cache Example](media/websiteOptimization/serverCache.png) -5: Enable Compression ---------------------- +# Enable Compression + Compressing content before it is transferred over the internet can significantly decrease the loading time of your website. The only trade off from this approach @@ -258,7 +258,7 @@ performance gains. Using Gzip on CSS and HTML can reduce the size by 60-70%. If you are running an NGINX server, you can enable Gzip there. There is also a simple node module which will use Gzip compression on an Express app. -#### Gzip on Express App +## Gzip on Express App ```bash npm install compression @@ -269,8 +269,8 @@ var compression = require('compression') app.use(compression()); ``` -6: Remove Unused CSS Definitions --------------------------------- +# Remove Unused CSS Definitions + If you use a CSS library like Bootstrap or W3-CSS, you will have a ton of css classes which go unused. The standard BootStrap CSS file is around 210kb. After @@ -316,8 +316,8 @@ You don't have to use this through the command line, you can run this directly in your node app to make it automated. Check out their [documentation](https://www.purgecss.com/) to learn more. -7: Minify CSS and Javascript ----------------------------- +# Minify CSS and Javascript + This is the easiest thing you can do to reduce the size of your website. You just run your CSS and JavaScript through a program which strips out all @@ -332,8 +332,8 @@ Ex of Minified CSS: There are Node libraries which can minify CSS and Javascript, however, if you are lazy, just use a website like [this](https://cssminifier.com/). -8: Keep Minimal JavaScript --------------------------- +# Keep Minimal JavaScript + Ignoring the gross amount of Node dependencies you have, it is critical to minimize the amount of dependencies the client needs. I completely removed @@ -364,8 +364,8 @@ most cases people don't full take advantage of Google Analytics, a simple backend analytics service would work just as good while saving the client load time. -Resources ---------- +# Resources + - [Pingdom Speed Test](https://tools.pingdom.com/)