Closed ghost closed 7 years ago
Hey @atjonathan how about some challenges on Sessions , Cookies etc... As all the projects in Dynamic Web Application Projects
needs these and these are one of major topics in web development (specially for guys coming from PHP background it maybe little hard to understand them)
@ChaituVR, sure defiantly! What others would like to be added?
Here are some thoughts i got.. (if there is some way to implement)
There are a lot more actually.. But we should consider the possibilities of creating them.. Whats going wrong is that.. We have a lot of frontend challenges.. Projects.. Etc.. And once some guy finishes it or ignore some part and goes to backend.. We are asking him to go to c9 or command line or modules like how-to-npm or other which are really confusing to some people. Who never used them before..
@ChaituVR, we are hoping to have a multi file editor soon, which will cater for these kind of challenges. This list looks solid, are you interested in helping with development?
Yes ofcourse i am interested but i had no idea what to or where to.. I am going through this repo from last four days so that i can find some way contribute..
@ChaituVR Awesome :smile: The best way to contribute for this kinda thing is to comment with the name of each challenge, challenge description, challenge seed, solution and tests!
Yes great :) i hope i can comment few more on other issues too.. And if there is some work needed with development.. I am interested.. You can msg me on gitter or i can msg you if you want me to :) lets end this long conversation on the issue ( people may feel hard reading all this stuff)
Challenge Description
Once you installed Nodejs in your system or C9 you'll have access to a new command called node
. You can use the node
command in two different ways. The first is with no arguments type node
in the command-line This will open an interactive shell (REPL: read-eval-print-loop) where you can execute raw JavaScript code.
Challenge Tests
Challenge Solution
console.log('Hello World');
Src- http://blog.modulus.io/absolute-beginners-guide-to-nodejs
Challenge Description
The other way to run Node is by providing it a JavaScript file to execute. This is almost always how you'll be using it. Create a file " hello.js " and type
console.log('Hello World');
and execute the following file with
$node hello.js
Node then runs the JavaScript in that file and prints "Hello World".
Challenge Seed
Challenge Tests
Challenge Solution
console.log('Hello World');
Src- http://blog.modulus.io/absolute-beginners-guide-to-nodejs
Challenge Description
REPL stands for Read Eval Print Loop and it represents a computer environment like a window console or Unix/Linux shell where a command is entered and system responds with an output. R - Reads user input, parse the input into JavaScript data-structure and stores in memory. E - Takes and evaluates the data structure P - Prints the result L - Loops the above command until user press ctrl-c twice.
It is very useful in experimenting with Node.js codes and to debug JavaScript codes.
REPL can be started by simply running node on shell without any argument
$ node
Play with it for some time Try doing some Mathematical operations like
$ node
> 10 + 3
13
> 20 + ( 5 * 3 ) - 10
25
>
try JavaScript
$ node
> x = 10
10
> var y = 10
undefined
> x + y
20
> 3 > 2 > 1
false
> console.log("Node is Cool...!")
Node is Cool...!
undefined
You can terminate your REPL any time by pressing ctrl + c twice
Src- http://www.tutorialspoint.com/nodejs/nodejs_repl_terminal.htm
Challenge Description
A Module is a separate piece of code that you need to include in your program. It could be your own module or someone else's module.
Node.js has several modules compiled into the binary. For example http
module to create a server or fs
for file system
The keyword require
is used in Node.js to import modules
var moduleX = require("path to the file")
For this challenge include http module into your program and assign it to a variable "http".
Remember that http
is the core module so you can give only its name as path
Challenge Seed
Challenge Tests
Challenge Solution
var http = require('http')
Challenge Description
In this Challenge we will create our own module and use it in another program by importing it
Create two files reverse.js
(As our module) and main.js
as our main program file
In `reverse.js' add your function to reverse the given name as a parameter
function reverseName(name){
return //your code to reverse a string
}
module.exports.reverseName=reverseName;
Here 'module.exports' Exports your code
Now Import this file into your main.js
file using require( )
and assign it to a variable " reverse" .
As the reverse.js is in same folder you should use ./
as the path before the name of the file.
then finally your reverse module is available in your main.js
console log your reverseName function with a string for example:
console.log(reverse.reverseName("cat"));
which should output "tac". Challenge Seed
Challenge Tests
Challenge Solution
reverse.js
function reverseName(name){
return name.split('').reverse().join('');
}
module.exports.reverseName=reverseName;
main.js
var reverse=require("./reverse.js")
console.log(reverse.reverseName("cat"));
Express helps you respond to client-side requests for information. If you visit a website created with express, express will analyze the route in the address bar to determine what to do next.
The first part of a URL is called the base URL of a website. When a user visits a route on their browser, the browser automatically issues a GET
request to the server at the route typed in the URL. If you only type the base URL, you are issuing the request at the /
route of the server. For example, when you type:
http://www.helloworld.com/
The browsers issues a GET
request to the /
route of the server located at www.helloworld.com
.
The job of a web server is to issue either a web page or information such as a JSON object, a number, or a string when a client makes a request. The simplest possible express server that serves 'Hello world' in the form of an HTML web page looks like this:
var express = require('express');
var app = express();
app.get('/', function(request, response) {
response.send('<p>Hello World!</p>');
});
app.listen(3000, function() {
console.log('Serving on port 3000');
});
In this app, you load the express library, then initialize an express app. You tell express that when a client requests the base URL of your web server, you send them the string '<p>Hello World!</p>'
. The client's browser then receives this string and renders it to the web browser as a paragraph tag in the body of the browser's HTML. The last block of code tells your express app what port on your computer your server will respond to requests from. If you are serving from your home computer, that means it serves at the IP address of your computer on the world wide web, and a specific port on that computer.
In your code, try sending the string 'Big Hello!!'
in an h1
tag when the client sends a GET
request to your server at the /bighello
route.
var express = require('express');
var app = express();
app.get('/', function(request, response) {
response.send('<p>Hello World!</p>');
});
// Enter code below this line
// Only change code above this line
app.listen(3000, function() {
console.log('Serving on port 3000');
});
var express = require('express');
var app = express();
app.get('/', function(request, response) {
response.send('<p>Hello World!</p>');
});
// Enter code below this line
app.get('/bighello', function(request, response) {
response.send('<h1>Big Hello!!</h1>');
});
// Only change code above this line
app.listen(3000, function() {
console.log('Serving on port 3000');
});
var request = require('request');
var base_url = 'http://localhost:3000/';
describe('Hello world server', function() {
describe('GET /bighello', function() {
it('returns status code 200', function(done) {
request.get(base_url+'bighello', function(err, res, body) {
expect(res.statusCode).toBe(200);
done();
});
});
it('has Big Hello!! in h1 tags in body', function(done) {
request.get(base_url+'bighello', function(err, res, body) {
expect(body).toBe('<h1>Big Hello!!</h1>');
done();
});
});
});
});
I'm not sure how these backend challenges will be implemented with the current technology so I don't know how to write the seed code or tests.
@atjonathan you stated `we are hoping to have a multi file editor soon, which will cater for these kind of challenges'. Does that mean you can have one file with 'client-side' code making requests and one with 'server-side' code issuing responses?
How would you structure seed code or tests using an in-browser editor like the one FCC uses? One thought would be making it a faux-server that sends a 'response' to the console based on what the user typed for their code, but it seems like we're missing the bigger picture doing it that way. We need to understand that the server is a separate entity sending things that the browser then renders, and I'm not sure how that would look with the in browser editor?
@Daynil We may seek to mimic some of HyperDev's functionality on FCC. It's possible that REPL.it or another technology will allow us to run back end code in the browser using containers or a similar technology.
So see if you can implement some challenges on HyperDev and then we can figure out a way to get those running on FCC.
@atjonathan my suggestion would be to leave out Pug since it's entirely optional. Better to focus on teaching raw HTML that works anywhere. Keep in mind that when campers hit the back end challenges, they will only have 800 hours of development experience and they could still use a lot more practice with HTML.
@ChaituVR some of these things you listed could be part of our security challenges section (which will come after these backend challenges): https://github.com/FreeCodeCamp/CurriculumExpansion/issues/25
@QuincyLarson Yea i guess
are part of the security challenges #25 if possible I will try to comment some challenges there with some detailed description :)
@quincylarson we should teach ejs instead of pug then :+1:
@QuincyLarson HyperDev looks awesome, I'll work on some more basic backend challenges with this framework in mind!
@atjonathan I agree with Quincy that we should avoid template engines in favor of vanilla HTML. Trying to learn a template engine while learning the very basics of node is putting the cart before the horse, not to mention FCC is very front-end heavy so most users will utilize node/express as a thin API layer to interface with their databases and won't need templating in their html from the backend at all.
@Daynil, agreed.
You'll want to send more than just simple strings with your express application. Luckily, express provides ways for you to do just that. Instead of serving a string, you can serve a file containing html, like myhomepage.html
.
app.get("/", function (request, response) {
response.sendFile(__dirname + '/myhomepage.html');
});
If you want users to see your homepage when they visit your base URL, you instruct express to send the desired file as the response to the GET
request that the browser makes when a user visits your website.
__dirname
is a special node variable that represents the string of the directory where the current script (in this case, the express server script) resides. If your myhomepage.html
resides in the same folder as your server, you would tell express to serve from the name of the current directory __dirname
plus the name of the file within that folder that you want to serve.
If your myhomepage.html
has a link to another page on your website called about
, a user clicking that link would send a GET
request to the route /about
. In your code, serve up the file aboutpage.html
in response to a request to that route.
var express = require('express');
var app = express();
app.get("/", function (request, response) {
response.sendFile(__dirname + '/myhomepage.html');
});
// Enter code below this line
// Only change code above this line
app.listen(3000, function() {
console.log('Serving on port 3000');
});
var express = require('express');
var app = express();
app.get("/", function (request, response) {
response.sendFile(__dirname + '/myhomepage.html');
});
// Enter code below this line
app.get("/about", function (request, response) {
response.sendFile(__dirname + '/aboutpage.html');
});
// Only change code above this line
app.listen(3000, function() {
console.log('Serving on port 3000');
});
var fs = require('fs');
var request = require('request');
var base_url = 'http://localhost:3000/';
var aboutpg = fs.readFileSync(__dirname + '/aboutpage.html', 'utf-8');
describe('Homepage server', function() {
describe('GET /about', function() {
it('returns status code 200', function(done) {
request.get(base_url+'about', function(err, res, body) {
expect(res.statusCode).toBe(200);
done();
});
});
it('returns the aboutpage.html file', function(done) {
request.get(base_url+'about', function(err, res, body) {
expect(body).toBe(aboutpg);
done();
});
});
});
});
In real world applications, a particular route on your website will often include multiple files. The index.html
of that route will often need to reference a styles.css
and a scripts.js
in order to serve a complex, interactive view. Instead of sending a series of files manually, express provides a way to serve static files as a full directory using static middleware.
Middleware is a function that express can trigger prior to invoking your final request handler. It sits between the raw request sent by the user and the final intended route. Express comes with the static
middleware function built in. We can use the static middleware to serve files or entire directories.
app.use(express.static(__dirname + '/staticfiledirectory'));
The static middleware is a very useful tool. For simple static websites, it is sufficient to invoke the static middleware on the directory containing all of your pages and files and let the browser make requests based on that directory's file structure.
You have a /public
directory containing all the files your website needs with a structure:
public
├─page2
│ └─otherpage.html
├─index.html
├─styles.css
Use the express static middleware to serve your entire webpage.
var express = require('express');
var app = express();
// Enter code below this line
// Only change code above this line
app.listen(3000, function() {
console.log('Serving on port 3000');
});
var express = require('express');
var app = express();
// Enter code below this line
app.use(express.static(__dirname + '/public'));
// Only change code above this line
app.listen(3000, function() {
console.log('Serving on port 3000');
});
var fs = require('fs');
var request = require('request');
var base_url = 'http://localhost:3000/';
var index = fs.readFileSync(__dirname + '/public/index.html', 'utf-8');
var otherpage = fs.readFileSync(__dirname + '/public/page2/otherpage.html', 'utf-8');
var styles = fs.readFileSync(__dirname + '/public/styles.css', 'utf-8');
describe('Directory server', function() {
describe('GET /', function() {
it('returns status code 200', function(done) {
request.get(base_url, function(err, res, body) {
expect(res.statusCode).toBe(200);
done();
});
});
it('returns the index.html file', function(done) {
request.get(base_url, function(err, res, body) {
expect(body).toBe(index);
done();
});
});
});
describe('GET /page2/otherpage.html', function() {
it('returns status code 200', function(done) {
request.get(base_url+'/page2/otherpage.html', function(err, res, body) {
expect(res.statusCode).toBe(200);
done();
});
});
it('returns the otherpage.html file', function(done) {
request.get(base_url+'/page2/otherpage.html', function(err, res, body) {
expect(body).toBe(otherpage);
done();
});
});
});
describe('GET /styles.css', function() {
it('returns status code 200', function(done) {
request.get(base_url+'/styles.css', function(err, res, body) {
expect(res.statusCode).toBe(200);
done();
});
});
it('returns the otherpage.html file', function(done) {
request.get(base_url+'/styles.css', function(err, res, body) {
expect(body).toBe(styles);
done();
});
});
});
});
Express can process parts of a url as a parameter that you can access. You can designate a portion of your route as a parameter by prefixing it with :
and the name of the parameter.
app.get('/name/:user', function(request, response) {
var clientName = request.params.user;
});
Now, if an application makes a GET
request to this route, you can grab a reference to the contents of :user
.
Create a server that can process GET
requests to the route /times42/:number
. Requests to this route should respond with the result of the number parameter * 42.
var express = require('express');
var app = express();
// Enter code below this line
// Only change code above this line
app.listen(3000, function() {
console.log('Serving on port 3000');
});
var express = require('express');
var app = express();
app.get('/times42/:number', function(request, response) {
var clientNumber = request.params.number;
response.send('' + clientNumber*42);
});
app.listen(3000, function() {
console.log('Serving on port 3000');
});
var request = require('request');
var base_url = 'http://localhost:3000/times42/';
describe('Hello world server', function() {
describe('GET /times42/12', function() {
it('returns correct output', function(done) {
request.get(base_url+'12', function(err, res, body) {
expect(body).toBe('504');
done();
});
});
});
});
Express makes an excellent API server. You can send JSON to the client using the response.json()
method.
response.json({message: 'hello world'});
A server's API works with client side AJAX to provide data for the front end. Create a server that responds to GET
requests to the route /api/productlist
with the product list stored on the server.
var express = require('express');
var app = express();
var productList = [
{
product: 'shirt',
price: 19.95,
quantity: 210
},
{
product: 'pants',
price: 25.00,
quanitity: 149
}
];
// Enter code below this line
// Only change code above this line
app.listen(3000, function() {
console.log('Serving on port 3000');
});
var express = require('express');
var app = express();
var productList = [
{
product: 'shirt',
price: 19.95,
quantity: 210
},
{
product: 'pants',
price: 25.00,
quanitity: 149
}
];
app.get('/api/productlist', function(request, response) {
response.json(productList);
});
app.listen(3000, function() {
console.log('Serving on port 3000');
});
var request = require('request');
var base_url = 'http://localhost:3000/api/productlist';
var productlist = [
{
product: 'shirt',
price: 19.95,
quantity: 210
},
{
product: 'pants',
price: 25.00,
quanitity: 149
}
];
describe('Product list api', function() {
describe('GET /api/productlist', function() {
it('returns the product list', function(done) {
request.get(base_url, function(err, res, body) {
var parsedBody = JSON.parse(body);
expect(parsedBody).toEqual(productlist);
done();
});
});
});
});
I implemented the tests with jasmine-node but I can always switch them to something else like mocha/chai or simple asserts with node, whatever ends up being most compatible with how we end up getting these challenges running. Hyperdev utilizes a package.json to dynamically install dependencies, so if we do it that way this should work well by making jasmine-node a dependency.
@Daynil that sounds like a good approach. For these back end challenges, I think just using plain JavaScript assert tests will work fine for now, and we can incorporate fancier libraries once we are farther along.
@Daynil @ChaituVR @atjonathan great work on designing these challenges so far.
Can we create a comprehensive checklist of the specific topics we want to cover? The more granular, the better. This will help us better prioritize which challenges to design and prevent us from duplicating our efforts.
@atjonathan while we're replacing expressworks, we should probably go ahead and cover what learnyounode covers as well. I think it's only like 15 challenges long. If we're already in the mindset of teaching express, Node is pretty similar and the two are pretty closely related imho and could be taught in tandem.
@QuincyLarson, yeh I agree.
@atjonathan OK - great. When you have a moment, could you come up with a list of topics we should cover (or challenge titles)? A good starting point is Learn You Node's sequence (not all of these titles are sufficiently descriptive):
Could you interpret these into proper challenge names and add them to the list of proposed challenges (your original post on this issue?)
Might want to add a challenge on exposing some data as REST API.
@Daynil thanks for the list to these markdown files. It's important to note that NodeSchool's challenges often involve multiple steps, and we want for each of our challenges to just involve a single step (or concept applied). So many of these concepts can be spread across multiple challenges.
@atjonathan @ChaituVR @Daynil we would like for these challenges to be runnable (and completable) on HyperDev.com. My thinking is that could fork a project there and it would have an HTML interface with test results. The challenge is that if they broke the express app, that HTML interface may not render properly. Do you all have any thoughts on how we might achieve this?
@QuincyLarson is there anyway of using the repl api for running challenges and tests in the freecodecamp editor?
cc/ @alayek
@atjonathan We would only use this for non-JavaScript challenges, as it would be much slower than running them in the camper's browser. I think repl.it eventually plans to support multiple files (node.js), which will be huge if and when it happens. @alayek knows a lot more about repl.it than I do.
@ChaituVR I think we should remove your first challenge, Hello NodeJs. You introduce REPL later on anyway.
One thing - do we introduce campers to the idea that you can use Google Chrome JS debugger to debug Node JS applications? I think we should add that, as being able to put breakpoints in execution path is a great plus.
Proposed challenges: (https://github.com/FreeCodeCamp/CurriculumExpansion/issues/33)
@alayek I think showing them how to use the Chrome JS debugger to debug Node JS applications would be better demonstrated in a video challenge.
Issue merged into https://github.com/FreeCodeCamp/CurriculumExpansion/issues/44
These should replace express-works.
Proposed Challenges:
pug
with views (Similar to https://github.com/azat-co/expressworks/blob/master/exercises/jade/problem.md)